From 5a5b86d3c6806f91f41991f1977ae9261c0ab8cd Mon Sep 17 00:00:00 2001 From: AntsyLich <59261191+AntsyLich@users.noreply.github.com> Date: Thu, 27 Feb 2025 23:32:51 +0600 Subject: [PATCH] Add option to mark new duplicate read chapters as read (mihonapp/mihon#1785) (cherry picked from commit cd0481592c09dc9cfb331805e90e6e5c3752a08c) --- CHANGELOG.md | 1 + .../java/eu/kanade/domain/DomainModule.kt | 2 +- .../interactor/SyncChaptersWithSource.kt | 31 +++++++++++------ .../settings/screen/SettingsLibraryScreen.kt | 7 ++-- .../data/library/LibraryUpdateJob.kt | 34 +------------------ .../library/service/LibraryPreferences.kt | 4 +-- .../moko-resources/base/strings.xml | 1 + 7 files changed, 29 insertions(+), 51 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a1465397..716f9c0e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co - Add private tracking support for Kitsu ([@MajorTanya](https://github.com/MajorTanya)) ([#1774](https://github.com/mihonapp/mihon/pull/1774)) - Add option to export minimal library information to a CSV file ([@Animeboynz](https://github.com/Animeboynz), [@AntsyLich](https://github.com/AntsyLich)) ([#1161](https://github.com/mihonapp/mihon/pull/1161)) - Add back support for drag-and-drop category reordering ([@cuong-tran](https://github.com/cuong-tran)) ([#1427](https://github.com/mihonapp/mihon/pull/1427)) +- Add option to mark new duplicate read chapters as read ### Changed - Apply "Downloaded only" filter to all entries regardless of favourite status ([@NGB-Was-Taken](https://github.com/NGB-Was-Taken)) ([#1603](https://github.com/mihonapp/mihon/pull/1603)) diff --git a/app/src/main/java/eu/kanade/domain/DomainModule.kt b/app/src/main/java/eu/kanade/domain/DomainModule.kt index 8d230117d..f36673aa2 100644 --- a/app/src/main/java/eu/kanade/domain/DomainModule.kt +++ b/app/src/main/java/eu/kanade/domain/DomainModule.kt @@ -157,7 +157,7 @@ class DomainModule : InjektModule { addFactory { UpdateChapter(get()) } addFactory { SetReadStatus(get(), get(), get(), get(), get()) } addFactory { ShouldUpdateDbChapter() } - addFactory { SyncChaptersWithSource(get(), get(), get(), get(), get(), get(), get(), get()) } + addFactory { SyncChaptersWithSource(get(), get(), get(), get(), get(), get(), get(), get(), get()) } addFactory { GetAvailableScanlators(get()) } addFactory { FilterChaptersForDownload(get(), get(), get(), get()) } diff --git a/app/src/main/java/eu/kanade/domain/chapter/interactor/SyncChaptersWithSource.kt b/app/src/main/java/eu/kanade/domain/chapter/interactor/SyncChaptersWithSource.kt index d4feb7c8b..01273526a 100644 --- a/app/src/main/java/eu/kanade/domain/chapter/interactor/SyncChaptersWithSource.kt +++ b/app/src/main/java/eu/kanade/domain/chapter/interactor/SyncChaptersWithSource.kt @@ -20,6 +20,7 @@ import tachiyomi.domain.chapter.model.NoChaptersException import tachiyomi.domain.chapter.model.toChapterUpdate import tachiyomi.domain.chapter.repository.ChapterRepository import tachiyomi.domain.chapter.service.ChapterRecognition +import tachiyomi.domain.library.service.LibraryPreferences import tachiyomi.domain.manga.model.Manga import tachiyomi.source.local.isLocal import java.lang.Long.max @@ -35,6 +36,7 @@ class SyncChaptersWithSource( private val updateChapter: UpdateChapter, private val getChaptersByMangaId: GetChaptersByMangaId, private val getExcludedScanlators: GetExcludedScanlators, + private val libraryPreferences: LibraryPreferences, ) { /** @@ -153,12 +155,18 @@ class SyncChaptersWithSource( return emptyList() } - val reAdded = mutableListOf() + val changedOrDuplicateReadUrls = mutableSetOf() val deletedChapterNumbers = TreeSet() val deletedReadChapterNumbers = TreeSet() val deletedBookmarkedChapterNumbers = TreeSet() + val readChapterNumbers = dbChapters + .asSequence() + .filter { it.read && it.isRecognizedNumber } + .map { it.chapterNumber } + .toSet() + removedChapters.forEach { chapter -> if (chapter.read) deletedReadChapterNumbers.add(chapter.chapterNumber) if (chapter.bookmark) deletedBookmarkedChapterNumbers.add(chapter.chapterNumber) @@ -168,12 +176,19 @@ class SyncChaptersWithSource( val deletedChapterNumberDateFetchMap = removedChapters.sortedByDescending { it.dateFetch } .associate { it.chapterNumber to it.dateFetch } + val markDuplicateAsRead = libraryPreferences.markDuplicateChapterRead().get() + // Date fetch is set in such a way that the upper ones will have bigger value than the lower ones // Sources MUST return the chapters from most to less recent, which is common. var itemCount = newChapters.size var updatedToAdd = newChapters.map { toAddItem -> var chapter = toAddItem.copy(dateFetch = nowMillis + itemCount--) + if (chapter.chapterNumber in readChapterNumbers && markDuplicateAsRead) { + changedOrDuplicateReadUrls.add(chapter.url) + chapter = chapter.copy(read = true) + } + if (!chapter.isRecognizedNumber || chapter.chapterNumber !in deletedChapterNumbers) return@map chapter chapter = chapter.copy( @@ -186,19 +201,19 @@ class SyncChaptersWithSource( chapter = chapter.copy(dateFetch = it) } - reAdded.add(chapter) + changedOrDuplicateReadUrls.add(chapter.url) chapter } // --> EXH (carry over reading progress) if (manga.isEhBasedManga()) { - val finalAdded = updatedToAdd.subtract(reAdded) - if (finalAdded.isNotEmpty()) { + val hasNewChapters = updatedToAdd.any { it.url !in changedOrDuplicateReadUrls } + if (hasNewChapters) { val max = dbChapters.maxOfOrNull { it.lastPageRead } if (max != null && max > 0) { updatedToAdd = updatedToAdd.map { - if (it !in reAdded) { + if (it.url !in changedOrDuplicateReadUrls) { it.copy(lastPageRead = max) } else { it @@ -228,12 +243,8 @@ class SyncChaptersWithSource( // Note that last_update actually represents last time the chapter list changed at all updateManga.awaitUpdateLastUpdate(manga.id) - val reAddedUrls = reAdded.map { it.url }.toHashSet() - val excludedScanlators = getExcludedScanlators.await(manga.id).toHashSet() - return updatedToAdd.filterNot { - it.url in reAddedUrls || it.scanlator in excludedScanlators - } + return updatedToAdd.filterNot { it.url in changedOrDuplicateReadUrls || it.scanlator in excludedScanlators } } } diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsLibraryScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsLibraryScreen.kt index db8d0969c..7b925f220 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsLibraryScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsLibraryScreen.kt @@ -231,13 +231,10 @@ object SettingsLibraryScreen : SearchableSettings { preference = libraryPreferences.newShowUpdatesCount(), title = stringResource(MR.strings.pref_library_update_show_tab_badge), ), - // SY --> Preference.PreferenceItem.SwitchPreference( - preference = libraryPreferences.libraryReadDuplicateChapters(), - title = stringResource(SYMR.strings.pref_library_mark_duplicate_chapters), - subtitle = stringResource(SYMR.strings.pref_library_mark_duplicate_chapters_summary), + preference = libraryPreferences.markDuplicateChapterRead(), + title = stringResource(MR.strings.pref_mark_duplicate_chapter_read), ), - // SY <-- // KMK --> Preference.PreferenceItem.SwitchPreference( preference = libraryPreferences.showUpdatingProgressBanner(), 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 1121269d1..05d81ec5d 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 @@ -18,7 +18,6 @@ import androidx.work.WorkInfo import androidx.work.WorkQuery import androidx.work.WorkerParameters import androidx.work.workDataOf -import eu.kanade.domain.chapter.interactor.SetReadStatus import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.domain.manga.model.copyFrom @@ -65,7 +64,6 @@ import tachiyomi.core.common.util.lang.withIOContext import tachiyomi.core.common.util.system.logcat import tachiyomi.domain.UnsortedPreferences import tachiyomi.domain.category.model.Category -import tachiyomi.domain.chapter.interactor.GetChaptersByMangaId import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.chapter.model.NoChaptersException import tachiyomi.domain.library.model.GroupLibraryMode @@ -130,8 +128,6 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet private val insertTrack: InsertTrack = Injekt.get() private val trackerManager: TrackerManager = Injekt.get() private val mdList = trackerManager.mdList - private val getChaptersByMangaId: GetChaptersByMangaId = Injekt.get() - private val setReadStatus: SetReadStatus = Injekt.get() // SY <-- private val notifier = LibraryUpdateNotifier(context) @@ -438,35 +434,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet ) { try { val newChapters = updateManga(manga, fetchWindow) - // SY --> - .sortedByDescending { it.sourceOrder }.run { - if (libraryPreferences.libraryReadDuplicateChapters().get()) { - val readChapters = getChaptersByMangaId.await(manga.id).filter { - it.read - } - val newReadChapters = this.filter { chapter -> - chapter.chapterNumber >= 0 && - readChapters.any { - it.chapterNumber == chapter.chapterNumber - } - } - - if (newReadChapters.isNotEmpty()) { - setReadStatus.await( - true, - *newReadChapters.toTypedArray(), - // KMK --> - manually = false, - // KMK <-- - ) - } - - this.filterNot { newReadChapters.contains(it) } - } else { - this - } - } - // SY <-- + .sortedByDescending { it.sourceOrder } if (newChapters.isNotEmpty()) { val chaptersToDownload = filterChaptersForDownload.await(manga, newChapters) diff --git a/domain/src/main/java/tachiyomi/domain/library/service/LibraryPreferences.kt b/domain/src/main/java/tachiyomi/domain/library/service/LibraryPreferences.kt index b1455b3a9..f2c038c96 100644 --- a/domain/src/main/java/tachiyomi/domain/library/service/LibraryPreferences.kt +++ b/domain/src/main/java/tachiyomi/domain/library/service/LibraryPreferences.kt @@ -112,8 +112,6 @@ class LibraryPreferences( "pref_filter_library_lewd_v2", TriState.DISABLED, ) - - fun libraryReadDuplicateChapters() = preferenceStore.getBoolean("pref_library_mark_duplicate_chapters", false) // SY <-- fun filterTracking(id: Int) = preferenceStore.getEnum( @@ -154,6 +152,8 @@ class LibraryPreferences( fun categorizedDisplaySettings() = preferenceStore.getBoolean("categorized_display", false) + fun markDuplicateChapterRead() = preferenceStore.getBoolean("mark_duplicate_chapter_read", false) + // KMK --> fun showHiddenCategories() = preferenceStore.getBoolean("hide_hidden_categories", false) // KMK <-- diff --git a/i18n/src/commonMain/moko-resources/base/strings.xml b/i18n/src/commonMain/moko-resources/base/strings.xml index c40373d66..76ab799f0 100644 --- a/i18n/src/commonMain/moko-resources/base/strings.xml +++ b/i18n/src/commonMain/moko-resources/base/strings.xml @@ -294,6 +294,7 @@ Skip unstarted entries Predict next release time Show unread count on Updates icon + Mark new duplicate read chapters as read Automatically refresh metadata Check for new cover and details when updating library