Fix: Exclude categories when delete read chapter, except manually deleting (#611)

* fix: exclude categories to delete chapter when mark as read

* Revert "Auxiliary commit to revert individual files from 3d3bbb7e4d56010af5bbec8a7c353da220d1f8d3"

This reverts commit d2db2fb1e3eb9b0b15958722a8d4e3cfd91efc2c.

* ignore category exclusion when manually delete downloaded chapters

* fix: properly ignore categories exclusion when manual delete

* also ignore bookmark chapter if manually delete single chapter
This commit is contained in:
Cuong-Tran 2024-12-31 11:29:35 +07:00 committed by GitHub
parent 8c4b43c5aa
commit 468529cd47
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 105 additions and 18 deletions

View file

@ -1,6 +1,11 @@
package eu.kanade.domain.chapter.interactor
import eu.kanade.domain.download.interactor.DeleteDownload
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.ui.library.LibraryScreenModel
import eu.kanade.tachiyomi.ui.manga.MangaScreenModel
import eu.kanade.tachiyomi.ui.reader.ReaderViewModel
import eu.kanade.tachiyomi.ui.updates.UpdatesScreenModel
import exh.source.MERGED_SOURCE_ID
import logcat.LogPriority
import tachiyomi.core.common.util.lang.withNonCancellableContext
@ -31,7 +36,26 @@ class SetReadStatus(
)
}
suspend fun await(read: Boolean, vararg chapters: Chapter): Result = withNonCancellableContext {
/**
* Mark chapters as read/unread, also delete downloaded chapters if 'After manually marked as read' is set.
*
* Called from:
* - [LibraryScreenModel]: Manually select mangas & mark as read
* - [MangaScreenModel.markChaptersRead]: Manually select chapters & mark as read or swipe chapter as read
* - [UpdatesScreenModel.markUpdatesRead]: Manually select chapters & mark as read
* - [LibraryUpdateJob.updateChapterList]: when a manga is updated and has new chapter but already read,
* it will mark that new **duplicated** chapter as read & delete downloading/downloaded -> should be treat as
* automatically ~ no auto delete
* - [ReaderViewModel.updateChapterProgress]: mark **duplicated** chapter as read after finish reading -> should be
* treated as not manually mark as read so not auto-delete (there are cases where chapter number is mistaken by volume number)
*/
suspend fun await(
read: Boolean,
vararg chapters: Chapter,
// KMK -->
manually: Boolean = true,
// KMK <--
): Result = withNonCancellableContext {
val chaptersToUpdate = chapters.filter {
when (read) {
true -> !it.read
@ -51,8 +75,17 @@ class SetReadStatus(
return@withNonCancellableContext Result.InternalError(e)
}
if (read && downloadPreferences.removeAfterMarkedAsRead().get()) {
if (
// KMK -->
manually &&
// KMK <--
read &&
downloadPreferences.removeAfterMarkedAsRead().get()
) {
chaptersToUpdate
// KMK -->
.map { it.copy(read = true) } // mark as read so it will respect category exclusion
// KMK <--
.groupBy { it.mangaId }
.forEach { (mangaId, chapters) ->
deleteDownload.awaitAll(

View file

@ -229,9 +229,23 @@ class DownloadManager(
* @param manga the manga of the chapters.
* @param source the source of the chapters.
*/
fun deleteChapters(chapters: List<Chapter>, manga: Manga, source: Source) {
fun deleteChapters(
chapters: List<Chapter>,
manga: Manga,
source: Source,
// KMK -->
/** Ignore categories exclusion */
ignoreCategoryExclusion: Boolean = false,
// KMK <--
) {
launchIO {
val filteredChapters = getChaptersToDelete(chapters, manga)
val filteredChapters = getChaptersToDelete(
chapters,
manga,
// KMK -->
ignoreCategoryExclusion,
// KMK <--
)
if (filteredChapters.isEmpty()) {
return@launchIO
}
@ -427,20 +441,38 @@ class DownloadManager(
}
}
private suspend fun getChaptersToDelete(chapters: List<Chapter>, manga: Manga): List<Chapter> {
// Retrieve the categories that are set to exclude from being deleted on read
val categoriesToExclude = downloadPreferences.removeExcludeCategories().get().map(String::toLong)
val categoriesForManga = getCategories.await(manga.id)
.map { it.id }
.ifEmpty { listOf(0) }
val filteredCategoryManga = if (categoriesForManga.intersect(categoriesToExclude).isNotEmpty()) {
chapters.filterNot { it.read }
} else {
private suspend fun getChaptersToDelete(
chapters: List<Chapter>,
manga: Manga,
// KMK -->
/** Ignore categories exclusion */
ignoreCategoryExclusion: Boolean = false,
// KMK <--
): List<Chapter> {
// KMK -->
val filteredCategoryManga = if (ignoreCategoryExclusion) {
chapters
} else {
// KMK <--
// Retrieve the categories that are set to exclude from being deleted on read
val categoriesToExclude = downloadPreferences.removeExcludeCategories().get().map(String::toLong).toSet()
val categoriesForManga = getCategories.await(manga.id)
.map { it.id }
.ifEmpty { listOf(0) }
if (categoriesForManga.intersect(categoriesToExclude).isNotEmpty()) {
chapters.filterNot { it.read }
} else {
chapters
}
}
return if (!downloadPreferences.removeBookmarkedChapters().get()) {
return if (!downloadPreferences.removeBookmarkedChapters().get() &&
// KMK -->
// if manually deleting single chapter then will allow deleting bookmark chapter
(chapters.size > 1 || !ignoreCategoryExclusion)
// KMK <--
) {
filteredCategoryManga.filterNot { it.bookmark }
} else {
filteredCategoryManga

View file

@ -438,7 +438,13 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
}
if (newReadChapters.isNotEmpty()) {
setReadStatus.await(true, *newReadChapters.toTypedArray())
setReadStatus.await(
true,
*newReadChapters.toTypedArray(),
// KMK -->
manually = false,
// KMK <--
)
}
this.filterNot { newReadChapters.contains(it) }

View file

@ -1418,6 +1418,9 @@ class MangaScreenModel(
chapters,
state.manga,
state.source,
// KMK -->
ignoreCategoryExclusion = true,
// KMK <--
)
}
} catch (e: Throwable) {

View file

@ -709,7 +709,13 @@ class ReaderViewModel @JvmOverloads constructor(
}
.ifEmpty { null }
?.also {
setReadStatus.await(true, *it.toTypedArray())
setReadStatus.await(
true,
*it.toTypedArray(),
// KMK -->
manually = false,
// KMK <--
)
it.forEach { chapter ->
deleteChapterIfNeeded(ReaderChapter(chapter))
}

View file

@ -265,7 +265,14 @@ class UpdatesScreenModel(
val manga = getManga.await(mangaId) ?: return@forEach
val source = sourceManager.get(manga.source) ?: return@forEach
val chapters = updates.mapNotNull { getChapter.await(it.update.chapterId) }
downloadManager.deleteChapters(chapters, manga, source)
downloadManager.deleteChapters(
chapters,
manga,
source,
// KMK -->
ignoreCategoryExclusion = true,
// KMK <--
)
}
}
toggleAllSelection(false)