Add option to mark new duplicate read chapters as read (#1785)

(cherry picked from commit cd0481592c09dc9cfb331805e90e6e5c3752a08c)

# Conflicts:
#	CHANGELOG.md
#	app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsLibraryScreen.kt
This commit is contained in:
AntsyLich 2025-02-27 23:32:51 +06:00 committed by Jobobby04
parent c59cb620dd
commit 56433a624e
6 changed files with 25 additions and 38 deletions

View File

@ -152,7 +152,7 @@ class DomainModule : InjektModule {
addFactory { UpdateChapter(get()) } addFactory { UpdateChapter(get()) }
addFactory { SetReadStatus(get(), get(), get(), get(), get()) } addFactory { SetReadStatus(get(), get(), get(), get(), get()) }
addFactory { ShouldUpdateDbChapter() } 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 { GetAvailableScanlators(get()) }
addFactory { FilterChaptersForDownload(get(), get(), get(), get()) } addFactory { FilterChaptersForDownload(get(), get(), get(), get()) }

View File

@ -20,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
@ -35,6 +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 libraryPreferences: LibraryPreferences,
) { ) {
/** /**
@ -150,12 +152,18 @@ class SyncChaptersWithSource(
return emptyList() return emptyList()
} }
val reAdded = mutableListOf<Chapter>() val changedOrDuplicateReadUrls = mutableSetOf<String>()
val deletedChapterNumbers = TreeSet<Double>() val deletedChapterNumbers = TreeSet<Double>()
val deletedReadChapterNumbers = TreeSet<Double>() val deletedReadChapterNumbers = TreeSet<Double>()
val deletedBookmarkedChapterNumbers = TreeSet<Double>() val deletedBookmarkedChapterNumbers = TreeSet<Double>()
val readChapterNumbers = dbChapters
.asSequence()
.filter { it.read && it.isRecognizedNumber }
.map { it.chapterNumber }
.toSet()
removedChapters.forEach { chapter -> removedChapters.forEach { chapter ->
if (chapter.read) deletedReadChapterNumbers.add(chapter.chapterNumber) if (chapter.read) deletedReadChapterNumbers.add(chapter.chapterNumber)
if (chapter.bookmark) deletedBookmarkedChapterNumbers.add(chapter.chapterNumber) if (chapter.bookmark) deletedBookmarkedChapterNumbers.add(chapter.chapterNumber)
@ -165,12 +173,19 @@ 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 = libraryPreferences.markDuplicateChapterRead().get()
// 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.
var itemCount = newChapters.size var itemCount = newChapters.size
var updatedToAdd = newChapters.map { toAddItem -> var updatedToAdd = newChapters.map { toAddItem ->
var chapter = toAddItem.copy(dateFetch = nowMillis + itemCount--) 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 if (!chapter.isRecognizedNumber || chapter.chapterNumber !in deletedChapterNumbers) return@map chapter
chapter = chapter.copy( chapter = chapter.copy(
@ -183,7 +198,7 @@ class SyncChaptersWithSource(
chapter = chapter.copy(dateFetch = it) chapter = chapter.copy(dateFetch = it)
} }
reAdded.add(chapter) changedOrDuplicateReadUrls.add(chapter.url)
chapter chapter
} }
@ -225,12 +240,8 @@ class SyncChaptersWithSource(
// Note that last_update actually represents last time the chapter list changed at all // Note that last_update actually represents last time the chapter list changed at all
updateManga.awaitUpdateLastUpdate(manga.id) updateManga.awaitUpdateLastUpdate(manga.id)
val reAddedUrls = reAdded.map { it.url }.toHashSet()
val excludedScanlators = getExcludedScanlators.await(manga.id).toHashSet() val excludedScanlators = getExcludedScanlators.await(manga.id).toHashSet()
return updatedToAdd.filterNot { return updatedToAdd.filterNot { it.url in changedOrDuplicateReadUrls || it.scanlator in excludedScanlators }
it.url in reAddedUrls || it.scanlator in excludedScanlators
}
} }
} }

View File

@ -228,13 +228,10 @@ object SettingsLibraryScreen : SearchableSettings {
preference = libraryPreferences.newShowUpdatesCount(), preference = libraryPreferences.newShowUpdatesCount(),
title = stringResource(MR.strings.pref_library_update_show_tab_badge), title = stringResource(MR.strings.pref_library_update_show_tab_badge),
), ),
// SY -->
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = libraryPreferences.libraryReadDuplicateChapters(), preference = libraryPreferences.markDuplicateChapterRead(),
title = stringResource(SYMR.strings.pref_library_mark_duplicate_chapters), title = stringResource(MR.strings.pref_mark_duplicate_chapter_read),
subtitle = stringResource(SYMR.strings.pref_library_mark_duplicate_chapters_summary),
), ),
// SY <--
), ),
) )
} }

View File

@ -401,29 +401,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
) { ) {
try { try {
val newChapters = updateManga(manga, fetchWindow) val newChapters = updateManga(manga, fetchWindow)
// SY --> .sortedByDescending { it.sourceOrder }
.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())
}
this.filterNot { newReadChapters.contains(it) }
} else {
this
}
}
// SY <--
if (newChapters.isNotEmpty()) { if (newChapters.isNotEmpty()) {
val chaptersToDownload = filterChaptersForDownload.await(manga, newChapters) val chaptersToDownload = filterChaptersForDownload.await(manga, newChapters)

View File

@ -94,8 +94,6 @@ class LibraryPreferences(
"pref_filter_library_lewd_v2", "pref_filter_library_lewd_v2",
TriState.DISABLED, TriState.DISABLED,
) )
fun libraryReadDuplicateChapters() = preferenceStore.getBoolean("pref_library_mark_duplicate_chapters", false)
// SY <-- // SY <--
fun filterTracking(id: Int) = preferenceStore.getEnum( fun filterTracking(id: Int) = preferenceStore.getEnum(
@ -130,6 +128,8 @@ class LibraryPreferences(
fun categorizedDisplaySettings() = preferenceStore.getBoolean("categorized_display", false) fun categorizedDisplaySettings() = preferenceStore.getBoolean("categorized_display", false)
fun markDuplicateChapterRead() = preferenceStore.getBoolean("mark_duplicate_chapter_read", false)
fun updateCategories() = preferenceStore.getStringSet(LIBRARY_UPDATE_CATEGORIES_PREF_KEY, emptySet()) fun updateCategories() = preferenceStore.getStringSet(LIBRARY_UPDATE_CATEGORIES_PREF_KEY, emptySet())
fun updateCategoriesExclude() = preferenceStore.getStringSet(LIBRARY_UPDATE_CATEGORIES_EXCLUDE_PREF_KEY, emptySet()) fun updateCategoriesExclude() = preferenceStore.getStringSet(LIBRARY_UPDATE_CATEGORIES_EXCLUDE_PREF_KEY, emptySet())

View File

@ -292,6 +292,7 @@
<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_chapter_read">Mark new 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>