Seperate mark duplicate read chapters as read behaviors as options (#1870)

(cherry picked from commit 8a3b6107755c768924a31c2b58d705296133839c)

# Conflicts:
#	CHANGELOG.md
#	app/src/main/java/eu/kanade/domain/chapter/interactor/SyncChaptersWithSource.kt
#	app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsLibraryScreen.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt
This commit is contained in:
AntsyLich 2025-03-19 02:27:58 +06:00 committed by Jobobby04
parent d62a8a138c
commit 9c198d0c33
8 changed files with 80 additions and 53 deletions

View File

@ -10,7 +10,6 @@ import eu.kanade.tachiyomi.data.download.DownloadProvider
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
import exh.source.isEhBasedManga import exh.source.isEhBasedManga
import tachiyomi.data.chapter.ChapterSanitizer import tachiyomi.data.chapter.ChapterSanitizer
import tachiyomi.domain.chapter.interactor.GetChaptersByMangaId 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.model.toChapterUpdate
import tachiyomi.domain.chapter.repository.ChapterRepository import tachiyomi.domain.chapter.repository.ChapterRepository
import tachiyomi.domain.chapter.service.ChapterRecognition import tachiyomi.domain.chapter.service.ChapterRecognition
import tachiyomi.domain.library.service.LibraryPreferences
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
import tachiyomi.source.local.isLocal import tachiyomi.source.local.isLocal
import java.lang.Long.max import java.lang.Long.max
@ -36,7 +36,7 @@ class SyncChaptersWithSource(
private val updateChapter: UpdateChapter, private val updateChapter: UpdateChapter,
private val getChaptersByMangaId: GetChaptersByMangaId, private val getChaptersByMangaId: GetChaptersByMangaId,
private val getExcludedScanlators: GetExcludedScanlators, private val getExcludedScanlators: GetExcludedScanlators,
private val readerPreferences: ReaderPreferences, private val libraryPreferences: LibraryPreferences,
) { ) {
/** /**
@ -173,7 +173,8 @@ class SyncChaptersWithSource(
val deletedChapterNumberDateFetchMap = removedChapters.sortedByDescending { it.dateFetch } val deletedChapterNumberDateFetchMap = removedChapters.sortedByDescending { it.dateFetch }
.associate { it.chapterNumber to 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 // 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. // Sources MUST return the chapters from most to less recent, which is common.

View File

@ -504,7 +504,7 @@ object SettingsDataScreen : SearchableSettings {
) )
} }
//SY --> // SY -->
@Composable @Composable
private fun getSyncPreferences(syncPreferences: SyncPreferences, syncService: Int): List<Preference> { private fun getSyncPreferences(syncPreferences: SyncPreferences, syncService: Int): List<Preference> {
return listOf( return listOf(

View File

@ -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_COMPLETED
import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_READ 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.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.MR
import tachiyomi.i18n.sy.SYMR import tachiyomi.i18n.sy.SYMR
import tachiyomi.presentation.core.i18n.pluralStringResource import tachiyomi.presentation.core.i18n.pluralStringResource
@ -64,7 +66,7 @@ object SettingsLibraryScreen : SearchableSettings {
return listOf( return listOf(
getCategoriesGroup(LocalNavigator.currentOrThrow, allCategories, libraryPreferences), getCategoriesGroup(LocalNavigator.currentOrThrow, allCategories, libraryPreferences),
getGlobalUpdateGroup(allCategories, libraryPreferences), getGlobalUpdateGroup(allCategories, libraryPreferences),
getChapterSwipeActionsGroup(libraryPreferences), getBehaviorGroup(libraryPreferences),
// SY --> // SY -->
getSortingCategory(LocalNavigator.currentOrThrow, libraryPreferences), getSortingCategory(LocalNavigator.currentOrThrow, libraryPreferences),
getMigrationCategory(unsortedPreferences), getMigrationCategory(unsortedPreferences),
@ -233,11 +235,11 @@ object SettingsLibraryScreen : SearchableSettings {
} }
@Composable @Composable
private fun getChapterSwipeActionsGroup( private fun getBehaviorGroup(
libraryPreferences: LibraryPreferences, libraryPreferences: LibraryPreferences,
): Preference.PreferenceGroup { ): Preference.PreferenceGroup {
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.pref_chapter_swipe), title = stringResource(MR.strings.pref_behavior),
preferenceItems = persistentListOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
preference = libraryPreferences.swipeToStartAction(), preference = libraryPreferences.swipeToStartAction(),
@ -267,6 +269,16 @@ object SettingsLibraryScreen : SearchableSettings {
), ),
title = stringResource(MR.strings.pref_chapter_swipe_end), 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),
),
), ),
) )
} }

View File

@ -238,10 +238,6 @@ object SettingsReaderScreen : SearchableSettings {
preference = readerPreferences.alwaysShowChapterTransition(), preference = readerPreferences.alwaysShowChapterTransition(),
title = stringResource(MR.strings.pref_always_show_chapter_transition), 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),
),
), ),
) )
} }

View File

@ -95,6 +95,7 @@ import tachiyomi.domain.download.service.DownloadPreferences
import tachiyomi.domain.history.interactor.GetNextChapters import tachiyomi.domain.history.interactor.GetNextChapters
import tachiyomi.domain.history.interactor.UpsertHistory import tachiyomi.domain.history.interactor.UpsertHistory
import tachiyomi.domain.history.model.HistoryUpdate import tachiyomi.domain.history.model.HistoryUpdate
import tachiyomi.domain.library.service.LibraryPreferences
import tachiyomi.domain.manga.interactor.GetFlatMetadataById import tachiyomi.domain.manga.interactor.GetFlatMetadataById
import tachiyomi.domain.manga.interactor.GetManga import tachiyomi.domain.manga.interactor.GetManga
import tachiyomi.domain.manga.interactor.GetMergedMangaById import tachiyomi.domain.manga.interactor.GetMergedMangaById
@ -129,6 +130,7 @@ class ReaderViewModel @JvmOverloads constructor(
private val updateChapter: UpdateChapter = Injekt.get(), private val updateChapter: UpdateChapter = Injekt.get(),
private val setMangaViewerFlags: SetMangaViewerFlags = Injekt.get(), private val setMangaViewerFlags: SetMangaViewerFlags = Injekt.get(),
private val getIncognitoState: GetIncognitoState = Injekt.get(), private val getIncognitoState: GetIncognitoState = Injekt.get(),
private val libraryPreferences: LibraryPreferences = Injekt.get(),
// SY --> // SY -->
private val syncPreferences: SyncPreferences = Injekt.get(), private val syncPreferences: SyncPreferences = Injekt.get(),
private val uiPreferences: UiPreferences = Injekt.get(), private val uiPreferences: UiPreferences = Injekt.get(),
@ -700,6 +702,32 @@ class ReaderViewModel @JvmOverloads constructor(
(hasExtraPage && readerChapter.pages?.lastIndex?.minus(1) == page.index) (hasExtraPage && readerChapter.pages?.lastIndex?.minus(1) == page.index)
) { ) {
// SY <-- // SY <--
updateChapterProgressOnComplete(readerChapter)
// Check if syncing is enabled for chapter read:
if (isSyncEnabled && syncTriggerOpt.syncOnChapterRead) {
SyncDataJob.startNow(Injekt.get<Application>())
}
}
updateChapter.await(
ChapterUpdate(
id = readerChapter.chapter.id!!,
read = readerChapter.chapter.read,
lastPageRead = readerChapter.chapter.last_page_read.toLong(),
),
)
// SY -->
// Check if syncing is enabled for chapter open:
if (isSyncEnabled && syncTriggerOpt.syncOnChapterOpen && readerChapter.chapter.last_page_read == 0) {
SyncDataJob.startNow(Injekt.get<Application>())
}
// SY <--
}
}
private suspend fun updateChapterProgressOnComplete(readerChapter: ReaderChapter) {
readerChapter.chapter.read = true readerChapter.chapter.read = true
// SY --> // SY -->
if (manga?.isEhBasedManga() == true) { if (manga?.isEhBasedManga() == true) {
@ -716,9 +744,14 @@ class ReaderViewModel @JvmOverloads constructor(
} }
} }
// SY <-- // SY <--
updateTrackChapterRead(readerChapter) updateTrackChapterRead(readerChapter)
deleteChapterIfNeeded(readerChapter) deleteChapterIfNeeded(readerChapter)
val markDuplicateAsRead = libraryPreferences.markDuplicateReadChapterAsRead().get()
.contains(LibraryPreferences.MARK_DUPLICATE_CHAPTER_READ_EXISTING)
if (!markDuplicateAsRead) return
val duplicateUnreadChapters = chapterList val duplicateUnreadChapters = chapterList
.mapNotNull { .mapNotNull {
val chapter = it.chapter val chapter = it.chapter
@ -736,26 +769,6 @@ class ReaderViewModel @JvmOverloads constructor(
} }
} }
updateChapter.awaitAll(duplicateUnreadChapters) updateChapter.awaitAll(duplicateUnreadChapters)
// Check if syncing is enabled for chapter read:
if (isSyncEnabled && syncTriggerOpt.syncOnChapterRead) {
SyncDataJob.startNow(Injekt.get<Application>())
}
}
updateChapter.await(
ChapterUpdate(
id = readerChapter.chapter.id!!,
read = readerChapter.chapter.read,
lastPageRead = readerChapter.chapter.last_page_read.toLong(),
),
)
// Check if syncing is enabled for chapter open:
if (isSyncEnabled && syncTriggerOpt.syncOnChapterOpen && readerChapter.chapter.last_page_read == 0) {
SyncDataJob.startNow(Injekt.get<Application>())
}
}
} }
fun restartReadTimer() { fun restartReadTimer() {

View File

@ -143,8 +143,6 @@ class ReaderPreferences(
fun showNavigationOverlayOnStart() = preferenceStore.getBoolean("reader_navigation_overlay_on_start", false) fun showNavigationOverlayOnStart() = preferenceStore.getBoolean("reader_navigation_overlay_on_start", false)
fun markDuplicateReadChapterAsRead() = preferenceStore.getBoolean("mark_duplicate_chapter_read", false)
// endregion // endregion
// SY --> // SY -->

View File

@ -60,6 +60,8 @@ class LibraryPreferences(
false, false,
) )
fun markDuplicateReadChapterAsRead() = preferenceStore.getStringSet("mark_duplicate_read_chapter_read", emptySet())
// region Filter // region Filter
fun filterDownloaded() = preferenceStore.getEnum( fun filterDownloaded() = preferenceStore.getEnum(
@ -225,6 +227,9 @@ class LibraryPreferences(
const val MANGA_NON_READ = "manga_started" const val MANGA_NON_READ = "manga_started"
const val MANGA_OUTSIDE_RELEASE_PERIOD = "manga_outside_release_period" 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" 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_PREF_KEY = "library_update_categories"
private const val LIBRARY_UPDATE_CATEGORIES_EXCLUDE_PREF_KEY = "library_update_categories_exclude" private const val LIBRARY_UPDATE_CATEGORIES_EXCLUDE_PREF_KEY = "library_update_categories_exclude"

View File

@ -293,7 +293,6 @@
<string name="pref_update_only_started">Skip unstarted entries</string> <string name="pref_update_only_started">Skip unstarted entries</string>
<string name="pref_update_only_in_release_period">Predict next release time</string> <string name="pref_update_only_in_release_period">Predict next release time</string>
<string name="pref_library_update_show_tab_badge">Show unread count on Updates icon</string> <string name="pref_library_update_show_tab_badge">Show unread count on Updates icon</string>
<string name="pref_mark_duplicate_read_chapter_read">Mark duplicate read chapters as read</string>
<string name="pref_library_update_refresh_metadata">Automatically refresh metadata</string> <string name="pref_library_update_refresh_metadata">Automatically refresh metadata</string>
<string name="pref_library_update_refresh_metadata_summary">Check for new cover and details when updating library</string> <string name="pref_library_update_refresh_metadata_summary">Check for new cover and details when updating library</string>
@ -307,11 +306,14 @@
<string name="include">Include: %s</string> <string name="include">Include: %s</string>
<string name="exclude">Exclude: %s</string> <string name="exclude">Exclude: %s</string>
<string name="pref_chapter_swipe">Chapter swipe</string> <string name="pref_behavior">Behavior</string>
<!-- This should be to the left for RTL locales --> <!-- This should be to the left for RTL locales -->
<string name="pref_chapter_swipe_end">Swipe to right action</string> <string name="pref_chapter_swipe_end">Chapter on swipe to right</string>
<!-- This should be to the right for RTL locales --> <!-- This should be to the right for RTL locales -->
<string name="pref_chapter_swipe_start">Swipe to left action</string> <string name="pref_chapter_swipe_start">Chapter on swipe to left</string>
<string name="pref_mark_duplicate_read_chapter_read">Mark duplicate read chapter as read</string>
<string name="pref_mark_duplicate_read_chapter_read_existing">After reading a chapter</string>
<string name="pref_mark_duplicate_read_chapter_read_new">After fetching new chapter</string>
<!-- Extension section --> <!-- Extension section -->
<string name="multi_lang">Multi</string> <string name="multi_lang">Multi</string>