Fix chapter list live update (#7296)

(cherry picked from commit b96686e6ad0b46a586958179e8cbb1d6a9182323)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt
This commit is contained in:
AntsyLich 2022-06-12 21:23:41 +06:00 committed by Jobobby04
parent e3f577a6e2
commit f7ccbd24f8
12 changed files with 183 additions and 89 deletions

View File

@ -6,6 +6,7 @@ import eu.kanade.domain.chapter.model.Chapter
import eu.kanade.domain.chapter.model.ChapterUpdate import eu.kanade.domain.chapter.model.ChapterUpdate
import eu.kanade.domain.chapter.repository.ChapterRepository import eu.kanade.domain.chapter.repository.ChapterRepository
import eu.kanade.tachiyomi.util.system.logcat import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.flow.Flow
import logcat.LogPriority import logcat.LogPriority
class ChapterRepositoryImpl( class ChapterRepositoryImpl(
@ -96,11 +97,20 @@ class ChapterRepositoryImpl(
} }
override suspend fun getChapterByMangaId(mangaId: Long): List<Chapter> { override suspend fun getChapterByMangaId(mangaId: Long): List<Chapter> {
return try { return handler.awaitList { chaptersQueries.getChaptersByMangaId(mangaId, chapterMapper) }
handler.awaitList { chaptersQueries.getChapterByMangaId(mangaId, chapterMapper) }
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
emptyList()
} }
override suspend fun getChapterByMangaIdFlow(mangaId: Long): Flow<List<Chapter>> {
return handler.subscribeToList { chaptersQueries.getChaptersByMangaId(mangaId, chapterMapper) }
} }
// SY -->
override suspend fun getMergedChapterByMangaId(mangaId: Long): List<Chapter> {
return handler.awaitList { chaptersQueries.getMergedChaptersByMangaId(mangaId, chapterMapper) }
}
override suspend fun getMergedChapterByMangaIdAsFlow(mangaId: Long): Flow<List<Chapter>> {
return handler.subscribeToList { chaptersQueries.getMergedChaptersByMangaId(mangaId, chapterMapper) }
}
// SY <--
} }

View File

@ -47,7 +47,7 @@ class HistoryRepositoryImpl(
else -> throw NotImplementedError("Unknown sorting method") else -> throw NotImplementedError("Unknown sorting method")
} }
val chapters = handler.awaitList { chaptersQueries.getChapterByMangaId(mangaId, chapterMapper) } val chapters = handler.awaitList { chaptersQueries.getChaptersByMangaId(mangaId, chapterMapper) }
.sortedWith(sortFunction) .sortedWith(sortFunction)
val currChapterIndex = chapters.indexOfFirst { chapter.id == it.id } val currChapterIndex = chapters.indexOfFirst { chapter.id == it.id }

View File

@ -4,6 +4,8 @@ import eu.kanade.data.chapter.ChapterRepositoryImpl
import eu.kanade.data.history.HistoryRepositoryImpl import eu.kanade.data.history.HistoryRepositoryImpl
import eu.kanade.data.manga.MangaRepositoryImpl import eu.kanade.data.manga.MangaRepositoryImpl
import eu.kanade.data.source.SourceRepositoryImpl import eu.kanade.data.source.SourceRepositoryImpl
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
import eu.kanade.domain.chapter.interactor.GetMergedChapterByMangaId
import eu.kanade.domain.chapter.interactor.ShouldUpdateDbChapter import eu.kanade.domain.chapter.interactor.ShouldUpdateDbChapter
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
import eu.kanade.domain.chapter.interactor.UpdateChapter import eu.kanade.domain.chapter.interactor.UpdateChapter
@ -55,6 +57,7 @@ class DomainModule : InjektModule {
addFactory { UpdateManga(get()) } addFactory { UpdateManga(get()) }
addSingletonFactory<ChapterRepository> { ChapterRepositoryImpl(get()) } addSingletonFactory<ChapterRepository> { ChapterRepositoryImpl(get()) }
addFactory { GetChapterByMangaId(get()) }
addFactory { UpdateChapter(get()) } addFactory { UpdateChapter(get()) }
addFactory { ShouldUpdateDbChapter() } addFactory { ShouldUpdateDbChapter() }
addFactory { SyncChaptersWithSource(get(), get(), get(), get()) } addFactory { SyncChaptersWithSource(get(), get(), get(), get()) }
@ -87,6 +90,7 @@ class DomainModule : InjektModule {
addFactory { ToggleExcludeFromDataSaver(get()) } addFactory { ToggleExcludeFromDataSaver(get()) }
addFactory { SetSourceCategories(get()) } addFactory { SetSourceCategories(get()) }
addFactory { ToggleSources(get()) } addFactory { ToggleSources(get()) }
addFactory { GetMergedChapterByMangaId(get()) }
// SY <-- // SY <--
} }
} }

