Browse Source

Don't include "app state" preferences in backups

arkon 1 year ago
parent
commit
ce7bf396eb

+ 1 - 1
app/build.gradle.kts

@@ -22,7 +22,7 @@ android {
     defaultConfig {
         applicationId = "eu.kanade.tachiyomi"
 
-        versionCode = 107
+        versionCode = 108
         versionName = "0.14.7"
 
         buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")

+ 6 - 2
app/src/main/java/eu/kanade/domain/base/BasePreferences.kt

@@ -5,6 +5,7 @@ import androidx.annotation.StringRes
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.util.system.isPreviewBuildType
 import eu.kanade.tachiyomi.util.system.isReleaseBuildType
+import tachiyomi.core.preference.Preference
 import tachiyomi.core.preference.PreferenceStore
 
 class BasePreferences(
@@ -12,9 +13,12 @@ class BasePreferences(
     private val preferenceStore: PreferenceStore,
 ) {
 
-    fun downloadedOnly() = preferenceStore.getBoolean("pref_downloaded_only", false)
+    fun downloadedOnly() = preferenceStore.getBoolean(
+        Preference.appStateKey("pref_downloaded_only"),
+        false,
+    )
 
-    fun incognitoMode() = preferenceStore.getBoolean("incognito_mode", false)
+    fun incognitoMode() = preferenceStore.getBoolean(Preference.appStateKey("incognito_mode"), false)
 
     fun extensionInstaller() = ExtensionInstallerPreference(context, preferenceStore)
 

+ 6 - 2
app/src/main/java/eu/kanade/domain/source/service/SourcePreferences.kt

@@ -2,6 +2,7 @@ package eu.kanade.domain.source.service
 
 import eu.kanade.domain.source.interactor.SetMigrateSorting
 import eu.kanade.tachiyomi.util.system.LocaleHelper
+import tachiyomi.core.preference.Preference
 import tachiyomi.core.preference.PreferenceStore
 import tachiyomi.core.preference.getEnum
 import tachiyomi.domain.library.model.LibraryDisplayMode
@@ -18,7 +19,10 @@ class SourcePreferences(
 
     fun pinnedSources() = preferenceStore.getStringSet("pinned_catalogues", emptySet())
 
-    fun lastUsedSource() = preferenceStore.getLong("last_catalogue_source", -1)
+    fun lastUsedSource() = preferenceStore.getLong(
+        Preference.appStateKey("last_catalogue_source"),
+        -1,
+    )
 
     fun showNsfwSource() = preferenceStore.getBoolean("show_nsfw_source", true)
 
@@ -28,7 +32,7 @@ class SourcePreferences(
 
     fun extensionUpdatesCount() = preferenceStore.getInt("ext_updates_count", 0)
 
-    fun trustedSignatures() = preferenceStore.getStringSet("trusted_signatures", emptySet())
+    fun trustedSignatures() = preferenceStore.getStringSet(Preference.appStateKey("trusted_signatures"), emptySet())
 
     fun hideInLibraryItems() = preferenceStore.getBoolean("browse_hide_in_library_items", false)
 }

+ 60 - 11
app/src/main/java/eu/kanade/tachiyomi/Migrations.kt

@@ -375,17 +375,28 @@ object Migrations {
                 }
             }
             if (oldVersion < 107) {
-                preferenceStore.getAll()
-                    .filter { it.key.startsWith("pref_mangasync_") || it.key.startsWith("track_token_") }
-                    .forEach { (key, value) ->
-                        if (value is String) {
-                            preferenceStore
-                                .getString(Preference.privateKey(key))
-                                .set(value)
-
-                            preferenceStore.getString(key).delete()
-                        }
-                    }
+                replacePreferences(
+                    preferenceStore = preferenceStore,
+                    filterPredicate = { it.key.startsWith("pref_mangasync_") || it.key.startsWith("track_token_") },
+                    newKey = { Preference.privateKey(it) },
+                )
+            }
+            if (oldVersion < 108) {
+                val prefsToReplace = listOf(
+                    "pref_download_only",
+                    "incognito_mode",
+                    "last_catalogue_source",
+                    "trusted_signatures",
+                    "last_app_closed",
+                    "library_update_last_timestamp",
+                    "library_unseen_updates_count",
+                    "last_used_category",
+                )
+                replacePreferences(
+                    preferenceStore = preferenceStore,
+                    filterPredicate = { it.key in prefsToReplace },
+                    newKey = { Preference.appStateKey(it) },
+                )
             }
             return true
         }
@@ -393,3 +404,41 @@ object Migrations {
         return false
     }
 }
+
+@Suppress("UNCHECKED_CAST")
+private fun replacePreferences(
+    preferenceStore: PreferenceStore,
+    filterPredicate: (Map.Entry<String, Any?>) -> Boolean,
+    newKey: (String) -> String,
+) {
+    preferenceStore.getAll()
+        .filter(filterPredicate)
+        .forEach { (key, value) ->
+            when (value) {
+                is Int -> {
+                    preferenceStore.getInt(newKey(key)).set(value)
+                    preferenceStore.getInt(key).delete()
+                }
+                is Long -> {
+                    preferenceStore.getLong(newKey(key)).set(value)
+                    preferenceStore.getLong(key).delete()
+                }
+                is Float -> {
+                    preferenceStore.getFloat(newKey(key)).set(value)
+                    preferenceStore.getFloat(key).delete()
+                }
+                is String -> {
+                    preferenceStore.getString(newKey(key)).set(value)
+                    preferenceStore.getString(key).delete()
+                }
+                is Boolean -> {
+                    preferenceStore.getBoolean(newKey(key)).set(value)
+                    preferenceStore.getBoolean(key).delete()
+                }
+                is Set<*> -> (value as? Set<String>)?.let {
+                    preferenceStore.getStringSet(newKey(key)).set(value)
+                    preferenceStore.getStringSet(key).delete()
+                }
+            }
+        }
+}

+ 3 - 1
app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreator.kt

@@ -250,7 +250,9 @@ class BackupCreator(
 
     @Suppress("UNCHECKED_CAST")
     private fun Map<String, *>.toBackupPreferences(): List<BackupPreference> {
-        return this.filterKeys { !Preference.isPrivate(it) }
+        return this.filterKeys {
+            !Preference.isPrivate(it) && !Preference.isAppState(it)
+        }
             .mapNotNull { (key, value) ->
                 when (value) {
                     is Int -> BackupPreference(key, IntPreferenceValue(value))

+ 5 - 1
core/src/main/java/eu/kanade/tachiyomi/core/security/SecurityPreferences.kt

@@ -1,6 +1,7 @@
 package eu.kanade.tachiyomi.core.security
 
 import eu.kanade.tachiyomi.core.R
+import tachiyomi.core.preference.Preference
 import tachiyomi.core.preference.PreferenceStore
 import tachiyomi.core.preference.getEnum
 
@@ -20,7 +21,10 @@ class SecurityPreferences(
      * For app lock. Will be set when there is a pending timed lock.
      * Otherwise this pref should be deleted.
      */
-    fun lastAppClosed() = preferenceStore.getLong("last_app_closed", 0)
+    fun lastAppClosed() = preferenceStore.getLong(
+        Preference.appStateKey("last_app_closed"),
+        0,
+    )
 
     enum class SecureScreenMode(val titleResId: Int) {
         ALWAYS(R.string.lock_always),

+ 13 - 5
core/src/main/java/tachiyomi/core/preference/Preference.kt

@@ -22,21 +22,29 @@ interface Preference<T> {
 
     fun stateIn(scope: CoroutineScope): StateFlow<T>
 
-    val isPrivate: Boolean
-        get() = key().startsWith(PRIVATE_PREFIX)
-
     companion object {
         /**
-         * A preference that should not be exposed in places like backups.
+         * A preference that should not be exposed in places like backups without user consent.
          */
         fun isPrivate(key: String): Boolean {
             return key.startsWith(PRIVATE_PREFIX)
         }
-
         fun privateKey(key: String): String {
             return "${PRIVATE_PREFIX}$key"
         }
 
+        /**
+         * A preference used for internal app state that isn't really a user preference
+         * and therefore should not be inplaces like backips.
+         */
+        fun isAppState(key: String): Boolean {
+            return key.startsWith(APP_STATE_PREFIX)
+        }
+        fun appStateKey(key: String): String {
+            return "${APP_STATE_PREFIX}$key"
+        }
+
+        private const val APP_STATE_PREFIX = "__APP_STATE_"
         private const val PRIVATE_PREFIX = "__PRIVATE_"
     }
 }

+ 2 - 2
domain/src/main/java/tachiyomi/domain/backup/service/BackupPreferences.kt

@@ -1,5 +1,6 @@
 package tachiyomi.domain.backup.service
 
+import tachiyomi.core.preference.Preference
 import tachiyomi.core.preference.PreferenceStore
 import tachiyomi.core.provider.FolderProvider
 
@@ -14,6 +15,5 @@ class BackupPreferences(
 
     fun backupInterval() = preferenceStore.getInt("backup_interval", 12)
 
-    // TODO: move this and other "app state" preferences elsewhere and exclude from backups
-    fun lastAutoBackupTimestamp() = preferenceStore.getLong("__APP_STATE_last_auto_backup_timestamp", 0L)
+    fun lastAutoBackupTimestamp() = preferenceStore.getLong(Preference.appStateKey("last_auto_backup_timestamp"), 0L)
 }

+ 4 - 3
domain/src/main/java/tachiyomi/domain/library/service/LibraryPreferences.kt

@@ -1,5 +1,6 @@
 package tachiyomi.domain.library.service
 
+import tachiyomi.core.preference.Preference
 import tachiyomi.core.preference.PreferenceStore
 import tachiyomi.core.preference.TriState
 import tachiyomi.core.preference.getEnum
@@ -29,7 +30,7 @@ class LibraryPreferences(
 
     fun landscapeColumns() = preferenceStore.getInt("pref_library_columns_landscape_key", 0)
 
-    fun lastUpdatedTimestamp() = preferenceStore.getLong("library_update_last_timestamp", 0L)
+    fun lastUpdatedTimestamp() = preferenceStore.getLong(Preference.appStateKey("library_update_last_timestamp"), 0L)
     fun autoUpdateInterval() = preferenceStore.getInt("pref_library_update_interval_key", 0)
 
     fun autoUpdateDeviceRestrictions() = preferenceStore.getStringSet(
@@ -120,7 +121,7 @@ class LibraryPreferences(
     fun languageBadge() = preferenceStore.getBoolean("display_language_badge", false)
 
     fun newShowUpdatesCount() = preferenceStore.getBoolean("library_show_updates_count", true)
-    fun newUpdatesCount() = preferenceStore.getInt("library_unseen_updates_count", 0)
+    fun newUpdatesCount() = preferenceStore.getInt(Preference.appStateKey("library_unseen_updates_count"), 0)
 
     // endregion
 
@@ -128,7 +129,7 @@ class LibraryPreferences(
 
     fun defaultCategory() = preferenceStore.getInt("default_category", -1)
 
-    fun lastUsedCategory() = preferenceStore.getInt("last_used_category", 0)
+    fun lastUsedCategory() = preferenceStore.getInt(Preference.appStateKey("last_used_category"), 0)
 
     fun categoryTabs() = preferenceStore.getBoolean("display_category_tabs", true)