diff --git a/app/src/main/java/com/infomaniak/mail/data/cache/RealmDatabase.kt b/app/src/main/java/com/infomaniak/mail/data/cache/RealmDatabase.kt index 8ace97abbe..82c7153315 100644 --- a/app/src/main/java/com/infomaniak/mail/data/cache/RealmDatabase.kt +++ b/app/src/main/java/com/infomaniak/mail/data/cache/RealmDatabase.kt @@ -161,7 +161,7 @@ object RealmDatabase { //region Configurations versions const val USER_INFO_SCHEMA_VERSION = 2L const val MAILBOX_INFO_SCHEMA_VERSION = 7L - const val MAILBOX_CONTENT_SCHEMA_VERSION = 19L + const val MAILBOX_CONTENT_SCHEMA_VERSION = 20L //endregion //region Configurations names diff --git a/app/src/main/java/com/infomaniak/mail/data/cache/RealmMigrations.kt b/app/src/main/java/com/infomaniak/mail/data/cache/RealmMigrations.kt index cb6dd7c90f..b832cbee58 100644 --- a/app/src/main/java/com/infomaniak/mail/data/cache/RealmMigrations.kt +++ b/app/src/main/java/com/infomaniak/mail/data/cache/RealmMigrations.kt @@ -21,6 +21,7 @@ import com.infomaniak.mail.utils.SentryDebug import io.realm.kotlin.dynamic.DynamicMutableRealmObject import io.realm.kotlin.dynamic.DynamicRealmObject import io.realm.kotlin.dynamic.getValue +import io.realm.kotlin.ext.realmSetOf import io.realm.kotlin.migration.AutomaticSchemaMigration import io.realm.kotlin.migration.AutomaticSchemaMigration.MigrationContext @@ -38,6 +39,7 @@ val MAILBOX_INFO_MIGRATION = AutomaticSchemaMigration { migrationContext -> val MAILBOX_CONTENT_MIGRATION = AutomaticSchemaMigration { migrationContext -> SentryDebug.addMigrationBreadcrumb(migrationContext) migrationContext.deleteRealmFromFirstMigration() + migrationContext.keepThreadsInFolderAfterNineteenthMigration() } // Migrate to version #1 @@ -73,3 +75,20 @@ private fun MigrationContext.keepDefaultValuesAfterSixthMigration() { } } } + +/** + * Migrate from version #19 + */ +private fun MigrationContext.keepThreadsInFolderAfterNineteenthMigration() { + if (oldRealm.schemaVersion() <= 19L) { + enumerate(className = "Folder") { oldObject: DynamicRealmObject, newObject: DynamicMutableRealmObject? -> + newObject?.apply { + // Backup previous value + set( + propertyName = "threads", + value = oldObject.getObjectList(propertyName = "threads").mapTo(realmSetOf(), newRealm::findLatest), + ) + } + } + } +} diff --git a/app/src/main/java/com/infomaniak/mail/data/cache/mailboxContent/FolderController.kt b/app/src/main/java/com/infomaniak/mail/data/cache/mailboxContent/FolderController.kt index e5ae656aa1..a29436665e 100644 --- a/app/src/main/java/com/infomaniak/mail/data/cache/mailboxContent/FolderController.kt +++ b/app/src/main/java/com/infomaniak/mail/data/cache/mailboxContent/FolderController.kt @@ -30,7 +30,7 @@ import io.realm.kotlin.MutableRealm import io.realm.kotlin.Realm import io.realm.kotlin.TypedRealm import io.realm.kotlin.ext.query -import io.realm.kotlin.ext.realmListOf +import io.realm.kotlin.ext.realmSetOf import io.realm.kotlin.notifications.ResultsChange import io.realm.kotlin.query.RealmQuery import io.realm.kotlin.query.RealmResults @@ -213,7 +213,7 @@ class FolderController @Inject constructor( } fun deleteSearchFolderData(realm: MutableRealm) = with(getOrCreateSearchFolder(realm)) { - threads = realmListOf() + threads = realmSetOf() } //endregion } diff --git a/app/src/main/java/com/infomaniak/mail/data/cache/mailboxContent/ThreadController.kt b/app/src/main/java/com/infomaniak/mail/data/cache/mailboxContent/ThreadController.kt index e25d97dcb2..804cf7ac19 100644 --- a/app/src/main/java/com/infomaniak/mail/data/cache/mailboxContent/ThreadController.kt +++ b/app/src/main/java/com/infomaniak/mail/data/cache/mailboxContent/ThreadController.kt @@ -40,7 +40,7 @@ import io.realm.kotlin.UpdatePolicy import io.realm.kotlin.ext.isManaged import io.realm.kotlin.ext.query import io.realm.kotlin.ext.realmListOf -import io.realm.kotlin.ext.toRealmList +import io.realm.kotlin.ext.toRealmSet import io.realm.kotlin.notifications.ResultsChange import io.realm.kotlin.notifications.SingleQueryChange import io.realm.kotlin.query.* @@ -169,7 +169,7 @@ class ThreadController @Inject constructor( suspend fun saveThreads(searchMessages: List) { mailboxContentRealm().write { FolderController.getOrCreateSearchFolder(realm = this).apply { - threads = searchMessages.convertToSearchThreads().toRealmList() + threads = searchMessages.convertToSearchThreads().toRealmSet() } } } diff --git a/app/src/main/java/com/infomaniak/mail/data/models/Folder.kt b/app/src/main/java/com/infomaniak/mail/data/models/Folder.kt index 76514c37d7..94d0e74091 100644 --- a/app/src/main/java/com/infomaniak/mail/data/models/Folder.kt +++ b/app/src/main/java/com/infomaniak/mail/data/models/Folder.kt @@ -34,10 +34,12 @@ import com.infomaniak.mail.utils.Utils import io.realm.kotlin.TypedRealm import io.realm.kotlin.ext.backlinks import io.realm.kotlin.ext.realmListOf +import io.realm.kotlin.ext.realmSetOf import io.realm.kotlin.serializers.RealmListKSerializer import io.realm.kotlin.types.RealmInstant import io.realm.kotlin.types.RealmList import io.realm.kotlin.types.RealmObject +import io.realm.kotlin.types.RealmSet import io.realm.kotlin.types.annotations.PrimaryKey import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -70,7 +72,7 @@ class Folder : RealmObject, Cloneable { @Transient var unreadCountLocal: Int = 0 @Transient - var threads = realmListOf() + var threads = realmSetOf() /** * List of old Messages UIDs of this Folder that we need to fetch. @@ -119,7 +121,7 @@ class Folder : RealmObject, Cloneable { lastUpdatedAt: RealmInstant?, cursor: String?, unreadCount: Int, - threads: RealmList, + threads: RealmSet, oldMessagesUidsToFetch: RealmList, newMessagesUidsToFetch: RealmList, remainingOldMessagesToFetch: Int, diff --git a/app/src/main/java/com/infomaniak/mail/data/models/thread/Thread.kt b/app/src/main/java/com/infomaniak/mail/data/models/thread/Thread.kt index 6c1be59b4a..7b740c145e 100644 --- a/app/src/main/java/com/infomaniak/mail/data/models/thread/Thread.kt +++ b/app/src/main/java/com/infomaniak/mail/data/models/thread/Thread.kt @@ -97,6 +97,7 @@ class Thread : RealmObject { var isLocallyMovedOut: Boolean = false //endregion + // TODO: Remove this `runCatching / getOrElse` when the issue is fixed private val _folders by backlinks(Folder::threads) val folder get() = runCatching {