From f84ac9f24c71b74c0704fad3ece6d960d0e10b56 Mon Sep 17 00:00:00 2001 From: Jays2Kings Date: Wed, 21 Apr 2021 01:11:05 -0400 Subject: [PATCH] More Recents options Using a tabbed sheet here too, options include: Updates: * Group chapters together (off by default) * Show updated time History: * Group chapters together (on by default) --- .../data/database/queries/ChapterQueries.kt | 10 +- .../data/database/queries/HistoryQueries.kt | 21 +++- .../data/database/queries/RawQueries.kt | 36 +++++-- .../data/preference/PreferenceKeys.kt | 5 + .../data/preference/PreferencesHelper.kt | 6 ++ .../ui/recents/RecentMangaAdapter.kt | 4 + .../tachiyomi/ui/recents/RecentMangaHolder.kt | 10 +- .../tachiyomi/ui/recents/RecentMangaItem.kt | 5 +- .../tachiyomi/ui/recents/RecentsController.kt | 16 ++- .../ui/recents/RecentsOptionsSheet.kt | 45 -------- .../tachiyomi/ui/recents/RecentsPresenter.kt | 102 ++++++++++++------ .../ui/recents/options/RecentsGeneralView.kt | 24 +++++ .../ui/recents/options/RecentsHistoryView.kt | 16 +++ .../ui/recents/options/RecentsUpdatesView.kt | 17 +++ .../options/TabbedRecentsOptionsSheet.kt | 43 ++++++++ .../tachiyomi/widget/BaseTabbedScrollView.kt | 6 ++ .../main/res/layout/recents_general_view.xml | 51 +++++++++ .../main/res/layout/recents_history_view.xml | 24 +++++ .../main/res/layout/recents_options_sheet.xml | 64 ----------- .../main/res/layout/recents_updates_view.xml | 34 ++++++ app/src/main/res/values/strings.xml | 2 + 21 files changed, 374 insertions(+), 167 deletions(-) delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentsOptionsSheet.kt create mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/recents/options/RecentsGeneralView.kt create mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/recents/options/RecentsHistoryView.kt create mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/recents/options/RecentsUpdatesView.kt create mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/recents/options/TabbedRecentsOptionsSheet.kt create mode 100644 app/src/main/res/layout/recents_general_view.xml create mode 100644 app/src/main/res/layout/recents_history_view.xml delete mode 100644 app/src/main/res/layout/recents_options_sheet.xml create mode 100644 app/src/main/res/layout/recents_updates_view.xml diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/ChapterQueries.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/ChapterQueries.kt index 4509835baf..48e3fc7157 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/ChapterQueries.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/ChapterQueries.kt @@ -6,13 +6,11 @@ import eu.kanade.tachiyomi.data.database.DbProvider import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.MangaChapter -import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory import eu.kanade.tachiyomi.data.database.resolvers.ChapterBackupPutResolver import eu.kanade.tachiyomi.data.database.resolvers.ChapterKnownBackupPutResolver import eu.kanade.tachiyomi.data.database.resolvers.ChapterProgressPutResolver import eu.kanade.tachiyomi.data.database.resolvers.ChapterSourceOrderPutResolver import eu.kanade.tachiyomi.data.database.resolvers.MangaChapterGetResolver -import eu.kanade.tachiyomi.data.database.resolvers.MangaChapterHistoryGetResolver import eu.kanade.tachiyomi.data.database.tables.ChapterTable import eu.kanade.tachiyomi.util.lang.sqLite @@ -48,16 +46,16 @@ interface ChapterQueries : DbProvider { * @param date recent date range * @offset offset the db by */ - fun getUpdatedManga(search: String = "", endless: Boolean, offset: Int, isResuming: Boolean) = db.get() - .listOfObjects(MangaChapterHistory::class.java) + fun getUpdatedChaptersDistinct(search: String = "", offset: Int, isResuming: Boolean) = db.get() + .listOfObjects(MangaChapter::class.java) .withQuery( RawQuery.builder() - .query(getRecentsQueryDistinct(search.sqLite, endless, offset, isResuming)) + .query(getRecentsQueryDistinct(search.sqLite, offset, isResuming)) // .args(date.time, startDate.time) .observesTables(ChapterTable.TABLE) .build() ) - .withGetResolver(MangaChapterHistoryGetResolver.INSTANCE) + .withGetResolver(MangaChapterGetResolver.INSTANCE) .prepare() fun getChapter(id: Long) = db.get() diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/HistoryQueries.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/HistoryQueries.kt index 8a1ba2c2b0..faa7f59576 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/HistoryQueries.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/HistoryQueries.kt @@ -40,11 +40,28 @@ interface HistoryQueries : DbProvider { * @param date recent date range * @offset offset the db by */ - fun getRecentMangaLimit(search: String = "", endless: Boolean, offset: Int, isResuming: Boolean) = db.get() + fun getRecentMangaLimit(search: String = "", offset: Int, isResuming: Boolean) = db.get() .listOfObjects(MangaChapterHistory::class.java) .withQuery( RawQuery.builder() - .query(getRecentMangasLimitQuery(search.sqLite, endless, offset, isResuming)) + .query(getRecentMangasLimitQuery(search.sqLite, offset, isResuming)) +// .args(date.time, startDate.time) + .observesTables(HistoryTable.TABLE) + .build() + ) + .withGetResolver(MangaChapterHistoryGetResolver.INSTANCE) + .prepare() + + /** + * Returns history of recent manga containing last read chapter in 25s + * @param date recent date range + * @offset offset the db by + */ + fun getHistoryUngrouped(search: String = "", offset: Int, isResuming: Boolean) = db.get() + .listOfObjects(MangaChapterHistory::class.java) + .withQuery( + RawQuery.builder() + .query(getRecentHistoryUngrouped(search.sqLite, offset, isResuming)) // .args(date.time, startDate.time) .observesTables(HistoryTable.TABLE) .build() diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/RawQueries.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/RawQueries.kt index f92831f030..405f5ff6be 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/RawQueries.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/RawQueries.kt @@ -76,25 +76,24 @@ fun limitAndOffset(endless: Boolean, isResuming: Boolean, offset: Int): String { /** * Query to get the manga with recently uploaded chapters */ -fun getRecentsQueryDistinct(search: String, endless: Boolean, offset: Int = 0, isResuming: Boolean) = +fun getRecentsQueryDistinct(search: String, offset: Int = 0, isResuming: Boolean) = """ SELECT ${Manga.TABLE}.${Manga.COL_URL} as mangaUrl, ${Manga.TABLE}.*, ${Chapter.TABLE}.* FROM ${Manga.TABLE} JOIN ${Chapter.TABLE} ON ${Manga.TABLE}.${Manga.COL_ID} = ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} JOIN ( - SELECT ${Chapter.TABLE}.${Chapter.COL_MANGA_ID},${Chapter.TABLE}.${Chapter.COL_ID} as ${History.COL_CHAPTER_ID},MAX(${Chapter.TABLE}.${Chapter.COL_DATE_UPLOAD}) + SELECT ${Chapter.TABLE}.${Chapter.COL_MANGA_ID},${Chapter.TABLE}.${Chapter.COL_ID},MAX(${Chapter.TABLE}.${Chapter.COL_DATE_FETCH}) FROM ${Chapter.TABLE} JOIN ${Manga.TABLE} ON ${Manga.TABLE}.${Manga.COL_ID} = ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} - WHERE ${Chapter.COL_READ} = 0 GROUP BY ${Chapter.TABLE}.${Chapter.COL_MANGA_ID}) AS newest_chapter ON ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} = newest_chapter.${Chapter.COL_MANGA_ID} WHERE ${Manga.COL_FAVORITE} = 1 - AND newest_chapter.${History.COL_CHAPTER_ID} = ${Chapter.TABLE}.${Chapter.COL_ID} + AND newest_chapter.${Chapter.COL_ID} = ${Chapter.TABLE}.${Chapter.COL_ID} AND ${Chapter.COL_DATE_FETCH} > ${Manga.COL_DATE_ADDED} AND lower(${Manga.COL_TITLE}) LIKE '%$search%' ORDER BY ${Chapter.COL_DATE_FETCH} DESC - ${limitAndOffset(endless, isResuming, offset)} + ${limitAndOffset(true, isResuming, offset)} """ /** @@ -105,7 +104,6 @@ fun getRecentsQueryDistinct(search: String, endless: Boolean, offset: Int = 0, i */ fun getRecentMangasLimitQuery( search: String = "", - endless: Boolean, offset: Int = 0, isResuming: Boolean ) = @@ -126,7 +124,31 @@ fun getRecentMangasLimitQuery( AND max_last_read.${History.COL_LAST_READ} > 0 AND lower(${Manga.TABLE}.${Manga.COL_TITLE}) LIKE '%$search%' ORDER BY max_last_read.${History.COL_LAST_READ} DESC - ${limitAndOffset(endless, isResuming, offset)} + ${limitAndOffset(true, isResuming, offset)} +""" + +/** + * Query to get the recently read chapters of manga from the library up to a date. + * The max_last_read table contains the most recent chapters grouped by manga + * The select statement returns all information of chapters that have the same id as the chapter in max_last_read + * and are read after the given time period + */ +fun getRecentHistoryUngrouped( + search: String = "", + offset: Int = 0, + isResuming: Boolean +) = + """ + SELECT ${Manga.TABLE}.${Manga.COL_URL} as mangaUrl, ${Manga.TABLE}.*, ${Chapter.TABLE}.*, ${History.TABLE}.* + FROM ${Manga.TABLE} + JOIN ${Chapter.TABLE} + ON ${Manga.TABLE}.${Manga.COL_ID} = ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} + JOIN ${History.TABLE} + ON ${Chapter.TABLE}.${Chapter.COL_ID} = ${History.TABLE}.${History.COL_CHAPTER_ID} + AND ${History.TABLE}.${History.COL_LAST_READ} > 0 + AND lower(${Manga.TABLE}.${Manga.COL_TITLE}) LIKE '%$search%' + ORDER BY ${History.TABLE}.${History.COL_LAST_READ} DESC + ${limitAndOffset(true, isResuming, offset)} """ /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt index a2f2bd3541..285805ab3b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt @@ -187,6 +187,11 @@ object PreferenceKeys { const val showReadInAllRecents = "show_read_in_all_recents" const val showTitleFirstInRecents = "show_title_first_in_recents" + const val groupChaptersHistory = "group_chapters_history" + + const val showUpdatedTime = "show_updated_time" + const val groupChaptersUpdates = "group_chapters_updates" + const val showLibraryUpdateErrors = "show_library_update_errors" const val alwaysShowChapterTransition = "always_show_chapter_transition" diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt index 4a27738688..d2af243862 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt @@ -335,6 +335,12 @@ class PreferencesHelper(val context: Context) { fun showReadInAllRecents() = flowPrefs.getBoolean(Keys.showReadInAllRecents, false) + fun showUpdatedTime() = flowPrefs.getBoolean(Keys.showUpdatedTime, false) + + fun groupChaptersUpdates() = flowPrefs.getBoolean(Keys.groupChaptersUpdates, true) + + fun groupChaptersHistory() = flowPrefs.getBoolean(Keys.groupChaptersHistory, false) + fun showTitleFirstInRecents() = flowPrefs.getBoolean(Keys.showTitleFirstInRecents, false) fun lastExtCheck() = rxPrefs.getLong("last_ext_check", 0) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentMangaAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentMangaAdapter.kt index d8247fb9a1..48034f63ad 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentMangaAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentMangaAdapter.kt @@ -6,6 +6,7 @@ import eu.davidea.flexibleadapter.items.IFlexible import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.ui.manga.chapter.BaseChapterAdapter import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import uy.kohesive.injekt.injectLazy @@ -20,6 +21,7 @@ class RecentMangaAdapter(val delegate: RecentsInterface) : var showDownloads = preferences.showRecentsDownloads().get() var showRemoveHistory = preferences.showRecentsRemHistory().get() var showTitleFirst = preferences.showTitleFirstInRecents().get() + var showUpdatedTime = preferences.showUpdatedTime().get() val viewType: Int get() = delegate.getViewType() @@ -39,10 +41,12 @@ class RecentMangaAdapter(val delegate: RecentsInterface) : preferences.showRecentsDownloads().register { showDownloads = it } preferences.showRecentsRemHistory().register { showRemoveHistory = it } preferences.showTitleFirstInRecents().register { showTitleFirst = it } + preferences.showUpdatedTime().register { showUpdatedTime = it } } private fun Preference.register(onChanged: (T) -> Unit) { asFlow() + .drop(1) .onEach { onChanged(it) notifyDataSetChanged() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentMangaHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentMangaHolder.kt index 813d549e09..96eada0b34 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentMangaHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentMangaHolder.kt @@ -29,7 +29,10 @@ class RecentMangaHolder( binding.removeHistory.setOnClickListener { adapter.delegate.onRemoveHistoryClicked(flexibleAdapterPosition) } } - fun bind(item: RecentMangaItem, showDLs: RecentMangaAdapter.ShowRecentsDLs, showRemoveHistory: Boolean, showTitleFirst: Boolean) { + fun bind(item: RecentMangaItem) { + val showDLs = adapter.showDownloads + val showRemoveHistory = adapter.showRemoveHistory + val showTitleFirst = adapter.showTitleFirst binding.downloadButton.downloadButton.isVisible = when (showDLs) { RecentMangaAdapter.ShowRecentsDLs.None -> false RecentMangaAdapter.ShowRecentsDLs.OnlyUnread, RecentMangaAdapter.ShowRecentsDLs.UnreadOrDownloaded -> !item.chapter.read @@ -37,7 +40,8 @@ class RecentMangaHolder( RecentMangaAdapter.ShowRecentsDLs.All -> true } && !item.mch.manga.isLocal() - val isUpdates = adapter.viewType == RecentsPresenter.VIEW_TYPE_ONLY_UPDATES + val isUpdates = adapter.viewType == RecentsPresenter.VIEW_TYPE_ONLY_UPDATES && + !adapter.showUpdatedTime binding.cardLayout.updateLayoutParams { height = (if (isUpdates) 40 else 80).dpToPx width = (if (isUpdates) 40 else 60).dpToPx @@ -101,7 +105,7 @@ class RecentMangaHolder( R.string.added_, item.mch.manga.date_added.timeSpanFromNow(itemView.context) ) - adapter.viewType == RecentsPresenter.VIEW_TYPE_ONLY_UPDATES -> "" + isUpdates -> "" item.mch.history.id == null -> binding.body.context.getString( R.string.updated_, item.chapter.date_upload.timeSpanFromNow(itemView.context) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentMangaItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentMangaItem.kt index a6f13fdf54..dae5f731f4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentMangaItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentMangaItem.kt @@ -57,10 +57,7 @@ class RecentMangaItem( position: Int, payloads: MutableList? ) { - val showDLs = (adapter as? RecentMangaAdapter)?.showDownloads ?: RecentMangaAdapter.ShowRecentsDLs.All - val showRemoveHistory = (adapter as? RecentMangaAdapter)?.showRemoveHistory ?: true - val showTitleFirst = (adapter as? RecentMangaAdapter)?.showTitleFirst ?: false if (mch.manga.id == null) (holder as? RecentMangaFooterHolder)?.bind((header as? RecentMangaHeaderItem)?.recentsType ?: 0) - else if (chapter.id != null) (holder as? RecentMangaHolder)?.bind(this, showDLs, showRemoveHistory, showTitleFirst) + else if (chapter.id != null) (holder as? RecentMangaHolder)?.bind(this) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentsController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentsController.kt index 07f4916d98..f71afb5ff0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentsController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentsController.kt @@ -36,6 +36,7 @@ import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.main.RootSearchInterface import eu.kanade.tachiyomi.ui.manga.MangaDetailsController import eu.kanade.tachiyomi.ui.reader.ReaderActivity +import eu.kanade.tachiyomi.ui.recents.options.TabbedRecentsOptionsSheet import eu.kanade.tachiyomi.ui.source.browse.ProgressItem import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.util.system.spToPx @@ -91,6 +92,7 @@ class RecentsController(bundle: Bundle? = null) : * Adapter containing the recent manga. */ private var adapter = RecentMangaAdapter(this) + var displaySheet: TabbedRecentsOptionsSheet? = null private var progressItem: ProgressItem? = null private var presenter = RecentsPresenter(this) @@ -364,6 +366,12 @@ class RecentsController(bundle: Bundle? = null) : presenter.cancelScope() } + override fun onDestroyView(view: View) { + super.onDestroyView(view) + displaySheet?.dismiss() + displaySheet = null + } + fun refresh() = presenter.getRecents() fun showLists( @@ -653,7 +661,13 @@ class RecentsController(bundle: Bundle? = null) : return binding.downloadBottomSheet.dlBottomSheet.onOptionsItemSelected(item) } when (item.itemId) { - R.id.display_options -> RecentsOptionsSheet(activity!!).show() + R.id.display_options -> { + displaySheet = TabbedRecentsOptionsSheet( + this, + (presenter.viewType - 1).coerceIn(0, 2) + ) + displaySheet?.show() + } } return super.onOptionsItemSelected(item) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentsOptionsSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentsOptionsSheet.kt deleted file mode 100644 index 117463f669..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentsOptionsSheet.kt +++ /dev/null @@ -1,45 +0,0 @@ -package eu.kanade.tachiyomi.ui.recents - -import android.app.Activity -import android.view.ViewGroup -import androidx.core.text.set -import com.google.android.material.bottomsheet.BottomSheetBehavior -import com.google.android.material.bottomsheet.BottomSheetDialog -import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.databinding.RecentsOptionsSheetBinding -import eu.kanade.tachiyomi.util.bindToPreference -import eu.kanade.tachiyomi.util.lang.withSubtitle -import eu.kanade.tachiyomi.util.view.RecyclerWindowInsetsListener -import eu.kanade.tachiyomi.util.view.setEdgeToEdge -import uy.kohesive.injekt.injectLazy - -class RecentsOptionsSheet(activity: Activity) : - BottomSheetDialog(activity, R.style.BottomSheetDialogTheme) { - - private val binding = RecentsOptionsSheetBinding.inflate(activity.layoutInflater) - private val preferences by injectLazy() - - init { - setContentView(binding.root) - setEdgeToEdge(activity, binding.root) - initGeneralPreferences() - binding.settingsScrollView.setOnApplyWindowInsetsListener(RecyclerWindowInsetsListener) - } - - override fun onStart() { - super.onStart() - BottomSheetBehavior.from(binding.root.parent as ViewGroup).skipCollapsed = true - - val titleText = context.getString(R.string.show_reset_history_button) - binding.showRemoveHistory.text = titleText - .withSubtitle(binding.showRemoveHistory.context, R.string.press_and_hold_to_also_reset) - } - - private fun initGeneralPreferences() { - binding.showRecentsDownload.bindToPreference(preferences.showRecentsDownloads()) - binding.showRemoveHistory.bindToPreference(preferences.showRecentsRemHistory()) - binding.showReadInAll.bindToPreference(preferences.showReadInAllRecents()) - binding.showTitleFirst.bindToPreference(preferences.showTitleFirstInRecents()) - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentsPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentsPresenter.kt index b7ec105163..3568559e44 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentsPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentsPresenter.kt @@ -73,14 +73,19 @@ class RecentsPresenter( get() = pageOffset == 0 init { - preferences.showReadInAllRecents() - .asFlow() - .drop(1) - .onEach { - resetOffsets() - getRecents() - } - .launchIn(scope) + listOf( + preferences.groupChaptersHistory(), + preferences.showReadInAllRecents(), + preferences.groupChaptersUpdates() + ).forEach { + it.asFlow() + .drop(1) + .onEach { + resetOffsets() + getRecents() + } + .launchIn(scope) + } } fun onCreate() { @@ -126,6 +131,8 @@ class RecentsPresenter( val showRead = preferences.showReadInAllRecents().get() && !limit val isUngrouped = viewType > VIEW_TYPE_GROUP_ALL || query.isNotEmpty() + val groupChaptersUpdates = preferences.groupChaptersUpdates().get() + val groupChaptersHistory = preferences.groupChaptersHistory().get() val isCustom = customViewType != null val isEndless = isUngrouped && !limit @@ -140,27 +147,43 @@ class RecentsPresenter( ).executeOnIO() } viewType == VIEW_TYPE_ONLY_HISTORY -> { - db.getRecentMangaLimit( - query, - isEndless, - if (isCustom) ENDLESS_LIMIT else pageOffset, - !updatePageCount && !isOnFirstPage - ).executeOnIO() + if (groupChaptersHistory) { + db.getRecentMangaLimit( + query, + if (isCustom) ENDLESS_LIMIT else pageOffset, + !updatePageCount && !isOnFirstPage + ) + } else { + db.getHistoryUngrouped( + query, + if (isCustom) ENDLESS_LIMIT else pageOffset, + !updatePageCount && !isOnFirstPage + ) + }.executeOnIO() } viewType == VIEW_TYPE_ONLY_UPDATES -> { - db.getRecentChapters( - query, - if (isCustom) ENDLESS_LIMIT else pageOffset, - !updatePageCount && !isOnFirstPage - ).executeOnIO().map { - MangaChapterHistory( - it.manga, - it.chapter, - HistoryImpl().apply { - last_read = it.chapter.date_fetch - } + if (groupChaptersUpdates) { + db.getUpdatedChaptersDistinct( + query, + if (isCustom) ENDLESS_LIMIT else pageOffset, + !updatePageCount && !isOnFirstPage ) - } + } else { + db.getRecentChapters( + query, + if (isCustom) ENDLESS_LIMIT else pageOffset, + !updatePageCount && !isOnFirstPage + ) + }.executeOnIO() + .map { + MangaChapterHistory( + it.manga, + it.chapter, + HistoryImpl().apply { + last_read = it.chapter.date_fetch + } + ) + } } else -> emptyList() } @@ -185,12 +208,21 @@ class RecentsPresenter( } val pairs = mangaList.mapNotNull { val chapter = when { - viewType == VIEW_TYPE_ONLY_UPDATES -> it.chapter - it.chapter.read || it.chapter.id == null -> getNextChapter(it.manga) - ?: if (showRead && it.chapter.id != null) it.chapter else null - it.history.id == null -> getFirstUpdatedChapter(it.manga, it.chapter) - ?: if (showRead && it.chapter.id != null) it.chapter else null - else -> it.chapter + (viewType == VIEW_TYPE_ONLY_UPDATES && !groupChaptersUpdates) || + (viewType == VIEW_TYPE_ONLY_HISTORY && !groupChaptersHistory) -> { + it.chapter + } + (it.chapter.read && viewType != VIEW_TYPE_ONLY_UPDATES) || it.chapter.id == null -> { + getNextChapter(it.manga) + ?: if (showRead && it.chapter.id != null) it.chapter else null + } + it.history.id == null -> { + getFirstUpdatedChapter(it.manga, it.chapter) + ?: if ((showRead && it.chapter.id != null) || viewType == VIEW_TYPE_ONLY_UPDATES) it.chapter else null + } + else -> { + it.chapter + } } if (chapter == null) if ((query.isNotEmpty() || viewType > VIEW_TYPE_UNGROUP_ALL) && it.chapter.id != null @@ -248,9 +280,9 @@ class RecentsPresenter( pairs.groupByTo(map, { getMapKey(it.first.history.last_read) }) byDay.flatMap { val dateItem = DateItem(it.key, true) - it.value.map { item -> - RecentMangaItem(item.first, item.second, dateItem) - } + it.value + .map { item -> RecentMangaItem(item.first, item.second, dateItem) } + .sortedByDescending { item -> item.chapter.date_upload } } } else pairs.map { RecentMangaItem(it.first, it.second, null) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recents/options/RecentsGeneralView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/options/RecentsGeneralView.kt new file mode 100644 index 0000000000..7f850ad50d --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/options/RecentsGeneralView.kt @@ -0,0 +1,24 @@ +package eu.kanade.tachiyomi.ui.recents.options + +import android.content.Context +import android.util.AttributeSet +import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.databinding.RecentsGeneralViewBinding +import eu.kanade.tachiyomi.util.bindToPreference +import eu.kanade.tachiyomi.util.lang.withSubtitle +import eu.kanade.tachiyomi.widget.BaseRecentsDisplayView + +class RecentsGeneralView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : + BaseRecentsDisplayView(context, attrs) { + + override fun inflateBinding() = RecentsGeneralViewBinding.bind(this) + override fun initGeneralPreferences() { + val titleText = context.getString(R.string.show_reset_history_button) + binding.showRemoveHistory.text = titleText + .withSubtitle(binding.showRemoveHistory.context, R.string.press_and_hold_to_also_reset) + binding.showRecentsDownload.bindToPreference(preferences.showRecentsDownloads()) + binding.showRemoveHistory.bindToPreference(preferences.showRecentsRemHistory()) + binding.showReadInAll.bindToPreference(preferences.showReadInAllRecents()) + binding.showTitleFirst.bindToPreference(preferences.showTitleFirstInRecents()) + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recents/options/RecentsHistoryView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/options/RecentsHistoryView.kt new file mode 100644 index 0000000000..e9c14616b8 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/options/RecentsHistoryView.kt @@ -0,0 +1,16 @@ +package eu.kanade.tachiyomi.ui.recents.options + +import android.content.Context +import android.util.AttributeSet +import eu.kanade.tachiyomi.databinding.RecentsHistoryViewBinding +import eu.kanade.tachiyomi.util.bindToPreference +import eu.kanade.tachiyomi.widget.BaseRecentsDisplayView + +class RecentsHistoryView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : + BaseRecentsDisplayView(context, attrs) { + + override fun inflateBinding() = RecentsHistoryViewBinding.bind(this) + override fun initGeneralPreferences() { + binding.groupChapters.bindToPreference(preferences.groupChaptersHistory()) + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recents/options/RecentsUpdatesView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/options/RecentsUpdatesView.kt new file mode 100644 index 0000000000..e9508d1052 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/options/RecentsUpdatesView.kt @@ -0,0 +1,17 @@ +package eu.kanade.tachiyomi.ui.recents.options + +import android.content.Context +import android.util.AttributeSet +import eu.kanade.tachiyomi.databinding.RecentsUpdatesViewBinding +import eu.kanade.tachiyomi.util.bindToPreference +import eu.kanade.tachiyomi.widget.BaseRecentsDisplayView + +class RecentsUpdatesView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : + BaseRecentsDisplayView(context, attrs) { + + override fun inflateBinding() = RecentsUpdatesViewBinding.bind(this) + override fun initGeneralPreferences() { + binding.showUpdatedTime.bindToPreference(preferences.showUpdatedTime()) + binding.groupChapters.bindToPreference(preferences.groupChaptersUpdates()) + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recents/options/TabbedRecentsOptionsSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/options/TabbedRecentsOptionsSheet.kt new file mode 100644 index 0000000000..72a94c241b --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/options/TabbedRecentsOptionsSheet.kt @@ -0,0 +1,43 @@ +package eu.kanade.tachiyomi.ui.recents.options + +import android.view.View +import android.view.View.inflate +import androidx.annotation.IntRange +import androidx.core.view.isVisible +import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.ui.recents.RecentsController +import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog + +class TabbedRecentsOptionsSheet(val controller: RecentsController, @IntRange(from = 0, to = 2) startingTab: Int) : + TabbedBottomSheetDialog(controller.activity!!) { + + private val generalView = inflate(controller.activity!!, R.layout.recents_general_view, null) as RecentsGeneralView + private val historyView = inflate(controller.activity!!, R.layout.recents_history_view, null) as RecentsHistoryView + private val updatesView = inflate(controller.activity!!, R.layout.recents_updates_view, null) as RecentsUpdatesView + + init { + binding.menu.isVisible = false + generalView.controller = controller + historyView.controller = controller + updatesView.controller = controller + + binding.tabs.getTabAt(startingTab)?.select() + } + + override fun dismiss() { + super.dismiss() + controller.displaySheet = null + } + + override fun getTabViews(): List = listOf( + generalView, + historyView, + updatesView + ) + + override fun getTabTitles(): List = listOf( + R.string.general, + R.string.history, + R.string.updates + ) +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/BaseTabbedScrollView.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/BaseTabbedScrollView.kt index 5a88c294af..b434024bd9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/BaseTabbedScrollView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/BaseTabbedScrollView.kt @@ -7,6 +7,7 @@ import androidx.viewbinding.ViewBinding import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.ui.library.LibraryController import eu.kanade.tachiyomi.ui.reader.ReaderActivity +import eu.kanade.tachiyomi.ui.recents.RecentsController import eu.kanade.tachiyomi.util.view.RecyclerWindowInsetsListener import uy.kohesive.injekt.injectLazy @@ -31,6 +32,11 @@ abstract class BaseTabbedScrollView @JvmOverloads constructor( } } +abstract class BaseRecentsDisplayView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : + BaseTabbedScrollView(context, attrs) { + var controller: RecentsController? = null +} + abstract class BaseLibraryDisplayView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : BaseTabbedScrollView(context, attrs) { var controller: LibraryController? = null diff --git a/app/src/main/res/layout/recents_general_view.xml b/app/src/main/res/layout/recents_general_view.xml new file mode 100644 index 0000000000..7471557995 --- /dev/null +++ b/app/src/main/res/layout/recents_general_view.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/recents_history_view.xml b/app/src/main/res/layout/recents_history_view.xml new file mode 100644 index 0000000000..90300c5e64 --- /dev/null +++ b/app/src/main/res/layout/recents_history_view.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/recents_options_sheet.xml b/app/src/main/res/layout/recents_options_sheet.xml deleted file mode 100644 index 5ee781e90a..0000000000 --- a/app/src/main/res/layout/recents_options_sheet.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/recents_updates_view.xml b/app/src/main/res/layout/recents_updates_view.xml new file mode 100644 index 0000000000..e46e8f5e17 --- /dev/null +++ b/app/src/main/res/layout/recents_updates_view.xml @@ -0,0 +1,34 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1ec174b889..248eacbc14 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -241,6 +241,8 @@ Show read chapters in Grouped and All Show title first A while ago + Show updated time + Group chapters together Search filters