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 c0f1a44668..413242d021 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 @@ -36,10 +36,10 @@ interface ChapterQueries : DbProvider { .withGetResolver(MangaChapterGetResolver.INSTANCE) .prepare() - fun getUpdatedManga(date: Date, search: String = "") = db.get() + fun getUpdatedManga(date: Date, search: String = "", endless: Boolean) = db.get() .listOfObjects(MangaChapterHistory::class.java) .withQuery(RawQuery.builder() - .query(getRecentsQueryDistinct(search)) + .query(getRecentsQueryDistinct(search, endless)) .args(date.time) .observesTables(ChapterTable.TABLE) .build()) 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 0de2f0cd61..f835d79f60 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 @@ -39,10 +39,10 @@ interface HistoryQueries : DbProvider { * @param date recent date range * @offset offset the db by */ - fun getRecentlyAdded(date: Date, search: String = "") = db.get() + fun getRecentlyAdded(date: Date, search: String = "", endless: Boolean) = db.get() .listOfObjects(MangaChapterHistory::class.java) .withQuery(RawQuery.builder() - .query(getRecentAdditionsQuery(search)) + .query(getRecentAdditionsQuery(search, endless)) .args(date.time) .observesTables(MangaTable.TABLE) .build()) @@ -69,10 +69,10 @@ interface HistoryQueries : DbProvider { * @param date recent date range * @offset offset the db by */ - fun getRecentsWithUnread(date: Date, search: String = "") = db.get() + fun getRecentsWithUnread(date: Date, search: String = "", endless: Boolean) = db.get() .listOfObjects(MangaChapterHistory::class.java) .withQuery(RawQuery.builder() - .query(getRecentReadWithUnreadChapters(search)) + .query(getRecentReadWithUnreadChapters(search, endless)) .args(date.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 8b771323e1..d2a1bf6b26 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 @@ -66,19 +66,19 @@ fun getRecentsQuery() = """ /** * Query to get the recently added manga */ -fun getRecentAdditionsQuery(search: String) = """ +fun getRecentAdditionsQuery(search: String, endless: Boolean) = """ SELECT ${Manga.TABLE}.${Manga.COL_URL} as mangaUrl, * FROM ${Manga.TABLE} WHERE ${Manga.COL_FAVORITE} = 1 AND ${Manga.COL_DATE_ADDED} > ? AND lower(${Manga.COL_TITLE}) LIKE '%$search%' ORDER BY ${Manga.COL_DATE_ADDED} DESC - LIMIT 8 + ${if (endless) "" else "LIMIT 8"} """ /** * Query to get the manga with recently uploaded chapters */ -fun getRecentsQueryDistinct(search: String) = """ +fun getRecentsQueryDistinct(search: String, endless: Boolean) = """ SELECT ${Manga.TABLE}.${Manga.COL_URL} as mangaUrl, ${Manga.TABLE}.*, ${Chapter.TABLE}.* FROM ${Manga.TABLE} JOIN ${Chapter.TABLE} @@ -96,7 +96,7 @@ fun getRecentsQueryDistinct(search: String) = """ AND ${Chapter.COL_DATE_FETCH} > ${Manga.COL_DATE_ADDED} AND lower(${Manga.COL_TITLE}) LIKE '%$search%' ORDER BY ${Chapter.COL_DATE_UPLOAD} DESC - LIMIT 8 + ${if (endless) "" else "LIMIT 8"} """ /** @@ -159,7 +159,7 @@ fun getRecentMangasLimitQuery(limit: Int = 25, search: String = "") = """ * 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 getRecentReadWithUnreadChapters(search: String = "") = """ +fun getRecentReadWithUnreadChapters(search: String = "", endless: Boolean) = """ SELECT ${Manga.TABLE}.${Manga.COL_URL} as mangaUrl, ${Manga.TABLE}.*, ${Chapter.TABLE}.*, ${History.TABLE}.* FROM ( SELECT ${Manga.TABLE}.* @@ -189,7 +189,7 @@ fun getRecentReadWithUnreadChapters(search: String = "") = """ AND max_last_read.${History.COL_CHAPTER_ID} = ${History.TABLE}.${History.COL_CHAPTER_ID} AND lower(${Manga.TABLE}.${Manga.COL_TITLE}) LIKE '%$search%' ORDER BY max_last_read.${History.COL_LAST_READ} DESC - LIMIT 8 + ${if (endless) "" else "LIMIT 8"} """ fun getHistoryByMangaId() = """ 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 32635c484f..2a52a9ace6 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 @@ -245,7 +245,7 @@ class PreferencesHelper(val context: Context) { fun extensionUpdatesCount() = rxPrefs.getInteger("ext_updates_count", 0) - fun showRecentUpdates() = rxPrefs.getBoolean("show_recents", false) + fun groupRecents() = rxPrefs.getBoolean("group_recents", true) 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 7beffcf690..a7ed1d7b31 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 @@ -22,6 +22,8 @@ class RecentMangaAdapter(val delegate: RecentsInterface) : fun onCoverClick(position: Int) fun markAsRead(position: Int) fun isSearching(): Boolean + fun showHistory() + fun showUpdates() } override fun onItemSwiped(position: Int, direction: Int) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentMangaHeaderItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentMangaHeaderItem.kt index ea75785f49..785c3a6467 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentMangaHeaderItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentMangaHeaderItem.kt @@ -8,6 +8,7 @@ import eu.davidea.flexibleadapter.items.IFlexible import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder import eu.kanade.tachiyomi.ui.library.LibraryHeaderItem +import eu.kanade.tachiyomi.util.view.visibleIf import kotlinx.android.synthetic.main.recents_header_item.* class RecentMangaHeaderItem(val recentsType: Int) : @@ -56,6 +57,11 @@ class RecentMangaHeaderItem(val recentsType: Int) : class Holder(val view: View, adapter: RecentMangaAdapter) : BaseFlexibleViewHolder(view, adapter, true) { + init { + action_history.setOnClickListener { adapter.delegate.showHistory() } + action_update.setOnClickListener { adapter.delegate.showUpdates() } + } + fun bind(recentsType: Int) { title.setText(when (recentsType) { CONTINUE_READING -> R.string.continue_reading @@ -63,6 +69,9 @@ class RecentMangaHeaderItem(val recentsType: Int) : NEWLY_ADDED -> R.string.newly_added else -> R.string.continue_reading }) + action_history.visibleIf(recentsType == -1) + action_update.visibleIf(recentsType == -1) + title.visibleIf(recentsType != -1) } } 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 f21f3b6f6a..187a74c2e4 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 @@ -52,25 +52,27 @@ class RecentMangaHolder( item.chapter.date_upload, Date().time, DateUtils.HOUR_IN_MILLIS ).toString() ) - item.chapter.id != item.mch.chapter.id -> body.context.getString( + item.chapter.id != item.mch.chapter.id -> + body.context.getString( + R.string.read_, DateUtils.getRelativeTimeSpanString( + item.mch.history.last_read, Date().time, DateUtils.MINUTE_IN_MILLIS + ).toString() + ) + "\n" + body.context.getString( if (notValidNum) R.string.last_read_ else R.string.last_read_chapter_, - if (notValidNum) item.mch.chapter.name else adapter.decimalFormat.format(item.mch.chapter.chapter_number) + - " (${DateUtils.getRelativeTimeSpanString( - item.mch.history.last_read, Date().time, DateUtils.MINUTE_IN_MILLIS - )})" + if (notValidNum) item.mch.chapter.name else adapter.decimalFormat.format(item.mch.chapter.chapter_number) ) - !isSearch && item.chapter.pages_left > 0 -> itemView.resources.getQuantityString( - R.plurals.pages_left, item.chapter.pages_left, item.chapter.pages_left - ) + - " (${DateUtils.getRelativeTimeSpanString( + item.chapter.pages_left > 0 && !item.chapter.read -> body.context.getString( + R.string.read_, DateUtils.getRelativeTimeSpanString( item.mch.history.last_read, Date().time, DateUtils.MINUTE_IN_MILLIS - )})" - isSearch -> body.context.getString( + ).toString() + ) + "\n" + itemView.resources.getQuantityString( + R.plurals.pages_left, item.chapter.pages_left, item.chapter.pages_left + ) + else -> body.context.getString( R.string.read_, DateUtils.getRelativeTimeSpanString( item.mch.history.last_read, Date().time, DateUtils.MINUTE_IN_MILLIS ).toString() ) - else -> "" } GlideApp.with(itemView.context).load(item.mch.manga).diskCacheStrategy(DiskCacheStrategy .AUTOMATIC) 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 be55d41004..c3c563f486 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 @@ -265,6 +265,9 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle), router.pushController(MangaDetailsController(manga).withFadeTransaction()) } + override fun showHistory() = router.pushController(RecentlyReadController().withFadeTransaction()) + override fun showUpdates() = router.pushController(RecentChaptersController().withFadeTransaction()) + override fun onItemClick(view: View?, position: Int): Boolean { val item = adapter.getItem(position) ?: return false if (item is RecentMangaItem) { @@ -321,6 +324,12 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle), inflater.inflate(R.menu.download_queue, menu) } else { inflater.inflate(R.menu.recents, menu) + + val viewItem = menu.findItem(R.id.action_view) + val endless = presenter.groupRecents + viewItem.setTitle(if (endless) R.string.group_recents else R.string.ungroup_recents) + viewItem.setIcon(if (endless) R.drawable.ic_view_stream_24dp else R.drawable.ic_view_headline_24dp) + val searchItem = menu.findItem(R.id.action_search) val searchView = searchItem.actionView as SearchView searchView.queryHint = view?.context?.getString(R.string.search_recents) @@ -350,11 +359,9 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle), view?.applyWindowInsetsForRootController(activity!!.bottom_nav) if (type == ControllerChangeType.POP_ENTER) presenter.onCreate() dl_bottom_sheet.dismiss() - setHasOptionsMenu(true) } else { if (type == ControllerChangeType.POP_EXIT) presenter.onDestroy() snack?.dismiss() - setHasOptionsMenu(false) } } @@ -379,14 +386,9 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle), if (showingDownloads) return dl_bottom_sheet.onOptionsItemSelected(item) when (item.itemId) { - R.id.action_refresh -> { - if (!LibraryUpdateService.isRunning()) { - val view = view ?: return true - LibraryUpdateService.start(view.context) - snack = view.snack(R.string.updating_library) { - anchorView = (activity as? MainActivity)?.bottom_nav - } - } + R.id.action_view -> { + presenter.toggleGroupRecents() + activity?.invalidateOptionsMenu() } } return super.onOptionsItemSelected(item) 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 58c56f0b65..1b411628d2 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 @@ -11,6 +11,7 @@ import eu.kanade.tachiyomi.data.download.model.DownloadQueue import eu.kanade.tachiyomi.data.library.LibraryServiceListener import eu.kanade.tachiyomi.data.library.LibraryUpdateService import eu.kanade.tachiyomi.data.preference.PreferencesHelper +import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.util.system.executeOnIO import kotlinx.coroutines.CoroutineScope @@ -39,8 +40,10 @@ class RecentsPresenter( var query = "" private val newAdditionsHeader = RecentMangaHeaderItem(RecentMangaHeaderItem.NEWLY_ADDED) private val newChaptersHeader = RecentMangaHeaderItem(RecentMangaHeaderItem.NEW_CHAPTERS) + private val endlessHeader = RecentMangaHeaderItem(-1) private val continueReadingHeader = RecentMangaHeaderItem(RecentMangaHeaderItem .CONTINUE_READING) + var groupRecents = preferences.groupRecents().getOrDefault() fun onCreate() { downloadManager.addListener(this) @@ -51,29 +54,42 @@ class RecentsPresenter( fun getRecents() { val oldQuery = query scope.launch { - val cal = Calendar.getInstance() - cal.time = Date() - if (query.isNotEmpty()) cal.add(Calendar.YEAR, -50) - else cal.add(Calendar.MONTH, -1) + val isEndless = groupRecents && query.isEmpty() + val cal = Calendar.getInstance().apply { + time = Date() + when { + query.isNotEmpty() -> add(Calendar.YEAR, -50) + isEndless -> add(Calendar.MONTH, -1) + else -> add(Calendar.MONTH, -1) + } + } - val calWeek = Calendar.getInstance() - calWeek.time = Date() - if (query.isNotEmpty()) calWeek.add(Calendar.YEAR, -50) - else calWeek.add(Calendar.WEEK_OF_YEAR, -1) + val calWeek = Calendar.getInstance().apply { + time = Date() + when { + query.isNotEmpty() -> add(Calendar.YEAR, -50) + isEndless -> add(Calendar.MONTH, -1) + else -> add(Calendar.WEEK_OF_YEAR, -1) + } + } - val calDay = Calendar.getInstance() - calDay.time = Date() - if (query.isNotEmpty()) calDay.add(Calendar.YEAR, -50) - else calDay.add(Calendar.DAY_OF_YEAR, -1) + val calDay = Calendar.getInstance().apply { + time = Date() + when { + query.isNotEmpty() -> add(Calendar.YEAR, -50) + isEndless -> add(Calendar.MONTH, -1) + else -> add(Calendar.DAY_OF_YEAR, -1) + } + } val cReading = - if (query.isEmpty()) db.getRecentsWithUnread(cal.time, query).executeOnIO() + if (query.isEmpty()) db.getRecentsWithUnread(cal.time, query, isEndless).executeOnIO() else db.getRecentMangaLimit(cal.time, 8, query).executeOnIO() - val rUpdates = db.getUpdatedManga(calWeek.time, query).executeOnIO() + val rUpdates = db.getUpdatedManga(calWeek.time, query, isEndless).executeOnIO() rUpdates.forEach { it.history.last_read = it.chapter.date_fetch } - val nAdditions = db.getRecentlyAdded(calDay.time, query).executeOnIO() + val nAdditions = db.getRecentlyAdded(calDay.time, query, isEndless).executeOnIO() nAdditions.forEach { it.history.last_read = it.manga.date_added } @@ -93,7 +109,7 @@ class RecentsPresenter( else null else Pair(it, chapter) } - if (query.isEmpty()) { + if (query.isEmpty() && !groupRecents) { val nChaptersItems = pairs.filter { it.first.history.id == null && it.first.chapter.id != null } .sortedWith(Comparator> { f1, f2 -> @@ -126,7 +142,8 @@ class RecentsPresenter( it.firstOrNull()?.mch?.history?.last_read ?: 0L }.flatten() } else { - recentItems = pairs.map { RecentMangaItem(it.first, it.second, null) } + val header = if (isEndless) endlessHeader else null + recentItems = pairs.map { RecentMangaItem(it.first, it.second, header) } } setDownloadedChapters(recentItems) withContext(Dispatchers.Main) { controller.showLists(recentItems) } @@ -154,6 +171,12 @@ class RecentsPresenter( scope.cancel() } + fun toggleGroupRecents() { + preferences.groupRecents().set(!groupRecents) + groupRecents = !groupRecents + getRecents() + } + /** * Finds and assigns the list of downloaded chapters. * diff --git a/app/src/main/res/drawable/ic_view_headline_24dp.xml b/app/src/main/res/drawable/ic_view_headline_24dp.xml new file mode 100644 index 0000000000..324610ff39 --- /dev/null +++ b/app/src/main/res/drawable/ic_view_headline_24dp.xml @@ -0,0 +1,6 @@ + + + diff --git a/app/src/main/res/drawable/ic_view_stream_24dp.xml b/app/src/main/res/drawable/ic_view_stream_24dp.xml new file mode 100644 index 0000000000..1a049b9f02 --- /dev/null +++ b/app/src/main/res/drawable/ic_view_stream_24dp.xml @@ -0,0 +1,6 @@ + + + diff --git a/app/src/main/res/layout/manga_header_item.xml b/app/src/main/res/layout/manga_header_item.xml index e753d3d4c3..ec5377d8aa 100644 --- a/app/src/main/res/layout/manga_header_item.xml +++ b/app/src/main/res/layout/manga_header_item.xml @@ -162,13 +162,13 @@ diff --git a/app/src/main/res/layout/recent_manga_item.xml b/app/src/main/res/layout/recent_manga_item.xml index cf6d9555c2..3465828cf3 100644 --- a/app/src/main/res/layout/recent_manga_item.xml +++ b/app/src/main/res/layout/recent_manga_item.xml @@ -121,7 +121,7 @@ android:layout_marginBottom="14dp" android:ellipsize="end" android:maxLines="2" - android:singleLine="true" + android:lineSpacingExtra="2dp" android:textColor="?android:attr/textColorSecondary" android:textSize="14sp" app:layout_constrainedWidth="true" diff --git a/app/src/main/res/layout/recents_header_item.xml b/app/src/main/res/layout/recents_header_item.xml index 9ff0886782..68e0cf7b19 100644 --- a/app/src/main/res/layout/recents_header_item.xml +++ b/app/src/main/res/layout/recents_header_item.xml @@ -20,4 +20,31 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" tools:text="@string/recent_updates" /> + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/recents.xml b/app/src/main/res/menu/recents.xml index beaaf2b549..c94ad70479 100644 --- a/app/src/main/res/menu/recents.xml +++ b/app/src/main/res/menu/recents.xml @@ -10,11 +10,10 @@ android:visible="false" app:showAsAction="ifRoom|collapseActionView" /> + android:id="@+id/action_view" + android:icon="@drawable/ic_view_stream_24dp" + android:title="@string/group_recents" + app:showAsAction="ifRoom" /> Search recents… No recent chapters No recently read manga + Group recents + Ungroup recents Search filters diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 9e0156497f..2669ced51c 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -244,7 +244,7 @@ 48dip -