Fix backup/restore of category related preferences (#1726)

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
This commit is contained in:
Cuong-Tran
2025-02-25 05:04:39 +07:00
committed by GitHub
parent 1a5b4c2804
commit e1724d1aa0
7 changed files with 135 additions and 55 deletions

View File

@ -8,6 +8,7 @@ import tachiyomi.domain.category.model.Category
class BackupCategory(
@ProtoNumber(1) var name: String,
@ProtoNumber(2) var order: Long = 0,
@ProtoNumber(3) var id: Long = 0,
// @ProtoNumber(3) val updateInterval: Int = 0, 1.x value not used in 0.x
@ProtoNumber(100) var flags: Long = 0,
) {
@ -21,6 +22,7 @@ class BackupCategory(
val backupCategoryMapper = { category: Category ->
BackupCategory(
id = category.id,
name = category.name,
order = category.order,
flags = category.flags,

View File

@ -91,7 +91,7 @@ class BackupRestorer(
restoreCategories(backup.backupCategories)
}
if (options.appSettings) {
restoreAppPreferences(backup.backupPreferences)
restoreAppPreferences(backup.backupPreferences, backup.backupCategories.takeIf { options.categories })
}
if (options.sourceSettings) {
restoreSourcePreferences(backup.backupSourcePreferences)
@ -140,9 +140,15 @@ class BackupRestorer(
}
}
private fun CoroutineScope.restoreAppPreferences(preferences: List<BackupPreference>) = launch {
private fun CoroutineScope.restoreAppPreferences(
preferences: List<BackupPreference>,
categories: List<BackupCategory>?,
) = launch {
ensureActive()
preferenceRestorer.restoreApp(preferences)
preferenceRestorer.restoreApp(
preferences,
categories,
)
restoreProgress += 1
notifier.showRestoreProgress(

View File

@ -1,7 +1,9 @@
package eu.kanade.tachiyomi.data.backup.restore.restorers
import android.content.Context
import android.util.Log
import eu.kanade.tachiyomi.data.backup.create.BackupCreateJob
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
import eu.kanade.tachiyomi.data.backup.models.BackupPreference
import eu.kanade.tachiyomi.data.backup.models.BackupSourcePreferences
import eu.kanade.tachiyomi.data.backup.models.BooleanPreferenceValue
@ -14,66 +16,122 @@ import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.source.sourcePreferences
import tachiyomi.core.common.preference.AndroidPreferenceStore
import tachiyomi.core.common.preference.PreferenceStore
import tachiyomi.core.common.preference.plusAssign
import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.category.model.Category
import tachiyomi.domain.download.service.DownloadPreferences
import tachiyomi.domain.library.service.LibraryPreferences
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
class PreferenceRestorer(
private val context: Context,
private val getCategories: GetCategories = Injekt.get(),
private val preferenceStore: PreferenceStore = Injekt.get(),
) {
fun restoreApp(preferences: List<BackupPreference>) {
restorePreferences(preferences, preferenceStore)
suspend fun restoreApp(
preferences: List<BackupPreference>,
backupCategories: List<BackupCategory>?,
) {
restorePreferences(
preferences,
preferenceStore,
backupCategories,
)
LibraryUpdateJob.setupTask(context)
BackupCreateJob.setupTask(context)
}
fun restoreSource(preferences: List<BackupSourcePreferences>) {
suspend fun restoreSource(preferences: List<BackupSourcePreferences>) {
preferences.forEach {
val sourcePrefs = AndroidPreferenceStore(context, sourcePreferences(it.sourceKey))
restorePreferences(it.prefs, sourcePrefs)
}
}
private fun restorePreferences(
private suspend fun restorePreferences(
toRestore: List<BackupPreference>,
preferenceStore: PreferenceStore,
backupCategories: List<BackupCategory>? = null,
) {
val allCategories = if (backupCategories != null) getCategories.await() else emptyList()
val categoriesByName = allCategories.associateBy { it.name }
val backupCategoriesById = backupCategories?.associateBy { it.id.toString() }.orEmpty()
val prefs = preferenceStore.getAll()
toRestore.forEach { (key, value) ->
when (value) {
is IntPreferenceValue -> {
if (prefs[key] is Int?) {
preferenceStore.getInt(key).set(value.value)
}
}
is LongPreferenceValue -> {
if (prefs[key] is Long?) {
preferenceStore.getLong(key).set(value.value)
}
}
is FloatPreferenceValue -> {
if (prefs[key] is Float?) {
preferenceStore.getFloat(key).set(value.value)
}
}
is StringPreferenceValue -> {
if (prefs[key] is String?) {
preferenceStore.getString(key).set(value.value)
}
}
is BooleanPreferenceValue -> {
if (prefs[key] is Boolean?) {
preferenceStore.getBoolean(key).set(value.value)
}
}
is StringSetPreferenceValue -> {
if (prefs[key] is Set<*>?) {
preferenceStore.getStringSet(key).set(value.value)
try {
when (value) {
is IntPreferenceValue -> {
if (prefs[key] is Int?) {
val newValue = if (key == LibraryPreferences.DEFAULT_CATEGORY_PREF_KEY) {
backupCategoriesById[value.value.toString()]
?.let { categoriesByName[it.name]?.id?.toInt() }
} else {
value.value
}
newValue?.let { preferenceStore.getInt(key).set(it) }
}
}
is LongPreferenceValue -> {
if (prefs[key] is Long?) {
preferenceStore.getLong(key).set(value.value)
}
}
is FloatPreferenceValue -> {
if (prefs[key] is Float?) {
preferenceStore.getFloat(key).set(value.value)
}
}
is StringPreferenceValue -> {
if (prefs[key] is String?) {
preferenceStore.getString(key).set(value.value)
}
}
is BooleanPreferenceValue -> {
if (prefs[key] is Boolean?) {
preferenceStore.getBoolean(key).set(value.value)
}
}
is StringSetPreferenceValue -> {
if (prefs[key] is Set<*>?) {
val restored = restoreCategoriesPreference(
key,
value.value,
preferenceStore,
backupCategoriesById,
categoriesByName,
)
if (!restored) preferenceStore.getStringSet(key).set(value.value)
}
}
}
} catch (e: Exception) {
Log.e("PreferenceRestorer", "Failed to restore preference <$key>", e)
}
}
}
private fun restoreCategoriesPreference(
key: String,
value: Set<String>,
preferenceStore: PreferenceStore,
backupCategoriesById: Map<String, BackupCategory>,
categoriesByName: Map<String, Category>,
): Boolean {
val categoryPreferences = LibraryPreferences.categoryPreferenceKeys + DownloadPreferences.categoryPreferenceKeys
if (key !in categoryPreferences) return false
val ids = value.mapNotNull {
backupCategoriesById[it]?.name?.let { name ->
categoriesByName[name]?.id?.toString()
}
}
if (ids.isNotEmpty()) {
preferenceStore.getStringSet(key) += ids
}
return true
}
}