diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreJob.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreJob.kt index 202072859..e4595a4b5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreJob.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreJob.kt @@ -26,8 +26,6 @@ class BackupRestoreJob(private val context: Context, workerParams: WorkerParamet private val notifier = BackupNotifier(context) override suspend fun doWork(): Result { - if (isRunning(context)) return Result.failure() - val uri = inputData.getString(LOCATION_URI_KEY)?.toUri() ?: return Result.failure() val sync = inputData.getBoolean(SYNC_KEY, false) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestorer.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestorer.kt index 3eb9daac2..499165ab8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestorer.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestorer.kt @@ -27,7 +27,7 @@ import exh.EXHMigrations import exh.source.MERGED_SOURCE_ID import exh.util.nullIfBlank 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 @@ -93,14 +93,12 @@ class BackupRestorer( private val errors = mutableListOf>() - 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 @@ -118,7 +116,6 @@ class BackupRestorer( } else { notifier.showRestoreComplete(time, errors.size, logFile.parent, logFile.name) } - return true } private fun writeErrorLog(): File { @@ -140,81 +137,62 @@ 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 + 4 // +4 for categories, app prefs, source prefs, saved searches - // Restore categories - if (backup.backupCategories.isNotEmpty()) { - restoreCategories(backup.backupCategories) - } - - // SY --> - if (backup.backupSavedSearches.isNotEmpty()) { - restoreSavedSearches(backup.backupSavedSearches) - } - // SY <-- - // 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) + + // SY --> + ensureActive() + restoreSavedSearches(backup.backupSavedSearches) + // SY <-- + + ensureActive() restoreAppPreferences(backup.backupPreferences) + + ensureActive() restoreSourcePreferences(backup.backupSourcePreferences) - // Restore individual manga, sort by merged source so that merged source manga go last and merged references get the proper ids - backup.backupManga /* SY --> */.sortedBy { it.source == MERGED_SOURCE_ID } /* SY <-- */.forEach { - if (!isActive) { - return@coroutineScope false - } - + // Restore individual manga + backup.backupManga/* SY --> */.sortedBy { it.source == MERGED_SOURCE_ID } /* SY <-- */.forEach { + ensureActive() restoreManga(it, backup.backupCategories, sync) } // TODO: optionally trigger online library + tracker update - - true } } private suspend fun restoreCategories(backupCategories: List) { - // Get categories from file and from db - val dbCategories = getCategories.await() + if (backupCategories.isNotEmpty()) { + val dbCategories = getCategories.await() + val dbCategoriesByName = dbCategories.associateBy { it.name } - 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) + 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, @@ -226,6 +204,8 @@ class BackupRestorer( // SY --> private suspend fun restoreSavedSearches(backupSavedSearches: List) { + if (backupSavedSearches.isEmpty()) return + val currentSavedSearches = handler.awaitList { saved_searchQueries.selectNamesAndSources() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/models/BackupCategory.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/models/BackupCategory.kt index 2d412bb10..eb5dd0833 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/models/BackupCategory.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/models/BackupCategory.kt @@ -13,15 +13,13 @@ class BackupCategory( // SY specific values /*@ProtoNumber(600) var mangaOrder: List = emptyList(),*/ ) { - fun getCategory(): Category { - return Category( - id = 0, - name = this@BackupCategory.name, - flags = this@BackupCategory.flags, - order = this@BackupCategory.order, - /*mangaOrder = this@BackupCategory.mangaOrder*/ - ) - } + fun toCategory(id: Long) = Category( + id = id, + name = this@BackupCategory.name, + flags = this@BackupCategory.flags, + order = this@BackupCategory.order, + /*mangaOrder = this@BackupCategory.mangaOrder*/ + ) } val backupCategoryMapper = { category: Category ->