From dec9442a65ae74da7f1f022127a0164deeb79497 Mon Sep 17 00:00:00 2001 From: NoodleMage Date: Thu, 18 Feb 2016 15:58:04 +0100 Subject: [PATCH 1/4] Can now download from recent tab. #118 --- .../ui/recent/RecentChaptersFragment.java | 31 ++++ .../ui/recent/RecentChaptersHolder.java | 151 ++++++++++++++++++ .../ui/recent/RecentChaptersPresenter.java | 95 ++++++++++- 3 files changed, 275 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersFragment.java b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersFragment.java index ff332773bb..e78c34ccd7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersFragment.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersFragment.java @@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.recent; import android.content.Intent; import android.os.Bundle; +import android.support.annotation.Nullable; import android.support.v4.content.ContextCompat; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; @@ -14,12 +15,17 @@ import java.util.List; import butterknife.Bind; import butterknife.ButterKnife; 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.download.DownloadService; +import eu.kanade.tachiyomi.data.download.model.Download; import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder; import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment; import eu.kanade.tachiyomi.ui.decoration.DividerItemDecoration; import eu.kanade.tachiyomi.ui.reader.ReaderActivity; import nucleus.factory.RequiresPresenter; +import rx.Observable; @RequiresPresenter(RecentChaptersPresenter.class) public class RecentChaptersFragment extends BaseRxFragment implements FlexibleViewHolder.OnListItemClickListener { @@ -72,4 +78,29 @@ public class RecentChaptersFragment extends BaseRxFragment chapters, Manga manga) { + // Start the download service. + DownloadService.start(getActivity()); + + // Refresh data on download competition. + Observable observable = chapters + .doOnCompleted(adapter::notifyDataSetChanged); + + // Download chapter. + getPresenter().downloadChapter(observable, manga); + return true; + } + } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersHolder.java b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersHolder.java index 93927e9fc0..8d3607e39b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersHolder.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersHolder.java @@ -1,32 +1,98 @@ package eu.kanade.tachiyomi.ui.recent; +import android.content.Context; import android.support.v4.content.ContextCompat; +import android.view.Menu; import android.view.View; +import android.widget.PopupMenu; +import android.widget.RelativeLayout; import android.widget.TextView; import butterknife.Bind; import butterknife.ButterKnife; 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.download.model.Download; import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder; +import eu.kanade.tachiyomi.util.ToastUtil; +import rx.Observable; 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; + + /** + * TextView containing manga name + */ @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; + + /** + * Color of unread chapter + */ 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) { super(view, adapter, onListItemClickListener); + this.adapter = adapter; + context = view.getContext(); ButterKnife.bind(this, view); + // Set colors. readColor = ContextCompat.getColor(view.getContext(), R.color.hint_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) { + this.mangaChapter = item; chapterTitle.setText(item.chapter.name); mangaTitle.setText(item.manga.title); @@ -36,7 +102,92 @@ public class RecentChaptersHolder extends FlexibleViewHolder { } else { chapterTitle.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 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(); + } + + } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersPresenter.java b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersPresenter.java index f991ee93b9..a849c9d1d2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersPresenter.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersPresenter.java @@ -15,20 +15,30 @@ import java.util.TreeMap; import javax.inject.Inject; 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.download.DownloadManager; +import eu.kanade.tachiyomi.data.download.model.Download; import eu.kanade.tachiyomi.data.source.SourceManager; import eu.kanade.tachiyomi.data.source.base.Source; +import eu.kanade.tachiyomi.event.DownloadChaptersEvent; import eu.kanade.tachiyomi.event.ReaderEvent; import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter; import rx.Observable; import rx.android.schedulers.AndroidSchedulers; +import timber.log.Timber; public class RecentChaptersPresenter extends BasePresenter { @Inject DatabaseHelper db; + @Inject DownloadManager downloadManager; @Inject SourceManager sourceManager; + private List mangaChapters; + private static final int GET_RECENT_CHAPTERS = 1; + private static final int CHAPTER_STATUS_CHANGES = 2; @Override protected void onCreate(Bundle savedState) { @@ -36,12 +46,69 @@ public class RecentChaptersPresenter extends BasePresenter { + 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); + } } + + private void updateMangaInformation(List mangaChapters) { + this.mangaChapters = mangaChapters; + + for (MangaChapter mangaChapter : mangaChapters) + setChapterStatus(mangaChapter); + + start(CHAPTER_STATUS_CHANGES); + } + + private List convertToMangaChaptersList(List chapters) { + List tempMangaChapterList = new ArrayList<>(); + for (Object object : chapters) { + if (object instanceof MangaChapter) { + tempMangaChapterList.add((MangaChapter) object); + } + } + return tempMangaChapterList; + } + + private Observable 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> getRecentChaptersObservable() { Calendar cal = Calendar.getInstance(); cal.setTime(new Date()); @@ -66,6 +133,22 @@ public class RecentChaptersPresenter extends BasePresenter selectedChapter, Manga manga) { + add(selectedChapter + .toList() + .subscribe(chapters -> { + EventBus.getDefault().postSticky(new DownloadChaptersEvent(manga, chapters)); + })); + } } From aac6b242a0c78ca0b64490dca966d795ae865ff2 Mon Sep 17 00:00:00 2001 From: NoodleMage Date: Thu, 18 Feb 2016 17:23:17 +0100 Subject: [PATCH 2/4] Can now delete manga from recent + added missing res files #118 --- .../ui/recent/RecentChaptersFragment.java | 38 +++++++++++++ .../ui/recent/RecentChaptersHolder.java | 14 ++--- .../ui/recent/RecentChaptersPresenter.java | 30 +++++++++++ .../main/res/layout/item_recent_chapter.xml | 53 +++++++++++++++++-- app/src/main/res/menu/chapter_recent.xml | 32 +++++++++++ build.gradle | 2 +- 6 files changed, 154 insertions(+), 15 deletions(-) create mode 100644 app/src/main/res/menu/chapter_recent.xml diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersFragment.java b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersFragment.java index e78c34ccd7..efc7847c9a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersFragment.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersFragment.java @@ -10,6 +10,8 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import com.afollestad.materialdialogs.MaterialDialog; + import java.util.List; import butterknife.Bind; @@ -26,6 +28,8 @@ import eu.kanade.tachiyomi.ui.decoration.DividerItemDecoration; import eu.kanade.tachiyomi.ui.reader.ReaderActivity; import nucleus.factory.RequiresPresenter; import rx.Observable; +import rx.android.schedulers.AndroidSchedulers; +import rx.schedulers.Schedulers; @RequiresPresenter(RecentChaptersPresenter.class) public class RecentChaptersFragment extends BaseRxFragment implements FlexibleViewHolder.OnListItemClickListener { @@ -103,4 +107,38 @@ public class RecentChaptersFragment extends BaseRxFragment chapters, Manga manga) { + int size = adapter.getSelectedItemCount(); + + MaterialDialog dialog = new MaterialDialog.Builder(getActivity()) + .title(R.string.deleting) + .progress(false, size, true) + .cancelable(false) + .show(); + + Observable observable = chapters + .concatMap(chapter -> { + getPresenter().deleteChapter(chapter, manga); + return Observable.just(chapter); + }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .doOnNext(chapter -> { + dialog.incrementProgress(1); + chapter.status = Download.NOT_DOWNLOADED; + }) + .doOnCompleted(adapter::notifyDataSetChanged) + .finallyDo(dialog::dismiss); + + getPresenter().deleteChapters(observable); + + return true; + } + + protected boolean onMarkAsRead(Observable chapters) { + getPresenter().markChaptersRead(chapters, true); + return true; + } + + } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersHolder.java b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersHolder.java index 8d3607e39b..88a106fa6f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersHolder.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersHolder.java @@ -133,11 +133,6 @@ public class RecentChaptersHolder extends FlexibleViewHolder { } } - 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); @@ -170,13 +165,10 @@ public class RecentChaptersHolder extends FlexibleViewHolder { 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); + return adapter.getFragment().onDelete(chapterObservable, mangaChapter.manga); case R.id.action_mark_as_read: - ToastUtil.showShort(context, "Mark as read does not work, yet...."); - return true; -// return adapter.getFragment().onMarkAsRead(chapterObservable); + ToastUtil.showShort(context, "Mark as read"); + return adapter.getFragment().onMarkAsRead(chapterObservable); case R.id.action_mark_as_unread: ToastUtil.showShort(context, "Mark as unread does not work, yet...."); return true; diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersPresenter.java b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersPresenter.java index a849c9d1d2..9db61c1212 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersPresenter.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersPresenter.java @@ -27,6 +27,7 @@ import eu.kanade.tachiyomi.event.ReaderEvent; import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter; import rx.Observable; import rx.android.schedulers.AndroidSchedulers; +import rx.schedulers.Schedulers; import timber.log.Timber; public class RecentChaptersPresenter extends BasePresenter { @@ -109,6 +110,7 @@ public class RecentChaptersPresenter extends BasePresenter> getRecentChaptersObservable() { Calendar cal = Calendar.getInstance(); cal.setTime(new Date()); @@ -171,4 +173,32 @@ public class RecentChaptersPresenter extends BasePresenter selectedChapters) { + add(selectedChapters + .subscribe(chapter -> { + downloadManager.getQueue().remove(chapter); + }, error -> { + Timber.e(error.getMessage()); + })); + } + + public void markChaptersRead(Observable selectedChapters, boolean read) { + add(selectedChapters + .subscribeOn(Schedulers.io()) + .map(chapter -> { + chapter.read = read; + if (!read) chapter.last_page_read = 0; + return chapter; + }) + .toList() + .flatMap(chapters -> db.insertChapters(chapters).asRxObservable()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe()); + } } diff --git a/app/src/main/res/layout/item_recent_chapter.xml b/app/src/main/res/layout/item_recent_chapter.xml index 4c2dd163a1..21d9111b7c 100644 --- a/app/src/main/res/layout/item_recent_chapter.xml +++ b/app/src/main/res/layout/item_recent_chapter.xml @@ -5,6 +5,7 @@ android:layout_height="?android:attr/listPreferredItemHeight" android:background="@drawable/selector_chapter_light"> + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/chapter_recent.xml b/app/src/main/res/menu/chapter_recent.xml new file mode 100644 index 0000000000..ec9883b9f7 --- /dev/null +++ b/app/src/main/res/menu/chapter_recent.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 11eb25d59a..e833b0f878 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.0.0-beta2' + classpath 'com.android.tools.build:gradle:2.0.0-beta4' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' classpath 'me.tatarka:gradle-retrolambda:3.2.4' classpath 'com.github.ben-manes:gradle-versions-plugin:0.12.0' From ba0f3778ce8156f8c435dd8bd9fab92c8d6fe6b8 Mon Sep 17 00:00:00 2001 From: NoodleMage Date: Thu, 18 Feb 2016 17:40:12 +0100 Subject: [PATCH 3/4] Can now mark as read / unread --- .../kanade/tachiyomi/ui/recent/RecentChaptersFragment.java | 5 +++++ .../eu/kanade/tachiyomi/ui/recent/RecentChaptersHolder.java | 6 +----- build.gradle | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersFragment.java b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersFragment.java index efc7847c9a..f14b6600c7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersFragment.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersFragment.java @@ -140,5 +140,10 @@ public class RecentChaptersFragment extends BaseRxFragment chapters) { + getPresenter().markChaptersRead(chapters, false); + return true; + } + } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersHolder.java b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersHolder.java index 88a106fa6f..0db33f2ac3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersHolder.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersHolder.java @@ -15,7 +15,6 @@ import eu.kanade.tachiyomi.data.database.models.Chapter; 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.util.ToastUtil; import rx.Observable; public class RecentChaptersHolder extends FlexibleViewHolder { @@ -167,12 +166,9 @@ public class RecentChaptersHolder extends FlexibleViewHolder { case R.id.action_delete: return adapter.getFragment().onDelete(chapterObservable, mangaChapter.manga); case R.id.action_mark_as_read: - ToastUtil.showShort(context, "Mark as read"); 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 adapter.getFragment().onMarkAsUnread(chapterObservable); } return false; }); diff --git a/build.gradle b/build.gradle index e833b0f878..11eb25d59a 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.0.0-beta4' + classpath 'com.android.tools.build:gradle:2.0.0-beta2' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' classpath 'me.tatarka:gradle-retrolambda:3.2.4' classpath 'com.github.ben-manes:gradle-versions-plugin:0.12.0' From b94f86765d1299c1baed9b0c80772a95af9d04fe Mon Sep 17 00:00:00 2001 From: NoodleMage Date: Thu, 18 Feb 2016 19:01:40 +0100 Subject: [PATCH 4/4] Code cleanup, implements #118 --- .../ui/recent/RecentChaptersAdapter.java | 34 +++- .../ui/recent/RecentChaptersFragment.java | 53 +++++- .../ui/recent/RecentChaptersHolder.java | 50 +++--- .../ui/recent/RecentChaptersPresenter.java | 157 +++++++++++++++--- 4 files changed, 244 insertions(+), 50 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersAdapter.java b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersAdapter.java index 3ff8d1c792..2f2fae2998 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersAdapter.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersAdapter.java @@ -16,13 +16,33 @@ import eu.davidea.flexibleadapter.FlexibleAdapter; import eu.kanade.tachiyomi.R; import eu.kanade.tachiyomi.data.database.models.MangaChapter; +/** + * Adapter of RecentChaptersHolder. + * Connection between Fragment and Holder + * Holder updates should be called from here. + */ public class RecentChaptersAdapter extends FlexibleAdapter { - private RecentChaptersFragment fragment; + /** + * Fragment of RecentChaptersFragment + */ + private final RecentChaptersFragment fragment; + /** + * The id of the view type + */ private static final int VIEW_TYPE_CHAPTER = 0; + + /** + * The id of the view type + */ private static final int VIEW_TYPE_SECTION = 1; + /** + * Constructor + * + * @param fragment fragment + */ public RecentChaptersAdapter(RecentChaptersFragment fragment) { this.fragment = fragment; setHasStableIds(true); @@ -37,6 +57,11 @@ public class RecentChaptersAdapter extends FlexibleAdapter items) { mItems = items; notifyDataSetChanged(); @@ -56,6 +81,8 @@ public class RecentChaptersAdapter extends FlexibleAdapter implements FlexibleViewHolder.OnListItemClickListener { @@ -60,14 +65,21 @@ public class RecentChaptersFragment extends BaseRxFragment chapters) { adapter.setItems(chapters); } @Override public boolean onListItemClick(int position) { + // Get item from position Object item = adapter.getItem(position); if (item instanceof MangaChapter) { + // Open chapter in reader openChapter((MangaChapter) item); } return false; @@ -75,14 +87,25 @@ public class RecentChaptersFragment extends BaseRxFragment chapters, Manga manga) { // Start the download service. DownloadService.start(getActivity()); @@ -107,6 +138,12 @@ public class RecentChaptersFragment extends BaseRxFragment chapters, Manga manga) { int size = adapter.getSelectedItemCount(); @@ -135,11 +172,25 @@ public class RecentChaptersFragment extends BaseRxFragment chapters) { getPresenter().markChaptersRead(chapters, true); return true; } + /** + * Mark chapter as unread + * + * @param chapters selected chapter + * @return true + */ + @SuppressWarnings("SameReturnValue") protected boolean onMarkAsUnread(Observable chapters) { getPresenter().markChaptersRead(chapters, false); return true; diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersHolder.java b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersHolder.java index 0db33f2ac3..7aa99ae0b1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersHolder.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersHolder.java @@ -1,6 +1,5 @@ package eu.kanade.tachiyomi.ui.recent; -import android.content.Context; import android.support.v4.content.ContextCompat; import android.view.Menu; import android.view.View; @@ -17,6 +16,11 @@ import eu.kanade.tachiyomi.data.download.model.Download; import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder; import rx.Observable; +/** + * Holder that contains chapter item + * Uses R.layout.item_recent_chapter. + * UI related actions should be called from here. + */ public class RecentChaptersHolder extends FlexibleViewHolder { /** @@ -24,11 +28,6 @@ public class RecentChaptersHolder extends FlexibleViewHolder { */ private final RecentChaptersAdapter adapter; - /** - * Interface to global information about an application environment. - */ - private Context context; - /** * TextView containing chapter title */ @@ -49,11 +48,6 @@ public class RecentChaptersHolder extends FlexibleViewHolder { */ @Bind(R.id.chapter_menu) RelativeLayout chapterMenu; - /** - * TextView containing read progress - */ -// @Bind(R.id.chapter_pages) TextView pages; - /** * Color of read chapter */ @@ -71,15 +65,13 @@ public class RecentChaptersHolder extends FlexibleViewHolder { /** * Constructor of RecentChaptersHolder - * - * @param view - * @param adapter - * @param onListItemClickListener + * @param view view of ChapterHolder + * @param adapter adapter of ChapterHolder + * @param onListItemClickListener ClickListener */ public RecentChaptersHolder(View view, RecentChaptersAdapter adapter, OnListItemClickListener onListItemClickListener) { super(view, adapter, onListItemClickListener); this.adapter = adapter; - context = view.getContext(); ButterKnife.bind(this, view); // Set colors. @@ -90,28 +82,38 @@ public class RecentChaptersHolder extends FlexibleViewHolder { chapterMenu.setOnClickListener(v -> v.post(() -> showPopupMenu(v))); } + /** + * Set values of view + * + * @param item item containing chapter information + */ public void onSetValues(MangaChapter item) { this.mangaChapter = item; + + // Set chapter title chapterTitle.setText(item.chapter.name); + + // Set manga title mangaTitle.setText(item.manga.title); + // Check if chapter is read and set correct color if (item.chapter.read) { chapterTitle.setTextColor(readColor); mangaTitle.setTextColor(readColor); } else { chapterTitle.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(""); -// } } + // Set chapter status onStatusChange(item.chapter.status); } + /** + * Updates chapter status in view. + * + * @param status download status + */ public void onStatusChange(int status) { switch (status) { case Download.QUEUE: @@ -132,6 +134,10 @@ public class RecentChaptersHolder extends FlexibleViewHolder { } } + /** + * Show pop up menu + * @param view view containing popup menu. + */ private void showPopupMenu(View view) { // Create a PopupMenu, giving it the clicked view for an anchor PopupMenu popup = new PopupMenu(adapter.getFragment().getActivity(), view); diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersPresenter.java b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersPresenter.java index 9db61c1212..898744cca5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersPresenter.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersPresenter.java @@ -30,58 +30,114 @@ import rx.android.schedulers.AndroidSchedulers; import rx.schedulers.Schedulers; import timber.log.Timber; +/** + * Presenter of RecentChaptersFragment. + * Contains information and data for fragment. + * Observable updates should be called from here. + */ public class RecentChaptersPresenter extends BasePresenter { + /** + * The id of the restartable. + */ + private static final int GET_RECENT_CHAPTERS = 1; + + /** + * The id of the restartable. + */ + private static final int CHAPTER_STATUS_CHANGES = 2; + + /** + * Used to connect to database + */ @Inject DatabaseHelper db; + + /** + * Used to get information from download manager + */ @Inject DownloadManager downloadManager; + + /** + * Used to get source from source id + */ @Inject SourceManager sourceManager; + /** + * List containing chapter and manga information + */ private List mangaChapters; - private static final int GET_RECENT_CHAPTERS = 1; - private static final int CHAPTER_STATUS_CHANGES = 2; - @Override protected void onCreate(Bundle savedState) { super.onCreate(savedState); + // Used to get recent chapters restartableLatestCache(GET_RECENT_CHAPTERS, this::getRecentChaptersObservable, (recentChaptersFragment, chapters) -> { + // Update adapter to show recent manga's recentChaptersFragment.onNextMangaChapters(chapters); - updateMangaInformation(convertToMangaChaptersList(chapters)); + // Update download status + updateChapterStatus(convertToMangaChaptersList(chapters)); }); + // Used to update download status startableLatestCache(CHAPTER_STATUS_CHANGES, this::getChapterStatusObs, RecentChaptersFragment::onChapterStatusChange, (view, error) -> Timber.e(error.getCause(), error.getMessage())); if (savedState == null) { + // Start fetching recent chapters start(GET_RECENT_CHAPTERS); } } - - private void updateMangaInformation(List mangaChapters) { - this.mangaChapters = mangaChapters; - - for (MangaChapter mangaChapter : mangaChapters) - setChapterStatus(mangaChapter); - - start(CHAPTER_STATUS_CHANGES); - } - - private List convertToMangaChaptersList(List chapters) { + /** + * Returns a list only containing MangaChapter objects. + * + * @param input the list that will be converted. + * @return list containing MangaChapters objects. + */ + private List convertToMangaChaptersList(List input) { + // Create temp list List tempMangaChapterList = new ArrayList<>(); - for (Object object : chapters) { + + // Only add MangaChapter objects + //noinspection Convert2streamapi + for (Object object : input) { if (object instanceof MangaChapter) { tempMangaChapterList.add((MangaChapter) object); } } + + // Return temp list return tempMangaChapterList; } + /** + * Update status of chapters + * + * @param mangaChapters list containing recent chapters + */ + private void updateChapterStatus(List mangaChapters) { + // Set global list of chapters. + this.mangaChapters = mangaChapters; + + // Update status. + //noinspection Convert2streamapi + for (MangaChapter mangaChapter : mangaChapters) + setChapterStatus(mangaChapter); + + // Start onChapterStatusChange restartable. + start(CHAPTER_STATUS_CHANGES); + } + + /** + * Returns observable containing chapter status. + * + * @return download object containing download progress. + */ private Observable getChapterStatusObs() { return downloadManager.getQueue().getStatusObservable() .observeOn(AndroidSchedulers.mainThread()) @@ -89,6 +145,11 @@ public class RecentChaptersPresenter extends BasePresenter> getRecentChaptersObservable() { + // Set date for recent chapters Calendar cal = Calendar.getInstance(); cal.setTime(new Date()); cal.add(Calendar.MONTH, -1); + // Get recent chapters from database. return db.getRecentChapters(cal.getTime()).asRxObservable() - // group chapters by the date they were fetched on a ordered map + // Group chapters by the date they were fetched on a ordered map. .flatMap(recents -> Observable.from(recents) .toMultimap( recent -> getMapKey(recent.chapter.date_fetch), recent -> recent, () -> new TreeMap<>((d1, d2) -> d2.compareTo(d1)))) - // add every day and all its chapters to a single list + // Add every day and all its chapters to a single list. .map(recents -> { List items = new ArrayList<>(); for (Map.Entry> recent : recents.entrySet()) { @@ -135,7 +204,12 @@ public class RecentChaptersPresenter extends BasePresenter selectedChapter, Manga manga) { add(selectedChapter .toList() @@ -174,11 +265,20 @@ public class RecentChaptersPresenter extends BasePresenter selectedChapters) { add(selectedChapters .subscribe(chapter -> { @@ -188,6 +288,11 @@ public class RecentChaptersPresenter extends BasePresenter selectedChapters, boolean read) { add(selectedChapters .subscribeOn(Schedulers.io())