From 7ed99fbbd61bd6748573b1c5463f3c552de8832d Mon Sep 17 00:00:00 2001 From: arkon Date: Sun, 8 Oct 2023 16:40:17 -0400 Subject: [PATCH] Account for skipped entries when showing large updates warning Closes #6159 --- .../data/library/LibraryUpdateJob.kt | 153 ++++++++++-------- .../data/library/LibraryUpdateNotifier.kt | 6 +- i18n/src/main/res/values/strings.xml | 2 +- 3 files changed, 88 insertions(+), 73 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt index 734b5180c..651858332 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt @@ -186,7 +186,40 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet .distinctBy { it.manga.id } } + val restrictions = libraryPreferences.autoUpdateMangaRestrictions().get() + val skippedUpdates = mutableListOf>() + val fetchWindow = fetchInterval.getWindow(ZonedDateTime.now()) + mangaToUpdate = listToUpdate + .filter { + when { + it.manga.updateStrategy != UpdateStrategy.ALWAYS_UPDATE -> { + skippedUpdates.add(it.manga to context.getString(R.string.skipped_reason_not_always_update)) + false + } + + MANGA_NON_COMPLETED in restrictions && it.manga.status.toInt() == SManga.COMPLETED -> { + skippedUpdates.add(it.manga to context.getString(R.string.skipped_reason_completed)) + false + } + + MANGA_HAS_UNREAD in restrictions && it.unreadCount != 0L -> { + skippedUpdates.add(it.manga to context.getString(R.string.skipped_reason_not_caught_up)) + false + } + + MANGA_NON_READ in restrictions && it.totalChapters > 0L && !it.hasStarted -> { + skippedUpdates.add(it.manga to context.getString(R.string.skipped_reason_not_started)) + false + } + + MANGA_OUTSIDE_RELEASE_PERIOD in restrictions && it.manga.nextUpdate > fetchWindow.second -> { + skippedUpdates.add(it.manga to context.getString(R.string.skipped_reason_not_in_release_period)) + false + } + else -> true + } + } .sortedBy { it.manga.title } // Warn when excessively checking a single source @@ -197,6 +230,17 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet if (maxUpdatesFromSource > MANGA_PER_SOURCE_QUEUE_WARNING_THRESHOLD) { notifier.showQueueSizeWarningNotification() } + + if (skippedUpdates.isNotEmpty()) { + // TODO: surface skipped reasons to user? + logcat { + skippedUpdates + .groupBy { it.second } + .map { (reason, entries) -> "$reason: [${entries.map { it.first.title }.sorted().joinToString()}]" } + .joinToString() + } + notifier.showUpdateSkippedNotification(skippedUpdates.size) + } } /** @@ -212,10 +256,8 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet val progressCount = AtomicInteger(0) val currentlyUpdatingManga = CopyOnWriteArrayList() val newUpdates = CopyOnWriteArrayList>>() - val skippedUpdates = CopyOnWriteArrayList>() val failedUpdates = CopyOnWriteArrayList>() val hasDownloads = AtomicBoolean(false) - val restrictions = libraryPreferences.autoUpdateMangaRestrictions().get() val fetchWindow = fetchInterval.getWindow(ZonedDateTime.now()) coroutineScope { @@ -237,49 +279,30 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet progressCount, manga, ) { - when { - manga.updateStrategy != UpdateStrategy.ALWAYS_UPDATE -> - skippedUpdates.add(manga to context.getString(R.string.skipped_reason_not_always_update)) + try { + val newChapters = updateManga(manga, fetchWindow) + .sortedByDescending { it.sourceOrder } - MANGA_NON_COMPLETED in restrictions && manga.status.toInt() == SManga.COMPLETED -> - skippedUpdates.add(manga to context.getString(R.string.skipped_reason_completed)) - - MANGA_HAS_UNREAD in restrictions && libraryManga.unreadCount != 0L -> - skippedUpdates.add(manga to context.getString(R.string.skipped_reason_not_caught_up)) - - MANGA_NON_READ in restrictions && libraryManga.totalChapters > 0L && !libraryManga.hasStarted -> - skippedUpdates.add(manga to context.getString(R.string.skipped_reason_not_started)) - - MANGA_OUTSIDE_RELEASE_PERIOD in restrictions && manga.nextUpdate > fetchWindow.second -> - skippedUpdates.add(manga to context.getString(R.string.skipped_reason_not_in_release_period)) - - else -> { - try { - val newChapters = updateManga(manga, fetchWindow) - .sortedByDescending { it.sourceOrder } - - if (newChapters.isNotEmpty()) { - val categoryIds = getCategories.await(manga.id).map { it.id } - if (manga.shouldDownloadNewChapters(categoryIds, downloadPreferences)) { - downloadChapters(manga, newChapters) - hasDownloads.set(true) - } - - libraryPreferences.newUpdatesCount().getAndSet { it + newChapters.size } - - // Convert to the manga that contains new chapters - newUpdates.add(manga to newChapters.toTypedArray()) - } - } catch (e: Throwable) { - val errorMessage = when (e) { - is NoChaptersException -> context.getString(R.string.no_chapters_error) - // failedUpdates will already have the source, don't need to copy it into the message - is SourceNotInstalledException -> context.getString(R.string.loader_not_implemented_error) - else -> e.message - } - failedUpdates.add(manga to errorMessage) + if (newChapters.isNotEmpty()) { + val categoryIds = getCategories.await(manga.id).map { it.id } + if (manga.shouldDownloadNewChapters(categoryIds, downloadPreferences)) { + downloadChapters(manga, newChapters) + hasDownloads.set(true) } + + libraryPreferences.newUpdatesCount().getAndSet { it + newChapters.size } + + // Convert to the manga that contains new chapters + newUpdates.add(manga to newChapters.toTypedArray()) } + } catch (e: Throwable) { + val errorMessage = when (e) { + is NoChaptersException -> context.getString(R.string.no_chapters_error) + // failedUpdates will already have the source, don't need to copy it into the message + is SourceNotInstalledException -> context.getString(R.string.loader_not_implemented_error) + else -> e.message + } + failedUpdates.add(manga to errorMessage) } if (libraryPreferences.autoUpdateTrackers().get()) { @@ -309,16 +332,6 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet errorFile.getUriCompat(context), ) } - if (skippedUpdates.isNotEmpty()) { - // TODO: surface skipped reasons to user - logcat { - skippedUpdates - .groupBy { it.second } - .map { (reason, entries) -> "$reason: [${entries.map { it.first.title }.sorted().joinToString()}]" } - .joinToString() - } - notifier.showUpdateSkippedNotification(skippedUpdates.size) - } } private fun downloadChapters(manga: Manga, chapters: List) { @@ -428,29 +441,27 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet completed: AtomicInteger, manga: Manga, block: suspend () -> Unit, - ) { - coroutineScope { - ensureActive() + ) = coroutineScope { + ensureActive() - updatingManga.add(manga) - notifier.showProgressNotification( - updatingManga, - completed.get(), - mangaToUpdate.size, - ) + updatingManga.add(manga) + notifier.showProgressNotification( + updatingManga, + completed.get(), + mangaToUpdate.size, + ) - block() + block() - ensureActive() + ensureActive() - updatingManga.remove(manga) - completed.getAndIncrement() - notifier.showProgressNotification( - updatingManga, - completed.get(), - mangaToUpdate.size, - ) - } + updatingManga.remove(manga) + completed.getAndIncrement() + notifier.showProgressNotification( + updatingManga, + completed.get(), + mangaToUpdate.size, + ) } /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt index 299889b8c..833680ba4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt @@ -30,10 +30,14 @@ import tachiyomi.core.util.lang.launchUI import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.manga.model.Manga import uy.kohesive.injekt.injectLazy +import java.text.NumberFormat class LibraryUpdateNotifier(private val context: Context) { private val preferences: SecurityPreferences by injectLazy() + private val percentFormatter = NumberFormat.getPercentInstance().apply { + maximumFractionDigits = 0 + } /** * Pending intent of action that cancels the library update @@ -78,7 +82,7 @@ class LibraryUpdateNotifier(private val context: Context) { } else { val updatingText = manga.joinToString("\n") { it.title.chop(40) } progressNotificationBuilder - .setContentTitle(context.getString(R.string.notification_updating, current, total)) + .setContentTitle(context.getString(R.string.notification_updating_progress, percentFormatter.format(current.toFloat() / total))) .setStyle(NotificationCompat.BigTextStyle().bigText(updatingText)) } diff --git a/i18n/src/main/res/values/strings.xml b/i18n/src/main/res/values/strings.xml index 612567f3f..bb2918baa 100644 --- a/i18n/src/main/res/values/strings.xml +++ b/i18n/src/main/res/values/strings.xml @@ -837,7 +837,7 @@ Checking for new chapters - Updating library… (%1$d/%2$d) + Updating library… (%s) Large updates harm sources and may lead to slower updates and also increased battery usage. Tap to learn more. New chapters found