mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01:00 
			
		
		
		
	Don't include "app state" preferences in backups
This commit is contained in:
		@@ -22,7 +22,7 @@ android {
 | 
			
		||||
    defaultConfig {
 | 
			
		||||
        applicationId = "eu.kanade.tachiyomi"
 | 
			
		||||
 | 
			
		||||
        versionCode = 107
 | 
			
		||||
        versionCode = 108
 | 
			
		||||
        versionName = "0.14.7"
 | 
			
		||||
 | 
			
		||||
        buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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()
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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))
 | 
			
		||||
 
 | 
			
		||||
@@ -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),
 | 
			
		||||
 
 | 
			
		||||
@@ -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_"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user