mirror of
https://github.com/mihonapp/mihon.git
synced 2025-03-01 18:34:13 +01:00
Fix backup/restore of category related preferences (#1726)
Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
This commit is contained in:
parent
1a5b4c2804
commit
e1724d1aa0
@ -25,6 +25,7 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co
|
||||
- Fix Bangumi and MAL tracking 401 errors due to Mihon sending expired credentials ([@MajorTanya](https://github.com/MajorTanya)) ([#1681](https://github.com/mihonapp/mihon/pull/1681), [#1682](https://github.com/mihonapp/mihon/pull/1682))
|
||||
- Fix certain Infinix devices being unable to use any "Open link in browser" actions, including tracker setup ([@MajorTanya](https://github.com/MajorTanya)) ([#1684](https://github.com/mihonapp/mihon/pull/1684))
|
||||
- Fix App's preferences referencing deleted categories ([@cuong-tran](https://github.com/cuong-tran)) ([#1734](https://github.com/mihonapp/mihon/pull/1734))
|
||||
- Fix backup/restore of category related preferences ([@cuong-tran](https://github.com/cuong-tran)) ([#1726](https://github.com/mihonapp/mihon/pull/1726))
|
||||
|
||||
### Other
|
||||
- Add zoned "Current time" to debug info and include year & timezone in logcat output ([@MajorTanya](https://github.com/MajorTanya)) ([#1672](https://github.com/mihonapp/mihon/pull/1672))
|
||||
|
@ -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,
|
||||
|
@ -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(
|
||||
|
@ -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,38 +16,62 @@ 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) ->
|
||||
try {
|
||||
when (value) {
|
||||
is IntPreferenceValue -> {
|
||||
if (prefs[key] is Int?) {
|
||||
preferenceStore.getInt(key).set(value.value)
|
||||
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 -> {
|
||||
@ -70,10 +96,42 @@ class PreferenceRestorer(
|
||||
}
|
||||
is StringSetPreferenceValue -> {
|
||||
if (prefs[key] is Set<*>?) {
|
||||
preferenceStore.getStringSet(key).set(value.value)
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -57,6 +57,10 @@ operator fun <T> Preference<Set<T>>.plusAssign(item: T) {
|
||||
set(get() + item)
|
||||
}
|
||||
|
||||
operator fun <T> Preference<Set<T>>.plusAssign(items: Iterable<T>) {
|
||||
set(get() + items)
|
||||
}
|
||||
|
||||
operator fun <T> Preference<Set<T>>.minusAssign(item: T) {
|
||||
set(get() - item)
|
||||
}
|
||||
|
@ -26,22 +26,25 @@ class DownloadPreferences(
|
||||
|
||||
fun removeBookmarkedChapters() = preferenceStore.getBoolean("pref_remove_bookmarked", false)
|
||||
|
||||
fun removeExcludeCategories() = preferenceStore.getStringSet(
|
||||
"remove_exclude_categories",
|
||||
emptySet(),
|
||||
)
|
||||
fun removeExcludeCategories() = preferenceStore.getStringSet(REMOVE_EXCLUDE_CATEGORIES_PREF_KEY, emptySet())
|
||||
|
||||
fun downloadNewChapters() = preferenceStore.getBoolean("download_new", false)
|
||||
|
||||
fun downloadNewChapterCategories() = preferenceStore.getStringSet(
|
||||
"download_new_categories",
|
||||
emptySet(),
|
||||
)
|
||||
fun downloadNewChapterCategories() = preferenceStore.getStringSet(DOWNLOAD_NEW_CATEGORIES_PREF_KEY, emptySet())
|
||||
|
||||
fun downloadNewChapterCategoriesExclude() = preferenceStore.getStringSet(
|
||||
"download_new_categories_exclude",
|
||||
emptySet(),
|
||||
)
|
||||
fun downloadNewChapterCategoriesExclude() =
|
||||
preferenceStore.getStringSet(DOWNLOAD_NEW_CATEGORIES_EXCLUDE_PREF_KEY, emptySet())
|
||||
|
||||
fun downloadNewUnreadChaptersOnly() = preferenceStore.getBoolean("download_new_unread_chapters_only", false)
|
||||
|
||||
companion object {
|
||||
private const val REMOVE_EXCLUDE_CATEGORIES_PREF_KEY = "remove_exclude_categories"
|
||||
private const val DOWNLOAD_NEW_CATEGORIES_PREF_KEY = "download_new_categories"
|
||||
private const val DOWNLOAD_NEW_CATEGORIES_EXCLUDE_PREF_KEY = "download_new_categories_exclude"
|
||||
val categoryPreferenceKeys = setOf(
|
||||
REMOVE_EXCLUDE_CATEGORIES_PREF_KEY,
|
||||
DOWNLOAD_NEW_CATEGORIES_PREF_KEY,
|
||||
DOWNLOAD_NEW_CATEGORIES_EXCLUDE_PREF_KEY,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ class LibraryPreferences(
|
||||
|
||||
// region Category
|
||||
|
||||
fun defaultCategory() = preferenceStore.getInt("default_category", -1)
|
||||
fun defaultCategory() = preferenceStore.getInt(DEFAULT_CATEGORY_PREF_KEY, -1)
|
||||
|
||||
fun lastUsedCategory() = preferenceStore.getInt(Preference.appStateKey("last_used_category"), 0)
|
||||
|
||||
@ -119,12 +119,9 @@ class LibraryPreferences(
|
||||
|
||||
fun categorizedDisplaySettings() = preferenceStore.getBoolean("categorized_display", false)
|
||||
|
||||
fun updateCategories() = preferenceStore.getStringSet("library_update_categories", emptySet())
|
||||
fun updateCategories() = preferenceStore.getStringSet(LIBRARY_UPDATE_CATEGORIES_PREF_KEY, emptySet())
|
||||
|
||||
fun updateCategoriesExclude() = preferenceStore.getStringSet(
|
||||
"library_update_categories_exclude",
|
||||
emptySet(),
|
||||
)
|
||||
fun updateCategoriesExclude() = preferenceStore.getStringSet(LIBRARY_UPDATE_CATEGORIES_EXCLUDE_PREF_KEY, emptySet())
|
||||
|
||||
// endregion
|
||||
|
||||
@ -206,5 +203,14 @@ 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"
|
||||
|
||||
const val DEFAULT_CATEGORY_PREF_KEY = "default_category"
|
||||
private const val LIBRARY_UPDATE_CATEGORIES_PREF_KEY = "library_update_categories"
|
||||
private const val LIBRARY_UPDATE_CATEGORIES_EXCLUDE_PREF_KEY = "library_update_categories_exclude"
|
||||
val categoryPreferenceKeys = setOf(
|
||||
DEFAULT_CATEGORY_PREF_KEY,
|
||||
LIBRARY_UPDATE_CATEGORIES_PREF_KEY,
|
||||
LIBRARY_UPDATE_CATEGORIES_EXCLUDE_PREF_KEY,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user