Can now download from recent tab. #118
This commit is contained in:
parent
dcfda61aba
commit
dec9442a65
3 changed files with 275 additions and 2 deletions
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.recent;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
import android.support.v7.widget.LinearLayoutManager;
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
@ -14,12 +15,17 @@ 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;
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.Chapter;
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.Manga;
|
||||||
import eu.kanade.tachiyomi.data.database.models.MangaChapter;
|
import eu.kanade.tachiyomi.data.database.models.MangaChapter;
|
||||||
|
import eu.kanade.tachiyomi.data.download.DownloadService;
|
||||||
|
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 eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment;
|
import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment;
|
||||||
import eu.kanade.tachiyomi.ui.decoration.DividerItemDecoration;
|
import eu.kanade.tachiyomi.ui.decoration.DividerItemDecoration;
|
||||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity;
|
import eu.kanade.tachiyomi.ui.reader.ReaderActivity;
|
||||||
import nucleus.factory.RequiresPresenter;
|
import nucleus.factory.RequiresPresenter;
|
||||||
|
import rx.Observable;
|
||||||
|
|
||||||
@RequiresPresenter(RecentChaptersPresenter.class)
|
@RequiresPresenter(RecentChaptersPresenter.class)
|
||||||
public class RecentChaptersFragment extends BaseRxFragment<RecentChaptersPresenter> implements FlexibleViewHolder.OnListItemClickListener {
|
public class RecentChaptersFragment extends BaseRxFragment<RecentChaptersPresenter> implements FlexibleViewHolder.OnListItemClickListener {
|
||||||
|
@ -72,4 +78,29 @@ public class RecentChaptersFragment extends BaseRxFragment<RecentChaptersPresent
|
||||||
Intent intent = ReaderActivity.newIntent(getActivity());
|
Intent intent = ReaderActivity.newIntent(getActivity());
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onChapterStatusChange(Download download) {
|
||||||
|
RecentChaptersHolder holder = getHolder(download.chapter);
|
||||||
|
if (holder != null)
|
||||||
|
holder.onStatusChange(download.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private RecentChaptersHolder getHolder(Chapter chapter) {
|
||||||
|
return (RecentChaptersHolder) recyclerView.findViewHolderForItemId(chapter.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean onDownload(Observable<Chapter> chapters, Manga manga) {
|
||||||
|
// Start the download service.
|
||||||
|
DownloadService.start(getActivity());
|
||||||
|
|
||||||
|
// Refresh data on download competition.
|
||||||
|
Observable<Chapter> observable = chapters
|
||||||
|
.doOnCompleted(adapter::notifyDataSetChanged);
|
||||||
|
|
||||||
|
// Download chapter.
|
||||||
|
getPresenter().downloadChapter(observable, manga);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,32 +1,98 @@
|
||||||
package eu.kanade.tachiyomi.ui.recent;
|
package eu.kanade.tachiyomi.ui.recent;
|
||||||
|
|
||||||
|
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.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import butterknife.Bind;
|
import butterknife.Bind;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
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.MangaChapter;
|
import eu.kanade.tachiyomi.data.database.models.MangaChapter;
|
||||||
|
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 eu.kanade.tachiyomi.util.ToastUtil;
|
||||||
|
import rx.Observable;
|
||||||
|
|
||||||
public class RecentChaptersHolder extends FlexibleViewHolder {
|
public class RecentChaptersHolder extends FlexibleViewHolder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapter for recent chapters
|
||||||
|
*/
|
||||||
|
private final RecentChaptersAdapter adapter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to global information about an application environment.
|
||||||
|
*/
|
||||||
|
private Context context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TextView containing chapter title
|
||||||
|
*/
|
||||||
@Bind(R.id.chapter_title) TextView chapterTitle;
|
@Bind(R.id.chapter_title) TextView chapterTitle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TextView containing manga name
|
||||||
|
*/
|
||||||
@Bind(R.id.manga_title) TextView mangaTitle;
|
@Bind(R.id.manga_title) TextView mangaTitle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TextView containing download status
|
||||||
|
*/
|
||||||
|
@Bind(R.id.download_text) TextView downloadText;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RelativeLayout containing popup menu with download options
|
||||||
|
*/
|
||||||
|
@Bind(R.id.chapter_menu) RelativeLayout chapterMenu;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TextView containing read progress
|
||||||
|
*/
|
||||||
|
// @Bind(R.id.chapter_pages) TextView pages;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Color of read chapter
|
||||||
|
*/
|
||||||
private final int readColor;
|
private final int readColor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Color of unread chapter
|
||||||
|
*/
|
||||||
private final int unreadColor;
|
private final int unreadColor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object containing chapter information
|
||||||
|
*/
|
||||||
|
private MangaChapter mangaChapter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor of RecentChaptersHolder
|
||||||
|
*
|
||||||
|
* @param view
|
||||||
|
* @param adapter
|
||||||
|
* @param onListItemClickListener
|
||||||
|
*/
|
||||||
public RecentChaptersHolder(View view, RecentChaptersAdapter adapter, OnListItemClickListener onListItemClickListener) {
|
public RecentChaptersHolder(View view, RecentChaptersAdapter adapter, OnListItemClickListener onListItemClickListener) {
|
||||||
super(view, adapter, onListItemClickListener);
|
super(view, adapter, onListItemClickListener);
|
||||||
|
this.adapter = adapter;
|
||||||
|
context = view.getContext();
|
||||||
ButterKnife.bind(this, view);
|
ButterKnife.bind(this, view);
|
||||||
|
|
||||||
|
// Set colors.
|
||||||
readColor = ContextCompat.getColor(view.getContext(), R.color.hint_text);
|
readColor = ContextCompat.getColor(view.getContext(), R.color.hint_text);
|
||||||
unreadColor = ContextCompat.getColor(view.getContext(), R.color.primary_text);
|
unreadColor = ContextCompat.getColor(view.getContext(), R.color.primary_text);
|
||||||
|
|
||||||
|
//Set OnClickListener for download menu
|
||||||
|
chapterMenu.setOnClickListener(v -> v.post(() -> showPopupMenu(v)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onSetValues(MangaChapter item) {
|
public void onSetValues(MangaChapter item) {
|
||||||
|
this.mangaChapter = item;
|
||||||
chapterTitle.setText(item.chapter.name);
|
chapterTitle.setText(item.chapter.name);
|
||||||
mangaTitle.setText(item.manga.title);
|
mangaTitle.setText(item.manga.title);
|
||||||
|
|
||||||
|
@ -36,7 +102,92 @@ public class RecentChaptersHolder extends FlexibleViewHolder {
|
||||||
} else {
|
} else {
|
||||||
chapterTitle.setTextColor(unreadColor);
|
chapterTitle.setTextColor(unreadColor);
|
||||||
mangaTitle.setTextColor(unreadColor);
|
mangaTitle.setTextColor(unreadColor);
|
||||||
|
|
||||||
|
// if (item.chapter.last_page_read > 0) {
|
||||||
|
// pages.setText(context.getString(R.string.chapter_progress, item.chapter.last_page_read + 1));
|
||||||
|
// } else {
|
||||||
|
// pages.setText("");
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
onStatusChange(item.chapter.status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onStatusChange(int status) {
|
||||||
|
switch (status) {
|
||||||
|
case Download.QUEUE:
|
||||||
|
downloadText.setText(R.string.chapter_queued);
|
||||||
|
break;
|
||||||
|
case Download.DOWNLOADING:
|
||||||
|
downloadText.setText(R.string.chapter_downloading);
|
||||||
|
break;
|
||||||
|
case Download.DOWNLOADED:
|
||||||
|
downloadText.setText(R.string.chapter_downloaded);
|
||||||
|
break;
|
||||||
|
case Download.ERROR:
|
||||||
|
downloadText.setText(R.string.chapter_error);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
downloadText.setText("");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onProgressChange(Context context, int downloaded, int total) {
|
||||||
|
downloadText.setText(context.getString(
|
||||||
|
R.string.chapter_downloading_progress, downloaded, total));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showPopupMenu(View view) {
|
||||||
|
// Create a PopupMenu, giving it the clicked view for an anchor
|
||||||
|
PopupMenu popup = new PopupMenu(adapter.getFragment().getActivity(), view);
|
||||||
|
|
||||||
|
// Inflate our menu resource into the PopupMenu's Menu
|
||||||
|
popup.getMenuInflater().inflate(R.menu.chapter_recent, popup.getMenu());
|
||||||
|
|
||||||
|
// Hide download and show delete if the chapter is downloaded and
|
||||||
|
if (mangaChapter.chapter.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 (!mangaChapter.chapter.read /*&& mangaChapter.chapter.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 (mangaChapter.chapter.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
|
||||||
|
popup.setOnMenuItemClickListener(menuItem -> {
|
||||||
|
Observable<Chapter> chapterObservable = Observable.just(mangaChapter.chapter);
|
||||||
|
|
||||||
|
switch (menuItem.getItemId()) {
|
||||||
|
case R.id.action_download:
|
||||||
|
return adapter.getFragment().onDownload(chapterObservable, mangaChapter.manga);
|
||||||
|
case R.id.action_delete:
|
||||||
|
ToastUtil.showShort(context, "Delete does not work, yet....");
|
||||||
|
return true;
|
||||||
|
// return adapter.getFragment().onDelete(chapterObservable);
|
||||||
|
case R.id.action_mark_as_read:
|
||||||
|
ToastUtil.showShort(context, "Mark as read does not work, yet....");
|
||||||
|
return true;
|
||||||
|
// return adapter.getFragment().onMarkAsRead(chapterObservable);
|
||||||
|
case R.id.action_mark_as_unread:
|
||||||
|
ToastUtil.showShort(context, "Mark as unread does not work, yet....");
|
||||||
|
return true;
|
||||||
|
// return adapter.getFragment().onMarkAsUnread(chapterObservable);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Finally show the PopupMenu
|
||||||
|
popup.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,20 +15,30 @@ import java.util.TreeMap;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper;
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper;
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.Chapter;
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.Manga;
|
||||||
import eu.kanade.tachiyomi.data.database.models.MangaChapter;
|
import eu.kanade.tachiyomi.data.database.models.MangaChapter;
|
||||||
|
import eu.kanade.tachiyomi.data.download.DownloadManager;
|
||||||
|
import eu.kanade.tachiyomi.data.download.model.Download;
|
||||||
import eu.kanade.tachiyomi.data.source.SourceManager;
|
import eu.kanade.tachiyomi.data.source.SourceManager;
|
||||||
import eu.kanade.tachiyomi.data.source.base.Source;
|
import eu.kanade.tachiyomi.data.source.base.Source;
|
||||||
|
import eu.kanade.tachiyomi.event.DownloadChaptersEvent;
|
||||||
import eu.kanade.tachiyomi.event.ReaderEvent;
|
import eu.kanade.tachiyomi.event.ReaderEvent;
|
||||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter;
|
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter;
|
||||||
import rx.Observable;
|
import rx.Observable;
|
||||||
import rx.android.schedulers.AndroidSchedulers;
|
import rx.android.schedulers.AndroidSchedulers;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
public class RecentChaptersPresenter extends BasePresenter<RecentChaptersFragment> {
|
public class RecentChaptersPresenter extends BasePresenter<RecentChaptersFragment> {
|
||||||
|
|
||||||
@Inject DatabaseHelper db;
|
@Inject DatabaseHelper db;
|
||||||
|
@Inject DownloadManager downloadManager;
|
||||||
@Inject SourceManager sourceManager;
|
@Inject SourceManager sourceManager;
|
||||||
|
|
||||||
|
private List<MangaChapter> mangaChapters;
|
||||||
|
|
||||||
private static final int GET_RECENT_CHAPTERS = 1;
|
private static final int GET_RECENT_CHAPTERS = 1;
|
||||||
|
private static final int CHAPTER_STATUS_CHANGES = 2;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedState) {
|
protected void onCreate(Bundle savedState) {
|
||||||
|
@ -36,12 +46,69 @@ public class RecentChaptersPresenter extends BasePresenter<RecentChaptersFragmen
|
||||||
|
|
||||||
restartableLatestCache(GET_RECENT_CHAPTERS,
|
restartableLatestCache(GET_RECENT_CHAPTERS,
|
||||||
this::getRecentChaptersObservable,
|
this::getRecentChaptersObservable,
|
||||||
RecentChaptersFragment::onNextMangaChapters);
|
(recentChaptersFragment, chapters) -> {
|
||||||
|
recentChaptersFragment.onNextMangaChapters(chapters);
|
||||||
|
updateMangaInformation(convertToMangaChaptersList(chapters));
|
||||||
|
});
|
||||||
|
|
||||||
if (savedState == null)
|
startableLatestCache(CHAPTER_STATUS_CHANGES,
|
||||||
|
this::getChapterStatusObs,
|
||||||
|
RecentChaptersFragment::onChapterStatusChange,
|
||||||
|
(view, error) -> Timber.e(error.getCause(), error.getMessage()));
|
||||||
|
|
||||||
|
if (savedState == null) {
|
||||||
start(GET_RECENT_CHAPTERS);
|
start(GET_RECENT_CHAPTERS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void updateMangaInformation(List<MangaChapter> mangaChapters) {
|
||||||
|
this.mangaChapters = mangaChapters;
|
||||||
|
|
||||||
|
for (MangaChapter mangaChapter : mangaChapters)
|
||||||
|
setChapterStatus(mangaChapter);
|
||||||
|
|
||||||
|
start(CHAPTER_STATUS_CHANGES);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<MangaChapter> convertToMangaChaptersList(List<Object> chapters) {
|
||||||
|
List<MangaChapter> tempMangaChapterList = new ArrayList<>();
|
||||||
|
for (Object object : chapters) {
|
||||||
|
if (object instanceof MangaChapter) {
|
||||||
|
tempMangaChapterList.add((MangaChapter) object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tempMangaChapterList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Observable<Download> getChapterStatusObs() {
|
||||||
|
return downloadManager.getQueue().getStatusObservable()
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.filter(download -> chapterIdEquals(download.chapter.id))
|
||||||
|
.doOnNext(this::updateChapterStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean chapterIdEquals(Long chaptersId) {
|
||||||
|
for (MangaChapter mangaChapter : mangaChapters) {
|
||||||
|
if (chaptersId.equals(mangaChapter.chapter.id)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateChapterStatus(Download download) {
|
||||||
|
for (Object item : mangaChapters) {
|
||||||
|
if (item instanceof MangaChapter) {
|
||||||
|
if (download.chapter.id.equals(((MangaChapter) item).chapter.id)) {
|
||||||
|
((MangaChapter) item).chapter.status = download.getStatus();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private Observable<List<Object>> getRecentChaptersObservable() {
|
private Observable<List<Object>> getRecentChaptersObservable() {
|
||||||
Calendar cal = Calendar.getInstance();
|
Calendar cal = Calendar.getInstance();
|
||||||
cal.setTime(new Date());
|
cal.setTime(new Date());
|
||||||
|
@ -66,6 +133,22 @@ public class RecentChaptersPresenter extends BasePresenter<RecentChaptersFragmen
|
||||||
.observeOn(AndroidSchedulers.mainThread());
|
.observeOn(AndroidSchedulers.mainThread());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setChapterStatus(MangaChapter mangaChapter) {
|
||||||
|
for (Download download : downloadManager.getQueue()) {
|
||||||
|
if (mangaChapter.chapter.id.equals(download.chapter.id)) {
|
||||||
|
mangaChapter.chapter.status = download.getStatus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Source source = sourceManager.get(mangaChapter.manga.source);
|
||||||
|
if (downloadManager.isChapterDownloaded(source, mangaChapter.manga, mangaChapter.chapter)) {
|
||||||
|
mangaChapter.chapter.status = Download.DOWNLOADED;
|
||||||
|
} else {
|
||||||
|
mangaChapter.chapter.status = Download.NOT_DOWNLOADED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Date getMapKey(long date) {
|
private Date getMapKey(long date) {
|
||||||
Calendar cal = Calendar.getInstance();
|
Calendar cal = Calendar.getInstance();
|
||||||
cal.setTime(new Date(date));
|
cal.setTime(new Date(date));
|
||||||
|
@ -80,4 +163,12 @@ public class RecentChaptersPresenter extends BasePresenter<RecentChaptersFragmen
|
||||||
Source source = sourceManager.get(item.manga.source);
|
Source source = sourceManager.get(item.manga.source);
|
||||||
EventBus.getDefault().postSticky(new ReaderEvent(source, item.manga, item.chapter));
|
EventBus.getDefault().postSticky(new ReaderEvent(source, item.manga, item.chapter));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void downloadChapter(Observable<Chapter> selectedChapter, Manga manga) {
|
||||||
|
add(selectedChapter
|
||||||
|
.toList()
|
||||||
|
.subscribe(chapters -> {
|
||||||
|
EventBus.getDefault().postSticky(new DownloadChaptersEvent(manga, chapters));
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue