From 48a78f77c85151fcb70154b6505329c590c6f813 Mon Sep 17 00:00:00 2001 From: Nik Clayton Date: Sat, 25 Jan 2025 14:21:21 +0100 Subject: [PATCH] refactor: Rename TimelineStatusEntity to StatusEntity --- .../viewmodel/CachedTimelineRemoteMediator.kt | 4 +- .../app/pachli/network/ContentFilterModel.kt | 4 +- .../components/timeline/StatusMocker.kt | 4 +- .../NotificationsRemoteMediator.kt | 6 +- .../15.json | 1980 +++++++++++++++++ .../app/pachli/core/database/AppDatabase.kt | 11 +- .../core/database/dao/NotificationDao.kt | 2 +- .../pachli/core/database/dao/TimelineDao.kt | 54 +- ...imelineStatusEntity.kt => StatusEntity.kt} | 10 +- .../database/model/TranslatedStatusEntity.kt | 2 +- .../core/database/dao/TimelineDaoTest.kt | 8 +- 11 files changed, 2035 insertions(+), 50 deletions(-) create mode 100644 core/database/schemas/app.pachli.core.database.AppDatabase/15.json rename core/database/src/main/kotlin/app/pachli/core/database/model/{TimelineStatusEntity.kt => StatusEntity.kt} (98%) diff --git a/app/src/main/java/app/pachli/components/timeline/viewmodel/CachedTimelineRemoteMediator.kt b/app/src/main/java/app/pachli/components/timeline/viewmodel/CachedTimelineRemoteMediator.kt index 5bb327072f..520aa8a75b 100644 --- a/app/src/main/java/app/pachli/components/timeline/viewmodel/CachedTimelineRemoteMediator.kt +++ b/app/src/main/java/app/pachli/components/timeline/viewmodel/CachedTimelineRemoteMediator.kt @@ -26,8 +26,8 @@ import app.pachli.core.database.dao.TimelineDao import app.pachli.core.database.di.TransactionProvider import app.pachli.core.database.model.RemoteKeyEntity import app.pachli.core.database.model.RemoteKeyEntity.RemoteKeyKind +import app.pachli.core.database.model.StatusEntity import app.pachli.core.database.model.TimelineAccountEntity -import app.pachli.core.database.model.TimelineStatusEntity import app.pachli.core.database.model.TimelineStatusWithAccount import app.pachli.core.network.model.Links import app.pachli.core.network.model.Status @@ -259,7 +259,7 @@ class CachedTimelineRemoteMediator( } timelineDao.upsertAccounts(accounts.map { TimelineAccountEntity.from(it, pachliAccountId) }) - timelineDao.upsertStatuses(statuses.map { TimelineStatusEntity.from(it, pachliAccountId) }) + timelineDao.upsertStatuses(statuses.map { StatusEntity.from(it, pachliAccountId) }) } companion object { diff --git a/app/src/main/java/app/pachli/network/ContentFilterModel.kt b/app/src/main/java/app/pachli/network/ContentFilterModel.kt index 82fdc3b52e..171666c4eb 100644 --- a/app/src/main/java/app/pachli/network/ContentFilterModel.kt +++ b/app/src/main/java/app/pachli/network/ContentFilterModel.kt @@ -1,7 +1,7 @@ package app.pachli.network import app.pachli.core.data.model.from -import app.pachli.core.database.model.TimelineStatusEntity +import app.pachli.core.database.model.StatusEntity import app.pachli.core.model.ContentFilter import app.pachli.core.model.FilterAction import app.pachli.core.model.FilterContext @@ -63,7 +63,7 @@ class ContentFilterModel(private val filterContext: FilterContext, v1ContentFilt } /** @return the [FilterAction] that should be applied to this status */ - fun filterActionFor(status: TimelineStatusEntity): FilterAction { + fun filterActionFor(status: StatusEntity): FilterAction { pattern?.let { pat -> // Patterns are expensive and thread-safe, matchers are neither. val matcher = pat.matcher("") ?: return FilterAction.NONE diff --git a/app/src/test/java/app/pachli/components/timeline/StatusMocker.kt b/app/src/test/java/app/pachli/components/timeline/StatusMocker.kt index e0aca2a724..b9dcc125c3 100644 --- a/app/src/test/java/app/pachli/components/timeline/StatusMocker.kt +++ b/app/src/test/java/app/pachli/components/timeline/StatusMocker.kt @@ -1,9 +1,9 @@ package app.pachli.components.timeline import app.pachli.core.data.model.StatusViewData +import app.pachli.core.database.model.StatusEntity import app.pachli.core.database.model.StatusViewDataEntity import app.pachli.core.database.model.TimelineAccountEntity -import app.pachli.core.database.model.TimelineStatusEntity import app.pachli.core.database.model.TimelineStatusWithAccount import app.pachli.core.database.model.TranslationState import app.pachli.core.network.model.Status @@ -99,7 +99,7 @@ fun mockStatusEntityWithAccount( val mockedStatus = mockStatus(id) return TimelineStatusWithAccount( - status = TimelineStatusEntity.from( + status = StatusEntity.from( mockedStatus, timelineUserId = userId, ), diff --git a/core/data/src/main/kotlin/app/pachli/core/data/repository/notifications/NotificationsRemoteMediator.kt b/core/data/src/main/kotlin/app/pachli/core/data/repository/notifications/NotificationsRemoteMediator.kt index 60fab301ba..613120c47f 100644 --- a/core/data/src/main/kotlin/app/pachli/core/data/repository/notifications/NotificationsRemoteMediator.kt +++ b/core/data/src/main/kotlin/app/pachli/core/data/repository/notifications/NotificationsRemoteMediator.kt @@ -32,8 +32,8 @@ import app.pachli.core.database.model.NotificationRelationshipSeveranceEventEnti import app.pachli.core.database.model.NotificationReportEntity import app.pachli.core.database.model.RemoteKeyEntity import app.pachli.core.database.model.RemoteKeyEntity.RemoteKeyKind +import app.pachli.core.database.model.StatusEntity import app.pachli.core.database.model.TimelineAccountEntity -import app.pachli.core.database.model.TimelineStatusEntity import app.pachli.core.database.model.TimelineStatusWithAccount import app.pachli.core.network.model.Links import app.pachli.core.network.model.Notification @@ -282,7 +282,7 @@ class NotificationsRemoteMediator( // Bulk upsert the discovered items. timelineDao.upsertAccounts(accounts.map { TimelineAccountEntity.from(it, pachliAccountId) }) - timelineDao.upsertStatuses(statuses.map { TimelineStatusEntity.from(it, pachliAccountId) }) + timelineDao.upsertStatuses(statuses.map { StatusEntity.from(it, pachliAccountId) }) notificationDao.upsertReports(reports.mapNotNull { NotificationReportEntity.from(pachliAccountId, it) }) notificationDao.upsertEvents( severanceEvents.mapNotNull { @@ -303,7 +303,7 @@ fun NotificationData.Companion.from(pachliAccountId: Long, notification: Notific account = TimelineAccountEntity.from(notification.account, pachliAccountId), status = notification.status?.let { status -> TimelineStatusWithAccount( - status = TimelineStatusEntity.from(status, pachliAccountId), + status = StatusEntity.from(status, pachliAccountId), account = TimelineAccountEntity.from(status.account, pachliAccountId), ) }, diff --git a/core/database/schemas/app.pachli.core.database.AppDatabase/15.json b/core/database/schemas/app.pachli.core.database.AppDatabase/15.json new file mode 100644 index 0000000000..c310f80e91 --- /dev/null +++ b/core/database/schemas/app.pachli.core.database.AppDatabase/15.json @@ -0,0 +1,1980 @@ +{ + "formatVersion": 1, + "database": { + "version": 15, + "identityHash": "3964d1676b1ccf34735e1c8c54e90313", + "entities": [ + { + "tableName": "DraftEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `accountId` INTEGER NOT NULL, `inReplyToId` TEXT, `content` TEXT, `contentWarning` TEXT, `sensitive` INTEGER NOT NULL, `visibility` INTEGER NOT NULL, `attachments` TEXT NOT NULL, `poll` TEXT, `failedToSend` INTEGER NOT NULL, `failedToSendNew` INTEGER NOT NULL, `scheduledAt` INTEGER, `language` TEXT, `statusId` TEXT, FOREIGN KEY(`accountId`) REFERENCES `AccountEntity`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "accountId", + "columnName": "accountId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "inReplyToId", + "columnName": "inReplyToId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "contentWarning", + "columnName": "contentWarning", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sensitive", + "columnName": "sensitive", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "visibility", + "columnName": "visibility", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "attachments", + "columnName": "attachments", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "poll", + "columnName": "poll", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "failedToSend", + "columnName": "failedToSend", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "failedToSendNew", + "columnName": "failedToSendNew", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "scheduledAt", + "columnName": "scheduledAt", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "language", + "columnName": "language", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "statusId", + "columnName": "statusId", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_DraftEntity_accountId", + "unique": false, + "columnNames": [ + "accountId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_DraftEntity_accountId` ON `${TABLE_NAME}` (`accountId`)" + } + ], + "foreignKeys": [ + { + "table": "AccountEntity", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "accountId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "AccountEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `domain` TEXT NOT NULL, `accessToken` TEXT NOT NULL, `clientId` TEXT NOT NULL, `clientSecret` TEXT NOT NULL, `isActive` INTEGER NOT NULL, `accountId` TEXT NOT NULL, `username` TEXT NOT NULL, `displayName` TEXT NOT NULL, `profilePictureUrl` TEXT NOT NULL, `profileHeaderPictureUrl` TEXT NOT NULL DEFAULT '', `notificationsEnabled` INTEGER NOT NULL, `notificationsMentioned` INTEGER NOT NULL, `notificationsFollowed` INTEGER NOT NULL, `notificationsFollowRequested` INTEGER NOT NULL, `notificationsReblogged` INTEGER NOT NULL, `notificationsFavorited` INTEGER NOT NULL, `notificationsPolls` INTEGER NOT NULL, `notificationsSubscriptions` INTEGER NOT NULL, `notificationsSignUps` INTEGER NOT NULL, `notificationsUpdates` INTEGER NOT NULL, `notificationsReports` INTEGER NOT NULL, `notificationsSeveredRelationships` INTEGER NOT NULL DEFAULT true, `notificationSound` INTEGER NOT NULL, `notificationVibration` INTEGER NOT NULL, `notificationLight` INTEGER NOT NULL, `defaultPostPrivacy` INTEGER NOT NULL, `defaultMediaSensitivity` INTEGER NOT NULL, `defaultPostLanguage` TEXT NOT NULL, `alwaysShowSensitiveMedia` INTEGER NOT NULL, `alwaysOpenSpoiler` INTEGER NOT NULL, `mediaPreviewEnabled` INTEGER NOT NULL, `notificationMarkerId` TEXT NOT NULL DEFAULT '0', `emojis` TEXT NOT NULL, `tabPreferences` TEXT NOT NULL, `notificationsFilter` TEXT NOT NULL, `oauthScopes` TEXT NOT NULL, `unifiedPushUrl` TEXT NOT NULL, `pushPubKey` TEXT NOT NULL, `pushPrivKey` TEXT NOT NULL, `pushAuth` TEXT NOT NULL, `pushServerKey` TEXT NOT NULL, `locked` INTEGER NOT NULL DEFAULT 0, `notificationAccountFilterNotFollowed` TEXT NOT NULL DEFAULT 'NONE', `notificationAccountFilterYounger30d` TEXT NOT NULL DEFAULT 'NONE', `notificationAccountFilterLimitedByServer` TEXT NOT NULL DEFAULT 'NONE')", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "domain", + "columnName": "domain", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "accessToken", + "columnName": "accessToken", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "clientId", + "columnName": "clientId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "clientSecret", + "columnName": "clientSecret", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isActive", + "columnName": "isActive", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "accountId", + "columnName": "accountId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "username", + "columnName": "username", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "displayName", + "columnName": "displayName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "profilePictureUrl", + "columnName": "profilePictureUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "profileHeaderPictureUrl", + "columnName": "profileHeaderPictureUrl", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "notificationsEnabled", + "columnName": "notificationsEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "notificationsMentioned", + "columnName": "notificationsMentioned", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "notificationsFollowed", + "columnName": "notificationsFollowed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "notificationsFollowRequested", + "columnName": "notificationsFollowRequested", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "notificationsReblogged", + "columnName": "notificationsReblogged", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "notificationsFavorited", + "columnName": "notificationsFavorited", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "notificationsPolls", + "columnName": "notificationsPolls", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "notificationsSubscriptions", + "columnName": "notificationsSubscriptions", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "notificationsSignUps", + "columnName": "notificationsSignUps", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "notificationsUpdates", + "columnName": "notificationsUpdates", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "notificationsReports", + "columnName": "notificationsReports", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "notificationsSeveredRelationships", + "columnName": "notificationsSeveredRelationships", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "true" + }, + { + "fieldPath": "notificationSound", + "columnName": "notificationSound", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "notificationVibration", + "columnName": "notificationVibration", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "notificationLight", + "columnName": "notificationLight", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "defaultPostPrivacy", + "columnName": "defaultPostPrivacy", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "defaultMediaSensitivity", + "columnName": "defaultMediaSensitivity", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "defaultPostLanguage", + "columnName": "defaultPostLanguage", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "alwaysShowSensitiveMedia", + "columnName": "alwaysShowSensitiveMedia", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "alwaysOpenSpoiler", + "columnName": "alwaysOpenSpoiler", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "mediaPreviewEnabled", + "columnName": "mediaPreviewEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "notificationMarkerId", + "columnName": "notificationMarkerId", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "'0'" + }, + { + "fieldPath": "emojis", + "columnName": "emojis", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "tabPreferences", + "columnName": "tabPreferences", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "notificationsFilter", + "columnName": "notificationsFilter", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "oauthScopes", + "columnName": "oauthScopes", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "unifiedPushUrl", + "columnName": "unifiedPushUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "pushPubKey", + "columnName": "pushPubKey", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "pushPrivKey", + "columnName": "pushPrivKey", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "pushAuth", + "columnName": "pushAuth", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "pushServerKey", + "columnName": "pushServerKey", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "locked", + "columnName": "locked", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "notificationAccountFilterNotFollowed", + "columnName": "notificationAccountFilterNotFollowed", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "'NONE'" + }, + { + "fieldPath": "notificationAccountFilterYounger30d", + "columnName": "notificationAccountFilterYounger30d", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "'NONE'" + }, + { + "fieldPath": "notificationAccountFilterLimitedByServer", + "columnName": "notificationAccountFilterLimitedByServer", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "'NONE'" + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_AccountEntity_domain_accountId", + "unique": true, + "columnNames": [ + "domain", + "accountId" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_AccountEntity_domain_accountId` ON `${TABLE_NAME}` (`domain`, `accountId`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "InstanceInfoEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`instance` TEXT NOT NULL, `maxPostCharacters` INTEGER, `maxPollOptions` INTEGER, `maxPollOptionLength` INTEGER, `minPollDuration` INTEGER, `maxPollDuration` INTEGER, `charactersReservedPerUrl` INTEGER, `version` TEXT, `videoSizeLimit` INTEGER, `imageSizeLimit` INTEGER, `imageMatrixLimit` INTEGER, `maxMediaAttachments` INTEGER, `maxFields` INTEGER, `maxFieldNameLength` INTEGER, `maxFieldValueLength` INTEGER, `enabledTranslation` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`instance`))", + "fields": [ + { + "fieldPath": "instance", + "columnName": "instance", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "maxPostCharacters", + "columnName": "maxPostCharacters", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "maxPollOptions", + "columnName": "maxPollOptions", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "maxPollOptionLength", + "columnName": "maxPollOptionLength", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "minPollDuration", + "columnName": "minPollDuration", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "maxPollDuration", + "columnName": "maxPollDuration", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "charactersReservedPerUrl", + "columnName": "charactersReservedPerUrl", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "videoSizeLimit", + "columnName": "videoSizeLimit", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "imageSizeLimit", + "columnName": "imageSizeLimit", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "imageMatrixLimit", + "columnName": "imageMatrixLimit", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "maxMediaAttachments", + "columnName": "maxMediaAttachments", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "maxFields", + "columnName": "maxFields", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "maxFieldNameLength", + "columnName": "maxFieldNameLength", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "maxFieldValueLength", + "columnName": "maxFieldValueLength", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "enabledTranslation", + "columnName": "enabledTranslation", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "instance" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "EmojisEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`accountId` INTEGER NOT NULL, `emojiList` TEXT NOT NULL, PRIMARY KEY(`accountId`), FOREIGN KEY(`accountId`) REFERENCES `AccountEntity`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)", + "fields": [ + { + "fieldPath": "accountId", + "columnName": "accountId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "emojiList", + "columnName": "emojiList", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "accountId" + ] + }, + "indices": [], + "foreignKeys": [ + { + "table": "AccountEntity", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "accountId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "StatusEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`serverId` TEXT NOT NULL, `url` TEXT, `timelineUserId` INTEGER NOT NULL, `authorServerId` TEXT NOT NULL, `inReplyToId` TEXT, `inReplyToAccountId` TEXT, `content` TEXT, `createdAt` INTEGER NOT NULL, `editedAt` INTEGER, `emojis` TEXT, `reblogsCount` INTEGER NOT NULL, `favouritesCount` INTEGER NOT NULL, `repliesCount` INTEGER NOT NULL, `reblogged` INTEGER NOT NULL, `bookmarked` INTEGER NOT NULL, `favourited` INTEGER NOT NULL, `sensitive` INTEGER NOT NULL, `spoilerText` TEXT NOT NULL, `visibility` INTEGER NOT NULL, `attachments` TEXT, `mentions` TEXT, `tags` TEXT, `application` TEXT, `reblogServerId` TEXT, `reblogAccountId` TEXT, `poll` TEXT, `muted` INTEGER, `pinned` INTEGER NOT NULL, `card` TEXT, `language` TEXT, `filtered` TEXT, PRIMARY KEY(`serverId`, `timelineUserId`), FOREIGN KEY(`authorServerId`, `timelineUserId`) REFERENCES `TimelineAccountEntity`(`serverId`, `timelineUserId`) ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED)", + "fields": [ + { + "fieldPath": "serverId", + "columnName": "serverId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "timelineUserId", + "columnName": "timelineUserId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "authorServerId", + "columnName": "authorServerId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "inReplyToId", + "columnName": "inReplyToId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "inReplyToAccountId", + "columnName": "inReplyToAccountId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "editedAt", + "columnName": "editedAt", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "emojis", + "columnName": "emojis", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "reblogsCount", + "columnName": "reblogsCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "favouritesCount", + "columnName": "favouritesCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "repliesCount", + "columnName": "repliesCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "reblogged", + "columnName": "reblogged", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bookmarked", + "columnName": "bookmarked", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "favourited", + "columnName": "favourited", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "sensitive", + "columnName": "sensitive", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "spoilerText", + "columnName": "spoilerText", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "visibility", + "columnName": "visibility", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "attachments", + "columnName": "attachments", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "mentions", + "columnName": "mentions", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "tags", + "columnName": "tags", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "application", + "columnName": "application", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "reblogServerId", + "columnName": "reblogServerId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "reblogAccountId", + "columnName": "reblogAccountId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "poll", + "columnName": "poll", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "muted", + "columnName": "muted", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "pinned", + "columnName": "pinned", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "card", + "columnName": "card", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "language", + "columnName": "language", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "filtered", + "columnName": "filtered", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "serverId", + "timelineUserId" + ] + }, + "indices": [ + { + "name": "index_StatusEntity_authorServerId_timelineUserId", + "unique": false, + "columnNames": [ + "authorServerId", + "timelineUserId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_StatusEntity_authorServerId_timelineUserId` ON `${TABLE_NAME}` (`authorServerId`, `timelineUserId`)" + } + ], + "foreignKeys": [ + { + "table": "TimelineAccountEntity", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "authorServerId", + "timelineUserId" + ], + "referencedColumns": [ + "serverId", + "timelineUserId" + ] + } + ] + }, + { + "tableName": "TimelineAccountEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`serverId` TEXT NOT NULL, `timelineUserId` INTEGER NOT NULL, `localUsername` TEXT NOT NULL, `username` TEXT NOT NULL, `displayName` TEXT NOT NULL, `url` TEXT NOT NULL, `avatar` TEXT NOT NULL, `emojis` TEXT NOT NULL, `bot` INTEGER NOT NULL, `createdAt` INTEGER, `limited` INTEGER NOT NULL DEFAULT false, `note` TEXT NOT NULL DEFAULT '', PRIMARY KEY(`serverId`, `timelineUserId`), FOREIGN KEY(`timelineUserId`) REFERENCES `AccountEntity`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)", + "fields": [ + { + "fieldPath": "serverId", + "columnName": "serverId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "timelineUserId", + "columnName": "timelineUserId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "localUsername", + "columnName": "localUsername", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "username", + "columnName": "username", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "displayName", + "columnName": "displayName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "avatar", + "columnName": "avatar", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "emojis", + "columnName": "emojis", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "bot", + "columnName": "bot", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "limited", + "columnName": "limited", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "false" + }, + { + "fieldPath": "note", + "columnName": "note", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "serverId", + "timelineUserId" + ] + }, + "indices": [ + { + "name": "index_TimelineAccountEntity_timelineUserId", + "unique": false, + "columnNames": [ + "timelineUserId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_TimelineAccountEntity_timelineUserId` ON `${TABLE_NAME}` (`timelineUserId`)" + } + ], + "foreignKeys": [ + { + "table": "AccountEntity", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "timelineUserId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "ConversationEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`accountId` INTEGER NOT NULL, `id` TEXT NOT NULL, `order` INTEGER NOT NULL, `accounts` TEXT NOT NULL, `unread` INTEGER NOT NULL, `s_id` TEXT NOT NULL, `s_url` TEXT, `s_inReplyToId` TEXT, `s_inReplyToAccountId` TEXT, `s_account` TEXT NOT NULL, `s_content` TEXT NOT NULL, `s_createdAt` INTEGER NOT NULL, `s_editedAt` INTEGER, `s_emojis` TEXT NOT NULL, `s_favouritesCount` INTEGER NOT NULL, `s_repliesCount` INTEGER NOT NULL, `s_favourited` INTEGER NOT NULL, `s_bookmarked` INTEGER NOT NULL, `s_sensitive` INTEGER NOT NULL, `s_spoilerText` TEXT NOT NULL, `s_attachments` TEXT NOT NULL, `s_mentions` TEXT NOT NULL, `s_tags` TEXT, `s_showingHiddenContent` INTEGER NOT NULL, `s_expanded` INTEGER NOT NULL, `s_collapsed` INTEGER NOT NULL, `s_muted` INTEGER NOT NULL, `s_poll` TEXT, `s_language` TEXT, PRIMARY KEY(`id`, `accountId`), FOREIGN KEY(`accountId`) REFERENCES `AccountEntity`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)", + "fields": [ + { + "fieldPath": "accountId", + "columnName": "accountId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "order", + "columnName": "order", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "accounts", + "columnName": "accounts", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "unread", + "columnName": "unread", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastStatus.id", + "columnName": "s_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "lastStatus.url", + "columnName": "s_url", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "lastStatus.inReplyToId", + "columnName": "s_inReplyToId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "lastStatus.inReplyToAccountId", + "columnName": "s_inReplyToAccountId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "lastStatus.account", + "columnName": "s_account", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "lastStatus.content", + "columnName": "s_content", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "lastStatus.createdAt", + "columnName": "s_createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastStatus.editedAt", + "columnName": "s_editedAt", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "lastStatus.emojis", + "columnName": "s_emojis", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "lastStatus.favouritesCount", + "columnName": "s_favouritesCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastStatus.repliesCount", + "columnName": "s_repliesCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastStatus.favourited", + "columnName": "s_favourited", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastStatus.bookmarked", + "columnName": "s_bookmarked", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastStatus.sensitive", + "columnName": "s_sensitive", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastStatus.spoilerText", + "columnName": "s_spoilerText", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "lastStatus.attachments", + "columnName": "s_attachments", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "lastStatus.mentions", + "columnName": "s_mentions", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "lastStatus.tags", + "columnName": "s_tags", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "lastStatus.showingHiddenContent", + "columnName": "s_showingHiddenContent", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastStatus.expanded", + "columnName": "s_expanded", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastStatus.collapsed", + "columnName": "s_collapsed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastStatus.muted", + "columnName": "s_muted", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastStatus.poll", + "columnName": "s_poll", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "lastStatus.language", + "columnName": "s_language", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id", + "accountId" + ] + }, + "indices": [ + { + "name": "index_ConversationEntity_accountId", + "unique": false, + "columnNames": [ + "accountId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_ConversationEntity_accountId` ON `${TABLE_NAME}` (`accountId`)" + } + ], + "foreignKeys": [ + { + "table": "AccountEntity", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "accountId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "RemoteKeyEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`accountId` INTEGER NOT NULL, `timelineId` TEXT NOT NULL, `kind` TEXT NOT NULL, `key` TEXT, PRIMARY KEY(`accountId`, `timelineId`, `kind`), FOREIGN KEY(`accountId`) REFERENCES `AccountEntity`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)", + "fields": [ + { + "fieldPath": "accountId", + "columnName": "accountId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "timelineId", + "columnName": "timelineId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "kind", + "columnName": "kind", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "key", + "columnName": "key", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "accountId", + "timelineId", + "kind" + ] + }, + "indices": [], + "foreignKeys": [ + { + "table": "AccountEntity", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "accountId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "StatusViewDataEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`serverId` TEXT NOT NULL, `timelineUserId` INTEGER NOT NULL, `expanded` INTEGER NOT NULL, `contentShowing` INTEGER NOT NULL, `contentCollapsed` INTEGER NOT NULL, `translationState` TEXT NOT NULL DEFAULT 'SHOW_ORIGINAL', PRIMARY KEY(`serverId`, `timelineUserId`), FOREIGN KEY(`timelineUserId`) REFERENCES `AccountEntity`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)", + "fields": [ + { + "fieldPath": "serverId", + "columnName": "serverId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "timelineUserId", + "columnName": "timelineUserId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "expanded", + "columnName": "expanded", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "contentShowing", + "columnName": "contentShowing", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "contentCollapsed", + "columnName": "contentCollapsed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "translationState", + "columnName": "translationState", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "'SHOW_ORIGINAL'" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "serverId", + "timelineUserId" + ] + }, + "indices": [ + { + "name": "index_StatusViewDataEntity_timelineUserId", + "unique": false, + "columnNames": [ + "timelineUserId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_StatusViewDataEntity_timelineUserId` ON `${TABLE_NAME}` (`timelineUserId`)" + } + ], + "foreignKeys": [ + { + "table": "AccountEntity", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "timelineUserId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "TranslatedStatusEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`serverId` TEXT NOT NULL, `timelineUserId` INTEGER NOT NULL, `content` TEXT NOT NULL, `spoilerText` TEXT NOT NULL, `poll` TEXT, `attachments` TEXT NOT NULL, `provider` TEXT NOT NULL, PRIMARY KEY(`serverId`, `timelineUserId`))", + "fields": [ + { + "fieldPath": "serverId", + "columnName": "serverId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "timelineUserId", + "columnName": "timelineUserId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "spoilerText", + "columnName": "spoilerText", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "poll", + "columnName": "poll", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "attachments", + "columnName": "attachments", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "provider", + "columnName": "provider", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "serverId", + "timelineUserId" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "LogEntryEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `instant` INTEGER NOT NULL, `priority` INTEGER, `tag` TEXT, `message` TEXT NOT NULL, `t` TEXT)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "instant", + "columnName": "instant", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "priority", + "columnName": "priority", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "tag", + "columnName": "tag", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "message", + "columnName": "message", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "t", + "columnName": "t", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "MastodonListEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`accountId` INTEGER NOT NULL, `listId` TEXT NOT NULL, `title` TEXT NOT NULL, `repliesPolicy` TEXT NOT NULL, `exclusive` INTEGER NOT NULL, PRIMARY KEY(`accountId`, `listId`), FOREIGN KEY(`accountId`) REFERENCES `AccountEntity`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)", + "fields": [ + { + "fieldPath": "accountId", + "columnName": "accountId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "listId", + "columnName": "listId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "repliesPolicy", + "columnName": "repliesPolicy", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "exclusive", + "columnName": "exclusive", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "accountId", + "listId" + ] + }, + "indices": [], + "foreignKeys": [ + { + "table": "AccountEntity", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "accountId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "ServerEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`accountId` INTEGER NOT NULL, `serverKind` TEXT NOT NULL, `version` TEXT NOT NULL, `capabilities` TEXT NOT NULL, PRIMARY KEY(`accountId`), FOREIGN KEY(`accountId`) REFERENCES `AccountEntity`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)", + "fields": [ + { + "fieldPath": "accountId", + "columnName": "accountId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "serverKind", + "columnName": "serverKind", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "capabilities", + "columnName": "capabilities", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "accountId" + ] + }, + "indices": [], + "foreignKeys": [ + { + "table": "AccountEntity", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "accountId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "ContentFiltersEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`accountId` INTEGER NOT NULL, `version` TEXT NOT NULL, `contentFilters` TEXT NOT NULL, PRIMARY KEY(`accountId`), FOREIGN KEY(`accountId`) REFERENCES `AccountEntity`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)", + "fields": [ + { + "fieldPath": "accountId", + "columnName": "accountId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "contentFilters", + "columnName": "contentFilters", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "accountId" + ] + }, + "indices": [], + "foreignKeys": [ + { + "table": "AccountEntity", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "accountId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "AnnouncementEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`accountId` INTEGER NOT NULL, `announcementId` TEXT NOT NULL, `announcement` TEXT NOT NULL, PRIMARY KEY(`accountId`), FOREIGN KEY(`accountId`) REFERENCES `AccountEntity`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)", + "fields": [ + { + "fieldPath": "accountId", + "columnName": "accountId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "announcementId", + "columnName": "announcementId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "announcement", + "columnName": "announcement", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "accountId" + ] + }, + "indices": [], + "foreignKeys": [ + { + "table": "AccountEntity", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "accountId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "FollowingAccountEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`pachliAccountId` INTEGER NOT NULL, `serverId` TEXT NOT NULL, PRIMARY KEY(`pachliAccountId`, `serverId`), FOREIGN KEY(`pachliAccountId`) REFERENCES `AccountEntity`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)", + "fields": [ + { + "fieldPath": "pachliAccountId", + "columnName": "pachliAccountId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "serverId", + "columnName": "serverId", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "pachliAccountId", + "serverId" + ] + }, + "indices": [], + "foreignKeys": [ + { + "table": "AccountEntity", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "pachliAccountId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "NotificationEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`pachliAccountId` INTEGER NOT NULL, `serverId` TEXT NOT NULL, `type` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `accountServerId` TEXT NOT NULL, `statusServerId` TEXT, PRIMARY KEY(`pachliAccountId`, `serverId`), FOREIGN KEY(`pachliAccountId`) REFERENCES `AccountEntity`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY(`accountServerId`, `pachliAccountId`) REFERENCES `TimelineAccountEntity`(`serverId`, `timelineUserId`) ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED)", + "fields": [ + { + "fieldPath": "pachliAccountId", + "columnName": "pachliAccountId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "serverId", + "columnName": "serverId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "accountServerId", + "columnName": "accountServerId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "statusServerId", + "columnName": "statusServerId", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "pachliAccountId", + "serverId" + ] + }, + "indices": [], + "foreignKeys": [ + { + "table": "AccountEntity", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "pachliAccountId" + ], + "referencedColumns": [ + "id" + ] + }, + { + "table": "TimelineAccountEntity", + "onDelete": "NO ACTION", + "onUpdate": "NO ACTION", + "columns": [ + "accountServerId", + "pachliAccountId" + ], + "referencedColumns": [ + "serverId", + "timelineUserId" + ] + } + ] + }, + { + "tableName": "NotificationReportEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`pachliAccountId` INTEGER NOT NULL, `serverId` TEXT NOT NULL, `reportId` TEXT NOT NULL, `actionTaken` INTEGER NOT NULL, `actionTakenAt` INTEGER, `category` TEXT NOT NULL, `comment` TEXT NOT NULL, `forwarded` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `statusIds` TEXT, `ruleIds` TEXT, `target_serverId` TEXT NOT NULL, `target_timelineUserId` INTEGER NOT NULL, `target_localUsername` TEXT NOT NULL, `target_username` TEXT NOT NULL, `target_displayName` TEXT NOT NULL, `target_url` TEXT NOT NULL, `target_avatar` TEXT NOT NULL, `target_emojis` TEXT NOT NULL, `target_bot` INTEGER NOT NULL, `target_createdAt` INTEGER, `target_limited` INTEGER NOT NULL DEFAULT false, `target_note` TEXT NOT NULL DEFAULT '', PRIMARY KEY(`pachliAccountId`, `serverId`), FOREIGN KEY(`pachliAccountId`, `serverId`) REFERENCES `NotificationEntity`(`pachliAccountId`, `serverId`) ON UPDATE NO ACTION ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)", + "fields": [ + { + "fieldPath": "pachliAccountId", + "columnName": "pachliAccountId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "serverId", + "columnName": "serverId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "reportId", + "columnName": "reportId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "actionTaken", + "columnName": "actionTaken", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "actionTakenAt", + "columnName": "actionTakenAt", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "comment", + "columnName": "comment", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "forwarded", + "columnName": "forwarded", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "statusIds", + "columnName": "statusIds", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleIds", + "columnName": "ruleIds", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "targetAccount.serverId", + "columnName": "target_serverId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "targetAccount.timelineUserId", + "columnName": "target_timelineUserId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "targetAccount.localUsername", + "columnName": "target_localUsername", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "targetAccount.username", + "columnName": "target_username", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "targetAccount.displayName", + "columnName": "target_displayName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "targetAccount.url", + "columnName": "target_url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "targetAccount.avatar", + "columnName": "target_avatar", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "targetAccount.emojis", + "columnName": "target_emojis", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "targetAccount.bot", + "columnName": "target_bot", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "targetAccount.createdAt", + "columnName": "target_createdAt", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "targetAccount.limited", + "columnName": "target_limited", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "false" + }, + { + "fieldPath": "targetAccount.note", + "columnName": "target_note", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "pachliAccountId", + "serverId" + ] + }, + "indices": [], + "foreignKeys": [ + { + "table": "NotificationEntity", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "pachliAccountId", + "serverId" + ], + "referencedColumns": [ + "pachliAccountId", + "serverId" + ] + } + ] + }, + { + "tableName": "NotificationViewDataEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`pachliAccountId` INTEGER NOT NULL, `serverId` TEXT NOT NULL, `contentFilterAction` TEXT, `accountFilterDecision` TEXT, PRIMARY KEY(`pachliAccountId`, `serverId`), FOREIGN KEY(`pachliAccountId`) REFERENCES `AccountEntity`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)", + "fields": [ + { + "fieldPath": "pachliAccountId", + "columnName": "pachliAccountId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "serverId", + "columnName": "serverId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "contentFilterAction", + "columnName": "contentFilterAction", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "accountFilterDecision", + "columnName": "accountFilterDecision", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "pachliAccountId", + "serverId" + ] + }, + "indices": [], + "foreignKeys": [ + { + "table": "AccountEntity", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "pachliAccountId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "NotificationRelationshipSeveranceEventEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`pachliAccountId` INTEGER NOT NULL, `serverId` TEXT NOT NULL, `eventId` TEXT NOT NULL, `type` TEXT NOT NULL, `purged` INTEGER NOT NULL, `followersCount` INTEGER NOT NULL, `followingCount` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, PRIMARY KEY(`pachliAccountId`, `serverId`, `eventId`), FOREIGN KEY(`pachliAccountId`, `serverId`) REFERENCES `NotificationEntity`(`pachliAccountId`, `serverId`) ON UPDATE NO ACTION ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)", + "fields": [ + { + "fieldPath": "pachliAccountId", + "columnName": "pachliAccountId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "serverId", + "columnName": "serverId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "eventId", + "columnName": "eventId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "purged", + "columnName": "purged", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "followersCount", + "columnName": "followersCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "followingCount", + "columnName": "followingCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "pachliAccountId", + "serverId", + "eventId" + ] + }, + "indices": [], + "foreignKeys": [ + { + "table": "NotificationEntity", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "pachliAccountId", + "serverId" + ], + "referencedColumns": [ + "pachliAccountId", + "serverId" + ] + } + ] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '3964d1676b1ccf34735e1c8c54e90313')" + ] + } +} \ No newline at end of file diff --git a/core/database/src/main/kotlin/app/pachli/core/database/AppDatabase.kt b/core/database/src/main/kotlin/app/pachli/core/database/AppDatabase.kt index 21091fd393..c8233199dc 100644 --- a/core/database/src/main/kotlin/app/pachli/core/database/AppDatabase.kt +++ b/core/database/src/main/kotlin/app/pachli/core/database/AppDatabase.kt @@ -26,6 +26,7 @@ import androidx.room.AutoMigration import androidx.room.Database import androidx.room.DeleteColumn import androidx.room.RenameColumn +import androidx.room.RenameTable import androidx.room.RoomDatabase import androidx.room.migration.AutoMigrationSpec import androidx.room.migration.Migration @@ -59,9 +60,9 @@ import app.pachli.core.database.model.NotificationReportEntity import app.pachli.core.database.model.NotificationViewDataEntity import app.pachli.core.database.model.RemoteKeyEntity import app.pachli.core.database.model.ServerEntity +import app.pachli.core.database.model.StatusEntity import app.pachli.core.database.model.StatusViewDataEntity import app.pachli.core.database.model.TimelineAccountEntity -import app.pachli.core.database.model.TimelineStatusEntity import app.pachli.core.database.model.TranslatedStatusEntity import app.pachli.core.model.ContentFilterVersion import java.text.SimpleDateFormat @@ -75,7 +76,7 @@ import java.util.TimeZone AccountEntity::class, InstanceInfoEntity::class, EmojisEntity::class, - TimelineStatusEntity::class, + StatusEntity::class, TimelineAccountEntity::class, ConversationEntity::class, RemoteKeyEntity::class, @@ -92,7 +93,7 @@ import java.util.TimeZone NotificationViewDataEntity::class, NotificationRelationshipSeveranceEventEntity::class, ], - version = 14, + version = 15, autoMigrations = [ AutoMigration(from = 1, to = 2, spec = AppDatabase.MIGRATE_1_2::class), AutoMigration(from = 2, to = 3), @@ -107,6 +108,7 @@ import java.util.TimeZone AutoMigration(from = 11, to = 12, spec = AppDatabase.MIGRATE_11_12::class), // 12 -> 13 is a custom migration AutoMigration(from = 13, to = 14, spec = AppDatabase.MIGRATE_13_14::class), + AutoMigration(from = 14, to = 15, spec = AppDatabase.MIGRATE_14_15::class), ], ) abstract class AppDatabase : RoomDatabase() { @@ -186,6 +188,9 @@ abstract class AppDatabase : RoomDatabase() { // lastVisibleHomeTimelineStatusId removed in favour of the REFRESH key in RemoteKeyEntity. @DeleteColumn("AccountEntity", "lastVisibleHomeTimelineStatusId") class MIGRATE_13_14 : AutoMigrationSpec + + @RenameTable("TimelineStatusEntity", "StatusEntity") + class MIGRATE_14_15 : AutoMigrationSpec } val MIGRATE_8_9 = object : Migration(8, 9) { diff --git a/core/database/src/main/kotlin/app/pachli/core/database/dao/NotificationDao.kt b/core/database/src/main/kotlin/app/pachli/core/database/dao/NotificationDao.kt index de108778af..405bf6745d 100644 --- a/core/database/src/main/kotlin/app/pachli/core/database/dao/NotificationDao.kt +++ b/core/database/src/main/kotlin/app/pachli/core/database/dao/NotificationDao.kt @@ -183,7 +183,7 @@ SELECT FROM NotificationEntity AS n LEFT JOIN TimelineAccountEntity AS a ON (n.pachliAccountId = a.timelineUserId AND n.accountServerId = a.serverId) -LEFT JOIN TimelineStatusEntity AS s ON (n.pachliAccountId = s.timelineUserId AND n.statusServerId = s.serverId) +LEFT JOIN StatusEntity AS s ON (n.pachliAccountId = s.timelineUserId AND n.statusServerId = s.serverId) LEFT JOIN TimelineAccountEntity AS sa ON (n.pachliAccountId = sa.timelineUserId AND s.authorServerId = sa.serverId) LEFT JOIN TimelineAccountEntity AS rb ON (n.pachliAccountId = rb.timelineUserId AND s.reblogAccountId = rb.serverId) LEFT JOIN diff --git a/core/database/src/main/kotlin/app/pachli/core/database/dao/TimelineDao.kt b/core/database/src/main/kotlin/app/pachli/core/database/dao/TimelineDao.kt index a1c5895cdf..9a7b90b0ab 100644 --- a/core/database/src/main/kotlin/app/pachli/core/database/dao/TimelineDao.kt +++ b/core/database/src/main/kotlin/app/pachli/core/database/dao/TimelineDao.kt @@ -27,9 +27,9 @@ import androidx.room.Transaction import androidx.room.TypeConverters import androidx.room.Upsert import app.pachli.core.database.Converters +import app.pachli.core.database.model.StatusEntity import app.pachli.core.database.model.StatusViewDataEntity import app.pachli.core.database.model.TimelineAccountEntity -import app.pachli.core.database.model.TimelineStatusEntity import app.pachli.core.database.model.TimelineStatusWithAccount import app.pachli.core.network.model.Poll @@ -44,10 +44,10 @@ abstract class TimelineDao { abstract suspend fun upsertAccounts(accounts: Collection) @Upsert - abstract suspend fun upsertStatuses(statuses: Collection) + abstract suspend fun upsertStatuses(statuses: Collection) @Upsert - abstract suspend fun insertStatus(timelineStatusEntity: TimelineStatusEntity): Long + abstract suspend fun insertStatus(statusEntity: StatusEntity): Long @Query( """ @@ -120,7 +120,7 @@ SELECT t.poll AS 't_poll', t.attachments AS 't_attachments', t.provider AS 't_provider' -FROM TimelineStatusEntity AS s +FROM StatusEntity AS s LEFT JOIN TimelineAccountEntity AS a ON (s.timelineUserId = a.timelineUserId AND s.authorServerId = a.serverId) LEFT JOIN TimelineAccountEntity AS rb ON (s.timelineUserId = rb.timelineUserId AND s.reblogAccountId = rb.serverId) LEFT JOIN @@ -148,9 +148,9 @@ FROM ( t1.timelineUserId, t1.serverId, COUNT(t2.serverId) - 1 AS rownum - FROM TimelineStatusEntity AS t1 + FROM StatusEntity AS t1 INNER JOIN - TimelineStatusEntity AS t2 + StatusEntity AS t2 ON t1.timelineUserId = t2.timelineUserId AND (LENGTH(t1.serverId) <= LENGTH(t2.serverId) AND t1.serverId <= t2.serverId) @@ -234,7 +234,7 @@ SELECT t.poll AS 't_poll', t.attachments AS 't_attachments', t.provider AS 't_provider' -FROM TimelineStatusEntity AS s +FROM StatusEntity AS s LEFT JOIN TimelineAccountEntity AS a ON (s.timelineUserId = a.timelineUserId AND s.authorServerId = a.serverId) LEFT JOIN TimelineAccountEntity AS rb ON (s.timelineUserId = rb.timelineUserId AND s.reblogAccountId = rb.serverId) LEFT JOIN @@ -253,7 +253,7 @@ WHERE @Query( """ DELETE -FROM TimelineStatusEntity +FROM StatusEntity WHERE timelineUserId = :accountId AND (LENGTH(serverId) < LENGTH(:maxId) OR LENGTH(serverId) == LENGTH(:maxId) AND serverId <= :maxId) AND (LENGTH(serverId) > LENGTH(:minId) OR LENGTH(serverId) == LENGTH(:minId) AND serverId >= :minId) @@ -263,7 +263,7 @@ WHERE timelineUserId = :accountId @Query( """ -UPDATE TimelineStatusEntity +UPDATE StatusEntity SET favourited = :favourited WHERE timelineUserId = :pachliAccountId AND (serverId = :statusId OR reblogServerId = :statusId) @@ -273,7 +273,7 @@ WHERE timelineUserId = :pachliAccountId AND (serverId = :statusId OR reblogServe @Query( """ -UPDATE TimelineStatusEntity +UPDATE StatusEntity SET bookmarked = :bookmarked WHERE timelineUserId = :pachliAccountId AND (serverId = :statusId OR reblogServerId = :statusId) @@ -283,7 +283,7 @@ WHERE timelineUserId = :pachliAccountId AND (serverId = :statusId OR reblogServe @Query( """ -UPDATE TimelineStatusEntity +UPDATE StatusEntity SET reblogged = :reblogged WHERE timelineUserId = :pachliAccountId AND (serverId = :statusId OR reblogServerId = :statusId) @@ -294,7 +294,7 @@ WHERE timelineUserId = :pachliAccountId AND (serverId = :statusId OR reblogServe @Query( """ DELETE -FROM TimelineStatusEntity +FROM StatusEntity WHERE timelineUserId = :pachliAccountId AND (authorServerId = :userId OR reblogAccountId = :userId) @@ -311,7 +311,7 @@ WHERE @Query( """ DELETE -FROM TimelineStatusEntity +FROM StatusEntity WHERE timelineUserId = :accountId AND serverId NOT IN ( @@ -344,7 +344,7 @@ WHERE timelineUserId = :accountId @Query( """ DELETE -FROM TimelineStatusEntity +FROM StatusEntity WHERE timelineUserId = :accountId AND serverId = :statusId @@ -353,7 +353,7 @@ WHERE abstract suspend fun delete(accountId: Long, statusId: String) /** - * Cleans the TimelineStatusEntity and TimelineAccountEntity tables from old entries. + * Cleans the StatusEntity and TimelineAccountEntity tables from old entries. * @param accountId id of the account for which to clean tables * @param limit how many statuses to keep */ @@ -366,7 +366,7 @@ WHERE } /** - * Deletes rows from [TimelineStatusEntity], keeping the newest [keep] + * Deletes rows from [StatusEntity], keeping the newest [keep] * statuses. * * @param accountId id of the account for which to clean statuses @@ -375,7 +375,7 @@ WHERE @Query( """ DELETE -FROM TimelineStatusEntity +FROM StatusEntity WHERE timelineUserId = :accountId AND serverId IN ( SELECT serverId FROM ( @@ -385,7 +385,7 @@ WHERE timelineUserId = :accountId AND serverId IN ( -- join returns a NULL notification ID (because the status has -- no associated notification) SELECT s.serverId - FROM TimelineStatusEntity AS s + FROM StatusEntity AS s LEFT JOIN NotificationEntity AS n ON (s.serverId = n.statusServerId AND s.timelineUserId = n.pachliAccountId) @@ -411,7 +411,7 @@ WHERE timelineUserId = :accountId AND serverId IN ( abstract suspend fun cleanupStatuses(accountId: Long, keep: Int) /** - * Cleans the TimelineAccountEntity table from accounts that are no longer referenced in the TimelineStatusEntity table + * Cleans the TimelineAccountEntity table from accounts that are no longer referenced in the StatusEntity table * @param accountId id of the user account for which to clean timeline accounts */ @Query( @@ -422,12 +422,12 @@ WHERE timelineUserId = :accountId AND serverId NOT IN ( SELECT authorServerId - FROM TimelineStatusEntity + FROM StatusEntity WHERE timelineUserId = :accountId ) AND serverId NOT IN ( SELECT reblogAccountId - FROM TimelineStatusEntity + FROM StatusEntity WHERE timelineUserId = :accountId AND reblogAccountId IS NOT NULL ) AND serverId NOT IN ( @@ -483,7 +483,7 @@ WHERE @Query( """ -UPDATE TimelineStatusEntity +UPDATE StatusEntity SET poll = :poll WHERE timelineUserId = :accountId AND (serverId = :statusId OR reblogServerId = :statusId) @@ -519,7 +519,7 @@ WHERE @Query( """ -UPDATE TimelineStatusEntity +UPDATE StatusEntity SET pinned = :pinned WHERE timelineUserId = :accountId AND (serverId = :statusId OR reblogServerId = :statusId) @@ -530,7 +530,7 @@ WHERE timelineUserId = :accountId AND (serverId = :statusId OR reblogServerId = @Query( """ DELETE -FROM TimelineStatusEntity +FROM StatusEntity WHERE timelineUserId = :accountId AND authorServerId IN ( SELECT serverId FROM TimelineAccountEntity @@ -544,7 +544,7 @@ WHERE timelineUserId = :accountId AND authorServerId IN ( @Query( """ -UPDATE TimelineStatusEntity +UPDATE StatusEntity SET filtered = NULL WHERE timelineUserId = :accountId AND (serverId = :statusId OR reblogServerId = :statusId) @@ -555,7 +555,7 @@ WHERE timelineUserId = :accountId AND (serverId = :statusId OR reblogServerId = @Query( """ SELECT COUNT(*) -FROM TimelineStatusEntity +FROM StatusEntity WHERE timelineUserId = :accountId """, ) @@ -565,7 +565,7 @@ WHERE timelineUserId = :accountId @Query( """ SELECT serverId -FROM TimelineStatusEntity +FROM StatusEntity WHERE timelineUserId = :accountId ORDER BY LENGTH(serverId) DESC, serverId DESC LIMIT :count diff --git a/core/database/src/main/kotlin/app/pachli/core/database/model/TimelineStatusEntity.kt b/core/database/src/main/kotlin/app/pachli/core/database/model/StatusEntity.kt similarity index 98% rename from core/database/src/main/kotlin/app/pachli/core/database/model/TimelineStatusEntity.kt rename to core/database/src/main/kotlin/app/pachli/core/database/model/StatusEntity.kt index 8847bd85d8..21f3685d41 100644 --- a/core/database/src/main/kotlin/app/pachli/core/database/model/TimelineStatusEntity.kt +++ b/core/database/src/main/kotlin/app/pachli/core/database/model/StatusEntity.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 Tusky Contributors + * Copyright (c) 2025 Pachli Association * * This file is a part of Pachli. * @@ -62,7 +62,7 @@ import java.util.Date indices = [Index("authorServerId", "timelineUserId")], ) @TypeConverters(Converters::class) -data class TimelineStatusEntity( +data class StatusEntity( // id never flips: we need it for sorting so it's a real id val serverId: String, val url: String?, @@ -99,7 +99,7 @@ data class TimelineStatusEntity( val filtered: List?, ) { companion object { - fun from(status: Status, timelineUserId: Long) = TimelineStatusEntity( + fun from(status: Status, timelineUserId: Long) = StatusEntity( serverId = status.id, url = status.actionableStatus.url, timelineUserId = timelineUserId, @@ -230,7 +230,7 @@ enum class TranslationState { /** * The local view data for a status. * - * There is *no* foreignkey relationship between this and [TimelineStatusEntity], as the view + * There is *no* foreignkey relationship between this and [StatusEntity], as the view * data is kept even if the status is deleted from the local cache (e.g., during a refresh * operation). */ @@ -263,7 +263,7 @@ data class StatusViewDataEntity( data class TimelineStatusWithAccount( @Embedded - val status: TimelineStatusEntity, + val status: StatusEntity, @Embedded(prefix = "a_") val account: TimelineAccountEntity, // null when no reblog diff --git a/core/database/src/main/kotlin/app/pachli/core/database/model/TranslatedStatusEntity.kt b/core/database/src/main/kotlin/app/pachli/core/database/model/TranslatedStatusEntity.kt index 265301ba51..ecfccd1acd 100644 --- a/core/database/src/main/kotlin/app/pachli/core/database/model/TranslatedStatusEntity.kt +++ b/core/database/src/main/kotlin/app/pachli/core/database/model/TranslatedStatusEntity.kt @@ -26,7 +26,7 @@ import app.pachli.core.network.model.TranslatedPoll /** * Translated version of a status, see https://docs.joinmastodon.org/entities/Translation/. * - * There is *no* foreignkey relationship between this and [TimelineStatusEntity], as the + * There is *no* foreignkey relationship between this and [StatusEntity], as the * translation data is kept even if the status is deleted from the local cache (e.g., during * a refresh operation). */ diff --git a/core/database/src/test/kotlin/app/pachli/core/database/dao/TimelineDaoTest.kt b/core/database/src/test/kotlin/app/pachli/core/database/dao/TimelineDaoTest.kt index 12c7fbd80f..258aa6c877 100644 --- a/core/database/src/test/kotlin/app/pachli/core/database/dao/TimelineDaoTest.kt +++ b/core/database/src/test/kotlin/app/pachli/core/database/dao/TimelineDaoTest.kt @@ -21,8 +21,8 @@ import androidx.paging.PagingSource import androidx.test.ext.junit.runners.AndroidJUnit4 import app.pachli.core.database.AppDatabase import app.pachli.core.database.model.AccountEntity +import app.pachli.core.database.model.StatusEntity import app.pachli.core.database.model.TimelineAccountEntity -import app.pachli.core.database.model.TimelineStatusEntity import app.pachli.core.database.model.TimelineStatusWithAccount import app.pachli.core.network.model.Card import app.pachli.core.network.model.Emoji @@ -360,7 +360,7 @@ class TimelineDaoTest { authorServerId: String = "20", domain: String = "mastodon.example", cardUrl: String? = null, - ): Triple { + ): Triple { val author = TimelineAccountEntity( serverId = authorServerId, timelineUserId = accountId, @@ -398,7 +398,7 @@ class TimelineDaoTest { else -> Card(cardUrl, "", "", PreviewCardKind.LINK, providerName = "", providerUrl = "") } val even = accountId % 2 == 0L - val status = TimelineStatusEntity( + val status = StatusEntity( serverId = statusId.toString(), url = "https://$domain/whatever/$statusId", timelineUserId = accountId, @@ -435,7 +435,7 @@ class TimelineDaoTest { } private fun assertStatuses( - expected: List>, + expected: List>, provided: List, ) { for ((exp, prov) in expected.zip(provided)) {