diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt index 6a1cbf2b3b..5410191ca4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt @@ -71,6 +71,7 @@ class LibraryUpdateService( private lateinit var notifier: LibraryUpdateNotifier private lateinit var ioScope: CoroutineScope + private var mangaToUpdate: List = mutableListOf() private var updateJob: Job? = null /** @@ -86,6 +87,8 @@ class LibraryUpdateService( companion object { + private var instance: LibraryUpdateService? = null + /** * Key for category to update. */ @@ -116,17 +119,18 @@ class LibraryUpdateService( * @return true if service newly started, false otherwise */ fun start(context: Context, category: Category? = null, target: Target = Target.CHAPTERS): Boolean { - if (!isRunning(context)) { + return if (!isRunning(context)) { val intent = Intent(context, LibraryUpdateService::class.java).apply { putExtra(KEY_TARGET, target) category?.let { putExtra(KEY_CATEGORY, it.id) } } ContextCompat.startForegroundService(context, intent) - return true + true + } else { + instance?.addMangaToQueue(category?.id ?: -1, target) + false } - - return false } /** @@ -163,6 +167,9 @@ class LibraryUpdateService( if (wakeLock.isHeld) { wakeLock.release() } + if (instance == this) { + instance = null + } super.onDestroy() } @@ -186,23 +193,25 @@ class LibraryUpdateService( val target = intent.getSerializableExtra(KEY_TARGET) as? Target ?: return START_NOT_STICKY - // Unsubscribe from any previous subscription if needed. + instance = this + + // Unsubscribe from any previous subscription if needed updateJob?.cancel() - // Update favorite manga. Destroy service when completed or in case of an error. - val selectedScheme = preferences.libraryUpdatePrioritization().get() - val mangaList = getMangaToUpdate(intent, target) - .sortedWith(rankingScheme[selectedScheme]) + // Update favorite manga + val categoryId = intent.getIntExtra(KEY_CATEGORY, -1) + addMangaToQueue(categoryId, target) + // Destroy service when completed or in case of an error. val handler = CoroutineExceptionHandler { _, exception -> Timber.e(exception) stopSelf(startId) } updateJob = ioScope.launch(handler) { when (target) { - Target.CHAPTERS -> updateChapterList(mangaList) - Target.COVERS -> updateCovers(mangaList) - Target.TRACKING -> updateTrackings(mangaList) + Target.CHAPTERS -> updateChapterList() + Target.COVERS -> updateCovers() + Target.TRACKING -> updateTrackings() } } updateJob?.invokeOnCompletion { stopSelf(startId) } @@ -211,32 +220,32 @@ class LibraryUpdateService( } /** - * Returns the list of manga to be updated. + * Adds list of manga to be updated. * - * @param intent the update intent. + * @param category the ID of the category to update, or -1 if no category specified. * @param target the target to update. - * @return a list of manga to update */ - fun getMangaToUpdate(intent: Intent, target: Target): List { - val categoryId = intent.getIntExtra(KEY_CATEGORY, -1) + fun addMangaToQueue(categoryId: Int, target: Target) { + val libraryManga = db.getLibraryMangas().executeAsBlocking() var listToUpdate = if (categoryId != -1) { - db.getLibraryMangas().executeAsBlocking().filter { it.category == categoryId } + libraryManga.filter { it.category == categoryId } } else { val categoriesToUpdate = preferences.libraryUpdateCategories().get().map(String::toInt) if (categoriesToUpdate.isNotEmpty()) { - db.getLibraryMangas().executeAsBlocking() - .filter { it.category in categoriesToUpdate } - .distinctBy { it.id } + libraryManga.filter { it.category in categoriesToUpdate } } else { - db.getLibraryMangas().executeAsBlocking().distinctBy { it.id } + libraryManga } } if (target == Target.CHAPTERS && preferences.updateOnlyNonCompleted()) { - listToUpdate = listToUpdate.filter { it.status != SManga.COMPLETED } + listToUpdate = listToUpdate.filterNot { it.status == SManga.COMPLETED } } - return listToUpdate + val selectedScheme = preferences.libraryUpdatePrioritization().get() + mangaToUpdate = listToUpdate + .distinctBy { it.id } + .sortedWith(rankingScheme[selectedScheme]) } /** @@ -248,7 +257,7 @@ class LibraryUpdateService( * @param mangaToUpdate the list to update * @return an observable delivering the progress of each update. */ - suspend fun updateChapterList(mangaToUpdate: List) { + suspend fun updateChapterList() { val progressCount = AtomicInteger(0) val newUpdates = mutableListOf>>() val failedUpdates = mutableListOf>() @@ -342,7 +351,7 @@ class LibraryUpdateService( return syncChaptersWithSource(db, chapters, manga, source) } - private suspend fun updateCovers(mangaToUpdate: List) { + private suspend fun updateCovers() { var progressCount = 0 mangaToUpdate.forEach { manga -> @@ -375,7 +384,7 @@ class LibraryUpdateService( * Method that updates the metadata of the connected tracking services. It's called in a * background thread, so it's safe to do heavy operations or network calls here. */ - private suspend fun updateTrackings(mangaToUpdate: List) { + private suspend fun updateTrackings() { var progressCount = 0 val loggedServices = trackManager.services.filter { it.isLogged } diff --git a/app/src/test/java/eu/kanade/tachiyomi/data/library/LibraryUpdateServiceTest.kt b/app/src/test/java/eu/kanade/tachiyomi/data/library/LibraryUpdateServiceTest.kt index 20483c0730..7bed711c89 100644 --- a/app/src/test/java/eu/kanade/tachiyomi/data/library/LibraryUpdateServiceTest.kt +++ b/app/src/test/java/eu/kanade/tachiyomi/data/library/LibraryUpdateServiceTest.kt @@ -100,7 +100,8 @@ class LibraryUpdateServiceTest { val intent = Intent() val target = LibraryUpdateService.Target.CHAPTERS runBlocking { - service.updateChapterList(service.getMangaToUpdate(intent, target)) + service.addMangaToQueue(intent, target) + service.updateChapterList() // There are 3 network attempts and 2 insertions (1 request failed) assertThat(service.db.getChapters(favManga[0]).executeAsBlocking()).hasSize(2)