Clean up library download chapters logic

We can probably clean up the same logic in the manga controller at some point too, but that stuff's messy.
Also fixes the spacing issue that the new icon introduced.

(cherry picked from commit 33e90d64497f920be825b803e1342a2e6c937111)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt
This commit is contained in:
arkon 2022-10-30 22:56:07 -04:00 committed by Jobobby04
parent 35bd6233d9
commit b2565c7f8b
12 changed files with 174 additions and 181 deletions

View File

@ -120,7 +120,7 @@ class SYDomainModule : InjektModule {
addFactory { GetMergedManga(get()) }
addFactory { GetMergedMangaById(get()) }
addFactory { GetMergedReferencesById(get()) }
addFactory { GetMergedChapterByMangaId(get()) }
addFactory { GetMergedChapterByMangaId(get(), get(), get()) }
addFactory { InsertMergedReference(get()) }
addFactory { UpdateMergedSettings(get()) }
addFactory { DeleteByMergeId(get()) }

View File

@ -2,16 +2,39 @@ package eu.kanade.domain.chapter.interactor
import eu.kanade.domain.chapter.model.Chapter
import eu.kanade.domain.chapter.repository.ChapterRepository
import eu.kanade.domain.manga.interactor.GetMergedReferencesById
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.util.system.logcat
import exh.merged.sql.models.MergedMangaReference
import exh.source.MERGED_SOURCE_ID
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import logcat.LogPriority
class GetMergedChapterByMangaId(
private val chapterRepository: ChapterRepository,
private val getMergedReferencesById: GetMergedReferencesById,
private val sourceManager: SourceManager,
) {
suspend fun await(mangaId: Long): List<Chapter> {
suspend fun await(mangaId: Long, editScanlators: Boolean = false, dedupe: Boolean = true): List<Chapter> {
return transformMergedChapters(mangaId, getFromDatabase(mangaId), editScanlators, dedupe)
}
suspend fun subscribe(mangaId: Long, editScanlators: Boolean = false, dedupe: Boolean = true): Flow<List<Chapter>> {
return try {
chapterRepository.getMergedChapterByMangaIdAsFlow(mangaId)
.map {
transformMergedChapters(mangaId, it, editScanlators, dedupe)
}
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
flowOf(emptyList())
}
}
private suspend fun getFromDatabase(mangaId: Long): List<Chapter> {
return try {
chapterRepository.getMergedChapterByMangaId(mangaId)
} catch (e: Exception) {
@ -20,12 +43,54 @@ class GetMergedChapterByMangaId(
}
}
suspend fun subscribe(mangaId: Long): Flow<List<Chapter>> {
return try {
chapterRepository.getMergedChapterByMangaIdAsFlow(mangaId)
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
flowOf(emptyList())
// TODO more chapter dedupe
suspend fun transformMergedChapters(mangaId: Long, chapterList: List<Chapter>, editScanlators: Boolean, dedupe: Boolean): List<Chapter> {
val mangaReferences = getMergedReferencesById.await(mangaId)
val chapters = if (editScanlators) {
val sources = mangaReferences.map { sourceManager.getOrStub(it.mangaSourceId) to it.mangaId }
chapterList.map { chapter ->
val source = sources.firstOrNull { chapter.mangaId == it.second }?.first
if (source != null) {
chapter.copy(
scanlator = if (chapter.scanlator.isNullOrBlank()) {
source.name
} else {
"$source: ${chapter.scanlator}"
},
)
} else {
chapter
}
}
} else {
chapterList
}
return if (dedupe) dedupeChapterList(mangaReferences, chapters) else chapters
}
private fun dedupeChapterList(mangaReferences: List<MergedMangaReference>, chapterList: List<Chapter>): List<Chapter> {
return when (mangaReferences.firstOrNull { it.mangaSourceId == MERGED_SOURCE_ID }?.chapterSortMode) {
MergedMangaReference.CHAPTER_SORT_NO_DEDUPE, MergedMangaReference.CHAPTER_SORT_NONE -> chapterList
MergedMangaReference.CHAPTER_SORT_PRIORITY -> chapterList
MergedMangaReference.CHAPTER_SORT_MOST_CHAPTERS -> {
findSourceWithMostChapters(chapterList)?.let { mangaId ->
chapterList.filter { it.mangaId == mangaId }
} ?: chapterList
}
MergedMangaReference.CHAPTER_SORT_HIGHEST_CHAPTER_NUMBER -> {
findSourceWithHighestChapterNumber(chapterList)?.let { mangaId ->
chapterList.filter { it.mangaId == mangaId }
} ?: chapterList
}
else -> chapterList
}
}
private fun findSourceWithMostChapters(chapterList: List<Chapter>): Long? {
return chapterList.groupBy { it.mangaId }.maxByOrNull { it.value.size }?.key
}
private fun findSourceWithHighestChapterNumber(chapterList: List<Chapter>): Long? {
return chapterList.maxByOrNull { it.chapterNumber }?.mangaId
}
}

View File

@ -7,8 +7,6 @@ import eu.kanade.domain.download.interactor.DeleteDownload
import eu.kanade.domain.download.service.DownloadPreferences
import eu.kanade.domain.manga.model.Manga
import eu.kanade.domain.manga.repository.MangaRepository
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.online.all.MergedSource
import eu.kanade.tachiyomi.util.lang.withNonCancellableContext
import eu.kanade.tachiyomi.util.system.logcat
import exh.source.MERGED_SOURCE_ID
@ -19,7 +17,9 @@ class SetReadStatus(
private val deleteDownload: DeleteDownload,
private val mangaRepository: MangaRepository,
private val chapterRepository: ChapterRepository,
private val sourceManager: SourceManager,
// SY -->
private val getMergedChapterByMangaId: GetMergedChapterByMangaId,
// SY <--
) {
private val mapper = { chapter: Chapter, read: Boolean ->
@ -75,11 +75,10 @@ class SetReadStatus(
// SY -->
private suspend fun awaitMerged(mangaId: Long, read: Boolean) = withNonCancellableContext f@{
val mergedSource = sourceManager.get(MERGED_SOURCE_ID) as MergedSource
return@f await(
read = read,
chapters = mergedSource
.getChapters(mangaId, dedupe = false)
chapters = getMergedChapterByMangaId
.await(mangaId, dedupe = false)
.toTypedArray(),
)
}

View File

@ -1,15 +1,19 @@
package eu.kanade.domain.history.interactor
import eu.kanade.domain.chapter.interactor.GetChapter
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
import eu.kanade.domain.chapter.interactor.GetMergedChapterByMangaId
import eu.kanade.domain.chapter.model.Chapter
import eu.kanade.domain.history.repository.HistoryRepository
import eu.kanade.domain.manga.interactor.GetManga
import eu.kanade.tachiyomi.util.chapter.getChapterSort
import exh.source.MERGED_SOURCE_ID
import kotlin.math.max
class GetNextUnreadChapters(
private val getChapter: GetChapter,
private val getChapterByMangaId: GetChapterByMangaId,
// SY -->
private val getMergedChapterByMangaId: GetMergedChapterByMangaId,
// SY <--
private val getManga: GetManga,
private val historyRepository: HistoryRepository,
) {
@ -19,15 +23,23 @@ class GetNextUnreadChapters(
return await(history.mangaId, history.chapterId).firstOrNull()
}
suspend fun await(mangaId: Long, chapterId: Long): List<Chapter> {
val chapter = getChapter.await(chapterId) ?: return emptyList()
suspend fun await(mangaId: Long): List<Chapter> {
val manga = getManga.await(mangaId) ?: return emptyList()
val chapters = getChapterByMangaId.await(mangaId)
// SY -->
if (manga.source == MERGED_SOURCE_ID) {
return getMergedChapterByMangaId.await(mangaId)
.sortedWith(getChapterSort(manga, sortDescending = false))
val currChapterIndex = chapters.indexOfFirst { chapter.id == it.id }
return chapters
.subList(currChapterIndex, chapters.size)
.filterNot { it.read }
}
// SY <--
return getChapterByMangaId.await(mangaId)
.sortedWith(getChapterSort(manga, sortDescending = false))
.filterNot { it.read }
}
suspend fun await(mangaId: Long, fromChapterId: Long): List<Chapter> {
val unreadChapters = await(mangaId)
val currChapterIndex = unreadChapters.indexOfFirst { it.id == fromChapterId }
return unreadChapters.subList(max(0, currChapterIndex), unreadChapters.size)
}
}

View File

@ -9,7 +9,6 @@ import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
@ -179,6 +178,7 @@ private fun RowScope.Button(
toConfirm: Boolean,
onLongClick: () -> Unit,
onClick: () -> Unit,
content: (@Composable () -> Unit)? = null,
) {
val animatedWeight by animateFloatAsState(if (toConfirm) 2f else 1f)
Column(
@ -210,6 +210,7 @@ private fun RowScope.Button(
style = MaterialTheme.typography.labelSmall,
)
}
content?.invoke()
}
}
@ -272,15 +273,14 @@ fun LibraryBottomActionMenu(
)
}
if (onDownloadClicked != null) {
Box {
var downloadExpanded by remember { mutableStateOf(false) }
this@Row.Button(
Button(
title = stringResource(R.string.action_download),
icon = Icons.Outlined.Download,
toConfirm = confirm[3],
onLongClick = { onLongClickItem(3) },
onClick = { downloadExpanded = !downloadExpanded },
)
) {
val onDismissRequest = { downloadExpanded = false }
DownloadDropdownMenu(
expanded = downloadExpanded,

View File

@ -72,7 +72,7 @@ fun LibraryComfortableGrid(
)
},
// SY -->
buttonBottom = if (showStartReadingButton) {
buttonBottom = if (showStartReadingButton && libraryItem.unreadCount > 0) {
{ StartReadingButton(onOpenReader = { onOpenReader(libraryItem.libraryManga) }) }
} else {
null

View File

@ -73,12 +73,12 @@ fun LibraryCompactGrid(
)
},
// SY -->
buttonTop = if (showStartReadingButton && showTitle) {
buttonTop = if (showStartReadingButton && showTitle && libraryItem.unreadCount > 0) {
{ StartReadingButton(onOpenReader = { onOpenReader(libraryItem.libraryManga) }) }
} else {
null
},
buttonBottom = if (showStartReadingButton && !showTitle) {
buttonBottom = if (showStartReadingButton && !showTitle && libraryItem.unreadCount > 0) {
{ StartReadingButton(onOpenReader = { onOpenReader(libraryItem.libraryManga) }) }
} else {
null

View File

@ -1,7 +1,6 @@
package eu.kanade.tachiyomi.source.online.all
import eu.kanade.domain.category.interactor.GetCategories
import eu.kanade.domain.chapter.interactor.GetMergedChapterByMangaId
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
import eu.kanade.domain.chapter.model.Chapter
import eu.kanade.domain.chapter.model.toDbChapter
@ -27,19 +26,16 @@ import exh.source.MERGED_SOURCE_ID
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.supervisorScope
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit
import okhttp3.Response
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
class MergedSource : HttpSource() {
private val getManga: GetManga by injectLazy()
private val getMergedReferencesById: GetMergedReferencesById by injectLazy()
private val getMergedChaptersByMangaId: GetMergedChapterByMangaId by injectLazy()
private val syncChaptersWithSource: SyncChaptersWithSource by injectLazy()
private val networkToLocalManga: NetworkToLocalManga by injectLazy()
private val updateManga: UpdateManga by injectLazy()
private val getCategories: GetCategories by injectLazy()
@ -76,18 +72,12 @@ class MergedSource : HttpSource() {
override suspend fun getMangaDetails(manga: SManga): SManga {
return withIOContext {
val mergedManga = getManga.await(manga.url, id) ?: throw Exception("merged manga not in db")
val mergedManga = requireNotNull(getManga.await(manga.url, id)) { "merged manga not in db" }
val mangaReferences = getMergedReferencesById.await(mergedManga.id)
.apply {
if (isEmpty()) {
throw IllegalArgumentException(
"Manga references are empty, info unavailable, merge is likely corrupted",
)
}
if (size == 1 && first().mangaSourceId == MERGED_SOURCE_ID) {
throw IllegalArgumentException(
"Manga references contain only the merged reference, merge is likely corrupted",
)
require(isNotEmpty()) { "Manga references are empty, info unavailable, merge is likely corrupted" }
require(!(size == 1 && first().mangaSourceId == MERGED_SOURCE_ID)) {
"Manga references contain only the merged reference, merge is likely corrupted"
}
}
@ -102,77 +92,14 @@ class MergedSource : HttpSource() {
}
}
// TODO more chapter dedupe
suspend fun transformMergedChapters(mangaId: Long, chapterList: List<Chapter>, editScanlators: Boolean, dedupe: Boolean): List<Chapter> {
val mangaReferences = getMergedReferencesById.await(mangaId)
val chapters = if (editScanlators) {
val sources = mangaReferences.map { sourceManager.getOrStub(it.mangaSourceId) to it.mangaId }
chapterList.map { chapter ->
val source = sources.firstOrNull { chapter.mangaId == it.second }?.first
if (source != null) {
chapter.copy(
scanlator = if (chapter.scanlator.isNullOrBlank()) {
source.name
} else {
"$source: ${chapter.scanlator}"
},
)
} else {
chapter
}
}
} else {
chapterList
}
return if (dedupe) dedupeChapterList(mangaReferences, chapters) else chapters
}
fun getChaptersAsBlocking(mangaId: Long, editScanlators: Boolean = false, dedupe: Boolean = true): List<Chapter> {
return runBlocking { getChapters(mangaId, editScanlators, dedupe) }
}
suspend fun getChapters(mangaId: Long, editScanlators: Boolean = false, dedupe: Boolean = true): List<Chapter> {
return transformMergedChapters(mangaId, getMergedChaptersByMangaId.await(mangaId), editScanlators, dedupe)
}
private fun dedupeChapterList(mangaReferences: List<MergedMangaReference>, chapterList: List<Chapter>): List<Chapter> {
return when (mangaReferences.firstOrNull { it.mangaSourceId == MERGED_SOURCE_ID }?.chapterSortMode) {
MergedMangaReference.CHAPTER_SORT_NO_DEDUPE, MergedMangaReference.CHAPTER_SORT_NONE -> chapterList
MergedMangaReference.CHAPTER_SORT_PRIORITY -> chapterList
MergedMangaReference.CHAPTER_SORT_MOST_CHAPTERS -> {
findSourceWithMostChapters(chapterList)?.let { mangaId ->
chapterList.filter { it.mangaId == mangaId }
} ?: chapterList
}
MergedMangaReference.CHAPTER_SORT_HIGHEST_CHAPTER_NUMBER -> {
findSourceWithHighestChapterNumber(chapterList)?.let { mangaId ->
chapterList.filter { it.mangaId == mangaId }
} ?: chapterList
}
else -> chapterList
}
}
private fun findSourceWithMostChapters(chapterList: List<Chapter>): Long? {
return chapterList.groupBy { it.mangaId }.maxByOrNull { it.value.size }?.key
}
private fun findSourceWithHighestChapterNumber(chapterList: List<Chapter>): Long? {
return chapterList.maxByOrNull { it.chapterNumber }?.mangaId
}
suspend fun fetchChaptersForMergedManga(manga: Manga, downloadChapters: Boolean = true, editScanlators: Boolean = false, dedupe: Boolean = true): List<Chapter> {
return withIOContext {
suspend fun fetchChaptersForMergedManga(manga: Manga, downloadChapters: Boolean = true, editScanlators: Boolean = false, dedupe: Boolean = true) {
fetchChaptersAndSync(manga, downloadChapters)
getChapters(manga.id, editScanlators, dedupe)
}
}
suspend fun fetchChaptersAndSync(manga: Manga, downloadChapters: Boolean = true): List<Chapter> {
val syncChaptersWithSource = Injekt.get<SyncChaptersWithSource>()
val mangaReferences = getMergedReferencesById.await(manga.id)
if (mangaReferences.isEmpty()) {
throw IllegalArgumentException("Manga references are empty, chapters unavailable, merge is likely corrupted")
require(mangaReferences.isNotEmpty()) {
"Manga references are empty, chapters unavailable, merge is likely corrupted"
}
val ifDownloadNewChapters = downloadChapters && manga.shouldDownloadNewChapters(getCategories.await(manga.id).map { it.id }, downloadPreferences)

View File

@ -35,6 +35,7 @@ import eu.kanade.tachiyomi.ui.manga.MangaController
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.system.toast
import exh.favorites.FavoritesIntroDialog
import exh.favorites.FavoritesSyncStatus
@ -509,10 +510,14 @@ class LibraryController(
private fun startReading(manga: Manga) {
val activity = activity ?: return
val chapter = presenter.getFirstUnread(manga) ?: return
viewScope.launchIO {
val chapter = presenter.getFirstUnread(manga) ?: return@launchIO
val intent = ReaderActivity.newIntent(activity, manga.id, chapter.id)
presenter.clearSelection()
withUIContext {
startActivity(intent)
}
}
}
// <-- EXH
}

View File

@ -20,11 +20,11 @@ import eu.kanade.domain.base.BasePreferences
import eu.kanade.domain.category.interactor.GetCategories
import eu.kanade.domain.category.interactor.SetMangaCategories
import eu.kanade.domain.category.model.Category
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
import eu.kanade.domain.chapter.interactor.GetMergedChapterByMangaId
import eu.kanade.domain.chapter.interactor.SetReadStatus
import eu.kanade.domain.chapter.model.Chapter
import eu.kanade.domain.chapter.model.toDbChapter
import eu.kanade.domain.history.interactor.GetNextUnreadChapters
import eu.kanade.domain.library.model.LibraryDisplayMode
import eu.kanade.domain.library.model.LibraryGroup
import eu.kanade.domain.library.model.LibraryManga
@ -54,7 +54,6 @@ import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.models.toDomainManga
import eu.kanade.tachiyomi.data.download.DownloadCache
import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.data.library.CustomMangaManager
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.TrackStatus
@ -65,7 +64,6 @@ import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.source.online.all.MergedSource
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.util.chapter.getChapterSort
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchNonCancellable
import eu.kanade.tachiyomi.util.lang.withIOContext
@ -82,7 +80,6 @@ import exh.search.SearchEngine
import exh.search.Text
import exh.source.EH_SOURCE_ID
import exh.source.MERGED_SOURCE_ID
import exh.source.isEhBasedManga
import exh.source.isMetadataSource
import exh.util.cancellable
import exh.util.isLewd
@ -123,7 +120,7 @@ class LibraryPresenter(
private val getLibraryManga: GetLibraryManga = Injekt.get(),
private val getTracksPerManga: GetTracksPerManga = Injekt.get(),
private val getCategories: GetCategories = Injekt.get(),
private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
private val getNextUnreadChapters: GetNextUnreadChapters = Injekt.get(),
private val setReadStatus: SetReadStatus = Injekt.get(),
private val updateManga: UpdateManga = Injekt.get(),
private val setMangaCategories: SetMangaCategories = Injekt.get(),
@ -602,25 +599,6 @@ class LibraryPresenter(
return mangaCategories.flatten().distinct().subtract(common)
}
fun shouldDownloadChapter(manga: Manga, chapter: Chapter): Boolean {
val activeDownload = downloadManager.queue.find { chapter.id == it.chapter.id }
val downloaded = downloadManager.isChapterDownloaded(chapter.name, chapter.scanlator, manga.title, manga.source)
val state = when {
activeDownload != null -> activeDownload.status
downloaded -> Download.State.DOWNLOADED
else -> Download.State.NOT_DOWNLOADED
}
return state == Download.State.NOT_DOWNLOADED
}
suspend fun getNotDownloadedUnreadChapters(manga: Manga): List<Chapter> {
return getChapterByMangaId.await(manga.id)
.filter { chapter ->
!chapter.read && shouldDownloadChapter(manga, chapter)
}
.sortedWith(getChapterSort(manga, sortDescending = false))
}
/**
* Queues the amount specified of unread chapters from the list of mangas given.
*
@ -630,31 +608,48 @@ class LibraryPresenter(
fun downloadUnreadChapters(mangas: List<Manga>, amount: Int?) {
presenterScope.launchNonCancellable {
mangas.forEach { manga ->
// SY -->
if (manga.source == MERGED_SOURCE_ID) {
val mergedSource = sourceManager.get(MERGED_SOURCE_ID) as MergedSource
val mergedMangas = getMergedMangaById.await(manga.id)
mergedSource
.getChapters(manga.id)
.filter { !it.read }
.associateBy { it.id }
getNextUnreadChapters.await(manga.id)
.let { if (amount != null) it.take(amount) else it }
.groupBy { it.mangaId }
.forEach ab@{ (mangaId, chapters) ->
val mergedManga = mergedMangas.firstOrNull { it.id == mangaId } ?: return@ab
downloadManager.downloadChapters(mergedManga, chapters.map(Chapter::toDbChapter))
}
} else {
/* SY --> */
val chapters = if (manga.isEhBasedManga()) {
getChapterByMangaId.await(manga.id).minByOrNull { it.sourceOrder }
?.takeUnless { it.read }
.let(::listOfNotNull)
} else {
/* SY <-- */ getNotDownloadedUnreadChapters(manga)
.let { if (amount != null) it.take(amount) else it }
val mergedManga = mergedMangas[mangaId] ?: return@ab
val downloadChapters = chapters.filterNot { chapter ->
downloadManager.queue.any { chapter.id == it.chapter.id } ||
downloadManager.isChapterDownloaded(
chapter.name,
chapter.scanlator,
mergedManga.ogTitle,
mergedManga.source,
)
}
downloadManager.downloadChapters(manga, chapters.map { it.toDbChapter() })
downloadManager.downloadChapters(mergedManga, downloadChapters.map(Chapter::toDbChapter))
}
return@forEach
}
// SY <--
val chapters = getNextUnreadChapters.await(manga.id)
.filterNot { chapter ->
downloadManager.queue.any { chapter.id == it.chapter.id } ||
downloadManager.isChapterDownloaded(
chapter.name,
chapter.scanlator,
// SY -->
manga.ogTitle,
// SY <--
manga.source,
)
}
.let { if (amount != null) it.take(amount) else it }
downloadManager.downloadChapters(manga, chapters.map { it.toDbChapter() })
}
}
}
@ -1082,18 +1077,8 @@ class LibraryPresenter(
// SY -->
/** Returns first unread chapter of a manga */
fun getFirstUnread(manga: Manga): Chapter? {
val chapters = if (manga.source == MERGED_SOURCE_ID) {
(sourceManager.get(MERGED_SOURCE_ID) as MergedSource).getChaptersAsBlocking(manga.id)
} else {
runBlocking { getChapterByMangaId.await(manga.id) }
}
return if (manga.isEhBasedManga()) {
val chapter = chapters.sortedBy { it.sourceOrder }.getOrNull(0)
if (chapter?.read == false) chapter else null
} else {
chapters.sortedByDescending { it.sourceOrder }.find { !it.read }
}
suspend fun getFirstUnread(manga: Manga): Chapter? {
return getNextUnreadChapters.await(manga.id).firstOrNull()
}
private fun getGroupedMangaItems(groupType: Int, libraryManga: List<LibraryItem>): Pair<LibraryMap, List<Category>> {

View File

@ -266,7 +266,7 @@ class MangaPresenter(
.distinctUntilChanged()
// SY -->
.combine(
getMergedChapterByMangaId.subscribe(mangaId)
getMergedChapterByMangaId.subscribe(mangaId, true)
.distinctUntilChanged(),
) { (manga, chapters), mergedChapters ->
if (manga.source == MERGED_SOURCE_ID) {
@ -351,7 +351,7 @@ class MangaPresenter(
presenterScope.launchIO {
val manga = getMangaAndChapters.awaitManga(mangaId)
// SY -->
val chapters = (if (manga.source == MERGED_SOURCE_ID) getMergedChapterByMangaId.await(mangaId) else getMangaAndChapters.awaitChapters(mangaId))
val chapters = (if (manga.source == MERGED_SOURCE_ID) getMergedChapterByMangaId.await(mangaId, true) else getMangaAndChapters.awaitChapters(mangaId))
.toChapterItemsParams(manga, null)
val mergedData = getMergedReferencesById.await(mangaId).takeIf { it.isNotEmpty() }?.let { references ->
MergedMangaData(
@ -1041,7 +1041,6 @@ class MangaPresenter(
}
} else {
successState.source.fetchChaptersForMergedManga(successState.manga, manualFetch, true, dedupe)
Unit
}
}
} catch (e: Throwable) {

View File

@ -8,6 +8,7 @@ import androidx.annotation.ColorInt
import com.jakewharton.rxrelay.BehaviorRelay
import eu.kanade.domain.base.BasePreferences
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
import eu.kanade.domain.chapter.interactor.GetMergedChapterByMangaId
import eu.kanade.domain.chapter.interactor.UpdateChapter
import eu.kanade.domain.chapter.model.ChapterUpdate
import eu.kanade.domain.chapter.model.toDbChapter
@ -121,6 +122,7 @@ class ReaderPresenter(
private val getFlatMetadataById: GetFlatMetadataById = Injekt.get(),
private val getMergedManga: GetMergedManga = Injekt.get(),
private val getMergedReferencesById: GetMergedReferencesById = Injekt.get(),
private val getMergedChapterByMangaId: GetMergedChapterByMangaId = Injekt.get(),
// SY <--
) : BasePresenter<ReaderActivity>() {
@ -183,8 +185,7 @@ class ReaderPresenter(
// SY <--
val chapters = runBlocking {
/* SY --> */ if (manga.source == MERGED_SOURCE_ID) {
(sourceManager.get(MERGED_SOURCE_ID) as MergedSource)
.getChapters(manga.id!!)
getMergedChapterByMangaId.await(manga.id!!)
} else {
/* SY <-- */ getChapterByMangaId.await(manga.id!!)
}