mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-03 23:58:55 +01:00 
			
		
		
		
	Add download queue features from J2K fork
This commit is contained in:
		@@ -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.
 | 
			
		||||
     *
 | 
			
		||||
 
 | 
			
		||||
@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user