diff --git a/app/src/main/java/eu/kanade/domain/base/BasePreferences.kt b/app/src/main/java/eu/kanade/domain/base/BasePreferences.kt index 34ef79b48..0acef84a9 100644 --- a/app/src/main/java/eu/kanade/domain/base/BasePreferences.kt +++ b/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) diff --git a/app/src/main/java/eu/kanade/domain/source/service/SourcePreferences.kt b/app/src/main/java/eu/kanade/domain/source/service/SourcePreferences.kt index 4cf18a0af..ab4f53e53 100644 --- a/app/src/main/java/eu/kanade/domain/source/service/SourcePreferences.kt +++ b/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) diff --git a/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt b/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt index c7826270a..79b76b03b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt @@ -378,17 +378,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 } @@ -396,3 +407,41 @@ object Migrations { return false } } + +@Suppress("UNCHECKED_CAST") +private fun replacePreferences( + preferenceStore: PreferenceStore, + filterPredicate: (Map.Entry) -> 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)?.let { + preferenceStore.getStringSet(newKey(key)).set(value) + preferenceStore.getStringSet(key).delete() + } + } + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreator.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreator.kt index 6939f1dca..cec972e54 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreator.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreator.kt @@ -306,7 +306,9 @@ class BackupCreator( @Suppress("UNCHECKED_CAST") private fun Map.toBackupPreferences(): List { - 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)) diff --git a/app/src/main/java/exh/EXHMigrations.kt b/app/src/main/java/exh/EXHMigrations.kt index 8a78eaffd..0a0e81737 100644 --- a/app/src/main/java/exh/EXHMigrations.kt +++ b/app/src/main/java/exh/EXHMigrations.kt @@ -587,6 +587,47 @@ object EXHMigrations { preferenceStore.getString(key).delete() } } + + 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", + "skip_pre_migration", + "eh_auto_update_stats", + ) + replacePreferences( + preferenceStore = preferenceStore, + filterPredicate = { it.key in prefsToReplace }, + newKey = { Preference.appStateKey(it) }, + ) + + val privatePrefsToReplace = listOf( + "sql_password", + "encrypt_database", + "cbz_password", + "password_protect_downloads", + "eh_ipb_member_id", + "enable_exhentai", + "eh_ipb_member_id", + "eh_ipb_pass_hash", + "eh_igneous", + "eh_ehSettingsProfile", + "eh_exhSettingsProfile", + "eh_settingsKey", + "eh_sessionCookie", + "eh_hathPerksCookie" + ) + + replacePreferences( + preferenceStore = preferenceStore, + filterPredicate = { it.key in privatePrefsToReplace }, + newKey = { Preference.privateKey(it) }, + ) } // if (oldVersion under 1) { } (1 is current release version) @@ -710,4 +751,43 @@ object EXHMigrations { handler.await { ehQueries.migrateSource(newId, oldId) } } } + + + @Suppress("UNCHECKED_CAST") + private fun replacePreferences( + preferenceStore: PreferenceStore, + filterPredicate: (Map.Entry) -> 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)?.let { + preferenceStore.getStringSet(newKey(key)).set(value) + preferenceStore.getStringSet(key).delete() + } + } + } + } } diff --git a/core/src/main/java/eu/kanade/tachiyomi/core/security/SecurityPreferences.kt b/core/src/main/java/eu/kanade/tachiyomi/core/security/SecurityPreferences.kt index 71b4e52dc..91342d3f0 100644 --- a/core/src/main/java/eu/kanade/tachiyomi/core/security/SecurityPreferences.kt +++ b/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 @@ -21,22 +22,25 @@ class SecurityPreferences( fun authenticatorDays() = this.preferenceStore.getInt("biometric_days", 0x7F) - fun encryptDatabase() = this.preferenceStore.getBoolean("encrypt_database", false) + fun encryptDatabase() = this.preferenceStore.getBoolean(Preference.privateKey("encrypt_database"), false) - fun sqlPassword() = this.preferenceStore.getString("sql_password", "") + fun sqlPassword() = this.preferenceStore.getString(Preference.privateKey("sql_password"), "") - fun passwordProtectDownloads() = preferenceStore.getBoolean("password_protect_downloads", false) + fun passwordProtectDownloads() = preferenceStore.getBoolean(Preference.privateKey("password_protect_downloads"), false) fun encryptionType() = this.preferenceStore.getEnum("encryption_type", EncryptionType.AES_256) - fun cbzPassword() = this.preferenceStore.getString("cbz_password", "") + fun cbzPassword() = this.preferenceStore.getString(Preference.privateKey("cbz_password"), "") // SY <-- /** * 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), diff --git a/core/src/main/java/tachiyomi/core/preference/Preference.kt b/core/src/main/java/tachiyomi/core/preference/Preference.kt index e10f6e7fe..bd95798ef 100644 --- a/core/src/main/java/tachiyomi/core/preference/Preference.kt +++ b/core/src/main/java/tachiyomi/core/preference/Preference.kt @@ -22,21 +22,29 @@ interface Preference { fun stateIn(scope: CoroutineScope): StateFlow - 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_" } } diff --git a/domain/src/main/java/tachiyomi/domain/UnsortedPreferences.kt b/domain/src/main/java/tachiyomi/domain/UnsortedPreferences.kt index 5a9268034..0c84e29a2 100644 --- a/domain/src/main/java/tachiyomi/domain/UnsortedPreferences.kt +++ b/domain/src/main/java/tachiyomi/domain/UnsortedPreferences.kt @@ -1,5 +1,6 @@ package tachiyomi.domain +import tachiyomi.core.preference.Preference import tachiyomi.core.preference.PreferenceStore class UnsortedPreferences( @@ -18,13 +19,13 @@ class UnsortedPreferences( fun useSourceWithMost() = preferenceStore.getBoolean("use_source_with_most", false) - fun skipPreMigration() = preferenceStore.getBoolean("skip_pre_migration", false) + fun skipPreMigration() = preferenceStore.getBoolean(Preference.appStateKey("skip_pre_migration"), false) fun hideNotFoundMigration() = preferenceStore.getBoolean("hide_not_found_migration", false) fun isHentaiEnabled() = preferenceStore.getBoolean("eh_is_hentai_enabled", true) - fun enableExhentai() = preferenceStore.getBoolean("enable_exhentai", false) + fun enableExhentai() = preferenceStore.getBoolean(Preference.privateKey("enable_exhentai"), false) fun imageQuality() = preferenceStore.getString("ehentai_quality", "auto") @@ -39,15 +40,15 @@ class UnsortedPreferences( fun ehTagWatchingValue() = preferenceStore.getInt("eh_tag_watching_value", 0) // EH Cookies - fun memberIdVal() = preferenceStore.getString("eh_ipb_member_id", "") + fun memberIdVal() = preferenceStore.getString(Preference.privateKey("eh_ipb_member_id"), "") - fun passHashVal() = preferenceStore.getString("eh_ipb_pass_hash", "") - fun igneousVal() = preferenceStore.getString("eh_igneous", "") - fun ehSettingsProfile() = preferenceStore.getInt("eh_ehSettingsProfile", -1) - fun exhSettingsProfile() = preferenceStore.getInt("eh_exhSettingsProfile", -1) - fun exhSettingsKey() = preferenceStore.getString("eh_settingsKey", "") - fun exhSessionCookie() = preferenceStore.getString("eh_sessionCookie", "") - fun exhHathPerksCookies() = preferenceStore.getString("eh_hathPerksCookie", "") + fun passHashVal() = preferenceStore.getString(Preference.privateKey("eh_ipb_pass_hash"), "") + fun igneousVal() = preferenceStore.getString(Preference.privateKey("eh_igneous"), "") + fun ehSettingsProfile() = preferenceStore.getInt(Preference.privateKey("eh_ehSettingsProfile"), -1) + fun exhSettingsProfile() = preferenceStore.getInt(Preference.privateKey("eh_exhSettingsProfile"), -1) + fun exhSettingsKey() = preferenceStore.getString(Preference.privateKey("eh_settingsKey"), "") + fun exhSessionCookie() = preferenceStore.getString(Preference.privateKey("eh_sessionCookie"), "") + fun exhHathPerksCookies() = preferenceStore.getString(Preference.privateKey("eh_hathPerksCookie"), "") fun exhShowSyncIntro() = preferenceStore.getBoolean("eh_show_sync_intro", true) @@ -63,7 +64,7 @@ class UnsortedPreferences( fun exhAutoUpdateRequirements() = preferenceStore.getStringSet("eh_auto_update_restrictions", emptySet()) - fun exhAutoUpdateStats() = preferenceStore.getString("eh_auto_update_stats", "") + fun exhAutoUpdateStats() = preferenceStore.getString(Preference.appStateKey("eh_auto_update_stats"), "") fun exhWatchedListDefaultState() = preferenceStore.getBoolean("eh_watched_list_default_state", false) diff --git a/domain/src/main/java/tachiyomi/domain/backup/service/BackupPreferences.kt b/domain/src/main/java/tachiyomi/domain/backup/service/BackupPreferences.kt index e0f96dffa..e923b2daa 100644 --- a/domain/src/main/java/tachiyomi/domain/backup/service/BackupPreferences.kt +++ b/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) } diff --git a/domain/src/main/java/tachiyomi/domain/library/service/LibraryPreferences.kt b/domain/src/main/java/tachiyomi/domain/library/service/LibraryPreferences.kt index ee1ce9a0a..7ab177cdc 100644 --- a/domain/src/main/java/tachiyomi/domain/library/service/LibraryPreferences.kt +++ b/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 @@ -31,7 +32,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( @@ -99,7 +100,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 @@ -107,7 +108,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)