mirror of
https://github.com/null2264/yokai.git
synced 2025-06-21 10:44:42 +00:00
fix: Chapter download state stuck in QUEUE on deletion
This commit is contained in:
parent
aa06a8ad2a
commit
498cafaae6
6 changed files with 61 additions and 41 deletions
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue