From ce7118084a1c4d80562b1e180874ed805abc52ac Mon Sep 17 00:00:00 2001 From: len Date: Fri, 1 Jul 2016 18:30:46 +0200 Subject: [PATCH] Downloads view now uses a copy of the original queue. Fixes #351 and some crashes while scrolling and removing a download from the queue --- .../data/download/model/DownloadQueue.kt | 24 +++++++++--- .../tachiyomi/data/glide/MangaDataFetcher.kt | 15 ++++---- .../tachiyomi/ui/download/DownloadFragment.kt | 4 ++ .../ui/download/DownloadPresenter.kt | 37 +++++++++++-------- .../tachiyomi/ui/library/LibraryHolder.kt | 1 - 5 files changed, 51 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/model/DownloadQueue.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/model/DownloadQueue.kt index e55e66e75d..46d87ec497 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/model/DownloadQueue.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/model/DownloadQueue.kt @@ -6,29 +6,41 @@ import rx.Observable import rx.subjects.PublishSubject import java.util.concurrent.CopyOnWriteArrayList -class DownloadQueue : CopyOnWriteArrayList() { +class DownloadQueue(private val queue: MutableList = CopyOnWriteArrayList()) +: List by queue { private val statusSubject = PublishSubject.create() - override fun add(download: Download): Boolean { + private val removeSubject = PublishSubject.create() + + fun add(download: Download): Boolean { download.setStatusSubject(statusSubject) download.status = Download.QUEUE - return super.add(download) + return queue.add(download) } fun del(download: Download) { - super.remove(download) + val removed = queue.remove(download) download.setStatusSubject(null) + if (removed) { + removeSubject.onNext(download) + } } fun del(chapter: Chapter) { find { it.chapter.id == chapter.id }?.let { del(it) } } - fun getActiveDownloads() = + fun clear() { + queue.forEach { del(it) } + } + + fun getActiveDownloads(): Observable = Observable.from(this).filter { download -> download.status == Download.DOWNLOADING } - fun getStatusObservable() = statusSubject.onBackpressureBuffer() + fun getStatusObservable(): Observable = statusSubject.onBackpressureBuffer() + + fun getRemovedObservable(): Observable = removeSubject.onBackpressureBuffer() fun getProgressObservable(): Observable { return statusSubject.onBackpressureBuffer() diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/glide/MangaDataFetcher.kt b/app/src/main/java/eu/kanade/tachiyomi/data/glide/MangaDataFetcher.kt index 8d3453fc43..7d7e876a70 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/glide/MangaDataFetcher.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/glide/MangaDataFetcher.kt @@ -1,5 +1,6 @@ package eu.kanade.tachiyomi.data.glide +import android.support.v4.util.AtomicFile import com.bumptech.glide.Priority import com.bumptech.glide.load.data.DataFetcher import eu.kanade.tachiyomi.data.database.models.Manga @@ -27,16 +28,14 @@ class MangaDataFetcher(private val networkFetcher: DataFetcher, override fun loadData(priority: Priority): InputStream? { if (manga.favorite) { if (!file.exists()) { - file.parentFile.mkdirs() - networkFetcher.loadData(priority)?.let { + networkFetcher.loadData(priority)?.let { input -> + val atomicFile = AtomicFile(file) + val output = atomicFile.startWrite() try { - it.use { input -> - file.outputStream().use { output -> - input.copyTo(output) - } - } + input.use { it.copyTo(output) } + atomicFile.finishWrite(output) } catch (e: Exception) { - file.delete() + atomicFile.failWrite(output) throw e } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadFragment.kt index 3a58fa0288..31f5c74a1d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadFragment.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadFragment.kt @@ -236,6 +236,10 @@ class DownloadFragment : BaseRxFragment() { adapter.setItems(downloads) } + fun onDownloadRemoved(position: Int) { + adapter.notifyItemRemoved(position) + } + /** * Called when the progress of a download changes. * diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadPresenter.kt index bef58dbf60..ca6b312697 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadPresenter.kt @@ -6,21 +6,16 @@ import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.download.model.DownloadQueue import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import rx.Observable +import rx.android.schedulers.AndroidSchedulers import timber.log.Timber import uy.kohesive.injekt.injectLazy +import java.util.* /** * Presenter of [DownloadFragment]. */ class DownloadPresenter : BasePresenter() { - companion object { - /** - * Id of the restartable that returns the download queue. - */ - const val GET_DOWNLOAD_QUEUE = 1 - } - /** * Download manager. */ @@ -34,15 +29,28 @@ class DownloadPresenter : BasePresenter() { override fun onCreate(savedState: Bundle?) { super.onCreate(savedState) + + Observable.just(ArrayList(downloadQueue)) + .doOnNext { syncQueue(it) } + .subscribeLatestCache({ view, downloads -> + view.onNextDownloads(downloads) + }, { view, error -> + Timber.e(error, error.message) + }) + } - restartableLatestCache(GET_DOWNLOAD_QUEUE, - { Observable.just(downloadQueue) }, - { view, downloads -> view.onNextDownloads(downloads) }, - { view, error -> Timber.e(error.message) }) + private fun syncQueue(queue: MutableList) { + add(downloadQueue.getRemovedObservable() + .observeOn(AndroidSchedulers.mainThread()) + .subscribe { download -> + val position = queue.indexOf(download) + if (position != -1) { + queue.removeAt(position) - if (savedState == null) { - start(GET_DOWNLOAD_QUEUE) - } + @Suppress("DEPRECATION") + view?.onDownloadRemoved(position) + } + }) } fun getStatusObservable(): Observable { @@ -60,7 +68,6 @@ class DownloadPresenter : BasePresenter() { */ fun clearQueue() { downloadManager.clearQueue() - start(GET_DOWNLOAD_QUEUE) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.kt index fa3e6bd803..075803220e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.kt @@ -47,7 +47,6 @@ class LibraryHolder(private val view: View, .load(manga) .diskCacheStrategy(DiskCacheStrategy.RESULT) .centerCrop() - .placeholder(android.R.color.transparent) .into(view.thumbnail) }