diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt index 812434abe..33b37b429 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt @@ -23,6 +23,7 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.* import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.getOrDefault +import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.util.syncChaptersWithSource @@ -41,6 +42,11 @@ class BackupManager(val context: Context, version: Int = CURRENT_VERSION) { */ internal val sourceManager: SourceManager by injectLazy() + /** + * Tracking manager + */ + internal val trackManager: TrackManager by injectLazy() + /** * Version of parser */ @@ -67,18 +73,16 @@ class BackupManager(val context: Context, version: Int = CURRENT_VERSION) { parser = initParser() } - private fun initParser(): Gson { - return when (version) { - 1 -> GsonBuilder().create() - 2 -> GsonBuilder() - .registerTypeAdapter(MangaTypeAdapter.build()) - .registerTypeHierarchyAdapter(ChapterTypeAdapter.build()) - .registerTypeAdapter(CategoryTypeAdapter.build()) - .registerTypeAdapter(HistoryTypeAdapter.build()) - .registerTypeHierarchyAdapter(TrackTypeAdapter.build()) - .create() - else -> throw Exception("Json version unknown") - } + private fun initParser(): Gson = when (version) { + 1 -> GsonBuilder().create() + 2 -> GsonBuilder() + .registerTypeAdapter(MangaTypeAdapter.build()) + .registerTypeHierarchyAdapter(ChapterTypeAdapter.build()) + .registerTypeAdapter(CategoryTypeAdapter.build()) + .registerTypeAdapter(HistoryTypeAdapter.build()) + .registerTypeHierarchyAdapter(TrackTypeAdapter.build()) + .create() + else -> throw Exception("Json version unknown") } /** @@ -300,23 +304,26 @@ class BackupManager(val context: Context, version: Int = CURRENT_VERSION) { val trackToUpdate = ArrayList() for (track in tracks) { - var isInDatabase = false - for (dbTrack in dbTracks) { - if (track.sync_id == dbTrack.sync_id) { - // The sync is already in the db, only update its fields - if (track.remote_id != dbTrack.remote_id) { - dbTrack.remote_id = track.remote_id + val service = trackManager.getService(track.sync_id) + if (service != null && service.isLogged) { + var isInDatabase = false + for (dbTrack in dbTracks) { + if (track.sync_id == dbTrack.sync_id) { + // The sync is already in the db, only update its fields + if (track.remote_id != dbTrack.remote_id) { + dbTrack.remote_id = track.remote_id + } + dbTrack.last_chapter_read = Math.max(dbTrack.last_chapter_read, track.last_chapter_read) + isInDatabase = true + trackToUpdate.add(dbTrack) + break } - dbTrack.last_chapter_read = Math.max(dbTrack.last_chapter_read, track.last_chapter_read) - isInDatabase = true - trackToUpdate.add(dbTrack) - break } - } - if (!isInDatabase) { - // Insert new sync. Let the db assign the id - track.id = null - trackToUpdate.add(track) + if (!isInDatabase) { + // Insert new sync. Let the db assign the id + track.id = null + trackToUpdate.add(track) + } } } // Update database @@ -361,32 +368,29 @@ class BackupManager(val context: Context, version: Int = CURRENT_VERSION) { * * @return [Manga], null if not found */ - internal fun getMangaFromDatabase(manga: Manga): Manga? { - return databaseHelper.getManga(manga.url, manga.source).executeAsBlocking() - } + internal fun getMangaFromDatabase(manga: Manga): Manga? = + databaseHelper.getManga(manga.url, manga.source).executeAsBlocking() /** * Returns list containing manga from library * * @return [Manga] from library */ - internal fun getFavoriteManga(): List { - return databaseHelper.getFavoriteMangas().executeAsBlocking() - } + internal fun getFavoriteManga(): List = + databaseHelper.getFavoriteMangas().executeAsBlocking() /** * Inserts manga and returns id * * @return id of [Manga], null if not found */ - internal fun insertManga(manga: Manga): Long? { - return databaseHelper.insertManga(manga).executeAsBlocking().insertedId() - } + internal fun insertManga(manga: Manga): Long? = + databaseHelper.insertManga(manga).executeAsBlocking().insertedId() /** * Inserts list of chapters */ - internal fun insertChapters(chapters: List) { + private fun insertChapters(chapters: List) { databaseHelper.updateChaptersBackup(chapters).executeAsBlocking() } @@ -395,7 +399,5 @@ class BackupManager(val context: Context, version: Int = CURRENT_VERSION) { * * @return number of backups selected by user */ - fun numberOfBackups(): Int { - return preferences.numberOfBackups().getOrDefault() - } + fun numberOfBackups(): Int = preferences.numberOfBackups().getOrDefault() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt index 9b3bf8906..5ab30ab5b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt @@ -21,6 +21,7 @@ import eu.kanade.tachiyomi.data.backup.models.Backup.VERSION import eu.kanade.tachiyomi.data.backup.models.DHistory import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.* +import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.util.chop import eu.kanade.tachiyomi.util.isServiceRunning @@ -49,9 +50,8 @@ class BackupRestoreService : Service() { * @param context the application context. * @return true if the service is running, false otherwise. */ - fun isRunning(context: Context): Boolean { - return context.isServiceRunning(BackupRestoreService::class.java) - } + private fun isRunning(context: Context): Boolean = + context.isServiceRunning(BackupRestoreService::class.java) /** * Starts a service to restore a backup from Json @@ -113,7 +113,13 @@ class BackupRestoreService : Service() { */ private val db: DatabaseHelper by injectLazy() - lateinit var executor: ExecutorService + /** + * Tracking manager + */ + internal val trackManager: TrackManager by injectLazy() + + + private lateinit var executor: ExecutorService /** * Method called when the service is created. It injects dependencies and acquire the wake lock. @@ -142,9 +148,7 @@ class BackupRestoreService : Service() { /** * This method needs to be implemented, but it's not used/needed. */ - override fun onBind(intent: Intent): IBinder? { - return null - } + override fun onBind(intent: Intent): IBinder? = null /** * Method called when the service receives an intent. @@ -164,7 +168,7 @@ class BackupRestoreService : Service() { subscription = Observable.using( { db.lowLevel().beginTransaction() }, - { getRestoreObservable(uri).doOnNext{ db.lowLevel().setTransactionSuccessful() } }, + { getRestoreObservable(uri).doOnNext { db.lowLevel().setTransactionSuccessful() } }, { executor.execute { db.lowLevel().endTransaction() } }) .doAfterTerminate { stopSelf(startId) } .subscribeOn(Schedulers.from(executor)) @@ -294,14 +298,14 @@ class BackupRestoreService : Service() { val source = backupManager.sourceManager.get(manga.source) ?: return null val dbManga = backupManager.getMangaFromDatabase(manga) - if (dbManga == null) { + return if (dbManga == null) { // Manga not in database - return mangaFetchObservable(source, manga, chapters, categories, history, tracks) + mangaFetchObservable(source, manga, chapters, categories, history, tracks) } else { // Manga in database // Copy information from manga already in database backupManager.restoreMangaNoFetch(manga, dbManga) // Fetch rest of manga information - return mangaNoFetchObservable(source, manga, chapters, categories, history, tracks) + mangaNoFetchObservable(source, manga, chapters, categories, history, tracks) } } @@ -327,14 +331,12 @@ class BackupRestoreService : Service() { .map { manga } } .doOnNext { - // Restore categories - backupManager.restoreCategoriesForManga(it, categories) - - // Restore history - backupManager.restoreHistoryForManga(history) - - // Restore tracking - backupManager.restoreTrackForManga(it, tracks) + restoreExtraForManga(it, categories, history, tracks) + } + .flatMap { + trackingFetchObservable(it, tracks) + // Convert to the manga that contains new chapters. + .map { manga } } .doOnCompleted { restoreProgress += 1 @@ -356,14 +358,12 @@ class BackupRestoreService : Service() { } } .doOnNext { - // Restore categories - backupManager.restoreCategoriesForManga(it, categories) - - // Restore history - backupManager.restoreHistoryForManga(history) - - // Restore tracking - backupManager.restoreTrackForManga(it, tracks) + restoreExtraForManga(it, categories, history, tracks) + } + .flatMap { manga -> + trackingFetchObservable(manga, tracks) + // Convert to the manga that contains new chapters. + .map { manga } } .doOnCompleted { restoreProgress += 1 @@ -371,6 +371,17 @@ class BackupRestoreService : Service() { } } + private fun restoreExtraForManga(manga: Manga, categories: List, history: List, tracks: List) { + // Restore categories + backupManager.restoreCategoriesForManga(manga, categories) + + // Restore history + backupManager.restoreHistoryForManga(history) + + // Restore tracking + backupManager.restoreTrackForManga(manga, tracks) + } + /** * [Observable] that fetches chapter information * @@ -383,10 +394,33 @@ class BackupRestoreService : Service() { // If there's any error, return empty update and continue. .onErrorReturn { errors.add(Date() to "${manga.title} - ${it.message}") - Pair(emptyList(), emptyList()) + Pair(emptyList(), emptyList()) } } + /** + * [Observable] that refreshes tracking information + * @param manga manga that needs updating. + * @param tracks list containing tracks from restore file. + * @return [Observable] that contains updated track item + */ + private fun trackingFetchObservable(manga: Manga, tracks: List): Observable { + return Observable.from(tracks) + .concatMap { track -> + val service = trackManager.getService(track.sync_id) + if (service != null && service.isLogged) { + service.refresh(track) + .doOnNext { db.insertTrack(it).executeAsBlocking() } + .onErrorReturn { + errors.add(Date() to "${manga.title} - ${it.message}") + track + } + } else { + errors.add(Date() to "${manga.title} - ${service?.name} not logged in") + Observable.empty() + } + } + } /** * Called to update dialog in [BackupConst] diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index c614a97d2..a8d4907e1 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -201,7 +201,7 @@ Backup wird wiederhergestellt %1$s zur Bibliothek hinzugefĆ¼gt Quelle nicht gefunden - Backup wird wiederhergestellt %1%s + Backup wird wiederhergestellt %1$s \nQuelle nicht gefunden Backup erstellt Wiederherstellen erfolgreich