From a7e652f1f742065f91d318b6d0e965858d61f329 Mon Sep 17 00:00:00 2001 From: NoodleMage Date: Sat, 27 Feb 2016 10:08:37 +0100 Subject: [PATCH] Rewrote Recent to Kotlin --- .../tachiyomi/ui/main/MainActivity.java | 1 - .../ui/recent/RecentChaptersAdapter.java | 140 -------- .../ui/recent/RecentChaptersAdapter.kt | 128 ++++++++ .../ui/recent/RecentChaptersFragment.java | 200 ----------- .../ui/recent/RecentChaptersFragment.kt | 221 +++++++++++++ .../ui/recent/RecentChaptersHolder.java | 187 ----------- .../ui/recent/RecentChaptersHolder.kt | 140 ++++++++ .../ui/recent/RecentChaptersPresenter.java | 309 ----------------- .../ui/recent/RecentChaptersPresenter.kt | 310 ++++++++++++++++++ .../tachiyomi/ui/recent/SectionViewHolder.kt | 26 ++ .../res/layout/fragment_recent_chapters.xml | 2 +- .../main/res/layout/item_recent_chapter.xml | 5 +- 12 files changed, 830 insertions(+), 839 deletions(-) delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersAdapter.java create mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersAdapter.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersFragment.java create mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersFragment.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersHolder.java create mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersHolder.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersPresenter.java create mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersPresenter.kt create mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/recent/SectionViewHolder.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.java b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.java index e5ea78c7a..c386a995f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.java @@ -81,7 +81,6 @@ public class MainActivity extends BaseActivity { new PrimaryDrawerItem() .withName(R.string.label_catalogues) .withIdentifier(R.id.nav_drawer_catalogues) - .withIcon(GoogleMaterial.Icon.gmd_explore), new PrimaryDrawerItem() .withName(R.string.label_download_queue) 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 deleted file mode 100644 index 2f2fae299..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersAdapter.java +++ /dev/null @@ -1,140 +0,0 @@ -package eu.kanade.tachiyomi.ui.recent; - -import android.support.v7.widget.RecyclerView; -import android.text.format.DateUtils; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import java.util.Date; -import java.util.List; - -import butterknife.Bind; -import butterknife.ButterKnife; -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 { - - /** - * 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); - } - - @Override - public long getItemId(int position) { - Object item = getItem(position); - if (item instanceof MangaChapter) - return ((MangaChapter) item).chapter.id; - else - return item.hashCode(); - } - - /** - * Update items - * - * @param items items - */ - public void setItems(List items) { - mItems = items; - notifyDataSetChanged(); - } - - @Override - public void updateDataSet(String param) { - - } - - @Override - public int getItemViewType(int position) { - return getItem(position) instanceof MangaChapter ? VIEW_TYPE_CHAPTER : VIEW_TYPE_SECTION; - } - - @Override - public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - LayoutInflater inflater = LayoutInflater.from(parent.getContext()); - View v; - - // Check which view type and set correct values. - switch (viewType) { - case VIEW_TYPE_CHAPTER: - v = inflater.inflate(R.layout.item_recent_chapter, parent, false); - return new RecentChaptersHolder(v, this, fragment); - case VIEW_TYPE_SECTION: - v = inflater.inflate(R.layout.item_recent_chapter_section, parent, false); - return new SectionViewHolder(v); - } - return null; - } - - @Override - public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { - // Check which view type and set correct values. - switch (holder.getItemViewType()) { - case VIEW_TYPE_CHAPTER: - final MangaChapter chapter = (MangaChapter) getItem(position); - ((RecentChaptersHolder) holder).onSetValues(chapter); - break; - case VIEW_TYPE_SECTION: - final Date date = (Date) getItem(position); - ((SectionViewHolder) holder).onSetValues(date); - break; - } - - //When user scrolls this bind the correct selection status - holder.itemView.setActivated(isSelected(position)); - } - - /** - * Returns fragment - * @return RecentChaptersFragment - */ - public RecentChaptersFragment getFragment() { - return fragment; - } - - public static class SectionViewHolder extends RecyclerView.ViewHolder { - - @Bind(R.id.section_text) TextView section; - - private final long now = new Date().getTime(); - - public SectionViewHolder(View view) { - super(view); - ButterKnife.bind(this, view); - } - - public void onSetValues(Date date) { - CharSequence s = DateUtils.getRelativeTimeSpanString( - date.getTime(), now, DateUtils.DAY_IN_MILLIS); - section.setText(s); - } - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersAdapter.kt new file mode 100644 index 000000000..1bfe5ef52 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersAdapter.kt @@ -0,0 +1,128 @@ +package eu.kanade.tachiyomi.ui.recent + +import android.support.v7.widget.RecyclerView +import android.view.View +import android.view.ViewGroup +import eu.davidea.flexibleadapter.FlexibleAdapter +import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.data.database.models.MangaChapter +import eu.kanade.tachiyomi.util.inflate +import java.util.* + +/** + * Adapter of RecentChaptersHolder. + * Connection between Fragment and Holder + * Holder updates should be called from here. + * + * @param fragment a RecentChaptersFragment object + * @constructor creates an instance of the adapter. + */ + +class RecentChaptersAdapter(val fragment: RecentChaptersFragment) : FlexibleAdapter() { + /** + * The id of the view type + */ + private val VIEW_TYPE_CHAPTER = 0 + + /** + * The id of the view type + */ + private val VIEW_TYPE_SECTION = 1 + + init { + // Let each each item in the data set be represented with a unique identifier. + setHasStableIds(true) + } + + /** + * Called when ViewHolder is bind + * + * @param holder bind holder + * @param position position of holder + */ + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + // Check which view type and set correct values. + val item = getItem(position) + when (holder.itemViewType) { + VIEW_TYPE_CHAPTER -> { + if (item is MangaChapter) { + (holder as RecentChaptersHolder).onSetValues(item) + } + } + VIEW_TYPE_SECTION -> { + if (item is Date) { + (holder as SectionViewHolder).onSetValues(item) + } + } + } + + //When user scrolls this bind the correct selection status + holder.itemView.isActivated = isSelected(position) + } + + /** + * Called when ViewHolder is created + * + * @param parent parent View + * @param viewType int containing viewType + */ + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder? { + val view: View + + // Check which view type and set correct values. + when (viewType) { + VIEW_TYPE_CHAPTER -> { + view = parent.inflate(R.layout.item_recent_chapter) + return RecentChaptersHolder(view, this, fragment) + } + VIEW_TYPE_SECTION -> { + view = parent.inflate(R.layout.item_recent_chapter_section) + return SectionViewHolder(view) + } + } + return null + } + + /** + * Returns the correct ViewType + * + * @param position position of item + */ + override fun getItemViewType(position: Int): Int { + return if (getItem(position) is MangaChapter) VIEW_TYPE_CHAPTER else VIEW_TYPE_SECTION + } + + + /** + * Update items + + * @param items items + */ + fun setItems(items: List) { + mItems = items + notifyDataSetChanged() + } + + /** + * Needed to determine holder id + * + * @param position position of holder item + */ + override fun getItemId(position: Int): Long { + val item = getItem(position) + if (item is MangaChapter) + return item.chapter.id + else + return item.hashCode().toLong() + } + + /** + * Abstract function (not needed). + * + * @param p0 a string. + */ + override fun updateDataSet(p0: String) { + // Empty function. + } + +} \ No newline at end of file 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 deleted file mode 100644 index fc9807ea7..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersFragment.java +++ /dev/null @@ -1,200 +0,0 @@ -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; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import com.afollestad.materialdialogs.MaterialDialog; - -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; -import rx.android.schedulers.AndroidSchedulers; -import rx.schedulers.Schedulers; - -/** - * Fragment that shows recent chapters. - * Uses R.layout.fragment_recent_chapters. - * UI related actions should be called from here. - */ -@RequiresPresenter(RecentChaptersPresenter.class) -public class RecentChaptersFragment extends BaseRxFragment implements FlexibleViewHolder.OnListItemClickListener { - - @Bind(R.id.chapter_list) RecyclerView recyclerView; - - private RecentChaptersAdapter adapter; - - public static RecentChaptersFragment newInstance() { - return new RecentChaptersFragment(); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) { - // Inflate the layout for this fragment - View view = inflater.inflate(R.layout.fragment_recent_chapters, container, false); - ButterKnife.bind(this, view); - - // Init RecyclerView and adapter - recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); - recyclerView.addItemDecoration(new DividerItemDecoration(ContextCompat.getDrawable( - getContext(), R.drawable.line_divider))); - recyclerView.setHasFixedSize(true); - adapter = new RecentChaptersAdapter(this); - recyclerView.setAdapter(adapter); - - setToolbarTitle(R.string.label_recent_updates); - return view; - } - - /** - * Populate adapter with chapters - * - * @param chapters list of chapters - */ - public void onNextMangaChapters(List 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; - } - - @Override - public void onListItemLongClick(int position) { - // Empty function - } - - /** - * Open chapter in reader - * - * @param chapter selected chapter - */ - private void openChapter(MangaChapter chapter) { - getPresenter().onOpenChapter(chapter); - Intent intent = ReaderActivity.newIntent(getActivity()); - startActivity(intent); - } - - /** - * Update download status of chapter - * - * @param download download object containing download progress. - */ - 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); - } - - /** - * Start downloading chapter - * - * @param chapters selected chapters - * @param manga manga that belongs to chapter - * @return true - */ - @SuppressWarnings("SameReturnValue") - protected boolean onDownload(Observable 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; - } - - /** - * Start deleting chapter - * @param chapters selected chapters - * @param manga manga that belongs to chapter - * @return success of deletion. - */ - protected boolean onDelete(Observable 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; - } - - /** - * Mark chapter as read - * - * @param chapters selected chapter - * @return true - */ - @SuppressWarnings("SameReturnValue") - protected boolean onMarkAsRead(Observable 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/RecentChaptersFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersFragment.kt new file mode 100644 index 000000000..be65d0af2 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersFragment.kt @@ -0,0 +1,221 @@ +package eu.kanade.tachiyomi.ui.recent + +import android.os.Bundle +import android.support.v4.content.ContextCompat +import android.support.v7.widget.LinearLayoutManager +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +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 kotlinx.android.synthetic.main.fragment_recent_chapters.* +import nucleus.factory.RequiresPresenter +import rx.Observable +import rx.android.schedulers.AndroidSchedulers +import rx.schedulers.Schedulers + +/** + * Fragment that shows recent chapters. + * Uses R.layout.fragment_recent_chapters. + * UI related actions should be called from here. + */ +@RequiresPresenter(RecentChaptersPresenter::class) +class RecentChaptersFragment : BaseRxFragment(), FlexibleViewHolder.OnListItemClickListener { + companion object { + /** + * Create new RecentChaptersFragment. + * + */ + @JvmStatic + fun newInstance(): RecentChaptersFragment { + return RecentChaptersFragment() + } + } + + /** + * Adapter containing the recent chapters. + */ + lateinit var adapter: RecentChaptersAdapter + private set + + /** + * Called when view gets created + * + * @param inflater layout inflater + * @param container view group + * @param savedState status of saved state + */ + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedState: Bundle?): View? { + // Inflate view + return inflater.inflate(R.layout.fragment_recent_chapters, container, false) + } + + /** + * Called when view is created + * + * @param view created view + * @param savedInstanceState status of saved sate + */ + override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { + // Init RecyclerView and adapter + recycler.layoutManager = LinearLayoutManager(activity) + recycler.addItemDecoration(DividerItemDecoration(ContextCompat.getDrawable( + context, R.drawable.line_divider))) + recycler.setHasFixedSize(true) + adapter = RecentChaptersAdapter(this) + recycler.adapter = adapter + + // Update toolbar text + setToolbarTitle(R.string.label_recent_updates) + } + + /** + * Called when item in list is clicked + * + * @param position position of clicked item + */ + override fun onListItemClick(position: Int): Boolean { + // Get item from position + val item = adapter.getItem(position) + if (item is MangaChapter) { + // Open chapter in reader + openChapter(item) + } + return false + } + + /** + * Called when item in list is long clicked + * + * @param position position of clicked item + */ + override fun onListItemLongClick(position: Int) { + // Empty function + } + + /** + * Open chapter in reader + + * @param chapter selected chapter + */ + private fun openChapter(chapter: MangaChapter) { + // Start reader event + presenter.onOpenChapter(chapter) + + //Start reader intent + val intent = ReaderActivity.newIntent(activity) + startActivity(intent) + } + + /** + * Populate adapter with chapters + + * @param chapters list of chapters + */ + fun onNextMangaChapters(chapters: List) { + adapter.setItems(chapters) + } + + /** + * Update download status of chapter + + * @param download download object containing download progress. + */ + fun onChapterStatusChange(download: Download) { + getHolder(download)?.onStatusChange(download.status) + + } + + /** + * Returns holder belonging to chapter + * + * @param download download object containing download progress. + */ + private fun getHolder(download: Download): RecentChaptersHolder? { + return recycler.findViewHolderForItemId(download.chapter.id) as? RecentChaptersHolder + } + + /** + * Start downloading chapter + + * @param chapters selected chapters + * @param manga manga that belongs to chapter + * @return true + */ + fun onDownload(chapters: Observable, manga: Manga): Boolean { + // Start the download service. + DownloadService.start(activity) + + // Refresh data on download competition. + val observable = chapters + .doOnCompleted({ + adapter.notifyDataSetChanged() + presenter.start(presenter.CHAPTER_STATUS_CHANGES) + }) + + // Download chapter. + presenter.downloadChapter(observable, manga) + return true + } + + /** + * Start deleting chapter + * + * @param chapters selected chapters + * @param manga manga that belongs to chapter + * @return success of deletion. + */ + fun onDelete(chapters: Observable, manga: Manga): Boolean { + //Create observable + val observable = chapters + .concatMap { chapter -> + presenter.deleteChapter(chapter, manga) + Observable.just(chapter) + } + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .doOnNext { chapter -> + chapter.status = Download.NOT_DOWNLOADED + } + .doOnCompleted { adapter.notifyDataSetChanged() } + + // Delete chapters with observable + presenter.deleteChapters(observable) + + return true + } + + /** + * Mark chapter as read + + * @param chapters selected chapter + * @return true + */ + fun onMarkAsRead(chapters: Observable): Boolean { + // Set marked as read + presenter.markChaptersRead(chapters, true) + return true + } + + /** + * Mark chapter as unread + + * @param chapters selected chapter + * @return true + */ + fun onMarkAsUnread(chapters: Observable): Boolean { + // Set marked as unread + presenter.markChaptersRead(chapters, false) + return true + } + + +} \ No newline at end of file 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 deleted file mode 100644 index 7aa99ae0b..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersHolder.java +++ /dev/null @@ -1,187 +0,0 @@ -package eu.kanade.tachiyomi.ui.recent; - -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 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 { - - /** - * Adapter for recent chapters - */ - private final RecentChaptersAdapter adapter; - - /** - * 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; - - /** - * 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 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; - 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))); - } - - /** - * 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); - } - - // 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: - 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; - } - } - - /** - * 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); - - // 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: - return adapter.getFragment().onDelete(chapterObservable, mangaChapter.manga); - case R.id.action_mark_as_read: - return adapter.getFragment().onMarkAsRead(chapterObservable); - case R.id.action_mark_as_unread: - 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/RecentChaptersHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersHolder.kt new file mode 100644 index 000000000..62159ce68 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersHolder.kt @@ -0,0 +1,140 @@ +package eu.kanade.tachiyomi.ui.recent + +import android.support.v4.content.ContextCompat +import android.view.View +import android.widget.PopupMenu +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 kotlinx.android.synthetic.main.item_recent_chapter.view.* +import rx.Observable + +/** + * Holder that contains chapter item + * Uses R.layout.item_recent_chapter. + * UI related actions should be called from here. + * + * @param view the inflated view for this holder. + * @param adapter the adapter handling this holder. + * @param listener a listener to react to single tap and long tap events. + * @constructor creates a new library holder. + */ +class RecentChaptersHolder(view: View, private val adapter: RecentChaptersAdapter, listener: FlexibleViewHolder.OnListItemClickListener) : FlexibleViewHolder(view, adapter, listener) { + /** + * Color of read chapter + */ + private val readColor: Int + + /** + * Color of unread chapter + */ + private val unreadColor: Int + + /** + * Object containing chapter information + */ + private var mangaChapter: MangaChapter? = null + + init { + // Set colors. + readColor = ContextCompat.getColor(view.context, R.color.hint_text) + unreadColor = ContextCompat.getColor(view.context, R.color.primary_text) + + //Set OnClickListener for download menu + itemView.chapterMenu.setOnClickListener { v -> v.post({ showPopupMenu(v) }) } + } + + /** + * Set values of view + * + * @param item item containing chapter information + */ + fun onSetValues(item: MangaChapter) { + this.mangaChapter = item + + // Set chapter title + itemView.chapter_title.text = item.chapter.name + + // Set manga title + itemView.manga_title.text = item.manga.title + + // Check if chapter is read and set correct color + if (item.chapter.read) { + itemView.chapter_title.setTextColor(readColor) + itemView.manga_title.setTextColor(readColor) + } else { + itemView.chapter_title.setTextColor(unreadColor) + itemView.manga_title.setTextColor(unreadColor) + } + + // Set chapter status + onStatusChange(item.chapter.status) + } + + /** + * Updates chapter status in view. + + * @param status download status + */ + fun onStatusChange(status: Int) { + when (status) { + Download.QUEUE -> itemView.download_text.setText(R.string.chapter_queued) + Download.DOWNLOADING -> itemView.download_text.setText(R.string.chapter_downloading) + Download.DOWNLOADED -> itemView.download_text.setText(R.string.chapter_downloaded) + Download.ERROR -> itemView.download_text.setText(R.string.chapter_error) + else -> itemView.download_text.text = "" + } + } + + /** + * Show pop up menu + * @param view view containing popup menu. + */ + private fun showPopupMenu(view: View) { + // Create a PopupMenu, giving it the clicked view for an anchor + val popup = PopupMenu(adapter.fragment.activity, view) + + // Inflate our menu resource into the PopupMenu's Menu + popup.menuInflater.inflate(R.menu.chapter_recent, popup.menu) + + mangaChapter?.let { + + // Hide download and show delete if the chapter is downloaded and + if (it.chapter.isDownloaded) { + val menu = popup.menu + menu.findItem(R.id.action_download).isVisible = false + menu.findItem(R.id.action_delete).isVisible = true + } + + // Hide mark as unread when the chapter is unread + if (!it.chapter.read /*&& mangaChapter.chapter.last_page_read == 0*/) { + popup.menu.findItem(R.id.action_mark_as_unread).isVisible = false + } + + // Hide mark as read when the chapter is read + if (it.chapter.read) { + popup.menu.findItem(R.id.action_mark_as_read).isVisible = false + } + + + // Set a listener so we are notified if a menu item is clicked + popup.setOnMenuItemClickListener { menuItem -> + val chapterObservable = Observable.just(it.chapter) + + when (menuItem.itemId) { + R.id.action_download -> adapter.fragment.onDownload(chapterObservable, it.manga) + R.id.action_delete -> adapter.fragment.onDelete(chapterObservable, it.manga) + R.id.action_mark_as_read -> adapter.fragment.onMarkAsRead(chapterObservable); + R.id.action_mark_as_unread -> adapter.fragment.onMarkAsUnread(chapterObservable); + } + false + } + + } + + // Finally show the PopupMenu + popup.show() + } +} \ No newline at end of file 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 deleted file mode 100644 index 898744cca..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersPresenter.java +++ /dev/null @@ -1,309 +0,0 @@ -package eu.kanade.tachiyomi.ui.recent; - -import android.os.Bundle; - -import org.greenrobot.eventbus.EventBus; - -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.Map; -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 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; - - @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); - // 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); - } - } - - /** - * 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<>(); - - // 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()) - .filter(download -> chapterIdEquals(download.chapter.id)) - .doOnNext(this::updateChapterStatus); - } - - /** - * Function to check if chapter is in recent list - * @param chaptersId id of chapter - * @return exist in recent list - */ - private boolean chapterIdEquals(Long chaptersId) { - for (MangaChapter mangaChapter : mangaChapters) { - if (chaptersId.equals(mangaChapter.chapter.id)) { - return true; - } - } - return false; - } - - /** - * Update status of chapters. - * - * @param download download object containing progress. - */ - private void updateChapterStatus(Download download) { - // Loop through list - for (MangaChapter item : mangaChapters) { - if (download.chapter.id.equals(item.chapter.id)) { - item.chapter.status = download.getStatus(); - break; - } - } - } - - /** - * Get observable containing recent chapters and date - * @return observable containing recent chapters and date - */ - private Observable> 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. - .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. - .map(recents -> { - List items = new ArrayList<>(); - for (Map.Entry> recent : recents.entrySet()) { - items.add(recent.getKey()); - items.addAll(recent.getValue()); - } - return items; - }) - .observeOn(AndroidSchedulers.mainThread()); - } - - /** - * Set the chapter status - * @param mangaChapter MangaChapter which status gets updated - */ - private void setChapterStatus(MangaChapter mangaChapter) { - // Check if chapter in queue - for (Download download : downloadManager.getQueue()) { - if (mangaChapter.chapter.id.equals(download.chapter.id)) { - mangaChapter.chapter.status = download.getStatus(); - return; - } - } - - // Get source of chapter - Source source = sourceManager.get(mangaChapter.manga.source); - - // Check if chapter is downloaded - if (downloadManager.isChapterDownloaded(source, mangaChapter.manga, mangaChapter.chapter)) { - mangaChapter.chapter.status = Download.DOWNLOADED; - } else { - mangaChapter.chapter.status = Download.NOT_DOWNLOADED; - } - } - - /** - * Get date as time key - * @param date desired date - * @return date as time key - */ - private Date getMapKey(long date) { - Calendar cal = Calendar.getInstance(); - cal.setTime(new Date(date)); - cal.set(Calendar.HOUR_OF_DAY, 0); - cal.set(Calendar.MINUTE, 0); - cal.set(Calendar.SECOND, 0); - cal.set(Calendar.MILLISECOND, 0); - return cal.getTime(); - } - - /** - * Open chapter in reader - * @param item chapter that is opened - */ - public void onOpenChapter(MangaChapter item) { - Source source = sourceManager.get(item.manga.source); - EventBus.getDefault().postSticky(new ReaderEvent(source, item.manga, item.chapter)); - } - - /** - * Download selected chapter - * @param selectedChapter chapter that is selected - * @param manga manga that belongs to chapter - */ - public void downloadChapter(Observable selectedChapter, Manga manga) { - add(selectedChapter - .toList() - .subscribe(chapters -> { - EventBus.getDefault().postSticky(new DownloadChaptersEvent(manga, chapters)); - })); - } - - /** - * Delete selected chapter - * @param chapter chapter that is selected - * @param manga manga that belongs to chapter - */ - public void deleteChapter(Chapter chapter, Manga manga) { - Source source = sourceManager.get(manga.source); - downloadManager.deleteChapter(source, manga, chapter); - } - - /** - * Delete selected chapter observable - * @param selectedChapters chapter that are selected - */ - public void deleteChapters(Observable selectedChapters) { - add(selectedChapters - .subscribe(chapter -> { - downloadManager.getQueue().remove(chapter); - }, error -> { - Timber.e(error.getMessage()); - })); - } - - /** - * Mark selected chapter as read - * @param selectedChapters chapter that is selected - * @param read read status - */ - 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/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersPresenter.kt new file mode 100644 index 000000000..a502a42c5 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersPresenter.kt @@ -0,0 +1,310 @@ +package eu.kanade.tachiyomi.ui.recent + +import android.os.Bundle +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.event.DownloadChaptersEvent +import eu.kanade.tachiyomi.event.ReaderEvent +import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter +import org.greenrobot.eventbus.EventBus +import rx.Observable +import rx.android.schedulers.AndroidSchedulers +import rx.schedulers.Schedulers +import timber.log.Timber +import java.util.* +import javax.inject.Inject + +class RecentChaptersPresenter : BasePresenter() { + /** + * Used to connect to database + */ + @Inject lateinit var db: DatabaseHelper + + /** + * Used to get information from download manager + */ + @Inject lateinit var downloadManager: DownloadManager + + /** + * Used to get source from source id + */ + @Inject lateinit var sourceManager: SourceManager + + /** + * List containing chapter and manga information + */ + private var mangaChapters: List? = null + + /** + * The id of the restartable. + */ + val GET_RECENT_CHAPTERS = 1 + + /** + * The id of the restartable. + */ + val CHAPTER_STATUS_CHANGES = 2 + + override fun onCreate(savedState: Bundle?) { + super.onCreate(savedState) + + // Used to get recent chapters + restartableLatestCache(GET_RECENT_CHAPTERS, + { getRecentChaptersObservable() }, + { recentChaptersFragment, chapters -> + // Update adapter to show recent manga's + recentChaptersFragment.onNextMangaChapters(chapters) + // Update download status + updateChapterStatus(convertToMangaChaptersList(chapters)) + } + ) + + // Used to update download status + startableLatestCache(CHAPTER_STATUS_CHANGES, + { getChapterStatusObs() }, + { recentChaptersFragment, download -> + // Set chapter status + recentChaptersFragment.onChapterStatusChange(download) + }, + { view, error -> Timber.e(error.cause, error.message) } + ) + + + if (savedState == null) { + // Start fetching recent chapters + start(GET_RECENT_CHAPTERS) + } + } + + + /** + * Returns observable containing chapter status. + + * @return download object containing download progress. + */ + private fun getChapterStatusObs(): Observable { + return downloadManager.queue.statusObservable + .observeOn(AndroidSchedulers.mainThread()) + .filter { download: Download -> + if (chapterIdEquals(download.chapter.id)) + true + else + false + } + .doOnNext { download1: Download -> updateChapterStatus(download1) } + + } + + /** + * Function to check if chapter is in recent list + * @param chaptersId id of chapter + * * + * @return exist in recent list + */ + private fun chapterIdEquals(chaptersId: Long): Boolean { + mangaChapters!!.forEach { mangaChapter -> + if (chaptersId == mangaChapter.chapter.id) { + return true + } + } + return false + } + + /** + * Returns a list only containing MangaChapter objects. + + * @param input the list that will be converted. + * * + * @return list containing MangaChapters objects. + */ + private fun convertToMangaChaptersList(input: List): List { + // Create temp list + val tempMangaChapterList = ArrayList() + + // Only add MangaChapter objects + //noinspection Convert2streamapi + input.forEach { `object` -> + if (`object` is MangaChapter) { + tempMangaChapterList.add(`object`) + } + } + + // Return temp list + return tempMangaChapterList + } + + /** + * Update status of chapters. + + * @param download download object containing progress. + */ + private fun updateChapterStatus(download: Download) { + // Loop through list + mangaChapters?.let { + for (item in it) { + if (download.chapter.id == item.chapter.id) { + // Update status. + item.chapter.status = download.status + break + } + } + } + } + + /** + * Update status of chapters + + * @param mangaChapters list containing recent chapters + */ + private fun updateChapterStatus(mangaChapters: List) { + // Set global list of chapters. + this.mangaChapters = mangaChapters + + // Update status. + //noinspection Convert2streamapi + for (mangaChapter in mangaChapters) + setChapterStatus(mangaChapter) + + // Start onChapterStatusChange restartable. + start(CHAPTER_STATUS_CHANGES) + } + + /** + * Set the chapter status + * @param mangaChapter MangaChapter which status gets updated + */ + private fun setChapterStatus(mangaChapter: MangaChapter) { + // Check if chapter in queue + for (download in downloadManager.queue) { + if (mangaChapter.chapter.id == download.chapter.id) { + mangaChapter.chapter.status = download.status + return + } + } + + // Get source of chapter + val source = sourceManager.get(mangaChapter.manga.source) + + // Check if chapter is downloaded + if (downloadManager.isChapterDownloaded(source, mangaChapter.manga, mangaChapter.chapter)) { + mangaChapter.chapter.status = Download.DOWNLOADED + } else { + mangaChapter.chapter.status = Download.NOT_DOWNLOADED + } + } + + /** + * Get observable containing recent chapters and date + * @return observable containing recent chapters and date + */ + fun getRecentChaptersObservable(): Observable>? { + // Set date for recent chapters + val cal = Calendar.getInstance() + cal.time = Date() + cal.add(Calendar.MONTH, -1) + + return db.getRecentChapters(cal.time).asRxObservable() + // Group chapters by the date they were fetched on a ordered map. + .flatMap { recentItems -> + Observable.from(recentItems) + .toMultimap { + recent -> + (getMapKey(recent.chapter.date_fetch)) + } + } + // Add every day and all its chapters to a single list. + .map { recentItems -> + val items = ArrayList() + recentItems.entries.forEach { recent -> + items.add(recent.key) + items.addAll(recent.value) + } + items + } + .observeOn(AndroidSchedulers.mainThread()) + } + + /** + * Get date as time key + * @param date desired date + * * + * @return date as time key + */ + private fun getMapKey(date: Long): Date { + val cal = Calendar.getInstance() + cal.time = Date(date) + cal[Calendar.HOUR_OF_DAY] = 0 + cal[Calendar.MINUTE] = 0 + cal[Calendar.SECOND] = 0 + cal[Calendar.MILLISECOND] = 0 + return cal.time + } + + /** + * Open chapter in reader + * @param item chapter that is opened + */ + fun onOpenChapter(item: MangaChapter) { + val source = sourceManager.get(item.manga.source) + EventBus.getDefault().postSticky(ReaderEvent(source, item.manga, item.chapter)) + } + + /** + * Download selected chapter + * @param selectedChapter chapter that is selected + * * + * @param manga manga that belongs to chapter + */ + fun downloadChapter(selectedChapter: Observable, manga: Manga) { + add(selectedChapter.toList().subscribe { chapters -> EventBus.getDefault().postSticky(DownloadChaptersEvent(manga, chapters)) }) + } + + /** + * Delete selected chapter + * @param chapter chapter that is selected + * * + * @param manga manga that belongs to chapter + */ + fun deleteChapter(chapter: Chapter, manga: Manga) { + val source = sourceManager.get(manga.source) + downloadManager.deleteChapter(source, manga, chapter) + } + + /** + * Delete selected chapter observable + * @param selectedChapters chapter that are selected + */ + fun deleteChapters(selectedChapters: Observable) { + add(selectedChapters + .subscribe( + { chapter -> downloadManager.queue.remove(chapter) }) + { error -> Timber.e(error.message) }) + } + + /** + * Mark selected chapter as read + * @param selectedChapters chapter that is selected + * * + * @param read read status + */ + fun markChaptersRead(selectedChapters: Observable, read: Boolean) { + add(selectedChapters + .subscribeOn(Schedulers.io()) + .map { chapter -> + chapter.read = read + if (!read) { + chapter.last_page_read = 0 + } + chapter + } + .toList() + .flatMap { chapters -> db.insertChapters(chapters).asRxObservable() } + .observeOn(AndroidSchedulers.mainThread()) + .subscribe()) + } +} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/SectionViewHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/SectionViewHolder.kt new file mode 100644 index 000000000..a629ce207 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/SectionViewHolder.kt @@ -0,0 +1,26 @@ +package eu.kanade.tachiyomi.ui.recent + +import android.support.v7.widget.RecyclerView +import android.text.format.DateUtils +import android.view.View +import kotlinx.android.synthetic.main.item_recent_chapter_section.view.* +import java.util.* + +class SectionViewHolder(view: View) : RecyclerView.ViewHolder(view) { + + /** + * Current date + */ + private val now = Date().time + + /** + * Set value of section header + * + * @param date of section header + */ + fun onSetValues(date: Date) { + val s = DateUtils.getRelativeTimeSpanString( + date.time, now, DateUtils.DAY_IN_MILLIS) + itemView.section_text.text = s + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_recent_chapters.xml b/app/src/main/res/layout/fragment_recent_chapters.xml index a05e196cf..9502792ec 100644 --- a/app/src/main/res/layout/fragment_recent_chapters.xml +++ b/app/src/main/res/layout/fragment_recent_chapters.xml @@ -6,7 +6,7 @@ android:orientation="vertical"> + android:paddingRight="?android:attr/listPreferredItemPaddingRight" + android:paddingStart="?android:attr/listPreferredItemPaddingStart" + android:paddingLeft="?android:attr/listPreferredItemPaddingLeft">