fix: Chapter download state stuck in QUEUE on deletion

This commit is contained in:
Ahmad Ansori Palembani 2024-12-13 09:49:52 +07:00
parent aa06a8ad2a
commit 498cafaae6
Signed by: null2264
GPG key ID: BA64F8B60AF3EFB6
6 changed files with 61 additions and 41 deletions

View file

@ -12,9 +12,6 @@ import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.util.system.ImageUtil
import eu.kanade.tachiyomi.util.system.launchIO
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.drop
@ -23,7 +20,6 @@ import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.launch
import uy.kohesive.injekt.injectLazy
import yokai.domain.download.DownloadPreferences
import yokai.i18n.MR
@ -242,24 +238,15 @@ class DownloadManager(val context: Context) {
* @param manga the manga of the chapters.
* @param source the source of the chapters.
*/
@OptIn(DelicateCoroutinesApi::class)
fun deleteChapters(chapters: List<Chapter>, manga: Manga, source: Source, force: Boolean = false) {
val filteredChapters = if (force) chapters else getChaptersToDelete(chapters, manga)
GlobalScope.launch(Dispatchers.IO) {
val wasPaused = isPaused()
launchIO {
val filteredChapters = if (force) chapters else getChaptersToDelete(chapters, manga)
if (filteredChapters.isEmpty()) {
return@launch
return@launchIO
}
downloader.pause()
downloader.removeFromQueue(filteredChapters)
if (!wasPaused && queueState.value.isNotEmpty()) {
downloader.start()
} else if (queueState.value.isEmpty() && DownloadJob.isRunning(context)) {
DownloadJob.stop(context)
} else if (queueState.value.isEmpty()) {
downloader.stop()
}
downloader.removeFromQueue(filteredChapters)
removeFromDownloadQueue(filteredChapters)
val chapterDirs =
provider.findChapterDirs(filteredChapters, manga, source) + provider.findTempChapterDirs(
filteredChapters,
@ -268,12 +255,30 @@ class DownloadManager(val context: Context) {
)
chapterDirs.forEach { it.delete() }
cache.removeChapters(filteredChapters, manga)
if (cache.getDownloadCount(manga, true) == 0) { // Delete manga directory if empty
chapterDirs.firstOrNull()?.parentFile?.delete()
}
}
}
private fun removeFromDownloadQueue(chapters: List<Chapter>) {
val wasRunning = downloader.isRunning
if (wasRunning) {
downloader.pause()
}
downloader.removeFromQueue(chapters)
if (wasRunning) {
if (queueState.value.isEmpty()) {
downloader.stop()
} else if (queueState.value.isNotEmpty()) {
downloader.start()
}
}
}
/**
* return the list of all manga folders
*/

View file

@ -700,7 +700,7 @@ class Downloader(
}
fun removeFromQueue(chapters: List<Chapter>) {
chapters.forEach(::removeFromQueue)
removeFromQueueIf { it.chapter.id in chapters.map { it.id } }
}
fun removeFromQueue(manga: Manga) {

View file

@ -45,7 +45,7 @@ class Download(val source: HttpSource, val manga: Manga, val chapter: Chapter) {
}
val progressFlows = pages!!.map(Page::progressFlow)
emitAll(combine(progressFlows) { it.average().toInt() })
emitAll(combine(progressFlows) { it.average().roundToInt() })
}
.distinctUntilChanged()
.debounce(50)

View file

@ -37,7 +37,7 @@ class DownloadBottomPresenter : BaseCoroutinePresenter<DownloadBottomSheet>(),
downloadManager.statusFlow().collect(::onStatusChange)
}
presenterScope.launchUI {
downloadManager.progressFlow().collect { view?.onUpdateDownloadedPages(it) }
downloadManager.progressFlow().collect(::onPageProgressUpdate)
}
}
@ -115,7 +115,6 @@ class DownloadBottomPresenter : BaseCoroutinePresenter<DownloadBottomSheet>(),
}
override fun onPageProgressUpdate(download: Download) {
super.onPageProgressUpdate(download)
view?.onUpdateDownloadedPages(download)
}
}

View file

