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 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 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 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
|
### 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))
|
- 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(
|
class BackupCategory(
|
||||||
@ProtoNumber(1) var name: String,
|
@ProtoNumber(1) var name: String,
|
||||||
@ProtoNumber(2) var order: Long = 0,
|
@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(3) val updateInterval: Int = 0, 1.x value not used in 0.x
|
||||||
@ProtoNumber(100) var flags: Long = 0,
|
@ProtoNumber(100) var flags: Long = 0,
|
||||||
) {
|
) {
|
||||||
@ -21,6 +22,7 @@ class BackupCategory(
|
|||||||
|
|
||||||
val backupCategoryMapper = { category: Category ->
|
val backupCategoryMapper = { category: Category ->
|
||||||
BackupCategory(
|
BackupCategory(
|
||||||
|
id = category.id,
|
||||||
name = category.name,
|
name = category.name,
|
||||||
order = category.order,
|
order = category.order,
|
||||||
flags = category.flags,
|
flags = category.flags,
|
||||||
|
@ -91,7 +91,7 @@ class BackupRestorer(
|
|||||||
restoreCategories(backup.backupCategories)
|
restoreCategories(backup.backupCategories)
|
||||||
}
|
}
|
||||||
if (options.appSettings) {
|
if (options.appSettings) {
|
||||||
restoreAppPreferences(backup.backupPreferences)
|
restoreAppPreferences(backup.backupPreferences, backup.backupCategories.takeIf { options.categories })
|
||||||
}
|
}
|
||||||
if (options.sourceSettings) {
|
if (options.sourceSettings) {
|
||||||
restoreSourcePreferences(backup.backupSourcePreferences)
|
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()
|
ensureActive()
|
||||||
preferenceRestorer.restoreApp(preferences)
|
preferenceRestorer.restoreApp(
|
||||||
|
preferences,
|
||||||
|
categories,
|
||||||
|
)
|
||||||
|
|
||||||
restoreProgress += 1
|
restoreProgress += 1
|
||||||
notifier.showRestoreProgress(
|
notifier.showRestoreProgress(
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.restore.restorers
|
package eu.kanade.tachiyomi.data.backup.restore.restorers
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.util.Log
|
||||||
import eu.kanade.tachiyomi.data.backup.create.BackupCreateJob
|
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.BackupPreference
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupSourcePreferences
|
import eu.kanade.tachiyomi.data.backup.models.BackupSourcePreferences
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BooleanPreferenceValue
|
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 eu.kanade.tachiyomi.source.sourcePreferences
|
||||||
import tachiyomi.core.common.preference.AndroidPreferenceStore
|
import tachiyomi.core.common.preference.AndroidPreferenceStore
|
||||||
import tachiyomi.core.common.preference.PreferenceStore
|
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.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
class PreferenceRestorer(
|
class PreferenceRestorer(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
|
private val getCategories: GetCategories = Injekt.get(),
|
||||||
private val preferenceStore: PreferenceStore = Injekt.get(),
|
private val preferenceStore: PreferenceStore = Injekt.get(),
|
||||||
) {
|
) {
|
||||||
|
suspend fun restoreApp(
|
||||||
fun restoreApp(preferences: List<BackupPreference>) {
|
preferences: List<BackupPreference>,
|
||||||
restorePreferences(preferences, preferenceStore)
|
backupCategories: List<BackupCategory>?,
|
||||||
|
) {
|
||||||
|
restorePreferences(
|
||||||
|
preferences,
|
||||||
|
preferenceStore,
|
||||||
|
backupCategories,
|
||||||
|
)
|
||||||
|
|
||||||
LibraryUpdateJob.setupTask(context)
|
LibraryUpdateJob.setupTask(context)
|
||||||
BackupCreateJob.setupTask(context)
|
BackupCreateJob.setupTask(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun restoreSource(preferences: List<BackupSourcePreferences>) {
|
suspend fun restoreSource(preferences: List<BackupSourcePreferences>) {
|
||||||
preferences.forEach {
|
preferences.forEach {
|
||||||
val sourcePrefs = AndroidPreferenceStore(context, sourcePreferences(it.sourceKey))
|
val sourcePrefs = AndroidPreferenceStore(context, sourcePreferences(it.sourceKey))
|
||||||
restorePreferences(it.prefs, sourcePrefs)
|
restorePreferences(it.prefs, sourcePrefs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun restorePreferences(
|
private suspend fun restorePreferences(
|
||||||
toRestore: List<BackupPreference>,
|
toRestore: List<BackupPreference>,
|
||||||
preferenceStore: PreferenceStore,
|
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()
|
val prefs = preferenceStore.getAll()
|
||||||
toRestore.forEach { (key, value) ->
|
toRestore.forEach { (key, value) ->
|
||||||
when (value) {
|
try {
|
||||||
is IntPreferenceValue -> {
|
when (value) {
|
||||||
if (prefs[key] is Int?) {
|
is IntPreferenceValue -> {
|
||||||
preferenceStore.getInt(key).set(value.value)
|
if (prefs[key] is Int?) {
|
||||||
}
|
val newValue = if (key == LibraryPreferences.DEFAULT_CATEGORY_PREF_KEY) {
|
||||||
}
|
backupCategoriesById[value.value.toString()]
|
||||||
is LongPreferenceValue -> {
|
?.let { categoriesByName[it.name]?.id?.toInt() }
|
||||||
if (prefs[key] is Long?) {
|
} else {
|
||||||
preferenceStore.getLong(key).set(value.value)
|
value.value
|
||||||
}
|
}
|
||||||
}
|
|
||||||
is FloatPreferenceValue -> {
|
newValue?.let { preferenceStore.getInt(key).set(it) }
|
||||||
if (prefs[key] is Float?) {
|
}
|
||||||
preferenceStore.getFloat(key).set(value.value)
|
}
|
||||||
}
|
is LongPreferenceValue -> {
|
||||||
}
|
if (prefs[key] is Long?) {
|
||||||
is StringPreferenceValue -> {
|
preferenceStore.getLong(key).set(value.value)
|
||||||
if (prefs[key] is String?) {
|
}
|
||||||
preferenceStore.getString(key).set(value.value)
|
}
|
||||||
}
|
is FloatPreferenceValue -> {
|
||||||
}
|
if (prefs[key] is Float?) {
|
||||||
is BooleanPreferenceValue -> {
|
preferenceStore.getFloat(key).set(value.value)
|
||||||
if (prefs[key] is Boolean?) {
|
}
|
||||||
preferenceStore.getBoolean(key).set(value.value)
|
}
|
||||||
}
|
is StringPreferenceValue -> {
|
||||||
}
|
if (prefs[key] is String?) {
|
||||||
is StringSetPreferenceValue -> {
|
preferenceStore.getString(key).set(value.value)
|
||||||
if (prefs[key] is Set<*>?) {
|
}
|
||||||
preferenceStore.getStringSet(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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,10 @@ operator fun <T> Preference<Set<T>>.plusAssign(item: T) {
|
|||||||
set(get() + item)
|
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) {
|
operator fun <T> Preference<Set<T>>.minusAssign(item: T) {
|
||||||
set(get() - item)
|
set(get() - item)
|
||||||
}
|
}
|
||||||
|
@ -26,22 +26,25 @@ class DownloadPreferences(
|
|||||||
|
|
||||||
fun removeBookmarkedChapters() = preferenceStore.getBoolean("pref_remove_bookmarked", false)
|
fun removeBookmarkedChapters() = preferenceStore.getBoolean("pref_remove_bookmarked", false)
|
||||||
|
|
||||||
fun removeExcludeCategories() = preferenceStore.getStringSet(
|
fun removeExcludeCategories() = preferenceStore.getStringSet(REMOVE_EXCLUDE_CATEGORIES_PREF_KEY, emptySet())
|
||||||
"remove_exclude_categories",
|
|
||||||
emptySet(),
|
|
||||||
)
|
|
||||||
|
|
||||||
fun downloadNewChapters() = preferenceStore.getBoolean("download_new", false)
|
fun downloadNewChapters() = preferenceStore.getBoolean("download_new", false)
|
||||||
|
|
||||||
fun downloadNewChapterCategories() = preferenceStore.getStringSet(
|
fun downloadNewChapterCategories() = preferenceStore.getStringSet(DOWNLOAD_NEW_CATEGORIES_PREF_KEY, emptySet())
|
||||||
"download_new_categories",
|
|
||||||
emptySet(),
|
|
||||||
)
|
|
||||||
|
|
||||||
fun downloadNewChapterCategoriesExclude() = preferenceStore.getStringSet(
|
fun downloadNewChapterCategoriesExclude() =
|
||||||
"download_new_categories_exclude",
|
preferenceStore.getStringSet(DOWNLOAD_NEW_CATEGORIES_EXCLUDE_PREF_KEY, emptySet())
|
||||||
emptySet(),
|
|
||||||
)
|
|
||||||
|
|
||||||
fun downloadNewUnreadChaptersOnly() = preferenceStore.getBoolean("download_new_unread_chapters_only", false)
|
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
|
// 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)
|
fun lastUsedCategory() = preferenceStore.getInt(Preference.appStateKey("last_used_category"), 0)
|
||||||
|
|
||||||
@ -119,12 +119,9 @@ class LibraryPreferences(
|
|||||||
|
|
||||||
fun categorizedDisplaySettings() = preferenceStore.getBoolean("categorized_display", false)
|
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(
|
fun updateCategoriesExclude() = preferenceStore.getStringSet(LIBRARY_UPDATE_CATEGORIES_EXCLUDE_PREF_KEY, emptySet())
|
||||||
"library_update_categories_exclude",
|
|
||||||
emptySet(),
|
|
||||||
)
|
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
@ -206,5 +203,14 @@ class LibraryPreferences(
|
|||||||
const val MANGA_HAS_UNREAD = "manga_fully_read"
|
const val MANGA_HAS_UNREAD = "manga_fully_read"
|
||||||
const val MANGA_NON_READ = "manga_started"
|
const val MANGA_NON_READ = "manga_started"
|
||||||
const val MANGA_OUTSIDE_RELEASE_PERIOD = "manga_outside_release_period"
|
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