Refactor notifications to Kotlin & paging (#4026)
This refactors the NotificationsFragment and related classes to Kotlin & paging. While trying to preserve as much of the original behavior as possible, this adds the following improvements as well: - The "show notifications filter" preference was added again - The "load more" button now has a background ripple effect when clicked - The "legal" report category of Mastodon 4.2 is now supported in report notifications - Unknown notifications now display "unknown notification type" instead of an empty line Other code quality improvements: - All views from xml layouts are now referenced via ViewBindings - the classes responsible for showing system notifications were moved to a new package `systemnotifications` while the classes from this refactoring are in `notifications` - the id of the local Tusky account is now called `tuskyAccountId` in all places I could find closes https://github.com/tuskyapp/Tusky/issues/3429 --------- Co-authored-by: Zongle Wang <wangzongler@gmail.com>
This commit is contained in:
parent
3bbf96b057
commit
b2c0b18c8e
121 changed files with 6992 additions and 4654 deletions
|
|
@ -0,0 +1,151 @@
|
|||
/* Copyright 2018 Conny Duck
|
||||
*
|
||||
* This file is a part of Tusky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky.db.entity
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.Index
|
||||
import androidx.room.PrimaryKey
|
||||
import androidx.room.TypeConverters
|
||||
import com.keylesspalace.tusky.TabData
|
||||
import com.keylesspalace.tusky.db.Converters
|
||||
import com.keylesspalace.tusky.defaultTabs
|
||||
import com.keylesspalace.tusky.entity.Emoji
|
||||
import com.keylesspalace.tusky.entity.Status
|
||||
|
||||
@Entity(
|
||||
indices = [
|
||||
Index(
|
||||
value = ["domain", "accountId"],
|
||||
unique = true
|
||||
)
|
||||
]
|
||||
)
|
||||
@TypeConverters(Converters::class)
|
||||
data class AccountEntity(
|
||||
@field:PrimaryKey(autoGenerate = true) var id: Long,
|
||||
val domain: String,
|
||||
var accessToken: String,
|
||||
// nullable for backward compatibility
|
||||
var clientId: String?,
|
||||
// nullable for backward compatibility
|
||||
var clientSecret: String?,
|
||||
var isActive: Boolean,
|
||||
var accountId: String = "",
|
||||
var username: String = "",
|
||||
var displayName: String = "",
|
||||
var profilePictureUrl: String = "",
|
||||
var notificationsEnabled: Boolean = true,
|
||||
var notificationsMentioned: Boolean = true,
|
||||
var notificationsFollowed: Boolean = true,
|
||||
var notificationsFollowRequested: Boolean = false,
|
||||
var notificationsReblogged: Boolean = true,
|
||||
var notificationsFavorited: Boolean = true,
|
||||
var notificationsPolls: Boolean = true,
|
||||
var notificationsSubscriptions: Boolean = true,
|
||||
var notificationsSignUps: Boolean = true,
|
||||
var notificationsUpdates: Boolean = true,
|
||||
var notificationsReports: Boolean = true,
|
||||
var notificationSound: Boolean = true,
|
||||
var notificationVibration: Boolean = true,
|
||||
var notificationLight: Boolean = true,
|
||||
var defaultPostPrivacy: Status.Visibility = Status.Visibility.PUBLIC,
|
||||
var defaultMediaSensitivity: Boolean = false,
|
||||
var defaultPostLanguage: String = "",
|
||||
var alwaysShowSensitiveMedia: Boolean = false,
|
||||
/** True if content behind a content warning is shown by default */
|
||||
var alwaysOpenSpoiler: Boolean = false,
|
||||
|
||||
/**
|
||||
* True if the "Download media previews" preference is true. This implies
|
||||
* that media previews are shown as well as downloaded.
|
||||
*/
|
||||
var mediaPreviewEnabled: Boolean = true,
|
||||
/**
|
||||
* ID of the last notification the user read on the Notification, list, and should be restored
|
||||
* to view when the user returns to the list.
|
||||
*
|
||||
* May not be the ID of the most recent notification if the user has scrolled down the list.
|
||||
*/
|
||||
var lastNotificationId: String = "0",
|
||||
/**
|
||||
* ID of the most recent Mastodon notification that Tusky has fetched to show as an
|
||||
* Android notification.
|
||||
*/
|
||||
@ColumnInfo(defaultValue = "0")
|
||||
var notificationMarkerId: String = "0",
|
||||
var emojis: List<Emoji> = emptyList(),
|
||||
var tabPreferences: List<TabData> = defaultTabs(),
|
||||
var notificationsFilter: String = "[\"follow_request\"]",
|
||||
// Scope cannot be changed without re-login, so store it in case
|
||||
// the scope needs to be changed in the future
|
||||
var oauthScopes: String = "",
|
||||
var unifiedPushUrl: String = "",
|
||||
var pushPubKey: String = "",
|
||||
var pushPrivKey: String = "",
|
||||
var pushAuth: String = "",
|
||||
var pushServerKey: String = "",
|
||||
|
||||
/**
|
||||
* ID of the status at the top of the visible list in the home timeline when the
|
||||
* user navigated away.
|
||||
*/
|
||||
var lastVisibleHomeTimelineStatusId: String? = null,
|
||||
|
||||
/** true if the connected Mastodon account is locked (has to manually approve all follow requests **/
|
||||
@ColumnInfo(defaultValue = "0")
|
||||
var locked: Boolean = false,
|
||||
|
||||
@ColumnInfo(defaultValue = "0")
|
||||
var hasDirectMessageBadge: Boolean = false,
|
||||
|
||||
var isShowHomeBoosts: Boolean = true,
|
||||
var isShowHomeReplies: Boolean = true,
|
||||
var isShowHomeSelfBoosts: Boolean = true
|
||||
) {
|
||||
|
||||
val identifier: String
|
||||
get() = "$domain:$accountId"
|
||||
|
||||
val fullName: String
|
||||
get() = "@$username@$domain"
|
||||
|
||||
fun logout() {
|
||||
// deleting credentials so they cannot be used again
|
||||
accessToken = ""
|
||||
clientId = null
|
||||
clientSecret = null
|
||||
}
|
||||
|
||||
fun isLoggedIn() = accessToken.isNotEmpty()
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as AccountEntity
|
||||
|
||||
if (id == other.id) return true
|
||||
return domain == other.domain && accountId == other.accountId
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = id.hashCode()
|
||||
result = 31 * result + domain.hashCode()
|
||||
result = 31 * result + accountId.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/* Copyright 2020 Tusky Contributors
|
||||
*
|
||||
* This file is a part of Tusky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky.db.entity
|
||||
|
||||
import android.net.Uri
|
||||
import android.os.Parcelable
|
||||
import androidx.core.net.toUri
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import androidx.room.TypeConverters
|
||||
import com.keylesspalace.tusky.db.Converters
|
||||
import com.keylesspalace.tusky.entity.Attachment
|
||||
import com.keylesspalace.tusky.entity.NewPoll
|
||||
import com.keylesspalace.tusky.entity.Status
|
||||
import com.squareup.moshi.JsonClass
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Entity
|
||||
@TypeConverters(Converters::class)
|
||||
data class DraftEntity(
|
||||
@PrimaryKey(autoGenerate = true) val id: Int = 0,
|
||||
val accountId: Long,
|
||||
val inReplyToId: String?,
|
||||
val content: String?,
|
||||
val contentWarning: String?,
|
||||
val sensitive: Boolean,
|
||||
val visibility: Status.Visibility,
|
||||
val attachments: List<DraftAttachment>,
|
||||
val poll: NewPoll?,
|
||||
val failedToSend: Boolean,
|
||||
val failedToSendNew: Boolean,
|
||||
val scheduledAt: String?,
|
||||
val language: String?,
|
||||
val statusId: String?
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
@Parcelize
|
||||
data class DraftAttachment(
|
||||
val uriString: String,
|
||||
val description: String?,
|
||||
val focus: Attachment.Focus?,
|
||||
val type: Type
|
||||
) : Parcelable {
|
||||
val uri: Uri
|
||||
get() = uriString.toUri()
|
||||
|
||||
@JsonClass(generateAdapter = false)
|
||||
enum class Type {
|
||||
IMAGE,
|
||||
VIDEO,
|
||||
AUDIO
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/* Copyright 2024 Tusky Contributors
|
||||
*
|
||||
* This file is a part of Tusky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky.db.entity
|
||||
|
||||
import androidx.room.Embedded
|
||||
import androidx.room.Entity
|
||||
import androidx.room.ForeignKey
|
||||
import androidx.room.Index
|
||||
|
||||
/**
|
||||
* Entity to store an item on the home timeline. Can be a standalone status, a reblog, or a placeholder.
|
||||
*/
|
||||
@Entity(
|
||||
primaryKeys = ["id", "tuskyAccountId"],
|
||||
foreignKeys = (
|
||||
[
|
||||
ForeignKey(
|
||||
entity = TimelineStatusEntity::class,
|
||||
parentColumns = ["serverId", "tuskyAccountId"],
|
||||
childColumns = ["statusId", "tuskyAccountId"]
|
||||
),
|
||||
ForeignKey(
|
||||
entity = TimelineAccountEntity::class,
|
||||
parentColumns = ["serverId", "tuskyAccountId"],
|
||||
childColumns = ["reblogAccountId", "tuskyAccountId"]
|
||||
)
|
||||
]
|
||||
),
|
||||
indices = [
|
||||
Index("statusId", "tuskyAccountId"),
|
||||
Index("reblogAccountId", "tuskyAccountId"),
|
||||
]
|
||||
)
|
||||
data class HomeTimelineEntity(
|
||||
val tuskyAccountId: Long,
|
||||
// the id by which the timeline is sorted
|
||||
val id: String,
|
||||
// the id of the status, null when a placeholder
|
||||
val statusId: String?,
|
||||
// the id of the account who reblogged the status, null if no reblog
|
||||
val reblogAccountId: String?,
|
||||
// only relevant when this is a placeholder
|
||||
val loading: Boolean = false
|
||||
)
|
||||
|
||||
/**
|
||||
* Helper class for queries that return HomeTimelineEntity including all references
|
||||
*/
|
||||
data class HomeTimelineData(
|
||||
val id: String,
|
||||
@Embedded val status: TimelineStatusEntity?,
|
||||
@Embedded(prefix = "a_") val account: TimelineAccountEntity?,
|
||||
@Embedded(prefix = "rb_") val reblogAccount: TimelineAccountEntity?,
|
||||
val loading: Boolean
|
||||
)
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/* Copyright 2018 Conny Duck
|
||||
*
|
||||
* This file is a part of Tusky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky.db.entity
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import androidx.room.TypeConverters
|
||||
import com.keylesspalace.tusky.db.Converters
|
||||
import com.keylesspalace.tusky.entity.Emoji
|
||||
|
||||
@Entity
|
||||
@TypeConverters(Converters::class)
|
||||
data class InstanceEntity(
|
||||
@PrimaryKey val instance: String,
|
||||
val emojiList: List<Emoji>?,
|
||||
val maximumTootCharacters: Int?,
|
||||
val maxPollOptions: Int?,
|
||||
val maxPollOptionLength: Int?,
|
||||
val minPollDuration: Int?,
|
||||
val maxPollDuration: Int?,
|
||||
val charactersReservedPerUrl: Int?,
|
||||
val version: String?,
|
||||
val videoSizeLimit: Int?,
|
||||
val imageSizeLimit: Int?,
|
||||
val imageMatrixLimit: Int?,
|
||||
val maxMediaAttachments: Int?,
|
||||
val maxFields: Int?,
|
||||
val maxFieldNameLength: Int?,
|
||||
val maxFieldValueLength: Int?,
|
||||
val translationEnabled: Boolean?,
|
||||
)
|
||||
|
||||
@TypeConverters(Converters::class)
|
||||
data class EmojisEntity(
|
||||
@PrimaryKey val instance: String,
|
||||
val emojiList: List<Emoji>?
|
||||
)
|
||||
|
||||
data class InstanceInfoEntity(
|
||||
@PrimaryKey val instance: String,
|
||||
val maximumTootCharacters: Int?,
|
||||
val maxPollOptions: Int?,
|
||||
val maxPollOptionLength: Int?,
|
||||
val minPollDuration: Int?,
|
||||
val maxPollDuration: Int?,
|
||||
val charactersReservedPerUrl: Int?,
|
||||
val version: String?,
|
||||
val videoSizeLimit: Int?,
|
||||
val imageSizeLimit: Int?,
|
||||
val imageMatrixLimit: Int?,
|
||||
val maxMediaAttachments: Int?,
|
||||
val maxFields: Int?,
|
||||
val maxFieldNameLength: Int?,
|
||||
val maxFieldValueLength: Int?,
|
||||
val translationEnabled: Boolean?,
|
||||
)
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/* Copyright 2024 Tusky Contributors
|
||||
*
|
||||
* This file is a part of Tusky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky.db.entity
|
||||
|
||||
import androidx.room.Embedded
|
||||
import androidx.room.Entity
|
||||
import androidx.room.ForeignKey
|
||||
import androidx.room.Index
|
||||
import androidx.room.TypeConverters
|
||||
import com.keylesspalace.tusky.db.Converters
|
||||
import com.keylesspalace.tusky.entity.Notification
|
||||
import java.util.Date
|
||||
|
||||
data class NotificationDataEntity(
|
||||
// id of the account logged into Tusky this notifications belongs to
|
||||
val tuskyAccountId: Long,
|
||||
// null when placeholder
|
||||
val type: Notification.Type?,
|
||||
val id: String,
|
||||
@Embedded(prefix = "a_") val account: TimelineAccountEntity?,
|
||||
@Embedded(prefix = "s_") val status: TimelineStatusEntity?,
|
||||
@Embedded(prefix = "sa_") val statusAccount: TimelineAccountEntity?,
|
||||
@Embedded(prefix = "r_") val report: NotificationReportEntity?,
|
||||
@Embedded(prefix = "ra_") val reportTargetAccount: TimelineAccountEntity?,
|
||||
// relevant when it is a placeholder
|
||||
val loading: Boolean = false
|
||||
)
|
||||
|
||||
@Entity(
|
||||
primaryKeys = ["id", "tuskyAccountId"],
|
||||
foreignKeys = (
|
||||
[
|
||||
ForeignKey(
|
||||
entity = TimelineAccountEntity::class,
|
||||
parentColumns = ["serverId", "tuskyAccountId"],
|
||||
childColumns = ["accountId", "tuskyAccountId"]
|
||||
),
|
||||
ForeignKey(
|
||||
entity = TimelineStatusEntity::class,
|
||||
parentColumns = ["serverId", "tuskyAccountId"],
|
||||
childColumns = ["statusId", "tuskyAccountId"]
|
||||
),
|
||||
ForeignKey(
|
||||
entity = NotificationReportEntity::class,
|
||||
parentColumns = ["serverId", "tuskyAccountId"],
|
||||
childColumns = ["reportId", "tuskyAccountId"]
|
||||
)
|
||||
]
|
||||
),
|
||||
indices = [
|
||||
Index("accountId", "tuskyAccountId"),
|
||||
Index("statusId", "tuskyAccountId"),
|
||||
Index("reportId", "tuskyAccountId"),
|
||||
]
|
||||
)
|
||||
@TypeConverters(Converters::class)
|
||||
data class NotificationEntity(
|
||||
// id of the account logged into Tusky this notifications belongs to
|
||||
val tuskyAccountId: Long,
|
||||
// null when placeholder
|
||||
val type: Notification.Type?,
|
||||
val id: String,
|
||||
val accountId: String?,
|
||||
val statusId: String?,
|
||||
val reportId: String?,
|
||||
// relevant when it is a placeholder
|
||||
val loading: Boolean = false
|
||||
)
|
||||
|
||||
@Entity(
|
||||
primaryKeys = ["serverId", "tuskyAccountId"],
|
||||
foreignKeys = (
|
||||
[
|
||||
ForeignKey(
|
||||
entity = TimelineAccountEntity::class,
|
||||
parentColumns = ["serverId", "tuskyAccountId"],
|
||||
childColumns = ["targetAccountId", "tuskyAccountId"]
|
||||
)
|
||||
]
|
||||
),
|
||||
indices = [
|
||||
Index("targetAccountId", "tuskyAccountId"),
|
||||
]
|
||||
)
|
||||
@TypeConverters(Converters::class)
|
||||
data class NotificationReportEntity(
|
||||
// id of the account logged into Tusky this report belongs to
|
||||
val tuskyAccountId: Long,
|
||||
val serverId: String,
|
||||
val category: String,
|
||||
val statusIds: List<String>?,
|
||||
val createdAt: Date,
|
||||
val targetAccountId: String?
|
||||
)
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/* Copyright 2024 Tusky Contributors
|
||||
*
|
||||
* This file is a part of Tusky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky.db.entity
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.TypeConverters
|
||||
import com.keylesspalace.tusky.db.Converters
|
||||
import com.keylesspalace.tusky.entity.Emoji
|
||||
|
||||
@Entity(
|
||||
primaryKeys = ["serverId", "tuskyAccountId"]
|
||||
)
|
||||
@TypeConverters(Converters::class)
|
||||
data class TimelineAccountEntity(
|
||||
val serverId: String,
|
||||
val tuskyAccountId: Long,
|
||||
val localUsername: String,
|
||||
val username: String,
|
||||
val displayName: String,
|
||||
val url: String,
|
||||
val avatar: String,
|
||||
val emojis: List<Emoji>,
|
||||
val bot: Boolean
|
||||
)
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
/* Copyright 2021 Tusky Contributors
|
||||
*
|
||||
* This file is a part of Tusky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
package com.keylesspalace.tusky.db.entity
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.ForeignKey
|
||||
import androidx.room.Index
|
||||
import androidx.room.TypeConverters
|
||||
import com.keylesspalace.tusky.db.Converters
|
||||
import com.keylesspalace.tusky.entity.Attachment
|
||||
import com.keylesspalace.tusky.entity.Card
|
||||
import com.keylesspalace.tusky.entity.Emoji
|
||||
import com.keylesspalace.tusky.entity.FilterResult
|
||||
import com.keylesspalace.tusky.entity.HashTag
|
||||
import com.keylesspalace.tusky.entity.Poll
|
||||
import com.keylesspalace.tusky.entity.Status
|
||||
|
||||
/**
|
||||
* Entity for caching status data. Used within home timelines and notifications.
|
||||
* The information if a status is a reblog is not stored here but in [HomeTimelineEntity].
|
||||
*/
|
||||
@Entity(
|
||||
primaryKeys = ["serverId", "tuskyAccountId"],
|
||||
foreignKeys = (
|
||||
[
|
||||
ForeignKey(
|
||||
entity = TimelineAccountEntity::class,
|
||||
parentColumns = ["serverId", "tuskyAccountId"],
|
||||
childColumns = ["authorServerId", "tuskyAccountId"]
|
||||
)
|
||||
]
|
||||
),
|
||||
// Avoiding rescanning status table when accounts table changes. Recommended by Room(c).
|
||||
indices = [Index("authorServerId", "tuskyAccountId")]
|
||||
)
|
||||
@TypeConverters(Converters::class)
|
||||
data class TimelineStatusEntity(
|
||||
// id never flips: we need it for sorting so it's a real id
|
||||
val serverId: String,
|
||||
val url: String?,
|
||||
// our local id for the logged in user in case there are multiple accounts per instance
|
||||
val tuskyAccountId: Long,
|
||||
val authorServerId: String,
|
||||
val inReplyToId: String?,
|
||||
val inReplyToAccountId: String?,
|
||||
val content: String,
|
||||
val createdAt: Long,
|
||||
val editedAt: Long?,
|
||||
val emojis: List<Emoji>,
|
||||
val reblogsCount: Int,
|
||||
val favouritesCount: Int,
|
||||
val repliesCount: Int,
|
||||
val reblogged: Boolean,
|
||||
val bookmarked: Boolean,
|
||||
val favourited: Boolean,
|
||||
val sensitive: Boolean,
|
||||
val spoilerText: String,
|
||||
val visibility: Status.Visibility,
|
||||
val attachments: List<Attachment>,
|
||||
val mentions: List<Status.Mention>,
|
||||
val tags: List<HashTag>,
|
||||
val application: Status.Application?,
|
||||
// if it has a reblogged status, it's id is stored here
|
||||
val poll: Poll?,
|
||||
val muted: Boolean,
|
||||
/** Also used as the "loading" attribute when this TimelineStatusEntity is a placeholder */
|
||||
val expanded: Boolean,
|
||||
val contentCollapsed: Boolean,
|
||||
val contentShowing: Boolean,
|
||||
val pinned: Boolean,
|
||||
val card: Card?,
|
||||
val language: String?,
|
||||
val filtered: List<FilterResult>
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue