Added option to ungroup recents

This commit is contained in:
Jay 2020-04-11 00:05:59 -04:00
parent 26c5214d2e
commit b5699154f4
17 changed files with 140 additions and 62 deletions

View File

@ -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())

View File

@ -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())

View File

@ -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() = """

View File

@ -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)

View File

@ -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) {

View File

@ -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)
}
}

View File

@ -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)

View File

@ -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)

View File

@ -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<Pair<MangaChapterHistory, Chapter>> { 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.
*

View File

@ -0,0 +1,6 @@
<vector android:height="24dp"
android:tint="?attr/actionBarTintColor"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M4,15h16v-2L4,13v2zM4,19h16v-2L4,17v2zM4,11h16L20,9L4,9v2zM4,5v2h16L20,5L4,5z"/>
</vector>

View File

@ -0,0 +1,6 @@
<vector android:height="24dp"
android:tint="?attr/actionBarTintColor"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M4,18h17v-6H4v6zM4,5v6h17V5H4z"/>
</vector>

View File

@ -162,13 +162,13 @@
<com.google.android.material.button.MaterialButton
android:id="@+id/favorite_button"
style="@style/Theme.Widget.Button.RounededOutline"
style="@style/Theme.Widget.Button.RoundedOutline"
android:text="@string/add_to_library"
app:icon="@drawable/ic_add_to_library_24dp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/track_button"
style="@style/Theme.Widget.Button.RounededOutline"
style="@style/Theme.Widget.Button.RoundedOutline"
android:layout_marginStart="6dp"
android:text="@string/tracking"
app:icon="@drawable/ic_sync_black_24dp" />

View File

@ -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"

View File

@ -20,4 +20,31 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
tools:text="@string/recent_updates" />
<com.google.android.material.button.MaterialButton
android:id="@+id/action_history"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:icon="@drawable/ic_history_black_24dp"
android:layout_marginStart="12dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:text="@string/history"
style="@style/Theme.Widget.Button.RoundedOutline"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/action_update"
android:layout_width="wrap_content"
android:visibility="gone"
android:layout_height="wrap_content"
app:icon="@drawable/ic_update_black_24dp"
android:layout_marginEnd="12dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:text="@string/updates"
style="@style/Theme.Widget.Button.RoundedOutline"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -10,11 +10,10 @@
android:visible="false"
app:showAsAction="ifRoom|collapseActionView" />
<item
android:id="@+id/action_refresh"
android:icon="@drawable/ic_refresh_white_24dp"
android:visible="false"
android:title="@string/update_library"
app:showAsAction="never" />
android:id="@+id/action_view"
android:icon="@drawable/ic_view_stream_24dp"
android:title="@string/group_recents"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_settings"

View File

@ -190,6 +190,8 @@
<string name="search_recents">Search recents…</string>
<string name="no_recent_chapters">No recent chapters</string>
<string name="no_recently_read_manga">No recently read manga</string>
<string name="group_recents">Group recents</string>
<string name="ungroup_recents">Ungroup recents</string>
<!-- Browse -->
<string name="search_filters">Search filters</string>

View File

@ -244,7 +244,7 @@
<item name="android:minWidth">48dip</item>
</style>
<style name="Theme.Widget.Button.RounededOutline" parent="Widget.MaterialComponents.Button.OutlinedButton">
<style name="Theme.Widget.Button.RoundedOutline" parent="Widget.MaterialComponents.Button.OutlinedButton">
<item name="android:layout_width">wrap_content</item>
<item name="android:textAllCaps">false</item>
<item name="android:letterSpacing">0.0</item>
@ -252,7 +252,7 @@
<item name="iconTint">?colorAccent</item>
<item name="rippleColor">@color/fullRippleColor</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="cornerRadius">15dp</item>
<item name="cornerRadius">20dp</item>
</style>
<style name="Theme.Widget.Button.Primary" parent="Widget.MaterialComponents.Button">