View File

@ -0,0 +1,31 @@
package eu.kanade.domain.chapter.interactor
import eu.kanade.domain.chapter.model.Chapter
import eu.kanade.domain.chapter.repository.ChapterRepository
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import logcat.LogPriority
class GetChapterByMangaId(
private val chapterRepository: ChapterRepository,
) {
suspend fun await(mangaId: Long): List<Chapter> {
return try {
chapterRepository.getChapterByMangaId(mangaId)
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
emptyList()
}
}
suspend fun subscribe(mangaId: Long): Flow<List<Chapter>> {
return try {
chapterRepository.getChapterByMangaIdFlow(mangaId)
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
flowOf(emptyList())
}
}
}

View File

@ -0,0 +1,31 @@
package eu.kanade.domain.chapter.interactor
import eu.kanade.domain.chapter.model.Chapter
import eu.kanade.domain.chapter.repository.ChapterRepository
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import logcat.LogPriority
class GetMergedChapterByMangaId(
private val chapterRepository: ChapterRepository,
) {
suspend fun await(mangaId: Long): List<Chapter> {
return try {
chapterRepository.getMergedChapterByMangaId(mangaId)
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
emptyList()
}
}
suspend fun subscribe(mangaId: Long): Flow<List<Chapter>> {
return try {
chapterRepository.getMergedChapterByMangaIdAsFlow(mangaId)
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
flowOf(emptyList())
}
}
}

View File