@ -68,7 +68,7 @@ class DownloadHolder(private val view: View, val adapter: DownloadAdapter) :
if (binding.downloadProgress.max == 1) {
binding.downloadProgress.max = pages.size * 100
}
binding.downloadProgress.progress = download.pageProgress
binding.downloadProgress.setProgressCompat(download.pageProgress, true)
}
/**

View file

@ -60,6 +60,7 @@ import eu.kanade.tachiyomi.util.manga.MangaUtil
import eu.kanade.tachiyomi.util.shouldDownloadNewChapters
import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.system.ImageUtil
import eu.kanade.tachiyomi.util.system.e
import eu.kanade.tachiyomi.util.system.launchIO
import eu.kanade.tachiyomi.util.system.launchNonCancellableIO
import eu.kanade.tachiyomi.util.system.launchNow
@ -75,6 +76,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.launchIn
@ -188,17 +190,23 @@ class MangaDetailsPresenter(
syncData()
presenterScope.launchUI {
downloadManager.statusFlow().collect(::onStatusChange)
downloadManager.statusFlow()
.filter { it.manga.id == mangaId }
.catch { error -> Logger.e(error) }
.collect(::onStatusChange)
}
presenterScope.launchUI {
downloadManager.progressFlow().collect(::onProgressUpdate)
downloadManager.progressFlow()
.filter { it.manga.id == mangaId }
.catch { error -> Logger.e(error) }
.collect(::onQueueUpdate)
}
presenterScope.launchIO {
downloadManager.queueState.collectLatest(::onQueueUpdate)
}
runBlocking {
tracks = getTrack.awaitAllByMangaId(manga.id!!)
tracks = getTrack.awaitAllByMangaId(mangaId)
}
}
@ -287,7 +295,7 @@ class MangaDetailsPresenter(
for (chapter in chapters) {
if (downloadManager.isChapterDownloaded(chapter, manga)) {
chapter.status = Download.State.DOWNLOADED
} else if (downloadManager.hasQueue()) {
} else if (queue.isNotEmpty()) {
chapter.status = queue.find { it.chapter.id == chapter.id }
?.status ?: Download.State.default
}
@ -380,14 +388,15 @@ class MangaDetailsPresenter(
* @param chapter the chapter to delete.
*/
fun deleteChapter(chapter: ChapterItem) {
downloadManager.deleteChapters(listOf(chapter), manga, source, true)
this.chapters.find { it.id == chapter.id }?.apply {
if (chapter.chapter.bookmark && !preferences.removeBookmarkedChapters().get()) return@apply
status = Download.State.QUEUE
status = Download.State.NOT_DOWNLOADED
download = null
}
view?.updateChapters(this.chapters)
downloadManager.deleteChapters(listOf(chapter), manga, source, true)
}
/**
@ -395,22 +404,21 @@ class MangaDetailsPresenter(
* @param chapters the list of chapters to delete.
*/
fun deleteChapters(chapters: List<ChapterItem>, update: Boolean = true, isEverything: Boolean = false) {
launchIO {
if (isEverything) {
downloadManager.deleteManga(manga, source)
} else {
downloadManager.deleteChapters(chapters, manga, source)
}
}
chapters.forEach { chapter ->
this.chapters.find { it.id == chapter.id }?.apply {
if (chapter.chapter.bookmark && !preferences.removeBookmarkedChapters().get() && !isEverything) return@apply
status = Download.State.QUEUE
status = Download.State.NOT_DOWNLOADED
download = null
}
}
if (update) view?.updateChapters(this.chapters)
if (isEverything) {
downloadManager.deleteManga(manga, source)
} else {
downloadManager.deleteChapters(chapters, manga, source)
}
}
suspend fun refreshMangaFromDb(): Manga {
@ -1143,6 +1151,12 @@ class MangaDetailsPresenter(
return if (date <= 0L) null else date
}
override fun onStatusChange(download: Download) {
super.onStatusChange(download)
chapters.find { it.id == download.chapter.id }?.status = download.status
onPageProgressUpdate(download)
}
private suspend fun onQueueUpdate(queue: List<Download>) = withIOContext {
getChapters(queue)
withUIContext {
@ -1151,12 +1165,14 @@ class MangaDetailsPresenter(
}
override fun onQueueUpdate(download: Download) {
presenterScope.launchIO {
onQueueUpdate(downloadManager.queueState.value)
}
// already handled by onStatusChange
}
override fun onProgressUpdate(download: Download) {
// already handled by onStatusChange
}
override fun onPageProgressUpdate(download: Download) {
chapters.find { it.id == download.chapter.id }?.download = download
view?.updateChapterDownload(download)
}