mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-12-23 21:01:51 +01:00
Remove old download controller
This commit is contained in:
parent
d0def563c8
commit
b79eb3f1d3
@ -1,307 +0,0 @@
|
||||
package eu.kanade.tachiyomi.ui.download
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.download.DownloadService
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
|
||||
import eu.kanade.tachiyomi.util.view.RecyclerWindowInsetsListener
|
||||
import eu.kanade.tachiyomi.util.view.applyWindowInsetsForController
|
||||
import kotlinx.android.synthetic.main.download_controller.*
|
||||
import rx.Observable
|
||||
import rx.Subscription
|
||||
import rx.android.schedulers.AndroidSchedulers
|
||||
import java.util.HashMap
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* Controller that shows the currently active downloads.
|
||||
* Uses R.layout.fragment_download_queue.
|
||||
*/
|
||||
class DownloadController : NucleusController<DownloadPresenter>(),
|
||||
DownloadAdapter.DownloadItemListener {
|
||||
|
||||
/**
|
||||
* Adapter containing the active downloads.
|
||||
*/
|
||||
private var adapter: DownloadAdapter? = null
|
||||
|
||||
/**
|
||||
* Map of subscriptions for active downloads.
|
||||
*/
|
||||
private val progressSubscriptions by lazy { HashMap<Download, Subscription>() }
|
||||
|
||||
/**
|
||||
* Whether the download queue is running or not.
|
||||
*/
|
||||
private var isRunning: Boolean = false
|
||||
|
||||
init {
|
||||
setHasOptionsMenu(true)
|
||||
}
|
||||
|
||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||
return inflater.inflate(R.layout.download_controller, container, false)
|
||||
}
|
||||
|
||||
override fun createPresenter(): DownloadPresenter {
|
||||
return DownloadPresenter()
|
||||
}
|
||||
|
||||
override fun getTitle(): String? {
|
||||
return resources?.getString(R.string.label_download_queue)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
view.applyWindowInsetsForController()
|
||||
|
||||
// Check if download queue is empty and update information accordingly.
|
||||
setInformationView()
|
||||
|
||||
// Initialize adapter.
|
||||
adapter = DownloadAdapter(this@DownloadController)
|
||||
recycler.adapter = adapter
|
||||
adapter?.isHandleDragEnabled = true
|
||||
|
||||
// Set the layout manager for the recycler and fixed size.
|
||||
recycler.layoutManager = LinearLayoutManager(view.context)
|
||||
recycler.setHasFixedSize(true)
|
||||
recycler.setOnApplyWindowInsetsListener(RecyclerWindowInsetsListener)
|
||||
|
||||
// Suscribe to changes
|
||||
DownloadService.runningRelay
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeUntilDestroy { onQueueStatusChange(it) }
|
||||
|
||||
presenter.getDownloadStatusObservable()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeUntilDestroy { onStatusChange(it) }
|
||||
|
||||
presenter.getDownloadProgressObservable()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeUntilDestroy { onUpdateDownloadedPages(it) }
|
||||
}
|
||||
|
||||
override fun onDestroyView(view: View) {
|
||||
for (subscription in progressSubscriptions.values) {
|
||||
subscription.unsubscribe()
|
||||
}
|
||||
progressSubscriptions.clear()
|
||||
adapter = null
|
||||
super.onDestroyView(view)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
inflater.inflate(R.menu.download_queue, menu)
|
||||
}
|
||||
|
||||
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||
// Set start button visibility.
|
||||
menu.findItem(R.id.start_queue).isVisible = !isRunning && !presenter.downloadQueue.isEmpty()
|
||||
|
||||
// Set pause button visibility.
|
||||
menu.findItem(R.id.pause_queue).isVisible = isRunning
|
||||
|
||||
// Set clear button visibility.
|
||||
menu.findItem(R.id.clear_queue).isVisible = !presenter.downloadQueue.isEmpty()
|
||||
|
||||
// Set reorder button visibility.
|
||||
menu.findItem(R.id.reorder).isVisible = !presenter.downloadQueue.isEmpty()
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
val context = applicationContext ?: return false
|
||||
when (item.itemId) {
|
||||
R.id.start_queue -> DownloadService.start(context)
|
||||
R.id.pause_queue -> {
|
||||
DownloadService.stop(context)
|
||||
presenter.pauseDownloads()
|
||||
}
|
||||
R.id.clear_queue -> {
|
||||
DownloadService.stop(context)
|
||||
presenter.clearQueue()
|
||||
}
|
||||
R.id.newest, R.id.oldest -> {
|
||||
val adapter = adapter ?: return false
|
||||
val items = adapter.currentItems.sortedBy { it.download.chapter.date_upload }
|
||||
.toMutableList()
|
||||
if (item.itemId == R.id.newest)
|
||||
items.reverse()
|
||||
adapter.updateDataSet(items)
|
||||
val downloads = items.mapNotNull { it.download }
|
||||
presenter.reorder(downloads)
|
||||
}
|
||||
else -> return super.onOptionsItemSelected(item)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the status of a download changes.
|
||||
*
|
||||
* @param download the download whose status has changed.
|
||||
*/
|
||||
private fun onStatusChange(download: Download) {
|
||||
when (download.status) {
|
||||
Download.DOWNLOADING -> {
|
||||
observeProgress(download)
|
||||
// Initial update of the downloaded pages
|
||||
onUpdateDownloadedPages(download)
|
||||
}
|
||||
Download.DOWNLOADED -> {
|
||||
unsubscribeProgress(download)
|
||||
onUpdateProgress(download)
|
||||
onUpdateDownloadedPages(download)
|
||||
}
|
||||
Download.ERROR -> unsubscribeProgress(download)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Observe the progress of a download and notify the view.
|
||||
*
|
||||
* @param download the download to observe its progress.
|
||||
*/
|
||||
private fun observeProgress(download: Download) {
|
||||
val subscription = Observable.interval(50, TimeUnit.MILLISECONDS)
|
||||
// Get the sum of percentages for all the pages.
|
||||
.flatMap {
|
||||
Observable.from(download.pages)
|
||||
.map(Page::progress)
|
||||
.reduce { x, y -> x + y }
|
||||
}
|
||||
// Keep only the latest emission to avoid backpressure.
|
||||
.onBackpressureLatest()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe { progress ->
|
||||
// Update the view only if the progress has changed.
|
||||
if (download.totalProgress != progress) {
|
||||
download.totalProgress = progress
|
||||
onUpdateProgress(download)
|
||||
}
|
||||
}
|
||||
|
||||
// Avoid leaking subscriptions
|
||||
progressSubscriptions.remove(download)?.unsubscribe()
|
||||
|
||||
progressSubscriptions[download] = subscription
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribes the given download from the progress subscriptions.
|
||||
*
|
||||
* @param download the download to unsubscribe.
|
||||
*/
|
||||
private fun unsubscribeProgress(download: Download) {
|
||||
progressSubscriptions.remove(download)?.unsubscribe()
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the queue's status has changed. Updates the visibility of the buttons.
|
||||
*
|
||||
* @param running whether the queue is now running or not.
|
||||
*/
|
||||
private fun onQueueStatusChange(running: Boolean) {
|
||||
isRunning = running
|
||||
activity?.invalidateOptionsMenu()
|
||||
|
||||
// Check if download queue is empty and update information accordingly.
|
||||
setInformationView()
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from the presenter to assign the downloads for the adapter.
|
||||
*
|
||||
* @param downloads the downloads from the queue.
|
||||
*/
|
||||
fun onNextDownloads(downloads: List<DownloadItem>) {
|
||||
activity?.invalidateOptionsMenu()
|
||||
setInformationView()
|
||||
adapter?.updateDataSet(downloads)
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the progress of a download changes.
|
||||
*
|
||||
* @param download the download whose progress has changed.
|
||||
*/
|
||||
fun onUpdateProgress(download: Download) {
|
||||
getHolder(download)?.notifyProgress()
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a page of a download is downloaded.
|
||||
*
|
||||
* @param download the download whose page has been downloaded.
|
||||
*/
|
||||
fun onUpdateDownloadedPages(download: Download) {
|
||||
getHolder(download)?.notifyDownloadedPages()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the holder for the given download.
|
||||
*
|
||||
* @param download the download to find.
|
||||
* @return the holder of the download or null if it's not bound.
|
||||
*/
|
||||
private fun getHolder(download: Download): DownloadHolder? {
|
||||
return recycler?.findViewHolderForItemId(download.chapter.id!!) as? DownloadHolder
|
||||
}
|
||||
|
||||
/**
|
||||
* Set information view when queue is empty
|
||||
*/
|
||||
private fun setInformationView() {
|
||||
if (presenter.downloadQueue.isEmpty()) {
|
||||
empty_view?.show(R.drawable.ic_file_download_black_128dp,
|
||||
R.string.information_no_downloads)
|
||||
} else {
|
||||
empty_view?.hide()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an item is released from a drag.
|
||||
*
|
||||
* @param position The position of the released item.
|
||||
*/
|
||||
override fun onItemReleased(position: Int) {
|
||||
val adapter = adapter ?: return
|
||||
val downloads = (0 until adapter.itemCount).mapNotNull { adapter.getItem(it)?.download }
|
||||
presenter.reorder(downloads)
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the menu item of a download is pressed
|
||||
*
|
||||
* @param position The position of the item
|
||||
* @param menuItem The menu Item pressed
|
||||
*/
|
||||
override fun onMenuItemClick(position: Int, menuItem: MenuItem) {
|
||||
when (menuItem.itemId) {
|
||||
R.id.move_to_top, R.id.move_to_bottom -> {
|
||||
val items = adapter?.currentItems?.toMutableList() ?: return
|
||||
val item = items[position]
|
||||
items.remove(item)
|
||||
if (menuItem.itemId == R.id.move_to_top)
|
||||
items.add(0, item)
|
||||
else
|
||||
items.add(item)
|
||||
adapter?.updateDataSet(items)
|
||||
val downloads = items.mapNotNull { it.download }
|
||||
presenter.reorder(downloads)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onItemRemoved(position: Int) {
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
package eu.kanade.tachiyomi.ui.download
|
||||
|
||||
import android.os.Bundle
|
||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||
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
|
||||
|
||||
/**
|
||||
* Presenter of [DownloadController].
|
||||
*/
|
||||
class DownloadPresenter : BasePresenter<DownloadController>() {
|
||||
|
||||
/**
|
||||
* Download manager.
|
||||
*/
|
||||
val downloadManager: DownloadManager by injectLazy()
|
||||
|
||||
/**
|
||||
* Property to get the queue from the download manager.
|
||||
*/
|
||||
val downloadQueue: DownloadQueue
|
||||
get() = downloadManager.queue
|
||||
|
||||
override fun onCreate(savedState: Bundle?) {
|
||||
super.onCreate(savedState)
|
||||
|
||||
downloadQueue.getUpdatedObservable()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.map { it.map(::DownloadItem) }
|
||||
.subscribeLatestCache(DownloadController::onNextDownloads) { _, error ->
|
||||
Timber.e(error)
|
||||
}
|
||||
}
|
||||
|
||||
fun getDownloadStatusObservable(): Observable<Download> {
|
||||
return downloadQueue.getStatusObservable()
|
||||
.startWith(downloadQueue.getActiveDownloads())
|
||||
}
|
||||
|
||||
fun getDownloadProgressObservable(): Observable<Download> {
|
||||
return downloadQueue.getProgressObservable()
|
||||
.onBackpressureBuffer()
|
||||
}
|
||||
|
||||
/**
|
||||
* Pauses the download queue.
|
||||
*/
|
||||
fun pauseDownloads() {
|
||||
downloadManager.pauseDownloads()
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the download queue.
|
||||
*/
|
||||
fun clearQueue() {
|
||||
downloadManager.clearQueue()
|
||||
}
|
||||
|
||||
fun reorder(downloads: List<Download>) {
|
||||
downloadManager.reorderQueue(downloads)
|
||||
}
|
||||
|
||||
fun cancelDownload(download: Download) {
|
||||
downloadManager.deletePendingDownloads(download)
|
||||
}
|
||||
}
|
@ -47,7 +47,6 @@ import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||
import eu.kanade.tachiyomi.ui.catalogue.CatalogueController
|
||||
import eu.kanade.tachiyomi.ui.catalogue.global_search.CatalogueSearchController
|
||||
import eu.kanade.tachiyomi.ui.download.DownloadController
|
||||
import eu.kanade.tachiyomi.ui.library.LibraryController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaDetailsController
|
||||
import eu.kanade.tachiyomi.ui.recent_updates.RecentChaptersController
|
||||
@ -399,9 +398,12 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
|
||||
router.pushController(MangaDetailsController(extras).withFadeTransaction())
|
||||
}
|
||||
SHORTCUT_DOWNLOADS -> {
|
||||
if (router.backstack.none { it.controller() is DownloadController }) {
|
||||
if (router.backstack.isEmpty()) bottom_nav.selectedItemId = R.id.nav_library
|
||||
router.pushController(DownloadController().withFadeTransaction())
|
||||
bottom_nav.selectedItemId = R.id.nav_catalogues
|
||||
router.popToRoot()
|
||||
bottom_nav.post {
|
||||
val controller =
|
||||
router.backstack.firstOrNull()?.controller() as? RecentsController
|
||||
controller?.showDownloads()
|
||||
}
|
||||
}
|
||||
Intent.ACTION_SEARCH, "com.google.android.gms.actions.SEARCH_ACTION" -> {
|
||||
|
@ -353,6 +353,10 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
|
||||
}
|
||||
}
|
||||
|
||||
fun showDownloads() {
|
||||
dl_bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
}
|
||||
|
||||
fun toggleDownloads() {
|
||||
if (dl_bottom_sheet.sheetBehavior?.isHideable == false) {
|
||||
if (showingDownloads) dl_bottom_sheet.dismiss()
|
||||
|
Loading…
Reference in New Issue
Block a user