From 6fa34ab5e912b2d503fded9a237562e4142c6bdf Mon Sep 17 00:00:00 2001 From: AntsyLich <59261191+AntsyLich@users.noreply.github.com> Date: Wed, 19 Mar 2025 02:27:58 +0600 Subject: [PATCH] Seperate mark duplicate read chapters as read behaviors as options (mihonapp/mihon#1870) (cherry picked from commit 8a3b6107755c768924a31c2b58d705296133839c) --- CHANGELOG.md | 3 +- .../interactor/SyncChaptersWithSource.kt | 7 +- .../settings/screen/SettingsLibraryScreen.kt | 18 ++- .../settings/screen/SettingsReaderScreen.kt | 11 -- .../tachiyomi/ui/reader/ReaderViewModel.kt | 116 +++++++++--------- .../ui/reader/setting/ReaderPreferences.kt | 4 - .../library/service/LibraryPreferences.kt | 5 + .../moko-resources/base/strings.xml | 10 +- 8 files changed, 87 insertions(+), 87 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7837a45c..05bc44391 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,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 duplicate read chapters as read +- Add option to mark duplicate read chapters as read after library update or while reading ([@AntsyLich](https://github.com/AntsyLich)) ([#1785](https://github.com/mihonapp/mihon/pull/1785), [#1791](https://github.com/mihonapp/mihon/pull/1791), [#1870](https://github.com/mihonapp/mihon/pull/1870)) - Display staff information on Anilist tracker search results ([@NarwhalHorns](https://github.com/NarwhalHorns)) ([#1810](https://github.com/mihonapp/mihon/pull/1810)) ### Changed @@ -32,6 +32,7 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co - Now showing manga starting dates in search - Reduced request load by 2-4x in certain situations - Bump default user agent +- Changed the label of chapter swipe settings and renamed the group to "Behavior" ([@AntsyLich](https://github.com/AntsyLich)) ([#1870](https://github.com/mihonapp/mihon/pull/1870)) ### Fixed - Fix MAL `main_picture` nullability breaking search if a result doesn't have a cover set ([@MajorTanya](https://github.com/MajorTanya)) ([#1618](https://github.com/mihonapp/mihon/pull/1618)) 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 df8872921..9d31f5d3d 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 @@ -10,7 +10,6 @@ import eu.kanade.tachiyomi.data.download.DownloadProvider import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.online.HttpSource -import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences import exh.source.isEhBasedManga import tachiyomi.data.chapter.ChapterSanitizer import tachiyomi.domain.chapter.interactor.GetChaptersByMangaId @@ -21,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 @@ -36,7 +36,7 @@ class SyncChaptersWithSource( private val updateChapter: UpdateChapter, private val getChaptersByMangaId: GetChaptersByMangaId, private val getExcludedScanlators: GetExcludedScanlators, - private val readerPreferences: ReaderPreferences, + private val libraryPreferences: LibraryPreferences, ) { /** @@ -176,7 +176,8 @@ class SyncChaptersWithSource( val deletedChapterNumberDateFetchMap = removedChapters.sortedByDescending { it.dateFetch } .associate { it.chapterNumber to it.dateFetch } - val markDuplicateAsRead = readerPreferences.markDuplicateReadChapterAsRead().get() + val markDuplicateAsRead = libraryPreferences.markDuplicateReadChapterAsRead().get() + .contains(LibraryPreferences.MARK_DUPLICATE_CHAPTER_READ_NEW) // 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. 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 3ad47503c..888245264 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 @@ -38,6 +38,8 @@ import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_HAS_U import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_COMPLETED import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_READ import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_OUTSIDE_RELEASE_PERIOD +import tachiyomi.domain.library.service.LibraryPreferences.Companion.MARK_DUPLICATE_CHAPTER_READ_EXISTING +import tachiyomi.domain.library.service.LibraryPreferences.Companion.MARK_DUPLICATE_CHAPTER_READ_NEW import tachiyomi.i18n.MR import tachiyomi.i18n.kmk.KMR import tachiyomi.i18n.sy.SYMR @@ -66,7 +68,7 @@ object SettingsLibraryScreen : SearchableSettings { return listOf( getCategoriesGroup(LocalNavigator.currentOrThrow, allCategories, libraryPreferences), getGlobalUpdateGroup(allCategories, libraryPreferences), - getChapterSwipeActionsGroup(libraryPreferences), + getBehaviorGroup(libraryPreferences), // SY --> getSortingCategory(LocalNavigator.currentOrThrow, libraryPreferences), getMigrationCategory(unsortedPreferences), @@ -242,11 +244,11 @@ object SettingsLibraryScreen : SearchableSettings { } @Composable - private fun getChapterSwipeActionsGroup( + private fun getBehaviorGroup( libraryPreferences: LibraryPreferences, ): Preference.PreferenceGroup { return Preference.PreferenceGroup( - title = stringResource(MR.strings.pref_chapter_swipe), + title = stringResource(MR.strings.pref_behavior), preferenceItems = persistentListOf( Preference.PreferenceItem.ListPreference( preference = libraryPreferences.swipeToStartAction(), @@ -276,6 +278,16 @@ object SettingsLibraryScreen : SearchableSettings { ), title = stringResource(MR.strings.pref_chapter_swipe_end), ), + Preference.PreferenceItem.MultiSelectListPreference( + preference = libraryPreferences.markDuplicateReadChapterAsRead(), + entries = persistentMapOf( + MARK_DUPLICATE_CHAPTER_READ_EXISTING to + stringResource(MR.strings.pref_mark_duplicate_read_chapter_read_existing), + MARK_DUPLICATE_CHAPTER_READ_NEW to + stringResource(MR.strings.pref_mark_duplicate_read_chapter_read_new), + ), + title = stringResource(MR.strings.pref_mark_duplicate_read_chapter_read), + ), ), ) } diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt index 05b84da9a..81c5a668b 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt @@ -228,21 +228,10 @@ object SettingsReaderScreen : SearchableSettings { preference = readerPreferences.skipDupe(), title = stringResource(MR.strings.pref_skip_dupe_chapters), ), - // SY --> - Preference.PreferenceItem.SwitchPreference( - preference = readerPreferences.markReadDupe(), - title = stringResource(SYMR.strings.pref_mark_read_dupe_chapters), - subtitle = stringResource(SYMR.strings.pref_mark_read_dupe_chapters_summary), - ), - // SY <-- Preference.PreferenceItem.SwitchPreference( preference = readerPreferences.alwaysShowChapterTransition(), title = stringResource(MR.strings.pref_always_show_chapter_transition), ), - Preference.PreferenceItem.SwitchPreference( - preference = readerPreferences.markDuplicateReadChapterAsRead(), - title = stringResource(MR.strings.pref_mark_duplicate_read_chapter_read), - ), ), ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt index cc1b6c42e..0e2641527 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt @@ -9,7 +9,6 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import eu.kanade.domain.base.BasePreferences -import eu.kanade.domain.chapter.interactor.SetReadStatus import eu.kanade.domain.chapter.model.toDbChapter import eu.kanade.domain.manga.interactor.SetMangaViewerFlags import eu.kanade.domain.manga.model.readerOrientation @@ -95,6 +94,7 @@ import tachiyomi.domain.download.service.DownloadPreferences import tachiyomi.domain.history.interactor.GetNextChapters import tachiyomi.domain.history.interactor.UpsertHistory import tachiyomi.domain.history.model.HistoryUpdate +import tachiyomi.domain.library.service.LibraryPreferences import tachiyomi.domain.manga.interactor.GetFlatMetadataById import tachiyomi.domain.manga.interactor.GetManga import tachiyomi.domain.manga.interactor.GetMergedMangaById @@ -129,14 +129,14 @@ class ReaderViewModel @JvmOverloads constructor( private val updateChapter: UpdateChapter = Injekt.get(), private val setMangaViewerFlags: SetMangaViewerFlags = Injekt.get(), private val getIncognitoState: GetIncognitoState = Injekt.get(), - private val syncPreferences: SyncPreferences = Injekt.get(), + private val libraryPreferences: LibraryPreferences = Injekt.get(), // SY --> + private val syncPreferences: SyncPreferences = Injekt.get(), private val uiPreferences: UiPreferences = Injekt.get(), private val getFlatMetadataById: GetFlatMetadataById = Injekt.get(), private val getMergedMangaById: GetMergedMangaById = Injekt.get(), private val getMergedReferencesById: GetMergedReferencesById = Injekt.get(), private val getMergedChaptersByMangaId: GetMergedChaptersByMangaId = Injekt.get(), - private val setReadStatus: SetReadStatus = Injekt.get(), // SY <-- ) : ViewModel() { @@ -702,71 +702,19 @@ class ReaderViewModel @JvmOverloads constructor( if (!incognitoMode && page.status != Page.State.ERROR) { readerChapter.chapter.last_page_read = pageIndex - // SY --> - if ( - readerChapter.pages?.lastIndex == pageIndex || - (hasExtraPage && readerChapter.pages?.lastIndex?.minus(1) == page.index) - ) { - // SY <-- - readerChapter.chapter.read = true + if (readerChapter.pages?.lastIndex == pageIndex || // SY --> - if (readerChapter.chapter.chapter_number >= 0 && readerPreferences.markReadDupe().get()) { - getChaptersByMangaId.await(manga!!.id).sortedByDescending { it.sourceOrder } - .filter { - it.id != readerChapter.chapter.id && - !it.read && - it.chapterNumber.toFloat() == readerChapter.chapter.chapter_number - } - .ifEmpty { null } - ?.also { - setReadStatus.await( - true, - *it.toTypedArray(), - // KMK --> - manually = false, - // KMK <-- - ) - it.forEach { chapter -> - deleteChapterIfNeeded(ReaderChapter(chapter)) - } - } - } - if (manga?.isEhBasedManga() == true) { - viewModelScope.launchNonCancellable { - val chapterUpdates = chapterList - .filter { it.chapter.source_order > readerChapter.chapter.source_order } - .map { chapter -> - ChapterUpdate( - id = chapter.chapter.id!!, - read = true, - ) - } - updateChapter.awaitAll(chapterUpdates) - } - } + (hasExtraPage && readerChapter.pages?.lastIndex?.minus(1) == page.index) // SY <-- - updateTrackChapterRead(readerChapter) - deleteChapterIfNeeded(readerChapter) - - val duplicateUnreadChapters = chapterList - .mapNotNull { - val chapter = it.chapter - if ( - !chapter.read && - chapter.isRecognizedNumber && - chapter.chapter_number == readerChapter.chapter.chapter_number - ) { - ChapterUpdate(id = chapter.id!!, read = true) - } else { - null - } - } - updateChapter.awaitAll(duplicateUnreadChapters) + ) { + updateChapterProgressOnComplete(readerChapter) + // SY --> // Check if syncing is enabled for chapter read: if (isSyncEnabled && syncTriggerOpt.syncOnChapterRead) { SyncDataJob.startNow(Injekt.get()) } + // SY <-- } updateChapter.await( @@ -777,13 +725,59 @@ class ReaderViewModel @JvmOverloads constructor( ), ) + // SY --> // Check if syncing is enabled for chapter open: if (isSyncEnabled && syncTriggerOpt.syncOnChapterOpen && readerChapter.chapter.last_page_read == 0) { SyncDataJob.startNow(Injekt.get()) } + // SY <-- } } + private suspend fun updateChapterProgressOnComplete(readerChapter: ReaderChapter) { + readerChapter.chapter.read = true + // SY --> + if (manga?.isEhBasedManga() == true) { + viewModelScope.launchNonCancellable { + val chapterUpdates = chapterList + .filter { it.chapter.source_order > readerChapter.chapter.source_order } + .map { chapter -> + ChapterUpdate( + id = chapter.chapter.id!!, + read = true, + ) + } + updateChapter.awaitAll(chapterUpdates) + } + } + // SY <-- + + updateTrackChapterRead(readerChapter) + deleteChapterIfNeeded(readerChapter) + + val markDuplicateAsRead = libraryPreferences.markDuplicateReadChapterAsRead().get() + .contains(LibraryPreferences.MARK_DUPLICATE_CHAPTER_READ_EXISTING) + if (!markDuplicateAsRead) return + + val duplicateUnreadChapters = chapterList + .mapNotNull { + val chapter = it.chapter + if ( + !chapter.read && + chapter.isRecognizedNumber && + chapter.chapter_number == readerChapter.chapter.chapter_number + ) { + ChapterUpdate(id = chapter.id!!, read = true) + // SY --> + .also { deleteChapterIfNeeded(ReaderChapter(chapter)) } + // SY <-- + } else { + null + } + } + updateChapter.awaitAll(duplicateUnreadChapters) + } + fun restartReadTimer() { chapterReadStartTime = Instant.now().toEpochMilli() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderPreferences.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderPreferences.kt index 05c8ac934..181940d36 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderPreferences.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderPreferences.kt @@ -143,8 +143,6 @@ class ReaderPreferences( fun showNavigationOverlayOnStart() = preferenceStore.getBoolean("reader_navigation_overlay_on_start", false) - fun markDuplicateReadChapterAsRead() = preferenceStore.getBoolean("mark_duplicate_chapter_read", false) - // endregion // SY --> @@ -186,8 +184,6 @@ class ReaderPreferences( fun centerMarginType() = preferenceStore.getInt("center_margin_type", PagerConfig.CenterMarginType.NONE) fun archiveReaderMode() = preferenceStore.getInt("archive_reader_mode", ArchiveReaderMode.LOAD_FROM_FILE) - - fun markReadDupe() = preferenceStore.getBoolean("mark_read_dupe", false) // SY <-- enum class FlashColor { 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 f7f808004..9a6309c70 100644 --- a/domain/src/main/java/tachiyomi/domain/library/service/LibraryPreferences.kt +++ b/domain/src/main/java/tachiyomi/domain/library/service/LibraryPreferences.kt @@ -78,6 +78,8 @@ class LibraryPreferences( false, ) + fun markDuplicateReadChapterAsRead() = preferenceStore.getStringSet("mark_duplicate_read_chapter_read", emptySet()) + // region Filter fun filterDownloaded() = preferenceStore.getEnum( @@ -251,6 +253,9 @@ class LibraryPreferences( const val MANGA_NON_READ = "manga_started" const val MANGA_OUTSIDE_RELEASE_PERIOD = "manga_outside_release_period" + const val MARK_DUPLICATE_CHAPTER_READ_NEW = "new" + const val MARK_DUPLICATE_CHAPTER_READ_EXISTING = "existing" + const val DEFAULT_CATEGORY_PREF_KEY = "default_category" private const val LIBRARY_UPDATE_CATEGORIES_PREF_KEY = "library_update_categories" private const val LIBRARY_UPDATE_CATEGORIES_EXCLUDE_PREF_KEY = "library_update_categories_exclude" diff --git a/i18n/src/commonMain/moko-resources/base/strings.xml b/i18n/src/commonMain/moko-resources/base/strings.xml index f0d0356eb..243ff3135 100644 --- a/i18n/src/commonMain/moko-resources/base/strings.xml +++ b/i18n/src/commonMain/moko-resources/base/strings.xml @@ -294,7 +294,6 @@ Skip unstarted entries Predict next release time Show unread count on Updates icon - Mark duplicate read chapters as read Automatically refresh metadata Check for new cover and details when updating library @@ -308,11 +307,14 @@ Include: %s Exclude: %s - Chapter swipe + Behavior - Swipe to right action + Chapter on swipe to right - Swipe to left action + Chapter on swipe to left + Mark duplicate read chapter as read + After reading a chapter + After fetching new chapter Multi