Add download queue features from J2K fork

This commit is contained in:
arkon
2020-02-23 12:42:10 -05:00
parent 3e5a48e5e4
commit fb897e37d1
16 changed files with 439 additions and 127 deletions

View File

@@ -5,6 +5,7 @@ import com.hippo.unifile.UniFile
import com.jakewharton.rxrelay.BehaviorRelay
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.data.download.model.DownloadQueue
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceManager
@@ -19,7 +20,7 @@ import uy.kohesive.injekt.injectLazy
*
* @param context the application context.
*/
class DownloadManager(context: Context) {
class DownloadManager(private val context: Context) {
/**
* The sources manager.
@@ -92,6 +93,29 @@ class DownloadManager(context: Context) {
downloader.clearQueue(isNotification)
}
/**
* Reorders the download queue.
*
* @param downloads value to set the download queue to
*/
fun reorderQueue(downloads: List<Download>) {
val wasRunning = downloader.isRunning
if (downloads.isEmpty()) {
DownloadService.stop(context)
downloader.queue.clear()
return
}
downloader.pause()
downloader.queue.clear()
downloader.queue.addAll(downloads)
if (wasRunning) {
downloader.start()
}
}
/**
* Tells the downloader to enqueue the given list of chapters.
*
@@ -157,6 +181,15 @@ class DownloadManager(context: Context) {
return cache.getDownloadCount(manga)
}
/**
* Calls delete chapter, which deletes a temp download.
*
* @param download the download to cancel.
*/
fun deletePendingDownload(download: Download) {
deleteChapters(listOf(download.chapter), download.manga, download.source)
}
/**
* Deletes the directories of a list of downloaded chapters.
*

View File

@@ -83,7 +83,8 @@ class Downloader(
* Whether the downloader is running.
*/
@Volatile
private var isRunning: Boolean = false
var isRunning: Boolean = false
private set
init {
launchNow {

View File

@@ -24,17 +24,30 @@ class Download(val source: HttpSource, val manga: Manga, val chapter: Chapter) {
set(status) {
field = status
statusSubject?.onNext(this)
statusCallback?.invoke(this)
}
@Transient
private var statusSubject: PublishSubject<Download>? = null
@Transient
private var statusCallback: ((Download) -> Unit)? = null
val progress: Int
get() {
val pages = pages ?: return 0
return pages.map(Page::progress).average().toInt()
}
fun setStatusSubject(subject: PublishSubject<Download>?) {
statusSubject = subject
}
companion object {
fun setStatusCallback(f: ((Download) -> Unit)?) {
statusCallback = f
}
companion object {
const val NOT_DOWNLOADED = 0
const val QUEUE = 1
const val DOWNLOADING = 2

View File

@@ -12,16 +12,18 @@ import rx.subjects.PublishSubject
class DownloadQueue(
private val store: DownloadStore,
private val queue: MutableList<Download> = CopyOnWriteArrayList<Download>()
) :
List<Download> by queue {
) : List<Download> by queue {
private val statusSubject = PublishSubject.create<Download>()
private val updatedRelay = PublishRelay.create<Unit>()
private val downloadListeners = mutableListOf<DownloadListener>()
fun addAll(downloads: List<Download>) {
downloads.forEach { download ->
download.setStatusSubject(statusSubject)
download.setStatusCallback(::setPagesFor)
download.status = Download.QUEUE
}
queue.addAll(downloads)
@@ -33,6 +35,11 @@ class DownloadQueue(
val removed = queue.remove(download)
store.remove(download)
download.setStatusSubject(null)
download.setStatusCallback(null)
if (download.status == Download.DOWNLOADING || download.status == Download.QUEUE) {
download.status = Download.NOT_DOWNLOADED
}
callListeners(download)
if (removed) {
updatedRelay.call(Unit)
}
@@ -55,6 +62,11 @@ class DownloadQueue(
fun clear() {
queue.forEach { download ->
download.setStatusSubject(null)
download.setStatusCallback(null)
if (download.status == Download.DOWNLOADING || download.status == Download.QUEUE) {
download.status = Download.NOT_DOWNLOADED
}
callListeners(download)
}
queue.clear()
store.clear()
@@ -70,6 +82,24 @@ class DownloadQueue(
.startWith(Unit)
.map { this }
private fun setPagesFor(download: Download) {
if (download.status == Download.DOWNLOADING) {
download.pages?.forEach { page ->
page.setStatusCallback {
callListeners(download)
}
}
} else if (download.status == Download.DOWNLOADED || download.status == Download.ERROR) {
setPagesSubject(download.pages, null)
}
callListeners(download)
}
private fun callListeners(download: Download) {
downloadListeners.forEach { it.updateDownload(download) }
}
fun getProgressObservable(): Observable<Download> {
return statusSubject.onBackpressureBuffer()
.startWith(getActiveDownloads())
@@ -77,12 +107,14 @@ class DownloadQueue(
if (download.status == Download.DOWNLOADING) {
val pageStatusSubject = PublishSubject.create<Int>()
setPagesSubject(download.pages, pageStatusSubject)
callListeners(download)
return@flatMap pageStatusSubject
.onBackpressureBuffer()
.filter { it == Page.READY }
.map { download }
} else if (download.status == Download.DOWNLOADED || download.status == Download.ERROR) {
setPagesSubject(download.pages, null)
callListeners(download)
}
Observable.just(download)
}
@@ -96,4 +128,16 @@ class DownloadQueue(
}
}
}
fun addListener(listener: DownloadListener) {
downloadListeners.add(listener)
}
fun removeListener(listener: DownloadListener) {
downloadListeners.remove(listener)
}
interface DownloadListener {
fun updateDownload(download: Download)
}
}