Simplify EHentaiUpdateHelper

This commit is contained in:
Jobobby04 2022-12-15 21:06:24 -05:00
parent 755f3377ad
commit a280a5ed77
3 changed files with 92 additions and 102 deletions

View File

@ -263,8 +263,9 @@ class MangaInfoScreenModel(
if (chapters.isNotEmpty() && manga.isEhBasedManga() && DebugToggles.ENABLE_EXH_ROOT_REDIRECT.enabled) { if (chapters.isNotEmpty() && manga.isEhBasedManga() && 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) launchIO {
.onEach { (acceptedChain, _) -> try {
val (acceptedChain) = updateHelper.findAcceptedRootAndDiscardOthers(manga.source, chapters)
// 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
@ -273,7 +274,10 @@ class MangaInfoScreenModel(
EXHRedirect(acceptedChain.manga.id), EXHRedirect(acceptedChain.manga.id),
) )
} }
}.launchIn(coroutineScope) } catch (e: Exception) {
logcat(LogPriority.ERROR, e) { "Error loading accepted chapter chain" }
}
}
} }
} }
.combine( .combine(

View File

@ -20,9 +20,6 @@ import eu.kanade.domain.manga.model.MangaUpdate
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.io.File import java.io.File
@ -50,111 +47,101 @@ class EHentaiUpdateHelper(context: Context) {
* *
* @return Triple<Accepted, Discarded, HasNew> * @return Triple<Accepted, Discarded, HasNew>
*/ */
fun findAcceptedRootAndDiscardOthers(sourceId: Long, chapters: List<Chapter>): Flow<Triple<ChapterChain, List<ChapterChain>, Boolean>> { suspend fun findAcceptedRootAndDiscardOthers(sourceId: Long, chapters: List<Chapter>): Triple<ChapterChain, List<ChapterChain>, Boolean> {
// Find other chains // Find other chains
val chainsFlow = flowOf(chapters) val chains = chapters
.map { chapterList -> .flatMap { chapter ->
chapterList.flatMap { chapter -> getChapterByUrl.await(chapter.url).map { it.mangaId }
getChapterByUrl.await(chapter.url).map { it.mangaId }
}.distinct()
} }
.map { mangaIds -> .distinct()
mangaIds .mapNotNull { mangaId ->
.mapNotNull { mangaId -> coroutineScope {
coroutineScope { val manga = async(Dispatchers.IO) {
val manga = async(Dispatchers.IO) { getManga.await(mangaId)
getManga.await(mangaId)
}
val chapterList = async(Dispatchers.IO) {
getChapterByMangaId.await(mangaId)
}
val history = async(Dispatchers.IO) {
getHistoryByMangaId.await(mangaId)
}
ChapterChain(
manga.await() ?: return@coroutineScope null,
chapterList.await(),
history.await(),
)
}
} }
.filter { it.manga.source == sourceId } val chapterList = async(Dispatchers.IO) {
getChapterByMangaId.await(mangaId)
}
val history = async(Dispatchers.IO) {
getHistoryByMangaId.await(mangaId)
}
ChapterChain(
manga.await() ?: return@coroutineScope null,
chapterList.await(),
history.await(),
)
}
} }
.filter { it.manga.source == sourceId }
// Accept oldest chain // Accept oldest chain
val chainsWithAccepted = chainsFlow.map { chains -> val accepted = chains.minBy { it.manga.id }
val acceptedChain = chains.minBy { it.manga.id }
acceptedChain to chains val toDiscard = chains.filter { it.manga.favorite && it.manga.id != accepted.manga.id }
} val mangaUpdates = mutableListOf<MangaUpdate>()
return chainsWithAccepted.map { (accepted, chains) -> val chainsAsChapters = chains.flatMap { it.chapters }
val toDiscard = chains.filter { it.manga.favorite && it.manga.id != accepted.manga.id } val chainsAsHistory = chains.flatMap { it.history }
val mangaUpdates = mutableListOf<MangaUpdate>()
val chainsAsChapters = chains.flatMap { it.chapters } return if (toDiscard.isNotEmpty()) {
val chainsAsHistory = chains.flatMap { it.history } // Copy chain chapters to curChapters
val (chapterUpdates, newChapters, new) = getChapterList(accepted, toDiscard, chainsAsChapters)
if (toDiscard.isNotEmpty()) { toDiscard.forEach {
// Copy chain chapters to curChapters mangaUpdates += MangaUpdate(
val (chapterUpdates, newChapters, new) = getChapterList(accepted, toDiscard, chainsAsChapters) id = it.manga.id,
favorite = false,
toDiscard.forEach { dateAdded = 0,
mangaUpdates += MangaUpdate( )
id = it.manga.id,
favorite = false,
dateAdded = 0,
)
}
if (!accepted.manga.favorite) {
mangaUpdates += MangaUpdate(
id = accepted.manga.id,
favorite = true,
dateAdded = System.currentTimeMillis(),
)
}
val newAccepted = ChapterChain(accepted.manga, newChapters, emptyList())
val rootsToMutate = toDiscard + newAccepted
// Apply changes to all manga
updateManga.awaitAll(mangaUpdates)
// Insert new chapters for accepted manga
chapterRepository.updateAll(chapterUpdates)
chapterRepository.addAll(newChapters)
val (newHistory, deleteHistory) = getHistory(getChapterByMangaId.await(accepted.manga.id), chainsAsChapters, chainsAsHistory)
// Delete the duplicate history first
deleteHistory.forEach {
removeHistory.awaitById(it)
}
// Insert new history
newHistory.forEach {
upsertHistory.await(it)
}
// Copy categories from all chains to accepted manga
val newCategories = rootsToMutate.flatMap { chapterChain ->
getCategories.await(chapterChain.manga.id).map { it.id }
}.distinct()
rootsToMutate.forEach {
setMangaCategories.await(it.manga.id, newCategories)
}
Triple(newAccepted, toDiscard, new)
} else {
/*val notNeeded = chains.filter { it.manga.id != accepted.manga.id }
val (newChapters, new) = getChapterList(accepted, notNeeded, chainsAsChapters)
val newAccepted = ChapterChain(accepted.manga, newChapters)
// Insert new chapters for accepted manga
db.insertChapters(newAccepted.chapters).await()*/
Triple(accepted, emptyList(), false)
} }
if (!accepted.manga.favorite) {
mangaUpdates += MangaUpdate(
id = accepted.manga.id,
favorite = true,
dateAdded = System.currentTimeMillis(),
)
}
val newAccepted = ChapterChain(accepted.manga, newChapters, emptyList())
val rootsToMutate = toDiscard + newAccepted
// Apply changes to all manga
updateManga.awaitAll(mangaUpdates)
// Insert new chapters for accepted manga
chapterRepository.updateAll(chapterUpdates)
chapterRepository.addAll(newChapters)
val (newHistory, deleteHistory) = getHistory(getChapterByMangaId.await(accepted.manga.id), chainsAsChapters, chainsAsHistory)
// Delete the duplicate history first
deleteHistory.forEach {
removeHistory.awaitById(it)
}
// Insert new history
newHistory.forEach {
upsertHistory.await(it)
}
// Copy categories from all chains to accepted manga
val newCategories = rootsToMutate.flatMap { chapterChain ->
getCategories.await(chapterChain.manga.id).map { it.id }
}.distinct()
rootsToMutate.forEach {
setMangaCategories.await(it.manga.id, newCategories)
}
Triple(newAccepted, toDiscard, new)
} else {
/*val notNeeded = chains.filter { it.manga.id != accepted.manga.id }
val (newChapters, new) = getChapterList(accepted, notNeeded, chainsAsChapters)
val newAccepted = ChapterChain(accepted.manga, newChapters)
// Insert new chapters for accepted manga
db.insertChapters(newAccepted.chapters).await()*/
Triple(accepted, emptyList(), false)
} }
} }

View File

@ -33,7 +33,6 @@ import exh.metadata.metadata.EHentaiSearchMetadata
import exh.util.cancellable import exh.util.cancellable
import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.single
import kotlinx.coroutines.flow.toList import kotlinx.coroutines.flow.toList
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
@ -165,7 +164,7 @@ class EHentaiUpdateWorker(private val context: Context, workerParams: WorkerPara
// Find accepted root and discard others // Find accepted root and discard others
val (acceptedRoot, discardedRoots, hasNew) = val (acceptedRoot, discardedRoots, hasNew) =
updateHelper.findAcceptedRootAndDiscardOthers(manga.source, chapters).single() updateHelper.findAcceptedRootAndDiscardOthers(manga.source, chapters)
if ((new.isNotEmpty() && manga.id == acceptedRoot.manga.id) || if ((new.isNotEmpty() && manga.id == acceptedRoot.manga.id) ||
(hasNew && updatedManga.none { it.first.id == acceptedRoot.manga.id }) (hasNew && updatedManga.none { it.first.id == acceptedRoot.manga.id })