|
@@ -21,7 +21,7 @@ import eu.kanade.tachiyomi.source.sourcePreferences
|
|
|
import eu.kanade.tachiyomi.util.BackupUtil
|
|
|
import eu.kanade.tachiyomi.util.system.createFileInCacheDir
|
|
|
import kotlinx.coroutines.coroutineScope
|
|
|
-import kotlinx.coroutines.isActive
|
|
|
+import kotlinx.coroutines.ensureActive
|
|
|
import tachiyomi.core.i18n.stringResource
|
|
|
import tachiyomi.core.preference.AndroidPreferenceStore
|
|
|
import tachiyomi.core.preference.PreferenceStore
|
|
@@ -74,14 +74,12 @@ class BackupRestorer(
|
|
|
|
|
|
private val errors = mutableListOf<Pair<Date, String>>()
|
|
|
|
|
|
- suspend fun syncFromBackup(uri: Uri, sync: Boolean): Boolean {
|
|
|
+ suspend fun syncFromBackup(uri: Uri, sync: Boolean) {
|
|
|
val startTime = System.currentTimeMillis()
|
|
|
restoreProgress = 0
|
|
|
errors.clear()
|
|
|
|
|
|
- if (!performRestore(uri, sync)) {
|
|
|
- return false
|
|
|
- }
|
|
|
+ performRestore(uri, sync)
|
|
|
|
|
|
val endTime = System.currentTimeMillis()
|
|
|
val time = endTime - startTime
|
|
@@ -99,7 +97,6 @@ class BackupRestorer(
|
|
|
} else {
|
|
|
notifier.showRestoreComplete(time, errors.size, logFile.parent, logFile.name)
|
|
|
}
|
|
|
- return true
|
|
|
}
|
|
|
|
|
|
private fun writeErrorLog(): File {
|
|
@@ -121,74 +118,57 @@ class BackupRestorer(
|
|
|
return File("")
|
|
|
}
|
|
|
|
|
|
- private suspend fun performRestore(uri: Uri, sync: Boolean): Boolean {
|
|
|
+ private suspend fun performRestore(uri: Uri, sync: Boolean) {
|
|
|
val backup = BackupUtil.decodeBackup(context, uri)
|
|
|
|
|
|
restoreAmount = backup.backupManga.size + 3 // +3 for categories, app prefs, source prefs
|
|
|
|
|
|
- // Restore categories
|
|
|
- if (backup.backupCategories.isNotEmpty()) {
|
|
|
- restoreCategories(backup.backupCategories)
|
|
|
- }
|
|
|
-
|
|
|
// Store source mapping for error messages
|
|
|
val backupMaps = backup.backupBrokenSources.map { BackupSource(it.name, it.sourceId) } + backup.backupSources
|
|
|
sourceMapping = backupMaps.associate { it.sourceId to it.name }
|
|
|
now = ZonedDateTime.now()
|
|
|
currentFetchWindow = fetchInterval.getWindow(now)
|
|
|
|
|
|
- return coroutineScope {
|
|
|
+ coroutineScope {
|
|
|
+ ensureActive()
|
|
|
+ restoreCategories(backup.backupCategories)
|
|
|
+
|
|
|
+ ensureActive()
|
|
|
restoreAppPreferences(backup.backupPreferences)
|
|
|
+
|
|
|
+ ensureActive()
|
|
|
restoreSourcePreferences(backup.backupSourcePreferences)
|
|
|
|
|
|
// Restore individual manga
|
|
|
backup.backupManga.forEach {
|
|
|
- if (!isActive) {
|
|
|
- return@coroutineScope false
|
|
|
- }
|
|
|
-
|
|
|
+ ensureActive()
|
|
|
restoreManga(it, backup.backupCategories, sync)
|
|
|
}
|
|
|
- // TODO: optionally trigger online library + tracker update
|
|
|
|
|
|
- true
|
|
|
+ // TODO: optionally trigger online library + tracker update
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private suspend fun restoreCategories(backupCategories: List<BackupCategory>) {
|
|
|
- // Get categories from file and from db
|
|
|
- val dbCategories = getCategories.await()
|
|
|
-
|
|
|
- val categories = backupCategories.map {
|
|
|
- var category = it.getCategory()
|
|
|
- var found = false
|
|
|
- for (dbCategory in dbCategories) {
|
|
|
- // If the category is already in the db, assign the id to the file's category
|
|
|
- // and do nothing
|
|
|
- if (category.name == dbCategory.name) {
|
|
|
- category = category.copy(id = dbCategory.id)
|
|
|
- found = true
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
- if (!found) {
|
|
|
- // Let the db assign the id
|
|
|
- val id = handler.awaitOneExecutable {
|
|
|
- categoriesQueries.insert(category.name, category.order, category.flags)
|
|
|
- categoriesQueries.selectLastInsertedRowId()
|
|
|
- }
|
|
|
- category = category.copy(id = id)
|
|
|
+ if (backupCategories.isNotEmpty()) {
|
|
|
+ val dbCategories = getCategories.await()
|
|
|
+ val dbCategoriesByName = dbCategories.associateBy { it.name }
|
|
|
+
|
|
|
+ val categories = backupCategories.map {
|
|
|
+ dbCategoriesByName[it.name]
|
|
|
+ ?: handler.awaitOneExecutable {
|
|
|
+ categoriesQueries.insert(it.name, it.order, it.flags)
|
|
|
+ categoriesQueries.selectLastInsertedRowId()
|
|
|
+ }.let { id -> it.toCategory(id) }
|
|
|
}
|
|
|
|
|
|
- category
|
|
|
+ libraryPreferences.categorizedDisplaySettings().set(
|
|
|
+ (dbCategories + categories)
|
|
|
+ .distinctBy { it.flags }
|
|
|
+ .size > 1,
|
|
|
+ )
|
|
|
}
|
|
|
|
|
|
- libraryPreferences.categorizedDisplaySettings().set(
|
|
|
- (dbCategories + categories)
|
|
|
- .distinctBy { it.flags }
|
|
|
- .size > 1,
|
|
|
- )
|
|
|
-
|
|
|
restoreProgress += 1
|
|
|
showRestoreProgress(
|
|
|
restoreProgress,
|