@ -26,6 +26,7 @@ class SyncChaptersWithSource(
private val chapterRepository: ChapterRepository = Injekt.get(), private val chapterRepository: ChapterRepository = Injekt.get(),
private val shouldUpdateDbChapter: ShouldUpdateDbChapter = Injekt.get(), private val shouldUpdateDbChapter: ShouldUpdateDbChapter = Injekt.get(),
private val updateManga: UpdateManga = Injekt.get(), private val updateManga: UpdateManga = Injekt.get(),
private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
) { ) {
suspend fun await( suspend fun await(
@ -46,7 +47,7 @@ class SyncChaptersWithSource(
} }
// Chapters from db. // Chapters from db.
val dbChapters = chapterRepository.getChapterByMangaId(manga.id) val dbChapters = getChapterByMangaId.await(manga.id)
// Chapters from the source not in db. // Chapters from the source not in db.
val toAdd = mutableListOf<Chapter>() val toAdd = mutableListOf<Chapter>()

View File

@ -2,6 +2,7 @@ package eu.kanade.domain.chapter.repository
import eu.kanade.domain.chapter.model.Chapter import eu.kanade.domain.chapter.model.Chapter
import eu.kanade.domain.chapter.model.ChapterUpdate import eu.kanade.domain.chapter.model.ChapterUpdate
import kotlinx.coroutines.flow.Flow
interface ChapterRepository { interface ChapterRepository {
@ -14,4 +15,12 @@ interface ChapterRepository {
suspend fun removeChaptersWithIds(chapterIds: List<Long>) suspend fun removeChaptersWithIds(chapterIds: List<Long>)
suspend fun getChapterByMangaId(mangaId: Long): List<Chapter> suspend fun getChapterByMangaId(mangaId: Long): List<Chapter>
suspend fun getChapterByMangaIdFlow(mangaId: Long): Flow<List<Chapter>>
// SY -->
suspend fun getMergedChapterByMangaId(mangaId: Long): List<Chapter>
suspend fun getMergedChapterByMangaIdAsFlow(mangaId: Long): Flow<List<Chapter>>
// SY <--
} }

View File

@ -1,5 +1,6 @@
package eu.kanade.tachiyomi.source.online.all package eu.kanade.tachiyomi.source.online.all
import eu.kanade.domain.chapter.interactor.GetMergedChapterByMangaId
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
import eu.kanade.domain.chapter.model.toDbChapter import eu.kanade.domain.chapter.model.toDbChapter
import eu.kanade.domain.manga.model.toDbManga import eu.kanade.domain.manga.model.toDbManga
@ -27,11 +28,11 @@ import exh.source.MERGED_SOURCE_ID
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.supervisorScope import kotlinx.coroutines.supervisorScope
import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit import kotlinx.coroutines.sync.withPermit
import okhttp3.Response import okhttp3.Response
import rx.Observable
import tachiyomi.source.model.ChapterInfo import tachiyomi.source.model.ChapterInfo
import tachiyomi.source.model.MangaInfo import tachiyomi.source.model.MangaInfo
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
@ -42,6 +43,7 @@ import eu.kanade.domain.manga.model.Manga as DomainManga
class MergedSource : HttpSource() { class MergedSource : HttpSource() {
private val db: DatabaseHelper by injectLazy() private val db: DatabaseHelper by injectLazy()
private val getMergedChaptersByMangaId: GetMergedChapterByMangaId by injectLazy()
private val sourceManager: SourceManager by injectLazy() private val sourceManager: SourceManager by injectLazy()
private val downloadManager: DownloadManager by injectLazy() private val downloadManager: DownloadManager by injectLazy()
private val preferences: PreferencesHelper by injectLazy() private val preferences: PreferencesHelper by injectLazy()
@ -99,62 +101,61 @@ class MergedSource : HttpSource() {
} }
// TODO more chapter dedupe // TODO more chapter dedupe
private fun transformMergedChapters(manga: DomainManga, chapterList: List<Chapter>, editScanlators: Boolean, dedupe: Boolean): List<Chapter> { fun transformMergedChapters(mangaId: Long, chapterList: List<DomainChapter>, editScanlators: Boolean, dedupe: Boolean): List<DomainChapter> {
val mangaReferences = db.getMergedMangaReferences(manga.id).executeAsBlocking() val mangaReferences = db.getMergedMangaReferences(mangaId).executeAsBlocking()
if (editScanlators) { val chapters = if (editScanlators) {
val sources = mangaReferences.map { sourceManager.getOrStub(it.mangaSourceId) to it.mangaId } val sources = mangaReferences.map { sourceManager.getOrStub(it.mangaSourceId) to it.mangaId }
chapterList.onEach { chapter -> chapterList.map { chapter ->
val source = sources.firstOrNull { chapter.manga_id == it.second }?.first val source = sources.firstOrNull { chapter.mangaId == it.second }?.first
if (source != null) { if (source != null) {
chapter.scanlator = if (chapter.scanlator.isNullOrBlank()) source.name chapter.copy(
else "$source: ${chapter.scanlator}" scanlator = if (chapter.scanlator.isNullOrBlank()) {
source.name
} else {
"$source: ${chapter.scanlator}"
},
)
} else chapter
} }
} } else chapterList
} return if (dedupe) dedupeChapterList(mangaReferences, chapters) else chapters
return if (dedupe) dedupeChapterList(mangaReferences, chapterList) else chapterList
} }
fun getChaptersAsBlocking(manga: DomainManga, editScanlators: Boolean = false, dedupe: Boolean = true): List<Chapter> { fun getChaptersAsBlocking(mangaId: Long, editScanlators: Boolean = false, dedupe: Boolean = true): List<Chapter> {
return transformMergedChapters(manga, db.getChaptersByMergedMangaId(manga.id).executeAsBlocking(), editScanlators, dedupe) return transformMergedChapters(mangaId, runBlocking { getMergedChaptersByMangaId.await(mangaId) }, editScanlators, dedupe)
.map(DomainChapter::toDbChapter)
} }
fun getChaptersObservable(manga: DomainManga, editScanlators: Boolean = false, dedupe: Boolean = true): Observable<List<Chapter>> { private fun dedupeChapterList(mangaReferences: List<MergedMangaReference>, chapterList: List<DomainChapter>): List<DomainChapter> {
return db.getChaptersByMergedMangaId(manga.id).asRxObservable()
.map { chapterList ->
transformMergedChapters(manga, chapterList, editScanlators, dedupe)
}
}
private fun dedupeChapterList(mangaReferences: List<MergedMangaReference>, chapterList: List<Chapter>): List<Chapter> {
return when (mangaReferences.firstOrNull { it.mangaSourceId == MERGED_SOURCE_ID }?.chapterSortMode) { return when (mangaReferences.firstOrNull { it.mangaSourceId == MERGED_SOURCE_ID }?.chapterSortMode) {
MergedMangaReference.CHAPTER_SORT_NO_DEDUPE, MergedMangaReference.CHAPTER_SORT_NONE -> chapterList MergedMangaReference.CHAPTER_SORT_NO_DEDUPE, MergedMangaReference.CHAPTER_SORT_NONE -> chapterList
MergedMangaReference.CHAPTER_SORT_PRIORITY -> chapterList MergedMangaReference.CHAPTER_SORT_PRIORITY -> chapterList
MergedMangaReference.CHAPTER_SORT_MOST_CHAPTERS -> { MergedMangaReference.CHAPTER_SORT_MOST_CHAPTERS -> {
findSourceWithMostChapters(chapterList)?.let { mangaId -> findSourceWithMostChapters(chapterList)?.let { mangaId ->
chapterList.filter { it.manga_id == mangaId } chapterList.filter { it.mangaId == mangaId }
} ?: chapterList } ?: chapterList
} }
MergedMangaReference.CHAPTER_SORT_HIGHEST_CHAPTER_NUMBER -> { MergedMangaReference.CHAPTER_SORT_HIGHEST_CHAPTER_NUMBER -> {
findSourceWithHighestChapterNumber(chapterList)?.let { mangaId -> findSourceWithHighestChapterNumber(chapterList)?.let { mangaId ->
chapterList.filter { it.manga_id == mangaId } chapterList.filter { it.mangaId == mangaId }
} ?: chapterList } ?: chapterList
} }
else -> chapterList else -> chapterList
} }
} }
private fun findSourceWithMostChapters(chapterList: List<Chapter>): Long? { private fun findSourceWithMostChapters(chapterList: List<DomainChapter>): Long? {
return chapterList.groupBy { it.manga_id }.maxByOrNull { it.value.size }?.key return chapterList.groupBy { it.mangaId }.maxByOrNull { it.value.size }?.key
} }
private fun findSourceWithHighestChapterNumber(chapterList: List<Chapter>): Long? { private fun findSourceWithHighestChapterNumber(chapterList: List<DomainChapter>): Long? {
return chapterList.maxByOrNull { it.chapter_number }?.manga_id return chapterList.maxByOrNull { it.chapterNumber }?.mangaId
} }
suspend fun fetchChaptersForMergedManga(manga: DomainManga, downloadChapters: Boolean = true, editScanlators: Boolean = false, dedupe: Boolean = true): List<Chapter> { suspend fun fetchChaptersForMergedManga(manga: DomainManga, downloadChapters: Boolean = true, editScanlators: Boolean = false, dedupe: Boolean = true): List<Chapter> {
return withIOContext { return withIOContext {
fetchChaptersAndSync(manga, downloadChapters) fetchChaptersAndSync(manga, downloadChapters)
getChaptersAsBlocking(manga, editScanlators, dedupe) getChaptersAsBlocking(manga.id, editScanlators, dedupe)
} }
} }

View File

@ -9,7 +9,6 @@ import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.MangaCategory import eu.kanade.tachiyomi.data.database.models.MangaCategory
import eu.kanade.tachiyomi.data.database.models.toDomainManga
import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.library.CustomMangaManager import eu.kanade.tachiyomi.data.library.CustomMangaManager
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
@ -642,7 +641,7 @@ class LibraryPresenter(
val mergedSource = sourceManager.get(MERGED_SOURCE_ID) as MergedSource val mergedSource = sourceManager.get(MERGED_SOURCE_ID) as MergedSource
val mergedMangas = db.getMergedMangas(manga.id!!).executeAsBlocking() val mergedMangas = db.getMergedMangas(manga.id!!).executeAsBlocking()
mergedSource mergedSource
.getChaptersAsBlocking(manga.toDomainManga()!!) .getChaptersAsBlocking(manga.id!!)
.filter { !it.read } .filter { !it.read }
.groupBy { it.manga_id!! } .groupBy { it.manga_id!! }
.forEach ab@{ (mangaId, chapters) -> .forEach ab@{ (mangaId, chapters) ->
@ -712,7 +711,7 @@ class LibraryPresenter(
mangas.forEach { manga -> mangas.forEach { manga ->
launchIO { launchIO {
val chapters = if (manga.source == MERGED_SOURCE_ID) { val chapters = if (manga.source == MERGED_SOURCE_ID) {
(sourceManager.get(MERGED_SOURCE_ID) as MergedSource).getChaptersAsBlocking(manga.toDomainManga()!!) (sourceManager.get(MERGED_SOURCE_ID) as MergedSource).getChaptersAsBlocking(manga.id!!)
} else { } else {
db.getChapters(manga).executeAsBlocking() db.getChapters(manga).executeAsBlocking()
} }
@ -820,7 +819,7 @@ class LibraryPresenter(
/** Returns first unread chapter of a manga */ /** Returns first unread chapter of a manga */
fun getFirstUnread(manga: Manga): Chapter? { fun getFirstUnread(manga: Manga): Chapter? {
val chapters = if (manga.source == MERGED_SOURCE_ID) { val chapters = if (manga.source == MERGED_SOURCE_ID) {
(sourceManager.get(MERGED_SOURCE_ID) as MergedSource).getChaptersAsBlocking(manga.toDomainManga()!!) (sourceManager.get(MERGED_SOURCE_ID) as MergedSource).getChaptersAsBlocking(manga.id!!)
} else db.getChapters(manga).executeAsBlocking() } else db.getChapters(manga).executeAsBlocking()
return if (manga.isEhBasedManga()) { return if (manga.isEhBasedManga()) {
val chapter = chapters.sortedBy { it.source_order }.getOrNull(0) val chapter = chapters.sortedBy { it.source_order }.getOrNull(0)

View File

@ -4,6 +4,9 @@ import android.content.Context
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import com.jakewharton.rxrelay.PublishRelay import com.jakewharton.rxrelay.PublishRelay
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
import eu.kanade.domain.chapter.interactor.GetMergedChapterByMangaId
import eu.kanade.domain.chapter.model.toDbChapter
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
@ -69,7 +72,9 @@ import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.supervisorScope import kotlinx.coroutines.supervisorScope
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -93,6 +98,8 @@ class MangaPresenter(
private val downloadManager: DownloadManager = Injekt.get(), private val downloadManager: DownloadManager = Injekt.get(),
private val coverCache: CoverCache = Injekt.get(), private val coverCache: CoverCache = Injekt.get(),
private val sourceManager: SourceManager = Injekt.get(), private val sourceManager: SourceManager = Injekt.get(),
private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
private val getMergedChapterByMangaId: GetMergedChapterByMangaId = Injekt.get(),
) : BasePresenter<MangaController>() { ) : BasePresenter<MangaController>() {
/** /**
@ -108,9 +115,7 @@ class MangaPresenter(
/** /**
* Subject of list of chapters to allow updating the view without going to DB. * Subject of list of chapters to allow updating the view without going to DB.
*/ */
private val chaptersRelay: PublishRelay<List<ChapterItem>> by lazy { private val chaptersRelay by lazy { PublishRelay.create<List<ChapterItem>>() }
PublishRelay.create<List<ChapterItem>>()
}
/** /**
* Whether the chapter list has been requested to the source. * Whether the chapter list has been requested to the source.
@ -220,37 +225,32 @@ class MangaPresenter(
// Chapters list - start // Chapters list - start
// Add the subscription that retrieves the chapters from the database, keeps subscribed to // Keeps subscribed to changes and sends the list of chapters to the relay.
// changes, and sends the list of chapters to the relay. presenterScope.launchIO {
add( manga.id?.let { mangaId ->
(/* SY --> */if (source is MergedSource) source.getChaptersObservable(manga.toDomainManga()!!, true, dedupe) else /* SY <-- */ db.getChapters(manga).asRxObservable()) if (source is MergedSource) {
.map { chapters -> getMergedChapterByMangaId.subscribe(mangaId)
// Convert every chapter to a model. .map { source.transformMergedChapters(mangaId, it, true, dedupe) }
chapters.map { it.toModel() } } else {
getChapterByMangaId.subscribe(mangaId)
} }
.doOnNext { chapters -> .collectLatest { domainChapters ->
// Find downloaded chapters val chapterItems = domainChapters.map { it.toDbChapter().toModel() }
setDownloadedChapters(chapters) setDownloadedChapters(chapterItems)
this@MangaPresenter.allChapters = chapterItems
allChapterScanlators = chapters.flatMap { MdUtil.getScanlators(it.chapter.scanlator) }.toSet()
// Store the last emission
this.allChapters = chapters
// Listen for download status changes
observeDownloads() observeDownloads()
// SY --> // SY -->
if (chapters.isNotEmpty() && (source.isEhBasedSource()) && DebugToggles.ENABLE_EXH_ROOT_REDIRECT.enabled) { if (domainChapters.isNotEmpty() && (source.isEhBasedSource()) && DebugToggles.ENABLE_EXH_ROOT_REDIRECT.enabled) {
// Check for gallery in library and accept manga with lowest id // Check for gallery in library and accept manga with lowest id
// Find chapters sharing same root // Find chapters sharing same root
updateHelper.findAcceptedRootAndDiscardOthers(manga.source, chapters) updateHelper.findAcceptedRootAndDiscardOthers(manga.source, domainChapters.map { it.toDbChapter() })
.onEach { (acceptedChain, _) -> .onEach { (acceptedChain, _) ->
// Redirect if we are not the accepted root // Redirect if we are not the accepted root
if (manga.id != acceptedChain.manga.id && acceptedChain.manga.favorite) { if (manga.id != acceptedChain.manga.id && acceptedChain.manga.favorite) {
// Update if any of our chapters are not in accepted manga's chapters // Update if any of our chapters are not in accepted manga's chapters
xLogD("Found accepted manga %s", manga.url) xLogD("Found accepted manga %s", manga.url)
val ourChapterUrls = chapters.map { it.url }.toSet() val ourChapterUrls = domainChapters.map { it.url }.toSet()
val acceptedChapterUrls = acceptedChain.chapters.map { it.url }.toSet() val acceptedChapterUrls = acceptedChain.chapters.map { it.url }.toSet()
val update = (ourChapterUrls - acceptedChapterUrls).isNotEmpty() val update = (ourChapterUrls - acceptedChapterUrls).isNotEmpty()
redirectFlow.emit( redirectFlow.emit(
@ -263,9 +263,10 @@ class MangaPresenter(
}.launchIn(presenterScope) }.launchIn(presenterScope)
} }
// SY <-- // SY <--
chaptersRelay.call(chapterItems)
}
}
} }
.subscribe { chaptersRelay.call(it) },
)
// Chapters list - end // Chapters list - end

View File

@ -15,7 +15,6 @@ import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.toDomainManga
import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.saver.Image import eu.kanade.tachiyomi.data.saver.Image
@ -146,7 +145,7 @@ class ReaderPresenter(
// SY <-- // SY <--
val dbChapters = /* SY --> */ if (manga.source == MERGED_SOURCE_ID) { val dbChapters = /* SY --> */ if (manga.source == MERGED_SOURCE_ID) {
(sourceManager.get(MERGED_SOURCE_ID) as MergedSource) (sourceManager.get(MERGED_SOURCE_ID) as MergedSource)
.getChaptersAsBlocking(manga.toDomainManga()!!) .getChaptersAsBlocking(manga.id!!)
} else /* SY <-- */ db.getChapters(manga).executeAsBlocking() } else /* SY <-- */ db.getChapters(manga).executeAsBlocking()
val selectedChapter = dbChapters.find { it.id == chapterId } val selectedChapter = dbChapters.find { it.id == chapterId }

View File

@ -23,11 +23,19 @@ SELECT *
FROM chapters FROM chapters
WHERE _id = :id; WHERE _id = :id;
getChapterByMangaId: getChaptersByMangaId:
SELECT * SELECT *
FROM chapters FROM chapters
WHERE manga_id = :mangaId; WHERE manga_id = :mangaId;
getMergedChaptersByMangaId:
SELECT chapters.*
FROM (
SELECT manga_id FROM merged WHERE merge_id = ?
) AS M
JOIN chapters
ON chapters.manga_id = M.manga_id;
removeChaptersWithIds: removeChaptersWithIds:
DELETE FROM chapters DELETE FROM chapters
WHERE _id IN :chapterIds; WHERE _id IN :chapterIds;