From 52434819c339cd22e0dd9b11e7dfb00f397080ef Mon Sep 17 00:00:00 2001 From: arkon Date: Fri, 6 Mar 2020 23:13:48 -0500 Subject: [PATCH] Add history date section headers --- .../tachiyomi/ui/more/AboutController.kt | 4 ++-- .../DateItem.kt => DateSectionItem.kt} | 10 ++++---- .../ui/recent/history/HistoryAdapter.kt | 10 ++++---- .../ui/recent/history/HistoryHolder.kt | 2 +- .../ui/recent/history/HistoryItem.kt | 7 +++--- .../ui/recent/history/HistoryPresenter.kt | 16 +++++++++++-- .../ui/recent/updates/UpdatesItem.kt | 6 ++--- .../ui/recent/updates/UpdatesPresenter.kt | 22 ++++-------------- .../tachiyomi/util/lang/DateExtensions.kt | 23 ++++++++++++++++++- .../main/res/layout/history_controller.xml | 2 -- ...ction_item.xml => recent_section_item.xml} | 0 11 files changed, 59 insertions(+), 43 deletions(-) rename app/src/main/java/eu/kanade/tachiyomi/ui/recent/{updates/DateItem.kt => DateSectionItem.kt} (84%) rename app/src/main/res/layout/{updates_section_item.xml => recent_section_item.xml} (100%) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt index f03a721768..6fc24d73a2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt @@ -19,7 +19,7 @@ import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.ui.main.ChangelogDialogController import eu.kanade.tachiyomi.ui.setting.SettingsController import eu.kanade.tachiyomi.util.lang.launchNow -import eu.kanade.tachiyomi.util.lang.toTimestampString +import eu.kanade.tachiyomi.util.lang.toDateTimestampString import eu.kanade.tachiyomi.util.preference.defaultValue import eu.kanade.tachiyomi.util.preference.onChange import eu.kanade.tachiyomi.util.preference.onClick @@ -180,7 +180,7 @@ class AboutController : SettingsController() { DateFormat.MEDIUM, DateFormat.SHORT, Locale.getDefault()) outputDf.timeZone = TimeZone.getDefault() - return buildTime.toTimestampString(dateFormat) + return buildTime.toDateTimestampString(dateFormat) } catch (e: ParseException) { return BuildConfig.BUILD_TIME } 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/DateSectionItem.kt similarity index 84% rename from app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/DateItem.kt rename to app/src/main/java/eu/kanade/tachiyomi/ui/recent/DateSectionItem.kt index 913e93f28b..0143f39128 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/DateItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/DateSectionItem.kt @@ -1,4 +1,4 @@ -package eu.kanade.tachiyomi.ui.recent.updates +package eu.kanade.tachiyomi.ui.recent import android.text.format.DateUtils import android.view.View @@ -11,10 +11,10 @@ import eu.davidea.viewholders.FlexibleViewHolder import eu.kanade.tachiyomi.R import java.util.Date -class DateItem(val date: Date) : AbstractHeaderItem() { +class DateSectionItem(val date: Date) : AbstractHeaderItem() { override fun getLayoutRes(): Int { - return R.layout.updates_section_item + return R.layout.recent_section_item } override fun createViewHolder(view: View, adapter: FlexibleAdapter>): Holder { @@ -27,7 +27,7 @@ class DateItem(val date: Date) : AbstractHeaderItem() { override fun equals(other: Any?): Boolean { if (this === other) return true - if (other is DateItem) { + if (other is DateSectionItem) { return date == other.date } return false @@ -43,7 +43,7 @@ class DateItem(val date: Date) : AbstractHeaderItem() { val section_text: TextView = view.findViewById(R.id.section_text) - fun bind(item: DateItem) { + fun bind(item: DateSectionItem) { section_text.text = DateUtils.getRelativeTimeSpanString(item.date.time, now, DateUtils.DAY_IN_MILLIS) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryAdapter.kt index a4889a17bf..9bcbce4b43 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryAdapter.kt @@ -1,10 +1,7 @@ package eu.kanade.tachiyomi.ui.recent.history import eu.davidea.flexibleadapter.FlexibleAdapter -import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.source.SourceManager -import java.text.DateFormat import java.text.DecimalFormat import java.text.DecimalFormatSymbols import uy.kohesive.injekt.injectLazy @@ -34,9 +31,10 @@ class HistoryAdapter(controller: HistoryController) : val decimalFormat = DecimalFormat("#.###", DecimalFormatSymbols() .apply { decimalSeparator = '.' }) - private val preferences: PreferencesHelper by injectLazy() - - val dateFormat: DateFormat = preferences.dateFormat().getOrDefault() + init { + setDisplayHeadersAtStartUp(true) + setStickyHeaders(true) + } interface OnResumeClickListener { fun onResumeClick(position: Int) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryHolder.kt index d096d0d23a..1a3ea2e4b8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryHolder.kt @@ -61,7 +61,7 @@ class HistoryHolder( .format(adapter.sourceManager.getOrStub(manga.source).toString(), formattedNumber) // Set last read timestamp title - last_read.text = Date(history.last_read).toTimestampString(adapter.dateFormat) + last_read.text = Date(history.last_read).toTimestampString() // Set cover GlideApp.with(itemView.context).clear(cover) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryItem.kt index a13f2dbfb0..41d5705387 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryItem.kt @@ -3,12 +3,14 @@ package eu.kanade.tachiyomi.ui.recent.history import android.view.View import androidx.recyclerview.widget.RecyclerView import eu.davidea.flexibleadapter.FlexibleAdapter -import eu.davidea.flexibleadapter.items.AbstractFlexibleItem +import eu.davidea.flexibleadapter.items.AbstractSectionableItem import eu.davidea.flexibleadapter.items.IFlexible import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory +import eu.kanade.tachiyomi.ui.recent.DateSectionItem -class HistoryItem(val mch: MangaChapterHistory) : AbstractFlexibleItem() { +class HistoryItem(val mch: MangaChapterHistory, header: DateSectionItem) : + AbstractSectionableItem(header) { override fun getLayoutRes(): Int { return R.layout.history_item @@ -24,7 +26,6 @@ class HistoryItem(val mch: MangaChapterHistory) : AbstractFlexibleItem? ) { - holder.bind(mch) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryPresenter.kt index 898d02f506..9ac0adee72 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryPresenter.kt @@ -5,10 +5,14 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.History import eu.kanade.tachiyomi.data.database.models.Manga +import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter +import eu.kanade.tachiyomi.ui.recent.DateSectionItem +import eu.kanade.tachiyomi.util.lang.toDateKey import java.util.Calendar import java.util.Comparator import java.util.Date +import java.util.TreeMap import rx.Observable import rx.android.schedulers.AndroidSchedulers import uy.kohesive.injekt.injectLazy @@ -38,13 +42,21 @@ class HistoryPresenter : BasePresenter() { * @return list of history */ fun getRecentMangaObservable(): Observable> { - // Set date for recent manga + // Set date limit for recent manga val cal = Calendar.getInstance() cal.time = Date() cal.add(Calendar.MONTH, -1) return db.getRecentManga(cal.time).asRxObservable() - .map { recents -> recents.map(::HistoryItem) } + .map { recents -> + val map = TreeMap> { d1, d2 -> d2.compareTo(d1) } + val byDay = recents + .groupByTo(map, { it.history.last_read.toDateKey() }) + byDay.flatMap { + val dateItem = DateSectionItem(it.key) + it.value.map { HistoryItem(it, dateItem) } + } + } .observeOn(AndroidSchedulers.mainThread()) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesItem.kt index 0925d039b2..56f1b52bcb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesItem.kt @@ -9,9 +9,10 @@ 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 +import eu.kanade.tachiyomi.ui.recent.DateSectionItem -class UpdatesItem(val chapter: Chapter, val manga: Manga, header: DateItem) : - AbstractSectionableItem(header) { +class UpdatesItem(val chapter: Chapter, val manga: Manga, header: DateSectionItem) : + AbstractSectionableItem(header) { private var _status: Int = 0 @@ -41,7 +42,6 @@ class UpdatesItem(val chapter: Chapter, val manga: Manga, header: DateItem) : position: Int, payloads: List? ) { - holder.bind(this) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesPresenter.kt index 39ebbbccdb..2cd1e18583 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesPresenter.kt @@ -8,6 +8,8 @@ import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter +import eu.kanade.tachiyomi.ui.recent.DateSectionItem +import eu.kanade.tachiyomi.util.lang.toDateKey import java.util.Calendar import java.util.Date import java.util.TreeMap @@ -60,9 +62,9 @@ class UpdatesPresenter( .map { mangaChapters -> val map = TreeMap> { d1, d2 -> d2.compareTo(d1) } val byDay = mangaChapters - .groupByTo(map, { getMapKey(it.chapter.date_fetch) }) + .groupByTo(map, { it.chapter.date_fetch.toDateKey() }) byDay.flatMap { - val dateItem = DateItem(it.key) + val dateItem = DateSectionItem(it.key) it.value .sortedWith(compareBy({ it.chapter.date_fetch }, { it.chapter.chapter_number })).asReversed() .map { UpdatesItem(it.chapter, it.manga, dateItem) } @@ -84,22 +86,6 @@ class UpdatesPresenter( } } - /** - * 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. * diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/lang/DateExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/lang/DateExtensions.kt index 509d4c71cf..c03d8bba36 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/lang/DateExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/lang/DateExtensions.kt @@ -1,10 +1,31 @@ package eu.kanade.tachiyomi.util.lang import java.text.DateFormat +import java.util.Calendar import java.util.Date -fun Date.toTimestampString(dateFormatter: DateFormat): String { +fun Date.toDateTimestampString(dateFormatter: DateFormat): String { val date = dateFormatter.format(this) val time = DateFormat.getTimeInstance(DateFormat.SHORT).format(this) return "$date $time" } + +fun Date.toTimestampString(): String { + return DateFormat.getTimeInstance(DateFormat.SHORT).format(this) +} + +/** + * Get date as time key + * + * @param date desired date + * @return date as time key + */ +fun Long.toDateKey(): Date { + val cal = Calendar.getInstance() + cal.time = Date(this) + cal[Calendar.HOUR_OF_DAY] = 0 + cal[Calendar.MINUTE] = 0 + cal[Calendar.SECOND] = 0 + cal[Calendar.MILLISECOND] = 0 + return cal.time +} diff --git a/app/src/main/res/layout/history_controller.xml b/app/src/main/res/layout/history_controller.xml index f43124068f..afe7ebfbac 100644 --- a/app/src/main/res/layout/history_controller.xml +++ b/app/src/main/res/layout/history_controller.xml @@ -10,8 +10,6 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:clipToPadding="false" - android:paddingTop="4dp" - android:paddingBottom="4dp" tools:listitem="@layout/history_item" />