diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsBackupScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsBackupScreen.kt index f2028e16a..455a48d4e 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsBackupScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsBackupScreen.kt @@ -148,6 +148,7 @@ object SettingsBackupScreen : SearchableSettings { BackupConst.BACKUP_TRACK to R.string.track, BackupConst.BACKUP_HISTORY to R.string.history, BackupConst.BACKUP_APP_PREFS to R.string.app_settings, + BackupConst.BACKUP_SOURCE_PREFS to R.string.source_settings, // SY --> BackupConst.BACKUP_CUSTOM_INFO to R.string.custom_entry_info, BackupConst.BACKUP_READ_MANGA to R.string.all_read_entries, diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupConst.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupConst.kt index 77432ddcf..6a0bcde28 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupConst.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupConst.kt @@ -17,13 +17,16 @@ internal object BackupConst { const val BACKUP_APP_PREFS = 0x10 const val BACKUP_APP_PREFS_MASK = 0x10 + const val BACKUP_SOURCE_PREFS = 0x20 + const val BACKUP_SOURCE_PREFS_MASK = 0x20 + // SY --> - const val BACKUP_CUSTOM_INFO = 0x20 - const val BACKUP_CUSTOM_INFO_MASK = 0x20 + const val BACKUP_CUSTOM_INFO = 0x40 + const val BACKUP_CUSTOM_INFO_MASK = 0x40 - const val BACKUP_READ_MANGA = 0x40 - const val BACKUP_READ_MANGA_MASK = 0x40 + const val BACKUP_READ_MANGA = 0x80 + const val BACKUP_READ_MANGA_MASK = 0x80 - const val BACKUP_ALL = 0x7F + const val BACKUP_ALL = 0xFF // SY <-- } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt index d6c8c96f9..c2ed39380 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt @@ -18,6 +18,8 @@ import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_HISTORY import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_HISTORY_MASK import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_READ_MANGA import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_READ_MANGA_MASK +import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_SOURCE_PREFS +import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_SOURCE_PREFS_MASK import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_TRACK import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_TRACK_MASK import eu.kanade.tachiyomi.data.backup.models.Backup @@ -28,6 +30,7 @@ import eu.kanade.tachiyomi.data.backup.models.BackupManga import eu.kanade.tachiyomi.data.backup.models.BackupMergedMangaReference import eu.kanade.tachiyomi.data.backup.models.BackupPreference import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch +import eu.kanade.tachiyomi.data.backup.models.BackupSourcePreferences import eu.kanade.tachiyomi.data.backup.models.BackupSerializer import eu.kanade.tachiyomi.data.backup.models.BackupSource import eu.kanade.tachiyomi.data.backup.models.BooleanPreferenceValue @@ -41,8 +44,11 @@ import eu.kanade.tachiyomi.data.backup.models.backupChapterMapper import eu.kanade.tachiyomi.data.backup.models.backupMergedMangaReferenceMapper import eu.kanade.tachiyomi.data.backup.models.backupSavedSearchMapper import eu.kanade.tachiyomi.data.backup.models.backupTrackMapper +import eu.kanade.tachiyomi.source.ConfigurableSource import eu.kanade.tachiyomi.source.model.copyFrom import eu.kanade.tachiyomi.source.online.MetadataSource +import eu.kanade.tachiyomi.source.preferenceKey +import eu.kanade.tachiyomi.source.sourcePreferences import eu.kanade.tachiyomi.util.system.hasPermission import exh.source.MERGED_SOURCE_ID import exh.source.getMainSource @@ -130,6 +136,7 @@ class BackupManager( emptyList(), prepExtensionInfoForSync(databaseManga), backupAppPreferences(flags), + backupSourcePreferences(flags), // SY --> backupSavedSearches(), // SY <-- @@ -299,12 +306,28 @@ class BackupManager( return mangaObject } - @Suppress("UNCHECKED_CAST") private fun backupAppPreferences(flags: Int): List { if (flags and BACKUP_APP_PREFS_MASK != BACKUP_APP_PREFS) return emptyList() - return preferenceStore.getAll() - .filterKeys { !Preference.isPrivate(it) } + return preferenceStore.getAll().toBackupPreferences() + } + + private fun backupSourcePreferences(flags: Int): List { + if (flags and BACKUP_SOURCE_PREFS_MASK != BACKUP_SOURCE_PREFS) return emptyList() + + return sourceManager.getOnlineSources() + .filterIsInstance() + .map { + BackupSourcePreferences( + it.preferenceKey(), + it.sourcePreferences().all.toBackupPreferences() + ) + } + } + + @Suppress("UNCHECKED_CAST") + private fun Map.toBackupPreferences(): List { + return this.filterKeys { !Preference.isPrivate(it) } .mapNotNull { (key, value) -> when (value) { is Int -> BackupPreference(key, IntPreferenceValue(value)) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestorer.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestorer.kt index 85b7a1c64..c14497288 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestorer.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestorer.kt @@ -12,18 +12,21 @@ import eu.kanade.tachiyomi.data.backup.models.BackupMergedMangaReference import eu.kanade.tachiyomi.data.backup.models.BackupPreference import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch import eu.kanade.tachiyomi.data.backup.models.BackupSource +import eu.kanade.tachiyomi.data.backup.models.BackupSourcePreferences import eu.kanade.tachiyomi.data.backup.models.BooleanPreferenceValue import eu.kanade.tachiyomi.data.backup.models.FloatPreferenceValue import eu.kanade.tachiyomi.data.backup.models.IntPreferenceValue import eu.kanade.tachiyomi.data.backup.models.LongPreferenceValue import eu.kanade.tachiyomi.data.backup.models.StringPreferenceValue import eu.kanade.tachiyomi.data.backup.models.StringSetPreferenceValue +import eu.kanade.tachiyomi.source.sourcePreferences import eu.kanade.tachiyomi.util.BackupUtil import eu.kanade.tachiyomi.util.system.createFileInCacheDir import exh.EXHMigrations import exh.source.MERGED_SOURCE_ID import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.isActive +import tachiyomi.core.preference.AndroidPreferenceStore import tachiyomi.core.preference.PreferenceStore import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.manga.interactor.FetchInterval @@ -126,6 +129,7 @@ class BackupRestorer( return coroutineScope { restoreAppPreferences(backup.backupPreferences) + restoreSourcePreferences(backup.backupSourcePreferences) // Restore individual manga, sort by merged source so that merged source manga go last and merged references get the proper ids backup.backupManga /* SY --> */.sortedBy { it.source == MERGED_SOURCE_ID } /* SY <-- */.forEach { @@ -268,9 +272,22 @@ class BackupRestorer( } private fun restoreAppPreferences(preferences: List) { - val prefs = preferenceStore.getAll() + restorePreferences(preferences, preferenceStore) + } - preferences.forEach { (key, value) -> + private fun restoreSourcePreferences(preferences: List) { + preferences.forEach { + val sourcePrefs = AndroidPreferenceStore(context, sourcePreferences(it.sourceKey)) + restorePreferences(it.prefs, sourcePrefs) + } + } + + private fun restorePreferences( + toRestore: List, + preferenceStore: PreferenceStore, + ) { + val prefs = preferenceStore.getAll() + toRestore.forEach { (key, value) -> when (value) { is IntPreferenceValue -> { if (prefs[key] is Int?) { @@ -306,13 +323,6 @@ class BackupRestorer( } } - /** - * Called to update dialog in [BackupConst] - * - * @param progress restore progress - * @param amount total restoreAmount of manga - * @param title title of restored manga - */ private fun showRestoreProgress(progress: Int, amount: Int, title: String, contentTitle: String) { notifier.showRestoreProgress(title, contentTitle, progress, amount) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/models/Backup.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/models/Backup.kt index fedac9c39..3ea2e835e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/models/Backup.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/models/Backup.kt @@ -14,6 +14,7 @@ data class Backup( @ProtoNumber(100) var backupBrokenSources: List = emptyList(), @ProtoNumber(101) var backupSources: List = emptyList(), @ProtoNumber(104) var backupPreferences: List = emptyList(), + @ProtoNumber(105) var backupSourcePreferences: List = emptyList(), // SY specific values @ProtoNumber(600) var backupSavedSearches: List = emptyList(), ) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/models/BackupPreference.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/models/BackupPreference.kt index 791c9706f..3884f37e3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/models/BackupPreference.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/models/BackupPreference.kt @@ -9,6 +9,12 @@ data class BackupPreference( @ProtoNumber(2) val value: PreferenceValue, ) +@Serializable +data class BackupSourcePreferences( + @ProtoNumber(1) val sourceKey: String, + @ProtoNumber(2) val prefs: List, +) + @Serializable sealed class PreferenceValue diff --git a/core/src/main/java/tachiyomi/core/preference/AndroidPreferenceStore.kt b/core/src/main/java/tachiyomi/core/preference/AndroidPreferenceStore.kt index 67e4db7fc..b24fa5dcc 100644 --- a/core/src/main/java/tachiyomi/core/preference/AndroidPreferenceStore.kt +++ b/core/src/main/java/tachiyomi/core/preference/AndroidPreferenceStore.kt @@ -15,10 +15,9 @@ import tachiyomi.core.preference.AndroidPreference.StringSetPrimitive class AndroidPreferenceStore( context: Context, + private val sharedPreferences: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context), ) : PreferenceStore { - private val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) - private val keyFlow = sharedPreferences.keyFlow override fun getString(key: String, defaultValue: String): Preference { diff --git a/i18n/src/main/res/values/strings.xml b/i18n/src/main/res/values/strings.xml index 129ed90cd..275eeb2b4 100755 --- a/i18n/src/main/res/values/strings.xml +++ b/i18n/src/main/res/values/strings.xml @@ -494,6 +494,7 @@ Backup is already in progress What do you want to backup? App settings + Source settings Creating backup Backup failed Storage permissions not granted diff --git a/source-api/src/commonMain/kotlin/eu/kanade/tachiyomi/source/ConfigurableSource.kt b/source-api/src/commonMain/kotlin/eu/kanade/tachiyomi/source/ConfigurableSource.kt index ea5eb848e..db9a98520 100644 --- a/source-api/src/commonMain/kotlin/eu/kanade/tachiyomi/source/ConfigurableSource.kt +++ b/source-api/src/commonMain/kotlin/eu/kanade/tachiyomi/source/ConfigurableSource.kt @@ -19,8 +19,11 @@ interface ConfigurableSource : Source { fun setupPreferenceScreen(screen: PreferenceScreen) } -private fun ConfigurableSource.preferenceKey(): String = "source_$id" +fun ConfigurableSource.preferenceKey(): String = "source_$id" // TODO: use getSourcePreferences once all extensions are on ext-lib 1.5 fun ConfigurableSource.sourcePreferences(): SharedPreferences = Injekt.get().getSharedPreferences(preferenceKey(), Context.MODE_PRIVATE) + +fun sourcePreferences(key: String): SharedPreferences = + Injekt.get().getSharedPreferences(key, Context.MODE_PRIVATE)