From 6c93555ad0b1ca7223643454761f12572a6a1382 Mon Sep 17 00:00:00 2001 From: Konrad Pozniak Date: Wed, 13 Feb 2019 19:20:31 +0100 Subject: [PATCH] remove unneeded instance id from db cache (#1035) * remove unneeded instance id from db cache * fix TimelineDAOTest * fix TimelineRepositoryTest --- .../13.json | 656 ++++++++++++++++++ .../keylesspalace/tusky/TimelineDAOTest.kt | 4 - .../keylesspalace/tusky/TuskyApplication.java | 2 +- .../keylesspalace/tusky/db/AppDatabase.java | 59 +- .../com/keylesspalace/tusky/db/TimelineDao.kt | 6 +- .../tusky/db/TimelineStatusEntity.kt | 2 - .../tusky/repository/TimelineRepository.kt | 23 +- .../tusky/fragment/TimelineRepositoryTest.kt | 24 +- 8 files changed, 739 insertions(+), 37 deletions(-) create mode 100644 app/schemas/com.keylesspalace.tusky.db.AppDatabase/13.json diff --git a/app/schemas/com.keylesspalace.tusky.db.AppDatabase/13.json b/app/schemas/com.keylesspalace.tusky.db.AppDatabase/13.json new file mode 100644 index 000000000..ba7e57b7c --- /dev/null +++ b/app/schemas/com.keylesspalace.tusky.db.AppDatabase/13.json @@ -0,0 +1,656 @@ +{ + "formatVersion": 1, + "database": { + "version": 13, + "identityHash": "9a63a3ab2c05004022c350aab0e472c0", + "entities": [ + { + "tableName": "TootEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `text` TEXT, `urls` TEXT, `descriptions` TEXT, `contentWarning` TEXT, `inReplyToId` TEXT, `inReplyToText` TEXT, `inReplyToUsername` TEXT, `visibility` INTEGER)", + "fields": [ + { + "fieldPath": "uid", + "columnName": "uid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "text", + "columnName": "text", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "urls", + "columnName": "urls", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "descriptions", + "columnName": "descriptions", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "contentWarning", + "columnName": "contentWarning", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "inReplyToId", + "columnName": "inReplyToId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "inReplyToText", + "columnName": "inReplyToText", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "inReplyToUsername", + "columnName": "inReplyToUsername", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "visibility", + "columnName": "visibility", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "uid" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "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, `isActive` INTEGER NOT NULL, `accountId` TEXT NOT NULL, `username` TEXT NOT NULL, `displayName` TEXT NOT NULL, `profilePictureUrl` TEXT NOT NULL, `notificationsEnabled` INTEGER NOT NULL, `notificationsMentioned` INTEGER NOT NULL, `notificationsFollowed` INTEGER NOT NULL, `notificationsReblogged` INTEGER NOT NULL, `notificationsFavorited` INTEGER NOT NULL, `notificationSound` INTEGER NOT NULL, `notificationVibration` INTEGER NOT NULL, `notificationLight` INTEGER NOT NULL, `defaultPostPrivacy` INTEGER NOT NULL, `defaultMediaSensitivity` INTEGER NOT NULL, `alwaysShowSensitiveMedia` INTEGER NOT NULL, `mediaPreviewEnabled` INTEGER NOT NULL, `lastNotificationId` TEXT NOT NULL, `activeNotifications` TEXT NOT NULL, `emojis` TEXT NOT NULL, `tabPreferences` TEXT NOT NULL)", + "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": "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": "notificationsEnabled", + "columnName": "notificationsEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "notificationsMentioned", + "columnName": "notificationsMentioned", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "notificationsFollowed", + "columnName": "notificationsFollowed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "notificationsReblogged", + "columnName": "notificationsReblogged", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "notificationsFavorited", + "columnName": "notificationsFavorited", + "affinity": "INTEGER", + "notNull": 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": "alwaysShowSensitiveMedia", + "columnName": "alwaysShowSensitiveMedia", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "mediaPreviewEnabled", + "columnName": "mediaPreviewEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastNotificationId", + "columnName": "lastNotificationId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "activeNotifications", + "columnName": "activeNotifications", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "emojis", + "columnName": "emojis", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "tabPreferences", + "columnName": "tabPreferences", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_AccountEntity_domain_accountId", + "unique": true, + "columnNames": [ + "domain", + "accountId" + ], + "createSql": "CREATE UNIQUE INDEX `index_AccountEntity_domain_accountId` ON `${TABLE_NAME}` (`domain`, `accountId`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "InstanceEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`instance` TEXT NOT NULL, `emojiList` TEXT, `maximumTootCharacters` INTEGER, PRIMARY KEY(`instance`))", + "fields": [ + { + "fieldPath": "instance", + "columnName": "instance", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "emojiList", + "columnName": "emojiList", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "maximumTootCharacters", + "columnName": "maximumTootCharacters", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "instance" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "TimelineStatusEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`serverId` TEXT NOT NULL, `url` TEXT, `timelineUserId` INTEGER NOT NULL, `authorServerId` TEXT, `inReplyToId` TEXT, `inReplyToAccountId` TEXT, `content` TEXT, `createdAt` INTEGER NOT NULL, `emojis` TEXT, `reblogsCount` INTEGER NOT NULL, `favouritesCount` INTEGER NOT NULL, `reblogged` INTEGER NOT NULL, `favourited` INTEGER NOT NULL, `sensitive` INTEGER NOT NULL, `spoilerText` TEXT, `visibility` INTEGER, `attachments` TEXT, `mentions` TEXT, `application` TEXT, `reblogServerId` TEXT, `reblogAccountId` TEXT, PRIMARY KEY(`serverId`, `timelineUserId`), FOREIGN KEY(`authorServerId`, `timelineUserId`) REFERENCES `TimelineAccountEntity`(`serverId`, `timelineUserId`) ON UPDATE NO ACTION ON DELETE NO ACTION )", + "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": false + }, + { + "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": "emojis", + "columnName": "emojis", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "reblogsCount", + "columnName": "reblogsCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "favouritesCount", + "columnName": "favouritesCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "reblogged", + "columnName": "reblogged", + "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": false + }, + { + "fieldPath": "visibility", + "columnName": "visibility", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "attachments", + "columnName": "attachments", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "mentions", + "columnName": "mentions", + "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 + } + ], + "primaryKey": { + "columnNames": [ + "serverId", + "timelineUserId" + ], + "autoGenerate": false + }, + "indices": [ + { + "name": "index_TimelineStatusEntity_authorServerId_timelineUserId", + "unique": false, + "columnNames": [ + "authorServerId", + "timelineUserId" + ], + "createSql": "CREATE INDEX `index_TimelineStatusEntity_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, PRIMARY KEY(`serverId`, `timelineUserId`))", + "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 + } + ], + "primaryKey": { + "columnNames": [ + "serverId", + "timelineUserId" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "ConversationEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`accountId` INTEGER NOT NULL, `id` TEXT 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_emojis` TEXT NOT NULL, `s_favouritesCount` INTEGER NOT NULL, `s_favourited` INTEGER NOT NULL, `s_sensitive` INTEGER NOT NULL, `s_spoilerText` TEXT NOT NULL, `s_attachments` TEXT NOT NULL, `s_mentions` TEXT NOT NULL, `s_showingHiddenContent` INTEGER NOT NULL, `s_expanded` INTEGER NOT NULL, `s_collapsible` INTEGER NOT NULL, `s_collapsed` INTEGER NOT NULL, PRIMARY KEY(`id`, `accountId`))", + "fields": [ + { + "fieldPath": "accountId", + "columnName": "accountId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "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.emojis", + "columnName": "s_emojis", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "lastStatus.favouritesCount", + "columnName": "s_favouritesCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastStatus.favourited", + "columnName": "s_favourited", + "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.showingHiddenContent", + "columnName": "s_showingHiddenContent", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastStatus.expanded", + "columnName": "s_expanded", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastStatus.collapsible", + "columnName": "s_collapsible", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastStatus.collapsed", + "columnName": "s_collapsed", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id", + "accountId" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + } + ], + "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, \"9a63a3ab2c05004022c350aab0e472c0\")" + ] + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/com/keylesspalace/tusky/TimelineDAOTest.kt b/app/src/androidTest/java/com/keylesspalace/tusky/TimelineDAOTest.kt index 6c51a1ade..51b50ba55 100644 --- a/app/src/androidTest/java/com/keylesspalace/tusky/TimelineDAOTest.kt +++ b/app/src/androidTest/java/com/keylesspalace/tusky/TimelineDAOTest.kt @@ -133,7 +133,6 @@ class TimelineDAOTest { val author = TimelineAccountEntity( authorServerId, accountId, - "birb.site", "localUsername", "username", "displayName", @@ -146,7 +145,6 @@ class TimelineDAOTest { TimelineAccountEntity( "R$authorServerId", accountId, - "Rbirb.site", "RlocalUsername", "Rusername", "RdisplayName", @@ -163,7 +161,6 @@ class TimelineDAOTest { url = "url$statusId", timelineUserId = accountId, authorServerId = authorServerId, - instance = "birb.site$statusId", inReplyToId = "inReplyToId$statusId", inReplyToAccountId = "inReplyToAccountId$statusId", content = "Content!$statusId", @@ -191,7 +188,6 @@ class TimelineDAOTest { url = null, timelineUserId = timelineUserId, authorServerId = null, - instance = null, inReplyToId = null, inReplyToAccountId = null, content = null, diff --git a/app/src/main/java/com/keylesspalace/tusky/TuskyApplication.java b/app/src/main/java/com/keylesspalace/tusky/TuskyApplication.java index fc278dc9e..a73021011 100644 --- a/app/src/main/java/com/keylesspalace/tusky/TuskyApplication.java +++ b/app/src/main/java/com/keylesspalace/tusky/TuskyApplication.java @@ -67,7 +67,7 @@ public class TuskyApplication extends Application implements HasActivityInjector .addMigrations(AppDatabase.MIGRATION_2_3, AppDatabase.MIGRATION_3_4, AppDatabase.MIGRATION_4_5, AppDatabase.MIGRATION_5_6, AppDatabase.MIGRATION_6_7, AppDatabase.MIGRATION_7_8, AppDatabase.MIGRATION_8_9, AppDatabase.MIGRATION_9_10, AppDatabase.MIGRATION_10_11, - AppDatabase.MIGRATION_11_12) + AppDatabase.MIGRATION_11_12, AppDatabase.MIGRATION_12_13, AppDatabase.MIGRATION_10_13) .build(); accountManager = new AccountManager(appDatabase); serviceLocator = new ServiceLocator() { diff --git a/app/src/main/java/com/keylesspalace/tusky/db/AppDatabase.java b/app/src/main/java/com/keylesspalace/tusky/db/AppDatabase.java index 7fe0d35e2..83e7898a1 100644 --- a/app/src/main/java/com/keylesspalace/tusky/db/AppDatabase.java +++ b/app/src/main/java/com/keylesspalace/tusky/db/AppDatabase.java @@ -30,7 +30,7 @@ import androidx.annotation.NonNull; @Database(entities = {TootEntity.class, AccountEntity.class, InstanceEntity.class, TimelineStatusEntity.class, TimelineAccountEntity.class, ConversationEntity.class - }, version = 12) + }, version = 13) public abstract class AppDatabase extends RoomDatabase { public abstract TootDao tootDao(); @@ -207,4 +207,61 @@ public abstract class AppDatabase extends RoomDatabase { } }; + public static final Migration MIGRATION_12_13 = new Migration(12, 13) { + @Override + public void migrate(@NonNull SupportSQLiteDatabase database) { + + database.execSQL("DROP TABLE IF EXISTS `TimelineAccountEntity`"); + database.execSQL("DROP TABLE IF EXISTS `TimelineStatusEntity`"); + + database.execSQL("CREATE TABLE IF NOT EXISTS `TimelineAccountEntity` (" + + "`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," + + "PRIMARY KEY(`serverId`, `timelineUserId`))"); + + database.execSQL("CREATE TABLE IF NOT EXISTS `TimelineStatusEntity` (" + + "`serverId` TEXT NOT NULL, " + + "`url` TEXT, " + + "`timelineUserId` INTEGER NOT NULL, " + + "`authorServerId` TEXT," + + "`inReplyToId` TEXT, " + + "`inReplyToAccountId` TEXT, " + + "`content` TEXT, " + + "`createdAt` INTEGER NOT NULL, " + + "`emojis` TEXT, " + + "`reblogsCount` INTEGER NOT NULL, " + + "`favouritesCount` INTEGER NOT NULL, " + + "`reblogged` INTEGER NOT NULL, " + + "`favourited` INTEGER NOT NULL, " + + "`sensitive` INTEGER NOT NULL, " + + "`spoilerText` TEXT, " + + "`visibility` INTEGER, " + + "`attachments` TEXT, " + + "`mentions` TEXT, " + + "`application` TEXT, " + + "`reblogServerId` TEXT, " + + "`reblogAccountId` TEXT," + + " PRIMARY KEY(`serverId`, `timelineUserId`)," + + " FOREIGN KEY(`authorServerId`, `timelineUserId`) REFERENCES `TimelineAccountEntity`(`serverId`, `timelineUserId`) " + + "ON UPDATE NO ACTION ON DELETE NO ACTION )"); + database.execSQL("CREATE INDEX IF NOT EXISTS" + + "`index_TimelineStatusEntity_authorServerId_timelineUserId` " + + "ON `TimelineStatusEntity` (`authorServerId`, `timelineUserId`)"); + } + }; + + public static final Migration MIGRATION_10_13 = new Migration(10, 13) { + @Override + public void migrate(@NonNull SupportSQLiteDatabase database) { + MIGRATION_11_12.migrate(database); + MIGRATION_12_13.migrate(database); + } + }; + } \ No newline at end of file diff --git a/app/src/main/java/com/keylesspalace/tusky/db/TimelineDao.kt b/app/src/main/java/com/keylesspalace/tusky/db/TimelineDao.kt index c2d638eaa..bedb50b6d 100644 --- a/app/src/main/java/com/keylesspalace/tusky/db/TimelineDao.kt +++ b/app/src/main/java/com/keylesspalace/tusky/db/TimelineDao.kt @@ -24,14 +24,14 @@ abstract class TimelineDao { @Query(""" SELECT s.serverId, s.url, s.timelineUserId, -s.authorServerId, s.instance, s.inReplyToId, s.inReplyToAccountId, s.createdAt, +s.authorServerId, s.inReplyToId, s.inReplyToAccountId, s.createdAt, s.emojis, s.reblogsCount, s.favouritesCount, s.reblogged, s.favourited, s.sensitive, s.spoilerText, s.visibility, s.mentions, s.application, s.reblogServerId,s.reblogAccountId, s.content, s.attachments, -a.serverId as 'a_serverId', a.timelineUserId as 'a_timelineUserId', a.instance as 'a_instance', +a.serverId as 'a_serverId', a.timelineUserId as 'a_timelineUserId', a.localUsername as 'a_localUsername', a.username as 'a_username', a.displayName as 'a_displayName', a.url as 'a_url', a.avatar as 'a_avatar', a.emojis as 'a_emojis', -rb.serverId as 'rb_serverId', rb.timelineUserId 'rb_timelineUserId', rb.instance as 'rb_instance', +rb.serverId as 'rb_serverId', rb.timelineUserId 'rb_timelineUserId', rb.localUsername as 'rb_localUsername', rb.username as 'rb_username', rb.displayName as 'rb_displayName', rb.url as 'rb_url', rb.avatar as 'rb_avatar', rb.emojis as'rb_emojis' diff --git a/app/src/main/java/com/keylesspalace/tusky/db/TimelineStatusEntity.kt b/app/src/main/java/com/keylesspalace/tusky/db/TimelineStatusEntity.kt index a54dae944..bf06b0349 100644 --- a/app/src/main/java/com/keylesspalace/tusky/db/TimelineStatusEntity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/db/TimelineStatusEntity.kt @@ -33,7 +33,6 @@ data class TimelineStatusEntity( // our local id for the logged in user in case there are multiple accounts per instance val timelineUserId: Long, val authorServerId: String?, - val instance: String?, val inReplyToId: String?, val inReplyToAccountId: String?, val content: String?, @@ -59,7 +58,6 @@ data class TimelineStatusEntity( data class TimelineAccountEntity( val serverId: String, val timelineUserId: Long, - val instance: String, val localUsername: String, val username: String, val displayName: String, diff --git a/app/src/main/java/com/keylesspalace/tusky/repository/TimelineRepository.kt b/app/src/main/java/com/keylesspalace/tusky/repository/TimelineRepository.kt index 26f1b6e4b..f9318f2bf 100644 --- a/app/src/main/java/com/keylesspalace/tusky/repository/TimelineRepository.kt +++ b/app/src/main/java/com/keylesspalace/tusky/repository/TimelineRepository.kt @@ -52,23 +52,21 @@ class TimelineRepositoryImpl( ): Single> { val acc = accountManager.activeAccount ?: throw IllegalStateException() val accountId = acc.id - val instance = acc.domain return if (requestMode == DISK) { this.getStatusesFromDb(accountId, maxId, sinceId, limit) } else { - getStatusesFromNetwork(maxId, sinceId, sincedIdMinusOne, limit, instance, accountId, - requestMode) + getStatusesFromNetwork(maxId, sinceId, sincedIdMinusOne, limit, accountId, requestMode) } } private fun getStatusesFromNetwork(maxId: String?, sinceId: String?, - sinceIdMinusOne: String?, limit: Int, instance: String, + sinceIdMinusOne: String?, limit: Int, accountId: Long, requestMode: TimelineRequestMode ): Single> { return mastodonApi.homeTimelineSingle(maxId, sinceIdMinusOne, limit + 1) .map { statuses -> - this.saveStatusesToDb(instance, accountId, statuses, maxId, sinceId) + this.saveStatusesToDb(accountId, statuses, maxId, sinceId) } .flatMap { statuses -> this.addFromDbIfNeeded(accountId, statuses, maxId, sinceId, limit, requestMode) @@ -116,7 +114,7 @@ class TimelineRepositoryImpl( } } - private fun saveStatusesToDb(instance: String, accountId: Long, statuses: List, + private fun saveStatusesToDb(accountId: Long, statuses: List, maxId: String?, sinceId: String? ): List> { var placeholderToInsert: Placeholder? = null @@ -146,9 +144,9 @@ class TimelineRepositoryImpl( Single.fromCallable { for (status in statuses) { timelineDao.insertInTransaction( - status.toEntity(accountId, instance, htmlConverter, gson), - status.account.toEntity(instance, accountId, gson), - status.reblog?.account?.toEntity(instance, accountId, gson) + status.toEntity(accountId, htmlConverter, gson), + status.account.toEntity(accountId, gson), + status.reblog?.account?.toEntity(accountId, gson) ) } @@ -279,11 +277,10 @@ class TimelineRepositoryImpl( private val emojisListTypeToken = object : TypeToken>() {} -fun Account.toEntity(instance: String, accountId: Long, gson: Gson): TimelineAccountEntity { +fun Account.toEntity(accountId: Long, gson: Gson): TimelineAccountEntity { return TimelineAccountEntity( serverId = id, timelineUserId = accountId, - instance = instance, localUsername = localUsername, username = username, displayName = displayName, @@ -320,7 +317,6 @@ fun Placeholder.toEntity(timelineUserId: Long): TimelineStatusEntity { return TimelineStatusEntity( serverId = this.id, url = null, - instance = null, timelineUserId = timelineUserId, authorServerId = null, inReplyToId = null, @@ -344,14 +340,13 @@ fun Placeholder.toEntity(timelineUserId: Long): TimelineStatusEntity { ) } -fun Status.toEntity(timelineUserId: Long, instance: String, +fun Status.toEntity(timelineUserId: Long, htmlConverter: HtmlConverter, gson: Gson): TimelineStatusEntity { val actionable = actionableStatus return TimelineStatusEntity( serverId = this.id, url = actionable.url!!, - instance = instance, timelineUserId = timelineUserId, authorServerId = actionable.account.id, inReplyToId = actionable.inReplyToId, diff --git a/app/src/test/java/com/keylesspalace/tusky/fragment/TimelineRepositoryTest.kt b/app/src/test/java/com/keylesspalace/tusky/fragment/TimelineRepositoryTest.kt index 8625f1470..c29e9e626 100644 --- a/app/src/test/java/com/keylesspalace/tusky/fragment/TimelineRepositoryTest.kt +++ b/app/src/test/java/com/keylesspalace/tusky/fragment/TimelineRepositoryTest.kt @@ -93,8 +93,8 @@ class TimelineRepositoryTest { verify(timelineDao).insertStatusIfNotThere(Placeholder("1").toEntity(account.id)) for (status in statuses) { verify(timelineDao).insertInTransaction( - status.toEntity(account.id, account.domain, htmlConverter, gson), - status.account.toEntity(account.domain, account.id, gson), + status.toEntity(account.id, htmlConverter, gson), + status.account.toEntity(account.id, gson), null ) } @@ -124,8 +124,8 @@ class TimelineRepositoryTest { // We assume for now that overlapped one is inserted but it's not that important for (status in response) { verify(timelineDao).insertInTransaction( - status.toEntity(account.id, account.domain, htmlConverter, gson), - status.account.toEntity(account.domain, account.id, gson), + status.toEntity(account.id, htmlConverter, gson), + status.account.toEntity(account.id, gson), null ) } @@ -153,8 +153,8 @@ class TimelineRepositoryTest { testScheduler.advanceTimeBy(100, TimeUnit.SECONDS) for (status in response) { verify(timelineDao).insertInTransaction( - status.toEntity(account.id, account.domain, htmlConverter, gson), - status.account.toEntity(account.domain, account.id, gson), + status.toEntity(account.id, htmlConverter, gson), + status.account.toEntity(account.id, gson), null ) } @@ -194,8 +194,8 @@ class TimelineRepositoryTest { // We assume for now that overlapped one is inserted but it's not that important for (status in response) { verify(timelineDao).insertInTransaction( - status.toEntity(account.id, account.domain, htmlConverter, gson), - status.account.toEntity(account.domain, account.id, gson), + status.toEntity(account.id, htmlConverter, gson), + status.account.toEntity(account.id, gson), null ) } @@ -236,8 +236,8 @@ class TimelineRepositoryTest { // We assume for now that overlapped one is inserted but it's not that important for (status in response) { verify(timelineDao).insertInTransaction( - status.toEntity(account.id, account.domain, htmlConverter, gson), - status.account.toEntity(account.domain, account.id, gson), + status.toEntity(account.id, htmlConverter, gson), + status.account.toEntity(account.id, gson), null ) } @@ -253,8 +253,8 @@ class TimelineRepositoryTest { val status = makeStatus("2") val dbStatus = makeStatus("1") val dbResult = TimelineStatusWithAccount() - dbResult.status = dbStatus.toEntity(account.id, account.domain, htmlConverter, gson) - dbResult.account = status.account.toEntity(account.domain, account.id, gson) + dbResult.status = dbStatus.toEntity(account.id, htmlConverter, gson) + dbResult.account = status.account.toEntity(account.id, gson) whenever(mastodonApi.homeTimelineSingle(any(), any(), any())) .thenReturn(Single.just(listOf(status)))