Add source preferences to backups
Closes #1857 Co-authored-by: jmir1 <jmir1@users.noreply.github.com> (cherry picked from commit 0f42b9f1544b188362d1c0046c8ff853827ed270) # Conflicts: # app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsBackupScreen.kt # app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupConst.kt # app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt # app/src/main/java/eu/kanade/tachiyomi/data/backup/models/Backup.kt
This commit is contained in:
parent
92daa4ea28
commit
b9fe9f7f52
@ -148,6 +148,7 @@ object SettingsBackupScreen : SearchableSettings {
|
|||||||
BackupConst.BACKUP_TRACK to R.string.track,
|
BackupConst.BACKUP_TRACK to R.string.track,
|
||||||
BackupConst.BACKUP_HISTORY to R.string.history,
|
BackupConst.BACKUP_HISTORY to R.string.history,
|
||||||
BackupConst.BACKUP_APP_PREFS to R.string.app_settings,
|
BackupConst.BACKUP_APP_PREFS to R.string.app_settings,
|
||||||
|
BackupConst.BACKUP_SOURCE_PREFS to R.string.source_settings,
|
||||||
// SY -->
|
// SY -->
|
||||||
BackupConst.BACKUP_CUSTOM_INFO to R.string.custom_entry_info,
|
BackupConst.BACKUP_CUSTOM_INFO to R.string.custom_entry_info,
|
||||||
BackupConst.BACKUP_READ_MANGA to R.string.all_read_entries,
|
BackupConst.BACKUP_READ_MANGA to R.string.all_read_entries,
|
||||||
|
@ -17,13 +17,16 @@ internal object BackupConst {
|
|||||||
const val BACKUP_APP_PREFS = 0x10
|
const val BACKUP_APP_PREFS = 0x10
|
||||||
const val BACKUP_APP_PREFS_MASK = 0x10
|
const val BACKUP_APP_PREFS_MASK = 0x10
|
||||||
|
|
||||||
|
const val BACKUP_SOURCE_PREFS = 0x20
|
||||||
|
const val BACKUP_SOURCE_PREFS_MASK = 0x20
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
const val BACKUP_CUSTOM_INFO = 0x20
|
const val BACKUP_CUSTOM_INFO = 0x40
|
||||||
const val BACKUP_CUSTOM_INFO_MASK = 0x20
|
const val BACKUP_CUSTOM_INFO_MASK = 0x40
|
||||||
|
|
||||||
const val BACKUP_READ_MANGA = 0x40
|
const val BACKUP_READ_MANGA = 0x80
|
||||||
const val BACKUP_READ_MANGA_MASK = 0x40
|
const val BACKUP_READ_MANGA_MASK = 0x80
|
||||||
|
|
||||||
const val BACKUP_ALL = 0x7F
|
const val BACKUP_ALL = 0xFF
|
||||||
// SY <--
|
// SY <--
|
||||||
}
|
}
|
||||||
|
@ -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_HISTORY_MASK
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_READ_MANGA
|
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_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
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_TRACK_MASK
|
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_TRACK_MASK
|
||||||
import eu.kanade.tachiyomi.data.backup.models.Backup
|
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.BackupMergedMangaReference
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupPreference
|
import eu.kanade.tachiyomi.data.backup.models.BackupPreference
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch
|
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.BackupSerializer
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupSource
|
import eu.kanade.tachiyomi.data.backup.models.BackupSource
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BooleanPreferenceValue
|
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.backupMergedMangaReferenceMapper
|
||||||
import eu.kanade.tachiyomi.data.backup.models.backupSavedSearchMapper
|
import eu.kanade.tachiyomi.data.backup.models.backupSavedSearchMapper
|
||||||
import eu.kanade.tachiyomi.data.backup.models.backupTrackMapper
|
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.model.copyFrom
|
||||||
import eu.kanade.tachiyomi.source.online.MetadataSource
|
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 eu.kanade.tachiyomi.util.system.hasPermission
|
||||||
import exh.source.MERGED_SOURCE_ID
|
import exh.source.MERGED_SOURCE_ID
|
||||||
import exh.source.getMainSource
|
import exh.source.getMainSource
|
||||||
@ -130,6 +136,7 @@ class BackupManager(
|
|||||||
emptyList(),
|
emptyList(),
|
||||||
prepExtensionInfoForSync(databaseManga),
|
prepExtensionInfoForSync(databaseManga),
|
||||||
backupAppPreferences(flags),
|
backupAppPreferences(flags),
|
||||||
|
backupSourcePreferences(flags),
|
||||||
// SY -->
|
// SY -->
|
||||||
backupSavedSearches(),
|
backupSavedSearches(),
|
||||||
// SY <--
|
// SY <--
|
||||||
@ -299,12 +306,28 @@ class BackupManager(
|
|||||||
return mangaObject
|
return mangaObject
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
private fun backupAppPreferences(flags: Int): List<BackupPreference> {
|
private fun backupAppPreferences(flags: Int): List<BackupPreference> {
|
||||||
if (flags and BACKUP_APP_PREFS_MASK != BACKUP_APP_PREFS) return emptyList()
|
if (flags and BACKUP_APP_PREFS_MASK != BACKUP_APP_PREFS) return emptyList()
|
||||||
|
|
||||||
return preferenceStore.getAll()
|
return preferenceStore.getAll().toBackupPreferences()
|
||||||
.filterKeys { !Preference.isPrivate(it) }
|
}
|
||||||
|
|
||||||
|
private fun backupSourcePreferences(flags: Int): List<BackupSourcePreferences> {
|
||||||
|
if (flags and BACKUP_SOURCE_PREFS_MASK != BACKUP_SOURCE_PREFS) return emptyList()
|
||||||
|
|
||||||
|
return sourceManager.getOnlineSources()
|
||||||
|
.filterIsInstance<ConfigurableSource>()
|
||||||
|
.map {
|
||||||
|
BackupSourcePreferences(
|
||||||
|
it.preferenceKey(),
|
||||||
|
it.sourcePreferences().all.toBackupPreferences()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
private fun Map<String, *>.toBackupPreferences(): List<BackupPreference> {
|
||||||
|
return this.filterKeys { !Preference.isPrivate(it) }
|
||||||
.mapNotNull { (key, value) ->
|
.mapNotNull { (key, value) ->
|
||||||
when (value) {
|
when (value) {
|
||||||
is Int -> BackupPreference(key, IntPreferenceValue(value))
|
is Int -> BackupPreference(key, IntPreferenceValue(value))
|
||||||
|
@ -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.BackupPreference
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch
|
import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupSource
|
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.BooleanPreferenceValue
|
||||||
import eu.kanade.tachiyomi.data.backup.models.FloatPreferenceValue
|
import eu.kanade.tachiyomi.data.backup.models.FloatPreferenceValue
|
||||||
import eu.kanade.tachiyomi.data.backup.models.IntPreferenceValue
|
import eu.kanade.tachiyomi.data.backup.models.IntPreferenceValue
|
||||||
import eu.kanade.tachiyomi.data.backup.models.LongPreferenceValue
|
import eu.kanade.tachiyomi.data.backup.models.LongPreferenceValue
|
||||||
import eu.kanade.tachiyomi.data.backup.models.StringPreferenceValue
|
import eu.kanade.tachiyomi.data.backup.models.StringPreferenceValue
|
||||||
import eu.kanade.tachiyomi.data.backup.models.StringSetPreferenceValue
|
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.BackupUtil
|
||||||
import eu.kanade.tachiyomi.util.system.createFileInCacheDir
|
import eu.kanade.tachiyomi.util.system.createFileInCacheDir
|
||||||
import exh.EXHMigrations
|
import exh.EXHMigrations
|
||||||
import exh.source.MERGED_SOURCE_ID
|
import exh.source.MERGED_SOURCE_ID
|
||||||
import kotlinx.coroutines.coroutineScope
|
import kotlinx.coroutines.coroutineScope
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
|
import tachiyomi.core.preference.AndroidPreferenceStore
|
||||||
import tachiyomi.core.preference.PreferenceStore
|
import tachiyomi.core.preference.PreferenceStore
|
||||||
import tachiyomi.domain.chapter.model.Chapter
|
import tachiyomi.domain.chapter.model.Chapter
|
||||||
import tachiyomi.domain.manga.interactor.FetchInterval
|
import tachiyomi.domain.manga.interactor.FetchInterval
|
||||||
@ -126,6 +129,7 @@ class BackupRestorer(
|
|||||||
|
|
||||||
return coroutineScope {
|
return coroutineScope {
|
||||||
restoreAppPreferences(backup.backupPreferences)
|
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
|
// 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 {
|
backup.backupManga /* SY --> */.sortedBy { it.source == MERGED_SOURCE_ID } /* SY <-- */.forEach {
|
||||||
@ -268,9 +272,22 @@ class BackupRestorer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun restoreAppPreferences(preferences: List<BackupPreference>) {
|
private fun restoreAppPreferences(preferences: List<BackupPreference>) {
|
||||||
val prefs = preferenceStore.getAll()
|
restorePreferences(preferences, preferenceStore)
|
||||||
|
}
|
||||||
|
|
||||||
preferences.forEach { (key, value) ->
|
private fun restoreSourcePreferences(preferences: List<BackupSourcePreferences>) {
|
||||||
|
preferences.forEach {
|
||||||
|
val sourcePrefs = AndroidPreferenceStore(context, sourcePreferences(it.sourceKey))
|
||||||
|
restorePreferences(it.prefs, sourcePrefs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun restorePreferences(
|
||||||
|
toRestore: List<BackupPreference>,
|
||||||
|
preferenceStore: PreferenceStore,
|
||||||
|
) {
|
||||||
|
val prefs = preferenceStore.getAll()
|
||||||
|
toRestore.forEach { (key, value) ->
|
||||||
when (value) {
|
when (value) {
|
||||||
is IntPreferenceValue -> {
|
is IntPreferenceValue -> {
|
||||||
if (prefs[key] is Int?) {
|
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) {
|
private fun showRestoreProgress(progress: Int, amount: Int, title: String, contentTitle: String) {
|
||||||
notifier.showRestoreProgress(title, contentTitle, progress, amount)
|
notifier.showRestoreProgress(title, contentTitle, progress, amount)
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ data class Backup(
|
|||||||
@ProtoNumber(100) var backupBrokenSources: List<BrokenBackupSource> = emptyList(),
|
@ProtoNumber(100) var backupBrokenSources: List<BrokenBackupSource> = emptyList(),
|
||||||
@ProtoNumber(101) var backupSources: List<BackupSource> = emptyList(),
|
@ProtoNumber(101) var backupSources: List<BackupSource> = emptyList(),
|
||||||
@ProtoNumber(104) var backupPreferences: List<BackupPreference> = emptyList(),
|
@ProtoNumber(104) var backupPreferences: List<BackupPreference> = emptyList(),
|
||||||
|
@ProtoNumber(105) var backupSourcePreferences: List<BackupSourcePreferences> = emptyList(),
|
||||||
// SY specific values
|
// SY specific values
|
||||||
@ProtoNumber(600) var backupSavedSearches: List<BackupSavedSearch> = emptyList(),
|
@ProtoNumber(600) var backupSavedSearches: List<BackupSavedSearch> = emptyList(),
|
||||||
) {
|
) {
|
||||||
|
@ -9,6 +9,12 @@ data class BackupPreference(
|
|||||||
@ProtoNumber(2) val value: PreferenceValue,
|
@ProtoNumber(2) val value: PreferenceValue,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class BackupSourcePreferences(
|
||||||
|
@ProtoNumber(1) val sourceKey: String,
|
||||||
|
@ProtoNumber(2) val prefs: List<BackupPreference>,
|
||||||
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
sealed class PreferenceValue
|
sealed class PreferenceValue
|
||||||
|
|
||||||
|
@ -15,10 +15,9 @@ import tachiyomi.core.preference.AndroidPreference.StringSetPrimitive
|
|||||||
|
|
||||||
class AndroidPreferenceStore(
|
class AndroidPreferenceStore(
|
||||||
context: Context,
|
context: Context,
|
||||||
|
private val sharedPreferences: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context),
|
||||||
) : PreferenceStore {
|
) : PreferenceStore {
|
||||||
|
|
||||||
private val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
|
|
||||||
|
|
||||||
private val keyFlow = sharedPreferences.keyFlow
|
private val keyFlow = sharedPreferences.keyFlow
|
||||||
|
|
||||||
override fun getString(key: String, defaultValue: String): Preference<String> {
|
override fun getString(key: String, defaultValue: String): Preference<String> {
|
||||||
|
@ -494,6 +494,7 @@
|
|||||||
<string name="backup_in_progress">Backup is already in progress</string>
|
<string name="backup_in_progress">Backup is already in progress</string>
|
||||||
<string name="backup_choice">What do you want to backup?</string>
|
<string name="backup_choice">What do you want to backup?</string>
|
||||||
<string name="app_settings">App settings</string>
|
<string name="app_settings">App settings</string>
|
||||||
|
<string name="source_settings">Source settings</string>
|
||||||
<string name="creating_backup">Creating backup</string>
|
<string name="creating_backup">Creating backup</string>
|
||||||
<string name="creating_backup_error">Backup failed</string>
|
<string name="creating_backup_error">Backup failed</string>
|
||||||
<string name="missing_storage_permission">Storage permissions not granted</string>
|
<string name="missing_storage_permission">Storage permissions not granted</string>
|
||||||
|
@ -19,8 +19,11 @@ interface ConfigurableSource : Source {
|
|||||||
fun setupPreferenceScreen(screen: PreferenceScreen)
|
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
|
// TODO: use getSourcePreferences once all extensions are on ext-lib 1.5
|
||||||
fun ConfigurableSource.sourcePreferences(): SharedPreferences =
|
fun ConfigurableSource.sourcePreferences(): SharedPreferences =
|
||||||
Injekt.get<Application>().getSharedPreferences(preferenceKey(), Context.MODE_PRIVATE)
|
Injekt.get<Application>().getSharedPreferences(preferenceKey(), Context.MODE_PRIVATE)
|
||||||
|
|
||||||
|
fun sourcePreferences(key: String): SharedPreferences =
|
||||||
|
Injekt.get<Application>().getSharedPreferences(key, Context.MODE_PRIVATE)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user