From 3c87b4cba9b1d1b6a5c3c8abf1e58a2c25747fb6 Mon Sep 17 00:00:00 2001 From: inorichi Date: Sat, 19 Dec 2015 14:58:36 +0100 Subject: [PATCH] Allow to start/stop queue from download queue fragment. DownloadQueue now extends from ArrayList. --- .../data/download/DownloadManager.java | 41 ++++++------ .../data/download/DownloadService.java | 18 +++-- .../data/download/model/DownloadQueue.java | 19 ++---- .../ui/download/DownloadFragment.java | 62 ++++++++++++++++++ .../ui/download/DownloadPresenter.java | 2 +- .../ui/manga/chapter/ChaptersPresenter.java | 2 +- .../main/res/drawable-hdpi/ic_play_arrow.png | Bin 0 -> 205 bytes app/src/main/res/drawable-hdpi/ic_stop.png | Bin 0 -> 99 bytes .../main/res/drawable-ldpi/ic_play_arrow.png | Bin 0 -> 149 bytes app/src/main/res/drawable-ldpi/ic_stop.png | Bin 0 -> 158 bytes .../main/res/drawable-mdpi/ic_play_arrow.png | Bin 0 -> 161 bytes app/src/main/res/drawable-mdpi/ic_stop.png | Bin 0 -> 86 bytes .../main/res/drawable-xhdpi/ic_play_arrow.png | Bin 0 -> 233 bytes app/src/main/res/drawable-xhdpi/ic_stop.png | Bin 0 -> 110 bytes .../res/drawable-xxhdpi/ic_play_arrow.png | Bin 0 -> 316 bytes app/src/main/res/drawable-xxhdpi/ic_stop.png | Bin 0 -> 131 bytes .../res/drawable-xxxhdpi/ic_play_arrow.png | Bin 0 -> 394 bytes app/src/main/res/drawable-xxxhdpi/ic_stop.png | Bin 0 -> 164 bytes app/src/main/res/menu/download_queue.xml | 17 +++++ app/src/main/res/values/strings.xml | 2 + 20 files changed, 123 insertions(+), 40 deletions(-) create mode 100644 app/src/main/res/drawable-hdpi/ic_play_arrow.png create mode 100644 app/src/main/res/drawable-hdpi/ic_stop.png create mode 100644 app/src/main/res/drawable-ldpi/ic_play_arrow.png create mode 100644 app/src/main/res/drawable-ldpi/ic_stop.png create mode 100644 app/src/main/res/drawable-mdpi/ic_play_arrow.png create mode 100644 app/src/main/res/drawable-mdpi/ic_stop.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_play_arrow.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_stop.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_play_arrow.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_stop.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_play_arrow.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_stop.png create mode 100644 app/src/main/res/menu/download_queue.xml diff --git a/app/src/main/java/eu/kanade/mangafeed/data/download/DownloadManager.java b/app/src/main/java/eu/kanade/mangafeed/data/download/DownloadManager.java index 545785d2c..67e2254f9 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/download/DownloadManager.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/download/DownloadManager.java @@ -42,11 +42,11 @@ public class DownloadManager { private PublishSubject downloadsQueueSubject; private BehaviorSubject threadsNumber; + private BehaviorSubject runningSubject; private Subscription downloadsSubscription; private Subscription threadsNumberSubscription; private DownloadQueue queue; - private volatile boolean isQueuePaused; private volatile boolean isRunning; public static final String PAGE_LIST_FILE = "index.json"; @@ -61,9 +61,10 @@ public class DownloadManager { downloadsQueueSubject = PublishSubject.create(); threadsNumber = BehaviorSubject.create(); + runningSubject = BehaviorSubject.create(); } - public void initializeSubscriptions() { + private void initializeSubscriptions() { if (downloadsSubscription != null && !downloadsSubscription.isUnsubscribed()) downloadsSubscription.unsubscribe(); @@ -71,8 +72,6 @@ public class DownloadManager { threadsNumberSubscription.unsubscribe(); threadsNumberSubscription = preferences.getDownloadTheadsObservable() - .filter(n -> !isQueuePaused) - .doOnNext(n -> isQueuePaused = (n == 0)) .subscribe(threadsNumber::onNext); downloadsSubscription = downloadsQueueSubject @@ -86,11 +85,17 @@ public class DownloadManager { } }, e -> Timber.e(e.getCause(), e.getMessage())); - isRunning = true; + if (!isRunning) { + isRunning = true; + runningSubject.onNext(true); + } } public void destroySubscriptions() { - isRunning = false; + if (isRunning) { + isRunning = false; + runningSubject.onNext(false); + } if (downloadsSubscription != null && !downloadsSubscription.isUnsubscribed()) { downloadsSubscription.unsubscribe(); @@ -131,7 +136,7 @@ public class DownloadManager { // Prepare the download. Returns true if the chapter is already downloaded private boolean prepareDownload(Download download) { // If the chapter is already queued, don't add it again - for (Download queuedDownload : queue.get()) { + for (Download queuedDownload : queue) { if (download.chapter.id.equals(queuedDownload.chapter.id)) return true; } @@ -376,28 +381,22 @@ public class DownloadManager { } public boolean areAllDownloadsFinished() { - for (Download download : queue.get()) { + for (Download download : queue) { if (download.getStatus() <= Download.DOWNLOADING) return false; } return true; } - public void resumeDownloads() { - isQueuePaused = false; - threadsNumber.onNext(preferences.getDownloadThreads()); - } - - public void pauseDownloads() { - threadsNumber.onNext(0); - } - public boolean startDownloads() { + if (queue.isEmpty()) + return false; + boolean hasPendingDownloads = false; if (downloadsSubscription == null || threadsNumberSubscription == null) initializeSubscriptions(); - for (Download download : queue.get()) { + for (Download download : queue) { if (download.getStatus() != Download.DOWNLOADED) { if (download.getStatus() != Download.QUEUE) download.setStatus(Download.QUEUE); if (!hasPendingDownloads) hasPendingDownloads = true; @@ -409,15 +408,15 @@ public class DownloadManager { public void stopDownloads() { destroySubscriptions(); - for (Download download : queue.get()) { + for (Download download : queue) { if (download.getStatus() == Download.DOWNLOADING) { download.setStatus(Download.ERROR); } } } - public boolean isRunning() { - return isRunning; + public BehaviorSubject getRunningSubject() { + return runningSubject; } } diff --git a/app/src/main/java/eu/kanade/mangafeed/data/download/DownloadService.java b/app/src/main/java/eu/kanade/mangafeed/data/download/DownloadService.java index 2b648a845..b65a9fe2b 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/download/DownloadService.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/download/DownloadService.java @@ -24,6 +24,7 @@ public class DownloadService extends Service { private PowerManager.WakeLock wakeLock; private Subscription networkChangeSubscription; + private Subscription queueRunningSubscription; public static void start(Context context) { context.startService(new Intent(context, DownloadService.class)); @@ -40,6 +41,7 @@ public class DownloadService extends Service { createWakeLock(); + listenQueueRunningChanges(); EventBus.getDefault().registerSticky(this); listenNetworkChanges(); } @@ -52,6 +54,7 @@ public class DownloadService extends Service { @Override public void onDestroy() { EventBus.getDefault().unregister(this); + queueRunningSubscription.unsubscribe(); networkChangeSubscription.unsubscribe(); downloadManager.destroySubscriptions(); destroyWakeLock(); @@ -67,8 +70,6 @@ public class DownloadService extends Service { public void onEvent(DownloadChaptersEvent event) { EventBus.getDefault().removeStickyEvent(event); downloadManager.onDownloadChaptersEvent(event); - if (downloadManager.isRunning()) - acquireWakeLock(); } private void listenNetworkChanges() { @@ -79,15 +80,22 @@ public class DownloadService extends Service { // If there are no remaining downloads, destroy the service if (!downloadManager.startDownloads()) stopSelf(); - else - acquireWakeLock(); } else { downloadManager.stopDownloads(); - releaseWakeLock(); } }); } + private void listenQueueRunningChanges() { + queueRunningSubscription = downloadManager.getRunningSubject() + .subscribe(running -> { + if (running) + acquireWakeLock(); + else + releaseWakeLock(); + }); + } + private void createWakeLock() { wakeLock = ((PowerManager)getSystemService(POWER_SERVICE)).newWakeLock( PowerManager.PARTIAL_WAKE_LOCK, "DownloadService:WakeLock"); diff --git a/app/src/main/java/eu/kanade/mangafeed/data/download/model/DownloadQueue.java b/app/src/main/java/eu/kanade/mangafeed/data/download/model/DownloadQueue.java index 0407c589a..06b0df460 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/download/model/DownloadQueue.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/download/model/DownloadQueue.java @@ -8,29 +8,28 @@ import eu.kanade.mangafeed.data.source.model.Page; import rx.Observable; import rx.subjects.PublishSubject; -public class DownloadQueue { +public class DownloadQueue extends ArrayList { - private List queue; private PublishSubject statusSubject; public DownloadQueue() { - queue = new ArrayList<>(); + super(); statusSubject = PublishSubject.create(); } - public void add(Download download) { + public boolean add(Download download) { download.setStatusSubject(statusSubject); download.setStatus(Download.QUEUE); - queue.add(download); + return super.add(download); } public void remove(Download download) { - queue.remove(download); + super.remove(download); download.setStatusSubject(null); } public void remove(Chapter chapter) { - for (Download download : queue) { + for (Download download : this) { if (download.chapter.id.equals(chapter.id)) { remove(download); break; @@ -38,12 +37,8 @@ public class DownloadQueue { } } - public List get() { - return queue; - } - public Observable getActiveDownloads() { - return Observable.from(queue) + return Observable.from(this) .filter(download -> download.getStatus() == Download.DOWNLOADING); } diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/download/DownloadFragment.java b/app/src/main/java/eu/kanade/mangafeed/ui/download/DownloadFragment.java index 9c3c7db78..b78cfa780 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/download/DownloadFragment.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/download/DownloadFragment.java @@ -5,6 +5,9 @@ import android.support.annotation.Nullable; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; @@ -13,9 +16,11 @@ import java.util.List; import butterknife.Bind; import butterknife.ButterKnife; import eu.kanade.mangafeed.R; +import eu.kanade.mangafeed.data.download.DownloadService; import eu.kanade.mangafeed.data.download.model.Download; import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment; import nucleus.factory.RequiresPresenter; +import rx.Subscription; @RequiresPresenter(DownloadPresenter.class) public class DownloadFragment extends BaseRxFragment { @@ -23,10 +28,22 @@ public class DownloadFragment extends BaseRxFragment { @Bind(R.id.download_list) RecyclerView recyclerView; private DownloadAdapter adapter; + private MenuItem startButton; + private MenuItem stopButton; + + private Subscription queueStatusSubscription; + private boolean isRunning; + public static DownloadFragment newInstance() { return new DownloadFragment(); } + @Override + public void onCreate(Bundle bundle) { + super.onCreate(bundle); + setHasOptionsMenu(true); + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -43,6 +60,51 @@ public class DownloadFragment extends BaseRxFragment { return view; } + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + inflater.inflate(R.menu.download_queue, menu); + startButton = menu.findItem(R.id.start_queue); + stopButton = menu.findItem(R.id.stop_queue); + + // Menu seems to be inflated after onResume in fragments, so we initialize them here + startButton.setVisible(!isRunning && !getPresenter().downloadManager.getQueue().isEmpty()); + stopButton.setVisible(isRunning); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.start_queue: + DownloadService.start(getActivity()); + break; + case R.id.stop_queue: + DownloadService.stop(getActivity()); + break; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void onResume() { + super.onResume(); + queueStatusSubscription = getPresenter().downloadManager.getRunningSubject() + .subscribe(this::onRunningChange); + } + + @Override + public void onPause() { + queueStatusSubscription.unsubscribe(); + super.onPause(); + } + + private void onRunningChange(boolean running) { + isRunning = running; + if (startButton != null) + startButton.setVisible(!running && !getPresenter().downloadManager.getQueue().isEmpty()); + if (stopButton != null) + stopButton.setVisible(running); + } + private void createAdapter() { adapter = new DownloadAdapter(getActivity()); recyclerView.setAdapter(adapter); diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/download/DownloadPresenter.java b/app/src/main/java/eu/kanade/mangafeed/ui/download/DownloadPresenter.java index 4d4954c6b..2b48da411 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/download/DownloadPresenter.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/download/DownloadPresenter.java @@ -37,7 +37,7 @@ public class DownloadPresenter extends BasePresenter { progressSubscriptions = new HashMap<>(); restartableLatestCache(GET_DOWNLOAD_QUEUE, - () -> Observable.just(downloadQueue.get()), + () -> Observable.just(downloadQueue), DownloadFragment::onNextDownloads, (view, error) -> Timber.e(error.getMessage())); diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/manga/chapter/ChaptersPresenter.java b/app/src/main/java/eu/kanade/mangafeed/ui/manga/chapter/ChaptersPresenter.java index fc0831c25..093e2144f 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/manga/chapter/ChaptersPresenter.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/manga/chapter/ChaptersPresenter.java @@ -148,7 +148,7 @@ public class ChaptersPresenter extends BasePresenter { } private void setChapterStatus(Chapter chapter) { - for (Download download : downloadManager.getQueue().get()) { + for (Download download : downloadManager.getQueue()) { if (chapter.id.equals(download.chapter.id)) { chapter.status = download.getStatus(); return; diff --git a/app/src/main/res/drawable-hdpi/ic_play_arrow.png b/app/src/main/res/drawable-hdpi/ic_play_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..2c96518624bf0582274123ae06639b2705f9ae25 GIT binary patch literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k0wldT1B8Lp6i*k&kcwMxuWsaRHV||k0wldT1B8K;mZytjNX4z>ALkupPZ(rfSm9`5 s)FA<8EN1JKGBM(nTI=e@D`n8k(6GageM;c8Wk6jFp00i_>zopr08vsJ5dZ)H literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-ldpi/ic_play_arrow.png b/app/src/main/res/drawable-ldpi/ic_play_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..b83fa2514ee44fcbccb0b467310ce2146f15a00b GIT binary patch literal 149 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a)47*7|+kcwN$2@6CzIywv{FZuD{ zVDmC5DJiBSSpt<`UtL|AeSMuTb5;;TQDn!(53la;ufN}LC3JyX{Q|ed1qRBByapeb wPQ<+Ol5(F21H)I{N1BR8_alK8GI+ZBxvX4>ezGPr6z~%G877h3Cj}5d z04)G7jxGRSuIx-8&%ntAVC2r;1oFH&y8ui)Iha764;L56QylMFpg7+3Kw-RfKta5< zz+${x0JHIK1I)zxC&0wRd`0R<9=VyB4s_s;@5&iJzf1=);T3K0RWGL B9OD20 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_play_arrow.png b/app/src/main/res/drawable-xxhdpi/ic_play_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..41061c1c821e64b0abbf02941daaf2e5cf118e63 GIT binary patch literal 316 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY0wn)GsXoKNz{u?B;uunK>+Q{rf`<%vSOYEx z7%>RXketz^c}C2DHD{vgCT8gimzSMjJCcsGoHBiUgq2C`&c<}6r&SNnurh_&6ea+fj}Nh)dMd^ir?B1N1G8mo zqy7m+o;{Aw3|=rAwK~dAP~`d5D0O&&{t88&s^(RP6IfPg@f>T=I+P%@!hpxEsq0X} zq1%?WP Mr>mdKI;Vst0MRglC;$Ke literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_stop.png b/app/src/main/res/drawable-xxhdpi/ic_stop.png new file mode 100644 index 0000000000000000000000000000000000000000..f9307dec06a8a3366f4c36f77e31084f8568cef4 GIT binary patch literal 131 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY0wn)GsXhawygXeTLn>~)yQ1;uunK>+P+BzRZRqt``#z zPhwiZkhP#I#Pf-`q@_+#bUy)&GC{{1RJHnapRWlK=b8{=S(JXb>{k z%pktEig`)=+^~)y>*b6!GME# + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 70ba9dbf8..cb0c10093 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -24,6 +24,8 @@ Unread Downloaded Next unread + Start + Stop OK