mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-31 06:17:57 +01:00 
			
		
		
		
	Downloads view now uses a copy of the original queue. Fixes #351 and some crashes while scrolling and removing a download from the queue
This commit is contained in:
		| @@ -6,29 +6,41 @@ import rx.Observable | ||||
| import rx.subjects.PublishSubject | ||||
| import java.util.concurrent.CopyOnWriteArrayList | ||||
|  | ||||
| class DownloadQueue : CopyOnWriteArrayList<Download>() { | ||||
| class DownloadQueue(private val queue: MutableList<Download> = CopyOnWriteArrayList<Download>()) | ||||
| : List<Download> by queue { | ||||
|  | ||||
|     private val statusSubject = PublishSubject.create<Download>() | ||||
|  | ||||
|     override fun add(download: Download): Boolean { | ||||
|     private val removeSubject = PublishSubject.create<Download>() | ||||
|  | ||||
|     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<Download> = | ||||
|         Observable.from(this).filter { download -> download.status == Download.DOWNLOADING } | ||||
|  | ||||
|     fun getStatusObservable() = statusSubject.onBackpressureBuffer() | ||||
|     fun getStatusObservable(): Observable<Download> = statusSubject.onBackpressureBuffer() | ||||
|  | ||||
|     fun getRemovedObservable(): Observable<Download> = removeSubject.onBackpressureBuffer() | ||||
|  | ||||
|     fun getProgressObservable(): Observable<Download> { | ||||
|         return statusSubject.onBackpressureBuffer() | ||||
|   | ||||
| @@ -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<InputStream>, | ||||
|     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 | ||||
|                     } | ||||
|                 } | ||||
|   | ||||
| @@ -236,6 +236,10 @@ class DownloadFragment : BaseRxFragment<DownloadPresenter>() { | ||||
|         adapter.setItems(downloads) | ||||
|     } | ||||
|  | ||||
|     fun onDownloadRemoved(position: Int) { | ||||
|         adapter.notifyItemRemoved(position) | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Called when the progress of a download changes. | ||||
|      * | ||||
|   | ||||
| @@ -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<DownloadFragment>() { | ||||
|  | ||||
|     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<DownloadFragment>() { | ||||
|  | ||||
|     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<Download>) { | ||||
|         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<Download> { | ||||
| @@ -60,7 +68,6 @@ class DownloadPresenter : BasePresenter<DownloadFragment>() { | ||||
|      */ | ||||
|     fun clearQueue() { | ||||
|         downloadManager.clearQueue() | ||||
|         start(GET_DOWNLOAD_QUEUE) | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -47,7 +47,6 @@ class LibraryHolder(private val view: View, | ||||
|                 .load(manga) | ||||
|                 .diskCacheStrategy(DiskCacheStrategy.RESULT) | ||||
|                 .centerCrop() | ||||
|                 .placeholder(android.R.color.transparent) | ||||
|                 .into(view.thumbnail) | ||||
|     } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user