|
@@ -186,7 +186,40 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
|
|
.distinctBy { it.manga.id }
|
|
|
}
|
|
|
|
|
|
+ val restrictions = libraryPreferences.autoUpdateMangaRestrictions().get()
|
|
|
+ val skippedUpdates = mutableListOf<Pair<Manga, String?>>()
|
|
|
+ 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<Manga>()
|
|
|
val newUpdates = CopyOnWriteArrayList<Pair<Manga, Array<Chapter>>>()
|
|
|
- val skippedUpdates = CopyOnWriteArrayList<Pair<Manga, String?>>()
|
|
|
val failedUpdates = CopyOnWriteArrayList<Pair<Manga, String?>>()
|
|
|
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))
|
|
|
-
|
|
|
- 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)
|
|
|
+ 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 (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<Chapter>) {
|
|
@@ -428,29 +441,27 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
|
|
completed: AtomicInteger,
|
|
|
manga: Manga,
|
|
|
block: suspend () -> Unit,
|
|
|
- ) {
|
|
|
- coroutineScope {
|
|
|
- ensureActive()
|
|
|
-
|
|
|
- updatingManga.add(manga)
|
|
|
- notifier.showProgressNotification(
|
|
|
- updatingManga,
|
|
|
- completed.get(),
|
|
|
- mangaToUpdate.size,
|
|
|
- )
|
|
|
+ ) = coroutineScope {
|
|
|
+ ensureActive()
|
|
|
+
|
|
|
+ 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,
|
|
|
+ )
|
|
|
}
|
|
|
|
|
|
/**
|