Merge pull request #126 from beschoenen/downloading

Download features
This commit is contained in:
inorichi 2016-02-09 21:15:36 +01:00
commit 7835921045
14 changed files with 124 additions and 61 deletions

View file

@ -4,15 +4,7 @@ import android.os.Bundle;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.*;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import eu.kanade.tachiyomi.R; import eu.kanade.tachiyomi.R;
@ -22,6 +14,8 @@ import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment;
import nucleus.factory.RequiresPresenter; import nucleus.factory.RequiresPresenter;
import rx.Subscription; import rx.Subscription;
import java.util.List;
@RequiresPresenter(DownloadPresenter.class) @RequiresPresenter(DownloadPresenter.class)
public class DownloadFragment extends BaseRxFragment<DownloadPresenter> { public class DownloadFragment extends BaseRxFragment<DownloadPresenter> {
@ -29,7 +23,8 @@ public class DownloadFragment extends BaseRxFragment<DownloadPresenter> {
private DownloadAdapter adapter; private DownloadAdapter adapter;
private MenuItem startButton; private MenuItem startButton;
private MenuItem stopButton; private MenuItem pauseButton;
private MenuItem clearButton;
private Subscription queueStatusSubscription; private Subscription queueStatusSubscription;
private boolean isRunning; private boolean isRunning;
@ -64,11 +59,16 @@ public class DownloadFragment extends BaseRxFragment<DownloadPresenter> {
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.download_queue, menu); inflater.inflate(R.menu.download_queue, menu);
startButton = menu.findItem(R.id.start_queue); startButton = menu.findItem(R.id.start_queue);
stopButton = menu.findItem(R.id.stop_queue); pauseButton = menu.findItem(R.id.pause_queue);
clearButton = menu.findItem(R.id.clear_queue);
if(adapter.getItemCount() > 0) {
clearButton.setVisible(true);
}
// Menu seems to be inflated after onResume in fragments, so we initialize them here // Menu seems to be inflated after onResume in fragments, so we initialize them here
startButton.setVisible(!isRunning && !getPresenter().downloadManager.getQueue().isEmpty()); startButton.setVisible(!isRunning && !getPresenter().downloadManager.getQueue().isEmpty());
stopButton.setVisible(isRunning); pauseButton.setVisible(isRunning);
} }
@Override @Override
@ -77,9 +77,14 @@ public class DownloadFragment extends BaseRxFragment<DownloadPresenter> {
case R.id.start_queue: case R.id.start_queue:
DownloadService.start(getActivity()); DownloadService.start(getActivity());
break; break;
case R.id.stop_queue: case R.id.pause_queue:
DownloadService.stop(getActivity()); DownloadService.stop(getActivity());
break; break;
case R.id.clear_queue:
DownloadService.stop(getActivity());
getPresenter().clearQueue();
clearButton.setVisible(false);
break;
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
@ -101,8 +106,8 @@ public class DownloadFragment extends BaseRxFragment<DownloadPresenter> {
isRunning = running; isRunning = running;
if (startButton != null) if (startButton != null)
startButton.setVisible(!running && !getPresenter().downloadManager.getQueue().isEmpty()); startButton.setVisible(!running && !getPresenter().downloadManager.getQueue().isEmpty());
if (stopButton != null) if (pauseButton != null)
stopButton.setVisible(running); pauseButton.setVisible(running);
} }
private void createAdapter() { private void createAdapter() {

View file

@ -1,12 +1,6 @@
package eu.kanade.tachiyomi.ui.download; package eu.kanade.tachiyomi.ui.download;
import android.os.Bundle; import android.os.Bundle;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import eu.kanade.tachiyomi.data.download.DownloadManager; import eu.kanade.tachiyomi.data.download.DownloadManager;
import eu.kanade.tachiyomi.data.download.model.Download; import eu.kanade.tachiyomi.data.download.model.Download;
import eu.kanade.tachiyomi.data.download.model.DownloadQueue; import eu.kanade.tachiyomi.data.download.model.DownloadQueue;
@ -18,6 +12,10 @@ import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers; import rx.schedulers.Schedulers;
import timber.log.Timber; import timber.log.Timber;
import javax.inject.Inject;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
public class DownloadPresenter extends BasePresenter<DownloadFragment> { public class DownloadPresenter extends BasePresenter<DownloadFragment> {
@Inject DownloadManager downloadManager; @Inject DownloadManager downloadManager;
@ -123,4 +121,8 @@ public class DownloadPresenter extends BasePresenter<DownloadFragment> {
remove(statusSubscription); remove(statusSubscription);
} }
public void clearQueue() {
downloadQueue.clear();
start(GET_DOWNLOAD_QUEUE);
}
} }

View file

@ -8,21 +8,12 @@ import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.view.ActionMode; import android.support.v7.view.ActionMode;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.*;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.ImageView; import android.widget.ImageView;
import com.afollestad.materialdialogs.MaterialDialog;
import java.util.List;
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import com.afollestad.materialdialogs.MaterialDialog;
import eu.kanade.tachiyomi.R; import eu.kanade.tachiyomi.R;
import eu.kanade.tachiyomi.data.database.models.Chapter; import eu.kanade.tachiyomi.data.database.models.Chapter;
import eu.kanade.tachiyomi.data.database.models.Manga; import eu.kanade.tachiyomi.data.database.models.Manga;
@ -40,6 +31,9 @@ import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers; import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers; import rx.schedulers.Schedulers;
import java.util.ArrayList;
import java.util.List;
@RequiresPresenter(ChaptersPresenter.class) @RequiresPresenter(ChaptersPresenter.class)
public class ChaptersFragment extends BaseRxFragment<ChaptersPresenter> implements public class ChaptersFragment extends BaseRxFragment<ChaptersPresenter> implements
ActionMode.Callback, FlexibleViewHolder.OnListItemClickListener { ActionMode.Callback, FlexibleViewHolder.OnListItemClickListener {
@ -110,6 +104,9 @@ public class ChaptersFragment extends BaseRxFragment<ChaptersPresenter> implemen
case R.id.action_display_mode: case R.id.action_display_mode:
showDisplayModeDialog(); showDisplayModeDialog();
return true; return true;
case R.id.manga_download:
showDownloadDialog();
return true;
} }
return false; return false;
} }
@ -190,6 +187,7 @@ public class ChaptersFragment extends BaseRxFragment<ChaptersPresenter> implemen
int selectedIndex = manga.getDisplayMode() == Manga.DISPLAY_NAME ? 0 : 1; int selectedIndex = manga.getDisplayMode() == Manga.DISPLAY_NAME ? 0 : 1;
new MaterialDialog.Builder(getActivity()) new MaterialDialog.Builder(getActivity())
.title(R.string.action_display_mode)
.items(modes) .items(modes)
.itemsIds(ids) .itemsIds(ids)
.itemsCallbackSingleChoice(selectedIndex, (dialog, itemView, which, text) -> { .itemsCallbackSingleChoice(selectedIndex, (dialog, itemView, which, text) -> {
@ -202,6 +200,32 @@ public class ChaptersFragment extends BaseRxFragment<ChaptersPresenter> implemen
.show(); .show();
} }
private void showDownloadDialog() {
// Get available modes
String[] modes = {getString(R.string.download_all), getString(R.string.download_unread)};
new MaterialDialog.Builder(getActivity())
.title(R.string.manga_download)
.items(modes)
.itemsCallback((dialog, view, i, charSequence) -> {
List<Chapter> chapters = new ArrayList<>();
for(Chapter chapter : getPresenter().getChapters()) {
if(!chapter.isDownloaded()) {
if(i == 0 || (i == 1 && !chapter.read)) {
chapters.add(chapter);
}
}
}
if(chapters.size() > 0) {
onDownload(Observable.from(chapters));
}
})
.negativeText(R.string.button_cancel)
.show();
}
private void observeChapterDownloadProgress() { private void observeChapterDownloadProgress() {
downloadProgressSubscription = getPresenter().getDownloadProgressObs() downloadProgressSubscription = getPresenter().getDownloadProgressObs()
.subscribe(this::onDownloadProgressChange, .subscribe(this::onDownloadProgressChange,

View file

@ -2,16 +2,11 @@ package eu.kanade.tachiyomi.ui.manga.chapter;
import android.content.Context; import android.content.Context;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
import android.view.Menu;
import android.view.View; import android.view.View;
import android.widget.PopupMenu; import android.widget.PopupMenu;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Date;
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import eu.kanade.tachiyomi.R; import eu.kanade.tachiyomi.R;
@ -21,6 +16,11 @@ import eu.kanade.tachiyomi.data.download.model.Download;
import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder; import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder;
import rx.Observable; import rx.Observable;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Date;
public class ChaptersHolder extends FlexibleViewHolder { public class ChaptersHolder extends FlexibleViewHolder {
@Bind(R.id.chapter_title) TextView title; @Bind(R.id.chapter_title) TextView title;
@ -110,19 +110,36 @@ public class ChaptersHolder extends FlexibleViewHolder {
// Inflate our menu resource into the PopupMenu's Menu // Inflate our menu resource into the PopupMenu's Menu
popup.getMenuInflater().inflate(R.menu.chapter_single, popup.getMenu()); popup.getMenuInflater().inflate(R.menu.chapter_single, popup.getMenu());
// Hide download and show delete if the chapter is downloaded and
if(item.isDownloaded()) {
Menu menu = popup.getMenu();
menu.findItem(R.id.action_download).setVisible(false);
menu.findItem(R.id.action_delete).setVisible(true);
}
// Hide mark as unread when the chapter is unread
if(!item.read && item.last_page_read == 0) {
popup.getMenu().findItem(R.id.action_mark_as_unread).setVisible(false);
}
// Hide mark as read when the chapter is read
if(item.read) {
popup.getMenu().findItem(R.id.action_mark_as_read).setVisible(false);
}
// Set a listener so we are notified if a menu item is clicked // Set a listener so we are notified if a menu item is clicked
popup.setOnMenuItemClickListener(menuItem -> { popup.setOnMenuItemClickListener(menuItem -> {
Observable<Chapter> chapter = Observable.just(item); Observable<Chapter> chapter = Observable.just(item);
switch (menuItem.getItemId()) { switch (menuItem.getItemId()) {
case R.id.action_mark_as_read:
return adapter.getFragment().onMarkAsRead(chapter);
case R.id.action_mark_as_unread:
return adapter.getFragment().onMarkAsUnread(chapter);
case R.id.action_download: case R.id.action_download:
return adapter.getFragment().onDownload(chapter); return adapter.getFragment().onDownload(chapter);
case R.id.action_delete: case R.id.action_delete:
return adapter.getFragment().onDelete(chapter); return adapter.getFragment().onDelete(chapter);
case R.id.action_mark_as_read:
return adapter.getFragment().onMarkAsRead(chapter);
case R.id.action_mark_as_unread:
return adapter.getFragment().onMarkAsUnread(chapter);
case R.id.action_mark_previous_as_read: case R.id.action_mark_previous_as_read:
return adapter.getFragment().onMarkPreviousAsRead(item); return adapter.getFragment().onMarkPreviousAsRead(item);
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 B

View file

@ -6,11 +6,13 @@
<item android:id="@+id/action_download" <item android:id="@+id/action_download"
android:title="@string/action_download" android:title="@string/action_download"
android:icon="@drawable/ic_file_download" android:icon="@drawable/ic_file_download"
android:visible="true"
app:showAsAction="ifRoom"/> app:showAsAction="ifRoom"/>
<item android:id="@+id/action_delete" <item android:id="@+id/action_delete"
android:title="@string/action_delete" android:title="@string/action_delete"
android:icon="@drawable/ic_action_delete" android:icon="@drawable/ic_action_delete"
android:visible="false"
app:showAsAction="ifRoom"/> app:showAsAction="ifRoom"/>
<item android:id="@+id/action_mark_as_read" <item android:id="@+id/action_mark_as_read"
@ -23,8 +25,7 @@
android:icon="@drawable/ic_action_undone_all" android:icon="@drawable/ic_action_undone_all"
app:showAsAction="ifRoom"/> app:showAsAction="ifRoom"/>
<item <item android:id="@+id/action_mark_previous_as_read"
android:id="@+id/action_mark_previous_as_read"
android:title="@string/action_mark_previous_as_read"/> android:title="@string/action_mark_previous_as_read"/>
</menu> </menu>

View file

@ -6,4 +6,9 @@
android:title="@string/action_display_mode" android:title="@string/action_display_mode"
android:id="@+id/action_display_mode" android:id="@+id/action_display_mode"
app:showAsAction="never" /> app:showAsAction="never" />
<item
android:title="@string/manga_download"
android:id="@+id/manga_download"
app:showAsAction="never" />
</menu> </menu>

View file

@ -8,10 +8,15 @@
android:visible="false" android:visible="false"
app:showAsAction="ifRoom"/> app:showAsAction="ifRoom"/>
<item android:title="@string/action_stop" <item android:title="@string/action_pause"
android:id="@+id/stop_queue" android:id="@+id/pause_queue"
android:icon="@drawable/ic_stop" android:icon="@drawable/ic_pause"
android:visible="false" android:visible="false"
app:showAsAction="ifRoom"/> app:showAsAction="ifRoom"/>
<item android:title="@string/action_clear"
android:id="@+id/clear_queue"
android:visible="false"
app:showAsAction="never"/>
</menu> </menu>

View file

@ -35,12 +35,13 @@
<string name="action_next_unread">Next unread</string> <string name="action_next_unread">Next unread</string>
<string name="action_start">Start</string> <string name="action_start">Start</string>
<string name="action_stop">Stop</string> <string name="action_stop">Stop</string>
<string name="action_pause">Pause</string>
<string name="action_clear">Clear</string>
<string name="action_previous_chapter">Previous chapter</string> <string name="action_previous_chapter">Previous chapter</string>
<string name="action_next_chapter">Next chapter</string> <string name="action_next_chapter">Next chapter</string>
<string name="action_retry">Retry</string> <string name="action_retry">Retry</string>
<string name="action_display_mode">Change display mode</string> <string name="action_display_mode">Change display mode</string>
<!-- Buttons --> <!-- Buttons -->
<string name="button_ok">OK</string> <string name="button_ok">OK</string>
<string name="button_cancel">Cancel</string> <string name="button_cancel">Cancel</string>
@ -179,6 +180,9 @@
<string name="fetch_chapters_error">Error while fetching chapters</string> <string name="fetch_chapters_error">Error while fetching chapters</string>
<string name="show_title">Show title</string> <string name="show_title">Show title</string>
<string name="show_chapter_number">Show chapter number</string> <string name="show_chapter_number">Show chapter number</string>
<string name="manga_download">Download</string>
<string name="download_all">Download all</string>
<string name="download_unread">Download unread</string>
<!-- MyAnimeList fragment --> <!-- MyAnimeList fragment -->
<string name="reading">Reading</string> <string name="reading">Reading</string>