Match infinite history and search history from preview (#3827)
* Add infinite history and search history * Cleanup code (cherry picked from commit 9d2adcd512c28872c9e958e9fcdcbccbd11b3b35) # Conflicts: # app/src/main/java/eu/kanade/tachiyomi/data/database/queries/HistoryQueries.kt # app/src/main/java/eu/kanade/tachiyomi/data/database/queries/RawQueries.kt # app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryController.kt # app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryPresenter.kt
This commit is contained in:
parent
8acd834783
commit
9c76f1fd8f
@ -18,16 +18,18 @@ interface HistoryQueries : DbProvider {
|
|||||||
*/
|
*/
|
||||||
fun insertHistory(history: History) = db.put().`object`(history).prepare()
|
fun insertHistory(history: History) = db.put().`object`(history).prepare()
|
||||||
|
|
||||||
// SY -->
|
|
||||||
/**
|
/**
|
||||||
* Returns history of recent manga containing last read chapter
|
* Returns history of recent manga containing last read chapter
|
||||||
* @param date recent date range
|
* @param date recent date range
|
||||||
|
* @param limit the limit of manga to grab
|
||||||
|
* @param offset offset the db by
|
||||||
|
* @param search what to search in the db history
|
||||||
*/
|
*/
|
||||||
fun getRecentManga(date: Date, offset: Int = 0, search: String = "") = db.get()
|
fun getRecentManga(date: Date, limit: Int = 25, offset: Int = 0, search: String = "") = db.get()
|
||||||
.listOfObjects(MangaChapterHistory::class.java)
|
.listOfObjects(MangaChapterHistory::class.java)
|
||||||
.withQuery(
|
.withQuery(
|
||||||
RawQuery.builder()
|
RawQuery.builder()
|
||||||
.query(getRecentMangasQuery(offset, search))
|
.query(getRecentMangasQuery(limit, offset, search))
|
||||||
.args(date.time)
|
.args(date.time)
|
||||||
.observesTables(HistoryTable.TABLE)
|
.observesTables(HistoryTable.TABLE)
|
||||||
.build()
|
.build()
|
||||||
@ -35,24 +37,6 @@ interface HistoryQueries : DbProvider {
|
|||||||
.withGetResolver(MangaChapterHistoryGetResolver.INSTANCE)
|
.withGetResolver(MangaChapterHistoryGetResolver.INSTANCE)
|
||||||
.prepare()
|
.prepare()
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns history of recent manga containing last read chapter in 25s
|
|
||||||
* @param date recent date range
|
|
||||||
* @offset offset the db by
|
|
||||||
*/
|
|
||||||
fun getRecentMangaLimit(date: Date, limit: Int = 0, search: String = "") = db.get()
|
|
||||||
.listOfObjects(MangaChapterHistory::class.java)
|
|
||||||
.withQuery(
|
|
||||||
RawQuery.builder()
|
|
||||||
.query(getRecentMangasLimitQuery(limit, search))
|
|
||||||
.args(date.time)
|
|
||||||
.observesTables(HistoryTable.TABLE)
|
|
||||||
.build()
|
|
||||||
)
|
|
||||||
.withGetResolver(MangaChapterHistoryGetResolver.INSTANCE)
|
|
||||||
.prepare()
|
|
||||||
// SY <--
|
|
||||||
|
|
||||||
fun getHistoryByMangaId(mangaId: Long) = db.get()
|
fun getHistoryByMangaId(mangaId: Long) = db.get()
|
||||||
.listOfObjects(History::class.java)
|
.listOfObjects(History::class.java)
|
||||||
.withQuery(
|
.withQuery(
|
||||||
|
@ -136,36 +136,8 @@ fun getRecentsQuery() =
|
|||||||
* The max_last_read table contains the most recent chapters grouped by manga
|
* 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
|
* 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
|
* and are read after the given time period
|
||||||
* @return return limit is 25
|
|
||||||
*/
|
*/
|
||||||
// SY -->
|
fun getRecentMangasQuery(limit: Int = 25, offset: Int = 0, search: String = "") =
|
||||||
fun getRecentMangasQuery(offset: Int = 0, search: String = "") =
|
|
||||||
"""
|
|
||||||
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}
|
|
||||||
JOIN (
|
|
||||||
SELECT ${Chapter.TABLE}.${Chapter.COL_MANGA_ID},${Chapter.TABLE}.${Chapter.COL_ID} as ${History.COL_CHAPTER_ID}, MAX(${History.TABLE}.${History.COL_LAST_READ}) as ${History.COL_LAST_READ}
|
|
||||||
FROM ${Chapter.TABLE} JOIN ${History.TABLE}
|
|
||||||
ON ${Chapter.TABLE}.${Chapter.COL_ID} = ${History.TABLE}.${History.COL_CHAPTER_ID}
|
|
||||||
GROUP BY ${Chapter.TABLE}.${Chapter.COL_MANGA_ID}) AS max_last_read
|
|
||||||
ON ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} = max_last_read.${Chapter.COL_MANGA_ID}
|
|
||||||
WHERE ${History.TABLE}.${History.COL_LAST_READ} > ? 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 25 OFFSET $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 getRecentMangasLimitQuery(limit: Int = 25, search: String = "") =
|
|
||||||
"""
|
"""
|
||||||
SELECT ${Manga.TABLE}.${Manga.COL_URL} as mangaUrl, ${Manga.TABLE}.*, ${Chapter.TABLE}.*, ${History.TABLE}.*
|
SELECT ${Manga.TABLE}.${Manga.COL_URL} as mangaUrl, ${Manga.TABLE}.*, ${Chapter.TABLE}.*, ${History.TABLE}.*
|
||||||
FROM ${Manga.TABLE}
|
FROM ${Manga.TABLE}
|
||||||
@ -183,9 +155,8 @@ fun getRecentMangasLimitQuery(limit: Int = 25, search: String = "") =
|
|||||||
AND max_last_read.${History.COL_CHAPTER_ID} = ${History.TABLE}.${History.COL_CHAPTER_ID}
|
AND max_last_read.${History.COL_CHAPTER_ID} = ${History.TABLE}.${History.COL_CHAPTER_ID}
|
||||||
AND lower(${Manga.TABLE}.${Manga.COL_TITLE}) LIKE '%$search%'
|
AND lower(${Manga.TABLE}.${Manga.COL_TITLE}) LIKE '%$search%'
|
||||||
ORDER BY max_last_read.${History.COL_LAST_READ} DESC
|
ORDER BY max_last_read.${History.COL_LAST_READ} DESC
|
||||||
LIMIT $limit
|
LIMIT $limit OFFSET $offset
|
||||||
"""
|
"""
|
||||||
// SY <--
|
|
||||||
|
|
||||||
fun getHistoryByMangaId() =
|
fun getHistoryByMangaId() =
|
||||||
"""
|
"""
|
||||||
|
@ -25,7 +25,6 @@ import kotlinx.coroutines.flow.filter
|
|||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import reactivecircus.flowbinding.appcompat.queryTextChanges
|
import reactivecircus.flowbinding.appcompat.queryTextChanges
|
||||||
import uy.kohesive.injekt.api.get
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fragment that shows recently read manga.
|
* Fragment that shows recently read manga.
|
||||||
@ -53,6 +52,10 @@ class HistoryController :
|
|||||||
* Endless loading item.
|
* Endless loading item.
|
||||||
*/
|
*/
|
||||||
private var progressItem: ProgressItem? = null
|
private var progressItem: ProgressItem? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search query.
|
||||||
|
*/
|
||||||
private var query = ""
|
private var query = ""
|
||||||
|
|
||||||
override fun getTitle(): String? {
|
override fun getTitle(): String? {
|
||||||
@ -105,6 +108,9 @@ class HistoryController :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Safely error if next page load fails
|
||||||
|
*/
|
||||||
fun onAddPageError(error: Throwable) {
|
fun onAddPageError(error: Throwable) {
|
||||||
adapter?.onLoadMoreComplete(null)
|
adapter?.onLoadMoreComplete(null)
|
||||||
adapter?.endlessTargetCount = 1
|
adapter?.endlessTargetCount = 1
|
||||||
|
@ -13,7 +13,6 @@ import rx.Observable
|
|||||||
import rx.android.schedulers.AndroidSchedulers
|
import rx.android.schedulers.AndroidSchedulers
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
import java.util.Comparator
|
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.TreeMap
|
import java.util.TreeMap
|
||||||
|
|
||||||
@ -28,8 +27,6 @@ class HistoryPresenter : BasePresenter<HistoryController>() {
|
|||||||
* Used to connect to database
|
* Used to connect to database
|
||||||
*/
|
*/
|
||||||
val db: DatabaseHelper by injectLazy()
|
val db: DatabaseHelper by injectLazy()
|
||||||
var lastCount = 25
|
|
||||||
var lastSearch = ""
|
|
||||||
|
|
||||||
override fun onCreate(savedState: Bundle?) {
|
override fun onCreate(savedState: Bundle?) {
|
||||||
super.onCreate(savedState)
|
super.onCreate(savedState)
|
||||||
@ -39,9 +36,7 @@ class HistoryPresenter : BasePresenter<HistoryController>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun requestNext(offset: Int, search: String = "") {
|
fun requestNext(offset: Int, search: String = "") {
|
||||||
lastCount = offset
|
getRecentMangaObservable(offset = offset, search = search)
|
||||||
lastSearch = search
|
|
||||||
getRecentMangaObservable((offset), search)
|
|
||||||
.subscribeLatestCache(
|
.subscribeLatestCache(
|
||||||
{ view, mangas ->
|
{ view, mangas ->
|
||||||
view.onNextManga(mangas)
|
view.onNextManga(mangas)
|
||||||
@ -54,37 +49,14 @@ class HistoryPresenter : BasePresenter<HistoryController>() {
|
|||||||
* Get recent manga observable
|
* Get recent manga observable
|
||||||
* @return list of history
|
* @return list of history
|
||||||
*/
|
*/
|
||||||
fun getRecentMangaObservable(offset: Int = 0, search: String = ""): Observable<List<HistoryItem>> {
|
private fun getRecentMangaObservable(limit: Int = 25, offset: Int = 0, search: String = ""): Observable<List<HistoryItem>> {
|
||||||
// Set date limit for recent manga
|
// Set date limit for recent manga
|
||||||
val cal = Calendar.getInstance().apply {
|
val cal = Calendar.getInstance().apply {
|
||||||
time = Date()
|
time = Date()
|
||||||
add(Calendar.YEAR, -50)
|
add(Calendar.YEAR, -50)
|
||||||
}
|
}
|
||||||
|
|
||||||
return db.getRecentManga(cal.time, offset, search).asRxObservable()
|
return db.getRecentManga(cal.time, limit, offset, search).asRxObservable()
|
||||||
.map { recents ->
|
|
||||||
val map = TreeMap<Date, MutableList<MangaChapterHistory>> { d1, d2 -> d2.compareTo(d1) }
|
|
||||||
val byDay = recents
|
|
||||||
.groupByTo(map, { it.history.last_read.toDateKey() })
|
|
||||||
byDay.flatMap { entry ->
|
|
||||||
val dateItem = DateSectionItem(entry.key)
|
|
||||||
entry.value.map { HistoryItem(it, dateItem) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get recent manga observable
|
|
||||||
* @return list of history
|
|
||||||
*/
|
|
||||||
private fun getRecentMangaLimitObservable(offset: Int = 0, search: String = ""): Observable<List<HistoryItem>> {
|
|
||||||
// Set limit for recent manga
|
|
||||||
val cal = Calendar.getInstance()
|
|
||||||
cal.time = Date()
|
|
||||||
cal.add(Calendar.YEAR, -50)
|
|
||||||
|
|
||||||
return db.getRecentMangaLimit(cal.time, lastCount, search).asRxObservable()
|
|
||||||
.map { recents ->
|
.map { recents ->
|
||||||
val map = TreeMap<Date, MutableList<MangaChapterHistory>> { d1, d2 -> d2.compareTo(d1) }
|
val map = TreeMap<Date, MutableList<MangaChapterHistory>> { d1, d2 -> d2.compareTo(d1) }
|
||||||
val byDay = recents
|
val byDay = recents
|
||||||
@ -103,13 +75,16 @@ class HistoryPresenter : BasePresenter<HistoryController>() {
|
|||||||
*/
|
*/
|
||||||
fun removeFromHistory(history: History) {
|
fun removeFromHistory(history: History) {
|
||||||
history.last_read = 0L
|
history.last_read = 0L
|
||||||
db.updateHistoryLastRead(history).executeAsBlocking()
|
db.updateHistoryLastRead(history).asRxObservable()
|
||||||
updateList()
|
.subscribe()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateList(search: String? = null) {
|
/**
|
||||||
lastSearch = search ?: lastSearch
|
* Pull a list of history from the db
|
||||||
getRecentMangaLimitObservable(lastCount, lastSearch).take(1)
|
* @param search a search query to use for filtering
|
||||||
|
*/
|
||||||
|
fun updateList(search: String = "") {
|
||||||
|
getRecentMangaObservable(search = search).take(1)
|
||||||
.subscribeLatestCache(
|
.subscribeLatestCache(
|
||||||
{ view, mangas ->
|
{ view, mangas ->
|
||||||
view.onNextManga(mangas, true)
|
view.onNextManga(mangas, true)
|
||||||
@ -123,10 +98,12 @@ class HistoryPresenter : BasePresenter<HistoryController>() {
|
|||||||
* @param mangaId id of manga
|
* @param mangaId id of manga
|
||||||
*/
|
*/
|
||||||
fun removeAllFromHistory(mangaId: Long) {
|
fun removeAllFromHistory(mangaId: Long) {
|
||||||
val history = db.getHistoryByMangaId(mangaId).executeAsBlocking()
|
db.getHistoryByMangaId(mangaId).asRxSingle()
|
||||||
history.forEach { it.last_read = 0L }
|
.map { list ->
|
||||||
db.updateHistoryLastRead(history).executeAsBlocking()
|
list.forEach { it.last_read = 0L }
|
||||||
updateList()
|
db.updateHistoryLastRead(list).executeAsBlocking()
|
||||||
|
}
|
||||||
|
.subscribe()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -148,7 +125,7 @@ class HistoryPresenter : BasePresenter<HistoryController>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val chapters = db.getChapters(manga).executeAsBlocking()
|
val chapters = db.getChapters(manga).executeAsBlocking()
|
||||||
.sortedWith(Comparator { c1, c2 -> sortFunction(c1, c2) })
|
.sortedWith { c1, c2 -> sortFunction(c1, c2) }
|
||||||
|
|
||||||
val currChapterIndex = chapters.indexOfFirst { chapter.id == it.id }
|
val currChapterIndex = chapters.indexOfFirst { chapter.id == it.id }
|
||||||
return when (manga.sorting) {
|
return when (manga.sorting) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user