Add source preferences to backups
Closes #1857 Co-authored-by: jmir1 <jmir1@users.noreply.github.com>
This commit is contained in:
parent
730f3a6e52
commit
0f42b9f154
9 changed files with 63 additions and 16 deletions
|
@ -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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val flags = remember { choices.keys.toMutableStateList() }
|
val flags = remember { choices.keys.toMutableStateList() }
|
||||||
|
|
|
@ -17,5 +17,8 @@ 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_ALL = 0x1F
|
const val BACKUP_SOURCE_PREFS = 0x20
|
||||||
|
const val BACKUP_SOURCE_PREFS_MASK = 0x20
|
||||||
|
|
||||||
|
const val BACKUP_ALL = 0x3F
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,15 @@ import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_CATEGORY
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_CATEGORY_MASK
|
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_CATEGORY_MASK
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_CHAPTER
|
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_CHAPTER
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_CHAPTER_MASK
|
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_CHAPTER_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_HISTORY
|
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_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
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
|
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
|
||||||
|
import eu.kanade.tachiyomi.data.backup.models.BackupSourcePreferences
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupHistory
|
import eu.kanade.tachiyomi.data.backup.models.BackupHistory
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupManga
|
import eu.kanade.tachiyomi.data.backup.models.BackupManga
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupPreference
|
import eu.kanade.tachiyomi.data.backup.models.BackupPreference
|
||||||
|
@ -32,7 +35,10 @@ import eu.kanade.tachiyomi.data.backup.models.StringSetPreferenceValue
|
||||||
import eu.kanade.tachiyomi.data.backup.models.backupCategoryMapper
|
import eu.kanade.tachiyomi.data.backup.models.backupCategoryMapper
|
||||||
import eu.kanade.tachiyomi.data.backup.models.backupChapterMapper
|
import eu.kanade.tachiyomi.data.backup.models.backupChapterMapper
|
||||||
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.preferenceKey
|
||||||
|
import eu.kanade.tachiyomi.source.sourcePreferences
|
||||||
import eu.kanade.tachiyomi.util.system.hasPermission
|
import eu.kanade.tachiyomi.util.system.hasPermission
|
||||||
import kotlinx.serialization.protobuf.ProtoBuf
|
import kotlinx.serialization.protobuf.ProtoBuf
|
||||||
import logcat.LogPriority
|
import logcat.LogPriority
|
||||||
|
@ -94,6 +100,7 @@ class BackupManager(
|
||||||
emptyList(),
|
emptyList(),
|
||||||
prepExtensionInfoForSync(databaseManga),
|
prepExtensionInfoForSync(databaseManga),
|
||||||
backupAppPreferences(flags),
|
backupAppPreferences(flags),
|
||||||
|
backupSourcePreferences(flags),
|
||||||
)
|
)
|
||||||
|
|
||||||
var file: UniFile? = null
|
var file: UniFile? = null
|
||||||
|
@ -232,12 +239,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))
|
||||||
|
|
|
@ -9,16 +9,19 @@ import eu.kanade.tachiyomi.data.backup.models.BackupHistory
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupManga
|
import eu.kanade.tachiyomi.data.backup.models.BackupManga
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupPreference
|
import eu.kanade.tachiyomi.data.backup.models.BackupPreference
|
||||||
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 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
|
||||||
|
@ -114,6 +117,7 @@ class BackupRestorer(
|
||||||
|
|
||||||
return coroutineScope {
|
return coroutineScope {
|
||||||
restoreAppPreferences(backup.backupPreferences)
|
restoreAppPreferences(backup.backupPreferences)
|
||||||
|
restoreSourcePreferences(backup.backupSourcePreferences)
|
||||||
|
|
||||||
// Restore individual manga
|
// Restore individual manga
|
||||||
backup.backupManga.forEach {
|
backup.backupManga.forEach {
|
||||||
|
@ -211,9 +215,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?) {
|
||||||
|
@ -249,13 +266,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(),
|
||||||
) {
|
) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Reference in a new issue