diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt index 404c39a3f..3ee8feeee 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt @@ -57,18 +57,22 @@ class MainActivity : BaseActivity() { empty_view.hide() val id = item.itemId - when (id) { - R.id.nav_drawer_library -> setFragment(LibraryFragment.newInstance(), id) - R.id.nav_drawer_recent_updates -> setFragment(RecentChaptersFragment.newInstance(), id) - R.id.nav_drawer_recently_read -> setFragment(RecentlyReadFragment.newInstance(), id) - R.id.nav_drawer_catalogues -> setFragment(CatalogueFragment.newInstance(), id) - R.id.nav_drawer_latest_updates -> setFragment(LatestUpdatesFragment.newInstance(), id) - R.id.nav_drawer_downloads -> startActivity(Intent(this, DownloadActivity::class.java)) - R.id.nav_drawer_settings -> { - val intent = Intent(this, SettingsActivity::class.java) - startActivityForResult(intent, REQUEST_OPEN_SETTINGS) + + val oldFragment = supportFragmentManager.findFragmentById(R.id.frame_container) + if (oldFragment == null || oldFragment.tag.toInt() != id) { + when (id) { + R.id.nav_drawer_library -> setFragment(LibraryFragment.newInstance(), id) + R.id.nav_drawer_recent_updates -> setFragment(RecentChaptersFragment.newInstance(), id) + R.id.nav_drawer_recently_read -> setFragment(RecentlyReadFragment.newInstance(), id) + R.id.nav_drawer_catalogues -> setFragment(CatalogueFragment.newInstance(), id) + R.id.nav_drawer_latest_updates -> setFragment(LatestUpdatesFragment.newInstance(), id) + R.id.nav_drawer_downloads -> startActivity(Intent(this, DownloadActivity::class.java)) + R.id.nav_drawer_settings -> { + val intent = Intent(this, SettingsActivity::class.java) + startActivityForResult(intent, REQUEST_OPEN_SETTINGS) + } + R.id.nav_drawer_backup -> setFragment(BackupFragment.newInstance(), id) } - R.id.nav_drawer_backup -> setFragment(BackupFragment.newInstance(), id) } drawer.closeDrawer(GravityCompat.START) true diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/DateItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/DateItem.kt new file mode 100644 index 000000000..cc13088dd --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/DateItem.kt @@ -0,0 +1,50 @@ +package eu.kanade.tachiyomi.ui.recent_updates + +import android.text.format.DateUtils +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import eu.davidea.flexibleadapter.FlexibleAdapter +import eu.davidea.flexibleadapter.items.AbstractHeaderItem +import eu.davidea.viewholders.FlexibleViewHolder +import eu.kanade.tachiyomi.R +import java.util.* + +class DateItem(val date: Date) : AbstractHeaderItem() { + + override fun getLayoutRes(): Int { + return R.layout.item_recent_chapter_section + } + + override fun createViewHolder(adapter: FlexibleAdapter<*>, inflater: LayoutInflater, parent: ViewGroup): Holder { + return Holder(inflater.inflate(layoutRes, parent, false), adapter) + } + + override fun bindViewHolder(adapter: FlexibleAdapter<*>, holder: Holder, position: Int, payloads: List?) { + holder.bind(this) + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other is DateItem) { + return date == other.date + } + return false + } + + override fun hashCode(): Int { + return date.hashCode() + } + + class Holder(view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter, true) { + + private val now = Date().time + + val section_text = view.findViewById(R.id.section_text) as TextView + + fun bind(item: DateItem) { + section_text.text = DateUtils.getRelativeTimeSpanString(item.date.time, now, DateUtils.DAY_IN_MILLIS) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChapter.kt deleted file mode 100644 index c9060f3e8..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChapter.kt +++ /dev/null @@ -1,22 +0,0 @@ -package eu.kanade.tachiyomi.ui.recent_updates - -import eu.kanade.tachiyomi.data.database.models.Chapter -import eu.kanade.tachiyomi.data.database.models.MangaChapter -import eu.kanade.tachiyomi.data.download.model.Download - -class RecentChapter(mc: MangaChapter) : Chapter by mc.chapter { - - val manga = mc.manga - - private var _status: Int = 0 - - var status: Int - get() = download?.status ?: _status - set(value) { _status = value } - - @Transient var download: Download? = null - - val isDownloaded: Boolean - get() = status == Download.DOWNLOADED - -} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChaptersHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChapterHolder.kt similarity index 75% rename from app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChaptersHolder.kt rename to app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChapterHolder.kt index 7f41f8bc2..7ee7e1fe9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChaptersHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChapterHolder.kt @@ -2,9 +2,9 @@ package eu.kanade.tachiyomi.ui.recent_updates import android.view.View import android.widget.PopupMenu +import eu.davidea.viewholders.FlexibleViewHolder import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.download.model.Download -import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder import eu.kanade.tachiyomi.util.getResourceColor import kotlinx.android.synthetic.main.item_recent_chapters.view.* @@ -18,11 +18,9 @@ import kotlinx.android.synthetic.main.item_recent_chapters.view.* * @param listener a listener to react to single tap and long tap events. * @constructor creates a new recent chapter holder. */ -class RecentChaptersHolder( - private val view: View, - private val adapter: RecentChaptersAdapter, - listener: OnListItemClickListener) -: FlexibleViewHolder(view, adapter, listener) { +class RecentChapterHolder(private val view: View, private val adapter: RecentChaptersAdapter) : + FlexibleViewHolder(view, adapter) { + /** * Color of read chapter */ @@ -34,33 +32,33 @@ class RecentChaptersHolder( private var unreadColor = view.context.getResourceColor(android.R.attr.textColorPrimary) /** - * Object containing chapter information + * Currently bound item. */ - private var chapter: RecentChapter? = null + private var item: RecentChapterItem? = null init { // We need to post a Runnable to show the popup to make sure that the PopupMenu is // correctly positioned. The reason being that the view may change position before the // PopupMenu is shown. - view.chapter_menu.setOnClickListener { it.post({ showPopupMenu(it) }) } + view.chapter_menu.setOnClickListener { it.post { showPopupMenu(it) } } } /** * Set values of view * - * @param chapter item containing chapter information + * @param item item containing chapter information */ - fun onSetValues(chapter: RecentChapter) { - this.chapter = chapter + fun bind(item: RecentChapterItem) { + this.item = item // Set chapter title - view.chapter_title.text = chapter.name + view.chapter_title.text = item.chapter.name // Set manga title - view.manga_title.text = chapter.manga.title + view.manga_title.text = item.manga.title // Check if chapter is read and set correct color - if (chapter.read) { + if (item.chapter.read) { view.chapter_title.setTextColor(readColor) view.manga_title.setTextColor(readColor) } else { @@ -69,7 +67,7 @@ class RecentChaptersHolder( } // Set chapter status - notifyStatus(chapter.status) + notifyStatus(item.status) } /** @@ -92,7 +90,7 @@ class RecentChaptersHolder( * * @param view view containing popup menu. */ - private fun showPopupMenu(view: View) = chapter?.let { chapter -> + private fun showPopupMenu(view: View) = item?.let { item -> // Create a PopupMenu, giving it the clicked view for an anchor val popup = PopupMenu(view.context, view) @@ -100,18 +98,18 @@ class RecentChaptersHolder( popup.menuInflater.inflate(R.menu.chapter_recent, popup.menu) // Hide download and show delete if the chapter is downloaded and - if (chapter.isDownloaded) { + if (item.isDownloaded) { popup.menu.findItem(R.id.action_download).isVisible = false popup.menu.findItem(R.id.action_delete).isVisible = true } // Hide mark as unread when the chapter is unread - if (!chapter.read /*&& mangaChapter.chapter.last_page_read == 0*/) { + if (!item.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 (chapter.read) { + if (item.chapter.read) { popup.menu.findItem(R.id.action_mark_as_read).isVisible = false } @@ -119,10 +117,10 @@ class RecentChaptersHolder( popup.setOnMenuItemClickListener { menuItem -> with(adapter.fragment) { when (menuItem.itemId) { - R.id.action_download -> downloadChapter(chapter) - R.id.action_delete -> deleteChapter(chapter) - R.id.action_mark_as_read -> markAsRead(listOf(chapter)) - R.id.action_mark_as_unread -> markAsUnread(listOf(chapter)) + R.id.action_download -> downloadChapter(item) + R.id.action_delete -> deleteChapter(item) + R.id.action_mark_as_read -> markAsRead(listOf(item)) + R.id.action_mark_as_unread -> markAsUnread(listOf(item)) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChapterItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChapterItem.kt new file mode 100644 index 000000000..7f1a1e4fd --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChapterItem.kt @@ -0,0 +1,50 @@ +package eu.kanade.tachiyomi.ui.recent_updates + +import android.view.LayoutInflater +import android.view.ViewGroup +import eu.davidea.flexibleadapter.FlexibleAdapter +import eu.davidea.flexibleadapter.items.AbstractSectionableItem +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.download.model.Download + +class RecentChapterItem(val chapter: Chapter, val manga: Manga, header: DateItem) : + AbstractSectionableItem(header) { + + private var _status: Int = 0 + + var status: Int + get() = download?.status ?: _status + set(value) { _status = value } + + @Transient var download: Download? = null + + val isDownloaded: Boolean + get() = status == Download.DOWNLOADED + + override fun getLayoutRes(): Int { + return R.layout.item_recent_chapters + } + + override fun createViewHolder(adapter: FlexibleAdapter<*>, inflater: LayoutInflater, parent: ViewGroup): RecentChapterHolder { + return RecentChapterHolder(inflater.inflate(layoutRes, parent, false), adapter as RecentChaptersAdapter) + } + + override fun bindViewHolder(adapter: FlexibleAdapter<*>, holder: RecentChapterHolder, position: Int, payloads: List?) { + holder.bind(this) + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other is RecentChapterItem) { + return chapter.id!! == other.chapter.id!! + } + return false + } + + override fun hashCode(): Int { + return chapter.id!!.hashCode() + } + +} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChaptersAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChaptersAdapter.kt index 37f5c17ed..61c4ac3b0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChaptersAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChaptersAdapter.kt @@ -1,128 +1,12 @@ package eu.kanade.tachiyomi.ui.recent_updates -import android.support.v7.widget.RecyclerView -import android.view.View -import android.view.ViewGroup -import eu.davidea.flexibleadapter4.FlexibleAdapter -import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.util.inflate -import java.util.* +import eu.davidea.flexibleadapter.FlexibleAdapter -/** - * 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 +class RecentChaptersAdapter(val fragment: RecentChaptersFragment) : + FlexibleAdapter(null, fragment, true) { init { - // Let each each item in the data set be represented with a unique identifier. - setHasStableIds(true) + setDisplayHeadersAtStartUp(true) + setStickyHeaders(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 RecentChapter) { - (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_chapters) - 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 RecentChapter) 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 RecentChapter) - return item.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_updates/RecentChaptersFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChaptersFragment.kt index 019e51dea..2a78c7dce 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChaptersFragment.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChaptersFragment.kt @@ -8,11 +8,10 @@ import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.RecyclerView import android.view.* import com.afollestad.materialdialogs.MaterialDialog -import eu.davidea.flexibleadapter4.FlexibleAdapter +import eu.davidea.flexibleadapter.FlexibleAdapter import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.library.LibraryUpdateService -import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.reader.ReaderActivity @@ -28,8 +27,11 @@ import timber.log.Timber * UI related actions should be called from here. */ @RequiresPresenter(RecentChaptersPresenter::class) -class RecentChaptersFragment -: BaseRxFragment(), ActionMode.Callback, FlexibleViewHolder.OnListItemClickListener { +class RecentChaptersFragment: + BaseRxFragment(), + ActionMode.Callback, + FlexibleAdapter.OnItemClickListener, + FlexibleAdapter.OnItemLongClickListener{ companion object { /** @@ -97,40 +99,45 @@ class RecentChaptersFragment // Update toolbar text setToolbarTitle(R.string.label_recent_updates) + + // Disable toolbar elevation, it looks better with sticky headers. +// ViewCompat.setElevation(activity.appbar, 0f) } +// override fun onDestroyView() { +// ViewCompat.setElevation(activity.appbar, 4.dpToPx.toFloat()) +// super.onDestroyView() +// } + /** * Returns selected chapters * @return list of selected chapters */ - fun getSelectedChapters(): List { - return adapter.selectedItems.map { adapter.getItem(it) as? RecentChapter }.filterNotNull() + fun getSelectedChapters(): List { + return adapter.selectedPositions.mapNotNull { adapter.getItem(it) } } /** * Called when item in list is clicked * @param position position of clicked item */ - override fun onListItemClick(position: Int): Boolean { + override fun onItemClick(position: Int): Boolean { // Get item from position val item = adapter.getItem(position) - if (item is RecentChapter) { - if (actionMode != null && adapter.mode == FlexibleAdapter.MODE_MULTI) { - toggleSelection(position) - return true - } else { - openChapter(item) - return false - } + if (actionMode != null && adapter.mode == FlexibleAdapter.MODE_MULTI) { + toggleSelection(position) + return true + } else { + openChapter(item) + return false } - return false } /** * Called when item in list is long clicked * @param position position of clicked item */ - override fun onListItemLongClick(position: Int) { + override fun onItemLongClick(position: Int) { if (actionMode == null) actionMode = activity.startSupportActionMode(this) @@ -142,31 +149,22 @@ class RecentChaptersFragment * @param position position of selected item */ private fun toggleSelection(position: Int) { - adapter.toggleSelection(position, false) + adapter.toggleSelection(position) val count = adapter.selectedItemCount if (count == 0) { actionMode?.finish() } else { - setContextTitle(count) - actionMode?.invalidate() + actionMode?.title = getString(R.string.label_selected, count) } } - /** - * Set the context title - * @param count count of selected items - */ - private fun setContextTitle(count: Int) { - actionMode?.title = getString(R.string.label_selected, count) - } - /** * Open chapter in reader * @param chapter selected chapter */ - private fun openChapter(chapter: RecentChapter) { - val intent = ReaderActivity.newIntent(activity, chapter.manga, chapter) + private fun openChapter(item: RecentChapterItem) { + val intent = ReaderActivity.newIntent(activity, item.manga, item.chapter) startActivity(intent) } @@ -174,7 +172,7 @@ class RecentChaptersFragment * Download selected items * @param chapters list of selected [RecentChapter]s */ - fun downloadChapters(chapters: List) { + fun downloadChapters(chapters: List) { destroyActionModeIfNeeded() presenter.downloadChapters(chapters) } @@ -183,12 +181,12 @@ class RecentChaptersFragment * Populate adapter with chapters * @param chapters list of [Any] */ - fun onNextRecentChapters(chapters: List) { + fun onNextRecentChapters(chapters: List) { (activity as MainActivity).updateEmptyView(chapters.isEmpty(), R.string.information_no_recent, R.drawable.ic_update_black_128dp) destroyActionModeIfNeeded() - adapter.setItems(chapters) + adapter.updateDataSet(chapters.toMutableList(), true) } /** @@ -203,15 +201,15 @@ class RecentChaptersFragment * 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 + private fun getHolder(download: Download): RecentChapterHolder? { + return recycler.findViewHolderForItemId(download.chapter.id!!) as? RecentChapterHolder } /** * Mark chapter as read * @param chapters list of chapters */ - fun markAsRead(chapters: List) { + fun markAsRead(chapters: List) { presenter.markChapterRead(chapters, true) if (presenter.preferences.removeAfterMarkedAsRead()) { deleteChapters(chapters) @@ -222,7 +220,7 @@ class RecentChaptersFragment * Delete selected chapters * @param chapters list of [RecentChapter] objects */ - fun deleteChapters(chapters: List) { + fun deleteChapters(chapters: List) { destroyActionModeIfNeeded() DeletingChaptersDialog().show(childFragmentManager, DeletingChaptersDialog.TAG) presenter.deleteChapters(chapters) @@ -239,7 +237,7 @@ class RecentChaptersFragment * Mark chapter as unread * @param chapters list of selected [RecentChapter] */ - fun markAsUnread(chapters: List) { + fun markAsUnread(chapters: List) { presenter.markChapterRead(chapters, false) } @@ -247,15 +245,15 @@ class RecentChaptersFragment * Start downloading chapter * @param chapter selected chapter with manga */ - fun downloadChapter(chapter: RecentChapter) { - presenter.downloadChapter(chapter) + fun downloadChapter(chapter: RecentChapterItem) { + presenter.downloadChapters(listOf(chapter)) } /** * Start deleting chapter * @param chapter selected chapter with manga */ - fun deleteChapter(chapter: RecentChapter) { + fun deleteChapter(chapter: RecentChapterItem) { DeletingChaptersDialog().show(childFragmentManager, DeletingChaptersDialog.TAG) presenter.deleteChapters(listOf(chapter)) } @@ -281,11 +279,8 @@ class RecentChaptersFragment * Called to dismiss deleting dialog */ fun dismissDeletingDialog() { - (childFragmentManager.findFragmentByTag(DeletingChaptersDialog.TAG) as? DialogFragment)?.dismiss() - } - - override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean { - return false + (childFragmentManager.findFragmentByTag(DeletingChaptersDialog.TAG) as? DialogFragment) + ?.dismissAllowingStateLoss() } /** @@ -322,12 +317,16 @@ class RecentChaptersFragment return true } + override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean { + return false + } + /** * Called when ActionMode destroyed * @param mode the ActionMode object */ override fun onDestroyActionMode(mode: ActionMode?) { - adapter.mode = FlexibleAdapter.MODE_SINGLE + adapter.mode = FlexibleAdapter.MODE_IDLE adapter.clearSelection() actionMode = null } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChaptersPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChaptersPresenter.kt index 55d6f3e71..434e287b7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChaptersPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/RecentChaptersPresenter.kt @@ -41,7 +41,7 @@ class RecentChaptersPresenter : BasePresenter() { /** * List containing chapter and manga information */ - private var chapters: List? = null + private var chapters: List = emptyList() override fun onCreate(savedState: Bundle?) { super.onCreate(savedState) @@ -53,15 +53,15 @@ class RecentChaptersPresenter : BasePresenter() { getChapterStatusObservable() .subscribeLatestCache(RecentChaptersFragment::onChapterStatusChange, { view, error -> Timber.e(error) }) - } /** * Get observable containing recent chapters and date + * * @return observable containing recent chapters and date */ - fun getRecentChaptersObservable(): Observable> { - // Set date for recent chapters + fun getRecentChaptersObservable(): Observable> { + // Set date limit for recent chapters val cal = Calendar.getInstance().apply { time = Date() add(Calendar.MONTH, -1) @@ -70,33 +70,48 @@ class RecentChaptersPresenter : BasePresenter() { return db.getRecentChapters(cal.time).asRxObservable() // Convert to a list of recent chapters. .map { mangaChapters -> - mangaChapters.map { it.toModel() } + val map = TreeMap> { d1, d2 -> d2.compareTo(d1) } + val byDay = mangaChapters.groupByTo(map, { getMapKey(it.chapter.date_fetch) }) + byDay.flatMap { + val dateItem = DateItem(it.key) + it.value.map { RecentChapterItem(it.chapter, it.manga, dateItem) } + } } .doOnNext { - setDownloadedChapters(it) - chapters = it - } - // Group chapters by the date they were fetched on a ordered map. - .flatMap { recentItems -> - Observable.from(recentItems) - .toMultimap( - { getMapKey(it.date_fetch) }, - { it }, - { TreeMap { d1, d2 -> d2.compareTo(d1) } }) - } - // Add every day and all its chapters to a single list. - .map { recentItems -> - ArrayList().apply { - for ((key, value) in recentItems) { - add(key) - addAll(value) + it.forEach { item -> + // Find an active download for this chapter. + val download = downloadManager.queue.find { it.chapter.id == item.chapter.id } + + // If there's an active download, assign it, otherwise ask the manager if the chapter is + // downloaded and assign it to the status. + if (download != null) { + item.download = download } } + setDownloadedChapters(it) + chapters = it } } + /** + * 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 + } + /** * Returns observable containing chapter status. + * * @return download object containing download progress. */ private fun getChapterStatusObservable(): Observable { @@ -105,38 +120,21 @@ class RecentChaptersPresenter : BasePresenter() { .doOnNext { download -> onDownloadStatusChange(download) } } - /** - * Converts a chapter from the database to an extended model, allowing to store new fields. - */ - private fun MangaChapter.toModel(): RecentChapter { - // Create the model object. - val model = RecentChapter(this) - - // Find an active download for this chapter. - val download = downloadManager.queue.find { it.chapter.id == chapter.id } - - // If there's an active download, assign it, otherwise ask the manager if the chapter is - // downloaded and assign it to the status. - if (download != null) { - model.download = download - } - return model - } - /** * Finds and assigns the list of downloaded chapters. * - * @param chapters the list of chapter from the database. + * @param items the list of chapter from the database. */ - private fun setDownloadedChapters(chapters: List) { + private fun setDownloadedChapters(items: List) { // Cached list of downloaded manga directories. val mangaDirectories = mutableMapOf>() // Cached list of downloaded chapter directories for a manga. val chapterDirectories = mutableMapOf>() - for (chapter in chapters) { - val manga = chapter.manga + for (item in items) { + val manga = item.manga + val chapter = item.chapter val source = sourceManager.get(manga.source) ?: continue val mangaDirs = mangaDirectories.getOrPut(source.id) { @@ -152,64 +150,52 @@ class RecentChaptersPresenter : BasePresenter() { val chapterDirName = downloadManager.getChapterDirName(chapter) if (chapterDirs.any { it.name == chapterDirName }) { - chapter.status = Download.DOWNLOADED + item.status = Download.DOWNLOADED } } } /** * Update status of chapters. + * * @param download download object containing progress. */ private fun onDownloadStatusChange(download: Download) { // Assign the download to the model object. if (download.status == Download.QUEUE) { - val chapter = chapters?.find { it.id == download.chapter.id } + val chapter = chapters.find { it.chapter.id == download.chapter.id } if (chapter != null && chapter.download == null) { chapter.download = download } } } - /** - * 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 - } - /** * Mark selected chapter as read - * @param chapters list of selected chapters + * + * @param items list of selected chapters * @param read read status */ - fun markChapterRead(chapters: List, read: Boolean) { - Observable.from(chapters) - .doOnNext { chapter -> - chapter.read = read - if (!read) { - chapter.last_page_read = 0 - } - } - .toList() - .flatMap { db.updateChaptersProgress(it).asRxObservable() } + fun markChapterRead(items: List, read: Boolean) { + val chapters = items.map { it.chapter } + chapters.forEach { + it.read = read + if (!read) { + it.last_page_read = 0 + } + } + + Observable.fromCallable { db.updateChaptersProgress(chapters).executeAsBlocking() } .subscribeOn(Schedulers.io()) .subscribe() } /** * Delete selected chapters + * * @param chapters list of chapters */ - fun deleteChapters(chapters: List) { + fun deleteChapters(chapters: List) { Observable.from(chapters) .doOnNext { deleteChapter(it) } .toList() @@ -217,42 +203,29 @@ class RecentChaptersPresenter : BasePresenter() { .observeOn(AndroidSchedulers.mainThread()) .subscribeFirst({ view, result -> view.onChaptersDeleted() - }, { view, error -> - view.onChaptersDeletedError(error) - }) + }, RecentChaptersFragment::onChaptersDeletedError) } /** * Download selected chapters - * @param chapters list of recent chapters seleted. + * @param items list of recent chapters seleted. */ - fun downloadChapters(chapters: List) { + fun downloadChapters(items: List) { + items.forEach { downloadManager.downloadChapters(it.manga, listOf(it.chapter)) } DownloadService.start(context) - Observable.from(chapters) - .doOnNext { downloadChapter(it) } - .subscribeOn(AndroidSchedulers.mainThread()) - .subscribe() - } - - /** - * Download selected chapter - * @param chapter chapter that is selected - */ - fun downloadChapter(chapter: RecentChapter) { - DownloadService.start(context) - downloadManager.downloadChapters(chapter.manga, listOf(chapter)) } /** * Delete selected chapter - * @param chapter chapter that is selected + * + * @param item chapter that is selected */ - private fun deleteChapter(chapter: RecentChapter) { - val source = sourceManager.get(chapter.manga.source) ?: return - downloadManager.queue.remove(chapter) - downloadManager.deleteChapter(source, chapter.manga, chapter) - chapter.status = Download.NOT_DOWNLOADED - chapter.download = null + private fun deleteChapter(item: RecentChapterItem) { + val source = sourceManager.get(item.manga.source) ?: return + downloadManager.queue.remove(item.chapter) + downloadManager.deleteChapter(source, item.manga, item.chapter) + item.status = Download.NOT_DOWNLOADED + item.download = null } } \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/SectionViewHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/SectionViewHolder.kt deleted file mode 100644 index d1f5e9cea..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent_updates/SectionViewHolder.kt +++ /dev/null @@ -1,25 +0,0 @@ -package eu.kanade.tachiyomi.ui.recent_updates - -import android.support.v7.widget.RecyclerView -import android.text.format.DateUtils -import android.text.format.DateUtils.DAY_IN_MILLIS -import android.view.View -import kotlinx.android.synthetic.main.item_recent_chapter_section.view.* -import java.util.* - -class SectionViewHolder(private val 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) { - view.section_text.text = DateUtils.getRelativeTimeSpanString(date.time, now, DAY_IN_MILLIS) - } -} \ 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 9991a0b26..b93720dc2 100644 --- a/app/src/main/res/layout/fragment_recent_chapters.xml +++ b/app/src/main/res/layout/fragment_recent_chapters.xml @@ -7,13 +7,17 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - + android:layout_height="match_parent"> - + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_recent_chapter_section.xml b/app/src/main/res/layout/item_recent_chapter_section.xml index 3bd4e8200..e8fbaf52a 100644 --- a/app/src/main/res/layout/item_recent_chapter_section.xml +++ b/app/src/main/res/layout/item_recent_chapter_section.xml @@ -9,7 +9,8 @@ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" android:paddingLeft="?android:attr/listPreferredItemPaddingLeft" android:paddingRight="?android:attr/listPreferredItemPaddingRight" - android:paddingStart="?android:attr/listPreferredItemPaddingStart"> + android:paddingStart="?android:attr/listPreferredItemPaddingStart" + android:elevation="4dp"> + android:maxLines="1"/> - -