Fix (PreferenceRestorer): correctly backup/restore preferences related to category

This commit is contained in:
Cuong-Tran 2025-02-11 15:39:28 +07:00
parent a2da8fdd35
commit ff8d48bf4c
7 changed files with 227 additions and 55 deletions

View file

@ -25,7 +25,12 @@ class SourcePreferences(
fun incognitoExtensions() = preferenceStore.getStringSet("incognito_extensions", emptySet())
fun pinnedSources() = preferenceStore.getStringSet(pinnedSourcesPrefKey, emptySet())
fun pinnedSources() = preferenceStore.getStringSet(
// KMK -->
PINNED_SOURCES_PREF_KEY,
// KMK <--
emptySet(),
)
fun lastUsedSource() = preferenceStore.getLong(
Preference.appStateKey("last_catalogue_source"),
@ -107,7 +112,9 @@ class SourcePreferences(
// KMK -->
fun relatedMangas() = preferenceStore.getBoolean("related_mangas", true)
companion object {
const val PINNED_SOURCES_PREF_KEY = "pinned_catalogues"
}
// KMK <--
}
const val pinnedSourcesPrefKey = "pinned_catalogues"

View file

@ -159,7 +159,7 @@ class BackupCreator(
return sourcesBackupCreator(mangas)
}
fun backupAppPreferences(options: BackupOptions): List<BackupPreference> {
/* KMK --> */ suspend /* KMK <-- */ fun backupAppPreferences(options: BackupOptions): List<BackupPreference> {
if (!options.appSettings) return emptyList()
return preferenceBackupCreator.createApp(includePrivatePreferences = options.privateSettings)

View file

@ -13,6 +13,14 @@ import eu.kanade.tachiyomi.source.preferenceKey
import eu.kanade.tachiyomi.source.sourcePreferences
import tachiyomi.core.common.preference.Preference
import tachiyomi.core.common.preference.PreferenceStore
import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.download.service.DownloadPreferences.Companion.DOWNLOAD_NEW_CATEGORIES_EXCLUDE_PREF_KEY
import tachiyomi.domain.download.service.DownloadPreferences.Companion.DOWNLOAD_NEW_CATEGORIES_PREF_KEY
import tachiyomi.domain.download.service.DownloadPreferences.Companion.REMOVE_EXCLUDE_CATEGORIES_PREF_KEY
import tachiyomi.domain.library.service.LibraryPreferences
import tachiyomi.domain.library.service.LibraryPreferences.Companion.DEFAULT_CATEGORY_PREF_KEY
import tachiyomi.domain.library.service.LibraryPreferences.Companion.LIBRARY_UPDATE_CATEGORIES_EXCLUDE_PREF_KEY
import tachiyomi.domain.library.service.LibraryPreferences.Companion.LIBRARY_UPDATE_CATEGORIES_PREF_KEY
import tachiyomi.domain.source.service.SourceManager
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -21,9 +29,48 @@ class PreferenceBackupCreator(
private val sourceManager: SourceManager = Injekt.get(),
private val preferenceStore: PreferenceStore = Injekt.get(),
) {
// KMK -->
private val getCategories by lazy { Injekt.get<GetCategories>() }
private val libraryPreferences by lazy { Injekt.get<LibraryPreferences>() }
// <--
/* KMK --> */ suspend /* KMK <-- */ fun createApp(includePrivatePreferences: Boolean): List<BackupPreference> {
// KMK -->
val allCategories = getCategories.await()
// KMK <--
fun createApp(includePrivatePreferences: Boolean): List<BackupPreference> {
return preferenceStore.getAll().toBackupPreferences()
// KMK -->
.map { backupPreference ->
when (backupPreference.key) {
// Convert CategoryId to CategoryOrder
DEFAULT_CATEGORY_PREF_KEY -> {
val id = (backupPreference.value as IntPreferenceValue).value.toLong()
val value = allCategories.find { it.id == id }?.order?.toInt()
?: libraryPreferences.defaultCategory().defaultValue()
BackupPreference(
backupPreference.key,
IntPreferenceValue(value),
)
}
// Convert CategoryId to CategoryOrder
LIBRARY_UPDATE_CATEGORIES_PREF_KEY, LIBRARY_UPDATE_CATEGORIES_EXCLUDE_PREF_KEY,
DOWNLOAD_NEW_CATEGORIES_PREF_KEY, DOWNLOAD_NEW_CATEGORIES_EXCLUDE_PREF_KEY,
REMOVE_EXCLUDE_CATEGORIES_PREF_KEY,
-> {
val categoryIds = (backupPreference.value as StringSetPreferenceValue).value
val categories = allCategories.associateBy({ it.id.toString() }, { it.order.toString() })
BackupPreference(
backupPreference.key,
StringSetPreferenceValue(
categoryIds.mapNotNull { categories[it] }.toSet(),
),
)
}
else -> backupPreference
}
}
// KMK <--
.withPrivatePreferences(includePrivatePreferences)
}

View file

@ -117,7 +117,12 @@ class BackupRestorer(
}
// SY <--
if (options.appSettings) {
restoreAppPreferences(backup.backupPreferences)
restoreAppPreferences(
backup.backupPreferences,
// KMK ->
if (options.categories) backup.backupCategories else emptyList(),
// KMK <--
)
}
if (options.sourceSettings) {
restoreSourcePreferences(backup.backupSourcePreferences)
@ -190,9 +195,19 @@ class BackupRestorer(
}
}
private fun CoroutineScope.restoreAppPreferences(preferences: List<BackupPreference>) = launch {
private fun CoroutineScope.restoreAppPreferences(
preferences: List<BackupPreference>,
// KMK -->
backupCategories: List<BackupCategory>,
// KMK <--
) = launch {
ensureActive()
preferenceRestorer.restoreApp(preferences)
preferenceRestorer.restoreApp(
preferences,
// KMK -->
backupCategories,
// KMK <--
)
restoreProgress += 1
notifier.showRestoreProgress(

View file

@ -1,8 +1,9 @@
package eu.kanade.tachiyomi.data.backup.restore.restorers
import android.content.Context
import eu.kanade.domain.source.service.pinnedSourcesPrefKey
import eu.kanade.domain.source.service.SourcePreferences.Companion.PINNED_SOURCES_PREF_KEY
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
@ -15,8 +16,17 @@ import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.data.updater.AppUpdateJob
import eu.kanade.tachiyomi.source.sourcePreferences
import exh.EXHMigrations
import exh.log.xLogE
import tachiyomi.core.common.preference.AndroidPreferenceStore
import tachiyomi.core.common.preference.PreferenceStore
import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.download.service.DownloadPreferences.Companion.DOWNLOAD_NEW_CATEGORIES_EXCLUDE_PREF_KEY
import tachiyomi.domain.download.service.DownloadPreferences.Companion.DOWNLOAD_NEW_CATEGORIES_PREF_KEY
import tachiyomi.domain.download.service.DownloadPreferences.Companion.REMOVE_EXCLUDE_CATEGORIES_PREF_KEY
import tachiyomi.domain.library.service.LibraryPreferences
import tachiyomi.domain.library.service.LibraryPreferences.Companion.DEFAULT_CATEGORY_PREF_KEY
import tachiyomi.domain.library.service.LibraryPreferences.Companion.LIBRARY_UPDATE_CATEGORIES_EXCLUDE_PREF_KEY
import tachiyomi.domain.library.service.LibraryPreferences.Companion.LIBRARY_UPDATE_CATEGORIES_PREF_KEY
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -24,9 +34,24 @@ class PreferenceRestorer(
private val context: Context,
private val preferenceStore: PreferenceStore = Injekt.get(),
) {
// KMK -->
private val getCategories by lazy { Injekt.get<GetCategories>() }
private val libraryPreferences by lazy { Injekt.get<LibraryPreferences>() }
// <--
fun restoreApp(preferences: List<BackupPreference>) {
restorePreferences(preferences, preferenceStore)
/* KMK --> */ suspend /* KMK <-- */ fun restoreApp(
preferences: List<BackupPreference>,
// KMK -->
backupCategories: List<BackupCategory>,
// KMK <--
) {
restorePreferences(
preferences,
preferenceStore,
// KMK -->
backupCategories,
// KMK <--
)
LibraryUpdateJob.setupTask(context)
BackupCreateJob.setupTask(context)
@ -35,58 +60,106 @@ class PreferenceRestorer(
// KMK <--
}
fun restoreSource(preferences: List<BackupSourcePreferences>) {
/* KMK --> */ suspend /* KMK <-- */ fun restoreSource(preferences: List<BackupSourcePreferences>) {
preferences.forEach {
val sourcePrefs = AndroidPreferenceStore(context, sourcePreferences(it.sourceKey))
restorePreferences(it.prefs, sourcePrefs)
}
}
private fun restorePreferences(
private /* KMK --> */ suspend /* KMK <-- */ fun restorePreferences(
toRestore: List<BackupPreference>,
preferenceStore: PreferenceStore,
// KMK -->
backupCategories: List<BackupCategory> = emptyList(),
// KMK <--
) {
// KMK -->
val allCategories = getCategories.await()
val categoriesByName = allCategories.associateBy { it.name }
val backupCategoriesByOrder = backupCategories.associateBy { it.order.toString() }
// KMK <--
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(
// KMK -->
try {
// KMK <--
when (value) {
is IntPreferenceValue -> {
if (prefs[key] is Int?) {
// KMK -->
if (key == pinnedSourcesPrefKey) {
EXHMigrations.migratePinnedSources(value.value)
} else {
// KMK <--
value.value
},
)
when (key) {
// Convert CategoryOrder to CategoryId
DEFAULT_CATEGORY_PREF_KEY -> {
if (backupCategories.isNotEmpty()) {
val order = value.value.toLong()
val newValue = backupCategories.find { it.order == order }
?.let {
categoriesByName[it.name]?.id?.toInt()
}
?: libraryPreferences.defaultCategory().defaultValue()
preferenceStore.getInt(key).set(newValue)
}
}
else ->
// KMK <--
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<*>?) {
// KMK -->
when (key) {
PINNED_SOURCES_PREF_KEY -> {
EXHMigrations.migratePinnedSources(value.value)
}
// Convert CategoryOrder to CategoryId
LIBRARY_UPDATE_CATEGORIES_PREF_KEY, LIBRARY_UPDATE_CATEGORIES_EXCLUDE_PREF_KEY,
DOWNLOAD_NEW_CATEGORIES_PREF_KEY, DOWNLOAD_NEW_CATEGORIES_EXCLUDE_PREF_KEY,
REMOVE_EXCLUDE_CATEGORIES_PREF_KEY,
-> {
val newValue = value.value.mapNotNull { order ->
backupCategoriesByOrder[order]?.let { backupCategory ->
categoriesByName[backupCategory.name]?.id?.toString()
}
}.toSet()
if (newValue.isNotEmpty()) {
preferenceStore.getStringSet(key).set(newValue)
}
}
else ->
// KMK <--
preferenceStore.getStringSet(key).set(value.value)
}
}
}
}
// KMK -->
} catch (e: Exception) {
xLogE("Failed to restore preference <$key>", e)
// KMK <--
}
}
}

View file

@ -27,19 +27,25 @@ class DownloadPreferences(
fun removeBookmarkedChapters() = preferenceStore.getBoolean("pref_remove_bookmarked", false)
fun removeExcludeCategories() = preferenceStore.getStringSet(
"remove_exclude_categories",
// KMK -->
REMOVE_EXCLUDE_CATEGORIES_PREF_KEY,
// KMK <--
emptySet(),
)
fun downloadNewChapters() = preferenceStore.getBoolean("download_new", false)
fun downloadNewChapterCategories() = preferenceStore.getStringSet(
"download_new_categories",
// KMK -->
DOWNLOAD_NEW_CATEGORIES_PREF_KEY,
// KMK <--
emptySet(),
)
fun downloadNewChapterCategoriesExclude() = preferenceStore.getStringSet(
"download_new_categories_exclude",
// KMK -->
DOWNLOAD_NEW_CATEGORIES_EXCLUDE_PREF_KEY,
// KMK <--
emptySet(),
)
@ -47,5 +53,11 @@ class DownloadPreferences(
// KMK -->
fun downloadCacheRenewInterval() = preferenceStore.getInt("download_cache_renew_interval", 1)
companion object {
const val REMOVE_EXCLUDE_CATEGORIES_PREF_KEY = "remove_exclude_categories"
const val DOWNLOAD_NEW_CATEGORIES_PREF_KEY = "download_new_categories"
const val DOWNLOAD_NEW_CATEGORIES_EXCLUDE_PREF_KEY = "download_new_categories_exclude"
}
// KMK <--
}

View file

@ -144,7 +144,12 @@ class LibraryPreferences(
// region Category
fun defaultCategory() = preferenceStore.getInt("default_category", -1)
fun defaultCategory() = preferenceStore.getInt(
// KMK -->
DEFAULT_CATEGORY_PREF_KEY,
// KMK <--
-1,
)
fun lastUsedCategory() = preferenceStore.getInt(Preference.appStateKey("last_used_category"), 0)
@ -158,10 +163,17 @@ class LibraryPreferences(
fun showHiddenCategories() = preferenceStore.getBoolean("hide_hidden_categories", false)
// KMK <--
fun updateCategories() = preferenceStore.getStringSet("library_update_categories", emptySet())
fun updateCategories() = preferenceStore.getStringSet(
// KMK -->
LIBRARY_UPDATE_CATEGORIES_PREF_KEY,
// KMK <--
emptySet(),
)
fun updateCategoriesExclude() = preferenceStore.getStringSet(
"library_update_categories_exclude",
// KMK -->
LIBRARY_UPDATE_CATEGORIES_EXCLUDE_PREF_KEY,
// KMK <--
emptySet(),
)
@ -255,5 +267,11 @@ class LibraryPreferences(
const val MANGA_HAS_UNREAD = "manga_fully_read"
const val MANGA_NON_READ = "manga_started"
const val MANGA_OUTSIDE_RELEASE_PERIOD = "manga_outside_release_period"
// KMK -->
const val DEFAULT_CATEGORY_PREF_KEY = "default_category"
const val LIBRARY_UPDATE_CATEGORIES_PREF_KEY = "library_update_categories"
const val LIBRARY_UPDATE_CATEGORIES_EXCLUDE_PREF_KEY = "library_update_categories_exclude"
// KMK <--
}
}