mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-12-23 16:11:51 +01:00
Steps to optimize recents loading
especially those with insanely large libraries
This commit is contained in:
parent
2ec4db3c10
commit
2f09ac8cb5
@ -56,5 +56,7 @@ open class DatabaseHelper(context: Context) :
|
||||
|
||||
inline fun inTransaction(block: () -> Unit) = db.inTransaction(block)
|
||||
|
||||
inline fun <T> inTransactionReturn(block: () -> T): T = db.inTransactionReturn(block)
|
||||
|
||||
fun lowLevel() = db.lowLevel()
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ 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
|
||||
import java.util.Date
|
||||
|
||||
interface ChapterQueries : DbProvider {
|
||||
|
||||
@ -32,14 +31,12 @@ interface ChapterQueries : DbProvider {
|
||||
)
|
||||
.prepare()
|
||||
|
||||
fun getRecentChapters(date: Date) = getRecentChapters(Date(), date)
|
||||
|
||||
fun getRecentChapters(startDate: Date, date: Date, search: String = "") = db.get()
|
||||
fun getRecentChapters(search: String = "", offset: Int, isResuming: Boolean) = db.get()
|
||||
.listOfObjects(MangaChapter::class.java)
|
||||
.withQuery(
|
||||
RawQuery.builder()
|
||||
.query(getRecentsQuery(search.sqLite))
|
||||
.args(date.time, startDate.time)
|
||||
.query(getRecentsQuery(search.sqLite, offset, isResuming))
|
||||
// .args(date.time, startDate.time)
|
||||
.observesTables(ChapterTable.TABLE)
|
||||
.build()
|
||||
)
|
||||
@ -51,15 +48,12 @@ interface ChapterQueries : DbProvider {
|
||||
* @param date recent date range
|
||||
* @offset offset the db by
|
||||
*/
|
||||
fun getUpdatedManga(date: Date, search: String = "", endless: Boolean) =
|
||||
getUpdatedManga(Date(), date, search, endless)
|
||||
|
||||
fun getUpdatedManga(startDate: Date, date: Date, search: String = "", endless: Boolean) = db.get()
|
||||
fun getUpdatedManga(search: String = "", endless: Boolean, offset: Int, isResuming: Boolean) = db.get()
|
||||
.listOfObjects(MangaChapterHistory::class.java)
|
||||
.withQuery(
|
||||
RawQuery.builder()
|
||||
.query(getRecentsQueryDistinct(search.sqLite, endless))
|
||||
.args(date.time, startDate.time)
|
||||
.query(getRecentsQueryDistinct(search.sqLite, endless, offset, isResuming))
|
||||
// .args(date.time, startDate.time)
|
||||
.observesTables(ChapterTable.TABLE)
|
||||
.build()
|
||||
)
|
||||
|
@ -10,7 +10,6 @@ import eu.kanade.tachiyomi.data.database.resolvers.MangaChapterHistoryGetResolve
|
||||
import eu.kanade.tachiyomi.data.database.tables.HistoryTable
|
||||
import eu.kanade.tachiyomi.data.database.tables.MangaTable
|
||||
import eu.kanade.tachiyomi.util.lang.sqLite
|
||||
import java.util.Date
|
||||
|
||||
interface HistoryQueries : DbProvider {
|
||||
|
||||
@ -18,36 +17,36 @@ interface HistoryQueries : DbProvider {
|
||||
* Insert history into database
|
||||
* @param history object containing history information
|
||||
*/
|
||||
fun insertHistory(history: History) = db.put().`object`(history).prepare()
|
||||
// fun insertHistory(history: History) = db.put().`object`(history).prepare()
|
||||
|
||||
// /**
|
||||
// * Returns history of recent manga containing last read chapter in 25s
|
||||
// * @param date recent date range
|
||||
// * @offset offset the db by
|
||||
// */
|
||||
// fun getRecentManga(date: Date, offset: Int = 0, search: String = "") = db.get()
|
||||
// .listOfObjects(MangaChapterHistory::class.java)
|
||||
// .withQuery(
|
||||
// RawQuery.builder()
|
||||
// .query(getRecentMangasQuery(offset, search.sqLite))
|
||||
// .args(date.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 getRecentManga(date: Date, offset: Int = 0, search: String = "") = db.get()
|
||||
fun getRecentlyAdded(search: String = "", endless: Boolean, offset: Int, isResuming: Boolean) = db.get()
|
||||
.listOfObjects(MangaChapterHistory::class.java)
|
||||
.withQuery(
|
||||
RawQuery.builder()
|
||||
.query(getRecentMangasQuery(offset, search.sqLite))
|
||||
.args(date.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 getRecentlyAdded(startDate: Date, date: Date, search: String = "", endless: Boolean) = db.get()
|
||||
.listOfObjects(MangaChapterHistory::class.java)
|
||||
.withQuery(
|
||||
RawQuery.builder()
|
||||
.query(getRecentAdditionsQuery(search.sqLite, endless))
|
||||
.args(date.time, startDate.time)
|
||||
.query(getRecentAdditionsQuery(search.sqLite, endless, offset, isResuming))
|
||||
// .args(date.time, startDate.time)
|
||||
.observesTables(MangaTable.TABLE)
|
||||
.build()
|
||||
)
|
||||
@ -59,20 +58,12 @@ interface HistoryQueries : DbProvider {
|
||||
* @param date recent date range
|
||||
* @offset offset the db by
|
||||
*/
|
||||
fun getRecentMangaLimit(date: Date, limit: Int = 0, search: String = "") =
|
||||
getRecentMangaLimit(Date(), date, limit, search)
|
||||
|
||||
/**
|
||||
* Returns history of recent manga containing last read chapter in 25s
|
||||
* @param date recent date range
|
||||
* @offset offset the db by
|
||||
*/
|
||||
fun getRecentMangaLimit(startDate: Date, date: Date, limit: Int = 0, search: String = "") = db.get()
|
||||
fun getRecentMangaLimit(search: String = "", endless: Boolean, offset: Int, isResuming: Boolean) = db.get()
|
||||
.listOfObjects(MangaChapterHistory::class.java)
|
||||
.withQuery(
|
||||
RawQuery.builder()
|
||||
.query(getRecentMangasLimitQuery(limit, search.sqLite))
|
||||
.args(date.time, startDate.time)
|
||||
.query(getRecentMangasLimitQuery(search.sqLite, endless, offset, isResuming))
|
||||
// .args(date.time, startDate.time)
|
||||
.observesTables(HistoryTable.TABLE)
|
||||
.build()
|
||||
)
|
||||
@ -84,29 +75,20 @@ interface HistoryQueries : DbProvider {
|
||||
* @param date recent date range
|
||||
* @offset offset the db by
|
||||
*/
|
||||
fun getRecentsWithUnread(startDate: Date, date: Date, search: String = "", endless: Boolean) = db.get()
|
||||
fun getAllRecents(search: String = "", includeRead: Boolean, endless: Boolean, offset: Int, isResuming: Boolean) = db.get()
|
||||
.listOfObjects(MangaChapterHistory::class.java)
|
||||
.withQuery(
|
||||
RawQuery.builder()
|
||||
.query(getRecentReadWithUnreadChapters(search.sqLite, endless))
|
||||
.args(date.time, startDate.time)
|
||||
.observesTables(HistoryTable.TABLE)
|
||||
.build()
|
||||
.query(
|
||||
getRecentRead(
|
||||
search.sqLite,
|
||||
includeRead,
|
||||
endless,
|
||||
offset,
|
||||
isResuming
|
||||
)
|
||||
.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 getAllRecents(startDate: Date, date: Date, search: String = "", endless: Boolean) = db.get()
|
||||
.listOfObjects(MangaChapterHistory::class.java)
|
||||
.withQuery(
|
||||
RawQuery.builder()
|
||||
.query(getRecentRead(search.sqLite, endless))
|
||||
.args(date.time, startDate.time)
|
||||
)
|
||||
// .args(date.time, startDate.time)
|
||||
.observesTables(HistoryTable.TABLE)
|
||||
.build()
|
||||
)
|
||||
|
@ -1,5 +1,6 @@
|
||||
package eu.kanade.tachiyomi.data.database.queries
|
||||
|
||||
import eu.kanade.tachiyomi.ui.recents.RecentsPresenter
|
||||
import eu.kanade.tachiyomi.data.database.tables.CategoryTable as Category
|
||||
import eu.kanade.tachiyomi.data.database.tables.ChapterTable as Chapter
|
||||
import eu.kanade.tachiyomi.data.database.tables.HistoryTable as History
|
||||
@ -41,36 +42,41 @@ val libraryQuery =
|
||||
/**
|
||||
* Query to get the recent chapters of manga from the library up to a date.
|
||||
*/
|
||||
fun getRecentsQuery(search: String) =
|
||||
fun getRecentsQuery(search: String, offset: Int, isResuming: Boolean) =
|
||||
"""
|
||||
SELECT ${Manga.TABLE}.${Manga.COL_URL} as mangaUrl, * FROM ${Manga.TABLE} JOIN ${Chapter.TABLE}
|
||||
ON ${Manga.TABLE}.${Manga.COL_ID} = ${Chapter.TABLE}.${Chapter.COL_MANGA_ID}
|
||||
WHERE ${Manga.COL_FAVORITE} = 1
|
||||
AND ${Chapter.COL_DATE_FETCH} > ?
|
||||
AND ${Chapter.COL_DATE_FETCH} < ?
|
||||
AND ${Chapter.COL_DATE_FETCH} > ${Manga.COL_DATE_ADDED}
|
||||
AND lower(${Manga.COL_TITLE}) LIKE '%$search%'
|
||||
ORDER BY ${Chapter.COL_DATE_UPLOAD} DESC
|
||||
ORDER BY ${Chapter.COL_DATE_FETCH} DESC
|
||||
${limitAndOffset(true, isResuming, offset)}
|
||||
"""
|
||||
|
||||
/**
|
||||
* Query to get the recently added manga
|
||||
*/
|
||||
fun getRecentAdditionsQuery(search: String, endless: Boolean) =
|
||||
fun getRecentAdditionsQuery(search: String, endless: Boolean, offset: Int, isResuming: Boolean) =
|
||||
"""
|
||||
SELECT ${Manga.TABLE}.${Manga.COL_URL} as mangaUrl, * FROM ${Manga.TABLE}
|
||||
WHERE ${Manga.COL_FAVORITE} = 1
|
||||
AND ${Manga.COL_DATE_ADDED} > ?
|
||||
AND ${Manga.COL_DATE_ADDED} < ?
|
||||
AND lower(${Manga.COL_TITLE}) LIKE '%$search%'
|
||||
ORDER BY ${Manga.COL_DATE_ADDED} DESC
|
||||
${if (endless) "" else "LIMIT 8"}
|
||||
${limitAndOffset(endless, isResuming, offset)}
|
||||
"""
|
||||
|
||||
fun limitAndOffset(endless: Boolean, isResuming: Boolean, offset: Int): String {
|
||||
return when {
|
||||
isResuming && endless -> "LIMIT $offset"
|
||||
endless -> "LIMIT ${RecentsPresenter.ENDLESS_LIMIT}\nOFFSET $offset"
|
||||
else -> "LIMIT 8"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query to get the manga with recently uploaded chapters
|
||||
*/
|
||||
fun getRecentsQueryDistinct(search: String, endless: Boolean) =
|
||||
fun getRecentsQueryDistinct(search: String, endless: Boolean, offset: Int = 0, isResuming: Boolean) =
|
||||
"""
|
||||
SELECT ${Manga.TABLE}.${Manga.COL_URL} as mangaUrl, ${Manga.TABLE}.*, ${Chapter.TABLE}.*
|
||||
FROM ${Manga.TABLE}
|
||||
@ -80,17 +86,15 @@ fun getRecentsQueryDistinct(search: String, endless: Boolean) =
|
||||
SELECT ${Chapter.TABLE}.${Chapter.COL_MANGA_ID},${Chapter.TABLE}.${Chapter.COL_ID} as ${History.COL_CHAPTER_ID},MAX(${Chapter.TABLE}.${Chapter.COL_DATE_UPLOAD})
|
||||
FROM ${Chapter.TABLE} JOIN ${Manga.TABLE}
|
||||
ON ${Manga.TABLE}.${Manga.COL_ID} = ${Chapter.TABLE}.${Chapter.COL_MANGA_ID}
|
||||
WHERE ${Chapter.COL_DATE_FETCH} > ?
|
||||
AND ${Chapter.COL_DATE_FETCH} < ?
|
||||
AND ${Chapter.COL_READ} = 0
|
||||
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 ${Chapter.COL_DATE_FETCH} > ${Manga.COL_DATE_ADDED}
|
||||
AND lower(${Manga.COL_TITLE}) LIKE '%$search%'
|
||||
ORDER BY ${Chapter.COL_DATE_UPLOAD} DESC
|
||||
${if (endless) "" else "LIMIT 8"}
|
||||
ORDER BY ${Chapter.COL_DATE_FETCH} DESC
|
||||
${limitAndOffset(endless, isResuming, offset)}
|
||||
"""
|
||||
|
||||
/**
|
||||
@ -98,9 +102,13 @@ fun getRecentsQueryDistinct(search: String, endless: Boolean) =
|
||||
* 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
|
||||
* @return return limit is 25
|
||||
*/
|
||||
fun getRecentMangasQuery(offset: Int = 0, search: String = "") =
|
||||
fun getRecentMangasLimitQuery(
|
||||
search: String = "",
|
||||
endless: Boolean,
|
||||
offset: Int = 0,
|
||||
isResuming: Boolean
|
||||
) =
|
||||
"""
|
||||
SELECT ${Manga.TABLE}.${Manga.COL_URL} as mangaUrl, ${Manga.TABLE}.*, ${Chapter.TABLE}.*, ${History.TABLE}.*
|
||||
FROM ${Manga.TABLE}
|
||||
@ -114,39 +122,10 @@ fun getRecentMangasQuery(offset: Int = 0, search: String = "") =
|
||||
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}.*
|
||||
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 ${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 $limit
|
||||
${limitAndOffset(endless, isResuming, offset)}
|
||||
"""
|
||||
|
||||
/**
|
||||
@ -156,7 +135,13 @@ 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 = "", endless: Boolean) =
|
||||
fun getRecentRead(
|
||||
search: String = "",
|
||||
includeRead: Boolean,
|
||||
endless: Boolean,
|
||||
offset: Int = 0,
|
||||
isResuming: Boolean
|
||||
) =
|
||||
"""
|
||||
SELECT ${Manga.TABLE}.${Manga.COL_URL} as mangaUrl, ${Manga.TABLE}.*, ${Chapter.TABLE}.*, ${History.TABLE}.*
|
||||
FROM (
|
||||
@ -165,11 +150,10 @@ fun getRecentReadWithUnreadChapters(search: String = "", endless: Boolean) =
|
||||
LEFT JOIN (
|
||||
SELECT ${Chapter.COL_MANGA_ID}, COUNT(*) AS unread
|
||||
FROM ${Chapter.TABLE}
|
||||
WHERE ${Chapter.COL_READ} = 0
|
||||
GROUP BY ${Chapter.COL_MANGA_ID}
|
||||
) AS C
|
||||
ON ${Manga.COL_ID} = C.${Chapter.COL_MANGA_ID}
|
||||
WHERE C.unread > 0
|
||||
${if (includeRead) "" else "WHERE C.unread > 0"}
|
||||
GROUP BY ${Manga.COL_ID}
|
||||
ORDER BY ${Manga.COL_TITLE}
|
||||
) AS ${Manga.TABLE}
|
||||
@ -183,53 +167,10 @@ fun getRecentReadWithUnreadChapters(search: String = "", endless: Boolean) =
|
||||
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 ${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
|
||||
${if (endless) "" else "LIMIT 8"}
|
||||
"""
|
||||
|
||||
/**
|
||||
* Query to get the recently read manga that has more chapters to read
|
||||
* The first from checks that there's an unread chapter
|
||||
* 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 getRecentRead(search: String = "", endless: Boolean) =
|
||||
"""
|
||||
SELECT ${Manga.TABLE}.${Manga.COL_URL} as mangaUrl, ${Manga.TABLE}.*, ${Chapter.TABLE}.*, ${History.TABLE}.*
|
||||
FROM (
|
||||
SELECT ${Manga.TABLE}.*
|
||||
FROM ${Manga.TABLE}
|
||||
LEFT JOIN (
|
||||
SELECT ${Chapter.COL_MANGA_ID}, COUNT(*) AS unread
|
||||
FROM ${Chapter.TABLE}
|
||||
GROUP BY ${Chapter.COL_MANGA_ID}
|
||||
) AS C
|
||||
ON ${Manga.COL_ID} = C.${Chapter.COL_MANGA_ID}
|
||||
WHERE C.unread > 0
|
||||
GROUP BY ${Manga.COL_ID}
|
||||
ORDER BY ${Manga.COL_TITLE}
|
||||
) AS ${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 ${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
|
||||
${if (endless) "" else "LIMIT 8"}
|
||||
${limitAndOffset(endless, isResuming, offset)}
|
||||
"""
|
||||
|
||||
fun getHistoryByMangaId() =
|
||||
|
@ -181,6 +181,8 @@ class RecentsController(bundle: Bundle? = null) :
|
||||
}
|
||||
|
||||
presenter.onCreate()
|
||||
binding.swipeRefresh.isRefreshing = true
|
||||
|
||||
if (presenter.recentItems.isNotEmpty()) {
|
||||
adapter.updateDataSet(presenter.recentItems)
|
||||
}
|
||||
@ -345,7 +347,9 @@ class RecentsController(bundle: Bundle? = null) :
|
||||
override fun onActivityResumed(activity: Activity) {
|
||||
super.onActivityResumed(activity)
|
||||
if (!isBindingInitialized) return
|
||||
if (!presenter.isLoading) {
|
||||
refresh()
|
||||
}
|
||||
setBottomPadding()
|
||||
binding.downloadBottomSheet.dlBottomSheet.update()
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ 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.source.SourceManager
|
||||
import eu.kanade.tachiyomi.util.system.executeOnIO
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
@ -46,7 +45,7 @@ class RecentsPresenter(
|
||||
var query = ""
|
||||
set(value) {
|
||||
field = value
|
||||
page = 0
|
||||
resetOffsets()
|
||||
}
|
||||
private val newAdditionsHeader = RecentMangaHeaderItem(RecentMangaHeaderItem.NEWLY_ADDED)
|
||||
private val newChaptersHeader = RecentMangaHeaderItem(RecentMangaHeaderItem.NEW_CHAPTERS)
|
||||
@ -55,23 +54,37 @@ class RecentsPresenter(
|
||||
.CONTINUE_READING
|
||||
)
|
||||
var finished = false
|
||||
var shouldMoveToTop = false
|
||||
var heldItems: HashMap<Int, List<RecentMangaItem>> = hashMapOf()
|
||||
private var shouldMoveToTop = false
|
||||
var viewType: Int = preferences.recentsViewType().get()
|
||||
private var page = 0
|
||||
set(value) {
|
||||
field = value
|
||||
if (value == 0) {
|
||||
ENDLESS_LIMIT = if (value == VIEW_TYPE_UNGROUP_ALL) 25 else 50
|
||||
}
|
||||
|
||||
private fun resetOffsets() {
|
||||
finished = false
|
||||
shouldMoveToTop = true
|
||||
updatesOffset = 0
|
||||
historyOffset = 0
|
||||
additionsOffset = 0
|
||||
}
|
||||
}
|
||||
|
||||
private var updatesOffset = 0
|
||||
private var historyOffset = 0
|
||||
private var additionsOffset = 0
|
||||
var isLoading = false
|
||||
private set
|
||||
|
||||
private val isOnFirstPage: Boolean
|
||||
get() = additionsOffset + historyOffset + updatesOffset == 0
|
||||
|
||||
init {
|
||||
preferences.showReadInAllRecents()
|
||||
.asFlow()
|
||||
.drop(1)
|
||||
.onEach {
|
||||
page = 0
|
||||
resetOffsets()
|
||||
getRecents()
|
||||
}
|
||||
.launchIn(scope)
|
||||
@ -97,97 +110,107 @@ class RecentsPresenter(
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun runRecents(oldQuery: String = "", updatePageCount: Boolean = false, retryCount: Int = 0, itemCount: Int = 0, limit: Boolean = false) {
|
||||
private suspend fun runRecents(
|
||||
oldQuery: String = "",
|
||||
updatePageCount: Boolean = false,
|
||||
retryCount: Int = 0,
|
||||
itemCount: Int = 0,
|
||||
limit: Boolean = false,
|
||||
customViewType: Int? = null
|
||||
) {
|
||||
if (retryCount > 15) {
|
||||
finished = true
|
||||
setDownloadedChapters(recentItems)
|
||||
withContext(Dispatchers.Main) { controller?.showLists(recentItems, false) }
|
||||
if (customViewType == null) {
|
||||
withContext(Dispatchers.Main) {
|
||||
controller?.showLists(recentItems, false)
|
||||
isLoading = false
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
val viewType = customViewType ?: viewType
|
||||
|
||||
// Timber.d("starting up items new page: $updatePageCount")
|
||||
val showRead = preferences.showReadInAllRecents().get() && !limit
|
||||
if (updatePageCount) {
|
||||
page++
|
||||
}
|
||||
|
||||
val isUngrouped = viewType > VIEW_TYPE_GROUP_ALL && query.isEmpty()
|
||||
val cal = Calendar.getInstance().apply {
|
||||
time = Date()
|
||||
when {
|
||||
query.isNotEmpty() -> add(Calendar.YEAR, -50)
|
||||
isUngrouped -> add(Calendar.MONTH, -(page + 1))
|
||||
else -> add(Calendar.MONTH, -1)
|
||||
}
|
||||
}
|
||||
|
||||
val startCal = Calendar.getInstance().apply {
|
||||
time = Date()
|
||||
when {
|
||||
query.isNotEmpty() -> {}
|
||||
isUngrouped && !updatePageCount -> {}
|
||||
isUngrouped -> add(Calendar.MONTH, -page)
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
val calWeek = Calendar.getInstance().apply {
|
||||
time = Date()
|
||||
when {
|
||||
query.isNotEmpty() -> add(Calendar.YEAR, -50)
|
||||
isUngrouped -> add(Calendar.MONTH, -(page + 1))
|
||||
else -> add(Calendar.WEEK_OF_YEAR, -1)
|
||||
}
|
||||
}
|
||||
|
||||
val calDay = Calendar.getInstance().apply {
|
||||
time = Date()
|
||||
when {
|
||||
query.isNotEmpty() -> add(Calendar.YEAR, -50)
|
||||
isUngrouped -> add(Calendar.MONTH, -(page + 1))
|
||||
else -> add(Calendar.DAY_OF_YEAR, -1)
|
||||
}
|
||||
}
|
||||
|
||||
val isCustom = customViewType != null
|
||||
val isEndless = isUngrouped && !limit
|
||||
// Timber.d("set up cal items")
|
||||
val (cReading, rUpdates, nAdditions) = db.inTransactionReturn {
|
||||
val cReading = if (viewType != VIEW_TYPE_ONLY_UPDATES) {
|
||||
if (query.isEmpty() && viewType != VIEW_TYPE_ONLY_HISTORY) {
|
||||
if (showRead) {
|
||||
db.getAllRecents(startCal.time, cal.time, query, isUngrouped && !limit)
|
||||
.executeOnIO()
|
||||
db.getAllRecents(
|
||||
query,
|
||||
showRead,
|
||||
isEndless,
|
||||
if (isCustom) ENDLESS_LIMIT else historyOffset,
|
||||
!updatePageCount && !isOnFirstPage
|
||||
)
|
||||
} else {
|
||||
db.getRecentsWithUnread(startCal.time, cal.time, query, isUngrouped && !limit)
|
||||
.executeOnIO()
|
||||
}
|
||||
} else db.getRecentMangaLimit(
|
||||
startCal.time,
|
||||
cal.time,
|
||||
if (viewType == VIEW_TYPE_ONLY_HISTORY) 200 else 8,
|
||||
query
|
||||
).executeOnIO()
|
||||
db.getRecentMangaLimit(
|
||||
query,
|
||||
isEndless,
|
||||
if (isCustom) ENDLESS_LIMIT else historyOffset,
|
||||
!updatePageCount && !isOnFirstPage
|
||||
)
|
||||
}.executeAsBlocking()
|
||||
} else emptyList()
|
||||
// Timber.d("set up cReader items: ${cReading.size}")
|
||||
val rUpdates = when {
|
||||
viewType == VIEW_TYPE_ONLY_UPDATES -> db.getRecentChapters(startCal.time, calWeek.time, query).executeOnIO().map {
|
||||
viewType == VIEW_TYPE_ONLY_UPDATES -> db.getRecentChapters(
|
||||
query,
|
||||
if (isCustom) ENDLESS_LIMIT else updatesOffset,
|
||||
!updatePageCount && !isOnFirstPage
|
||||
).executeAsBlocking().map {
|
||||
MangaChapterHistory(it.manga, it.chapter, HistoryImpl())
|
||||
}
|
||||
viewType != VIEW_TYPE_ONLY_HISTORY -> db.getUpdatedManga(startCal.time, calWeek.time, query, isUngrouped && !limit).executeOnIO()
|
||||
viewType != VIEW_TYPE_ONLY_HISTORY -> db.getUpdatedManga(
|
||||
query,
|
||||
isEndless,
|
||||
if (isCustom) ENDLESS_LIMIT else updatesOffset,
|
||||
!updatePageCount && !isOnFirstPage
|
||||
).executeAsBlocking()
|
||||
else -> emptyList()
|
||||
}
|
||||
rUpdates.forEach {
|
||||
it.history.last_read = it.chapter.date_fetch
|
||||
}
|
||||
// Timber.d("set up rUpdates items: ${rUpdates.size}")
|
||||
val nAdditions = if (viewType < VIEW_TYPE_ONLY_HISTORY) {
|
||||
db.getRecentlyAdded(startCal.time, calDay.time, query, isUngrouped && !limit).executeOnIO()
|
||||
db.getRecentlyAdded(
|
||||
query,
|
||||
isEndless,
|
||||
if (isCustom) ENDLESS_LIMIT else additionsOffset,
|
||||
!updatePageCount && !isOnFirstPage
|
||||
).executeAsBlocking()
|
||||
} else emptyList()
|
||||
nAdditions.forEach {
|
||||
it.history.last_read = it.manga.date_added
|
||||
}
|
||||
// Timber.d("set up nAdditons items: ${nAdditions.size}")
|
||||
Triple(cReading, rUpdates, nAdditions)
|
||||
}
|
||||
|
||||
if (!isCustom &&
|
||||
(historyOffset + updatesOffset + additionsOffset == 0 || updatePageCount)
|
||||
) {
|
||||
additionsOffset += nAdditions.size
|
||||
historyOffset += cReading.size
|
||||
updatesOffset += rUpdates.size
|
||||
}
|
||||
|
||||
// Timber.d("loaded items: ")
|
||||
if (query != oldQuery) return
|
||||
// Timber.d("query matches items: ")
|
||||
val mangaList = (cReading + rUpdates + nAdditions).sortedByDescending {
|
||||
it.history.last_read
|
||||
}.distinctBy {
|
||||
if (query.isEmpty() && viewType != VIEW_TYPE_ONLY_HISTORY) it.manga.id else it.chapter.id
|
||||
if (query.isEmpty() && viewType != VIEW_TYPE_ONLY_HISTORY && viewType != VIEW_TYPE_ONLY_UPDATES) it.manga.id else it.chapter.id
|
||||
}.filter { mch ->
|
||||
if (updatePageCount && page > 0 && query.isEmpty()) {
|
||||
if (viewType != VIEW_TYPE_ONLY_HISTORY) {
|
||||
if (updatePageCount && !isOnFirstPage && query.isEmpty()) {
|
||||
if (viewType != VIEW_TYPE_ONLY_HISTORY && viewType != VIEW_TYPE_ONLY_UPDATES) {
|
||||
recentItems.none { mch.manga.id == it.mch.manga.id }
|
||||
} else {
|
||||
recentItems.none { mch.chapter.id == it.mch.chapter.id }
|
||||
@ -209,9 +232,11 @@ class RecentsPresenter(
|
||||
else null
|
||||
else Pair(it, chapter)
|
||||
}
|
||||
// Timber.d("setting new items")
|
||||
val newItems = if (query.isEmpty() && !isUngrouped) {
|
||||
val nChaptersItems =
|
||||
pairs.asSequence().filter { it.first.history.id == null && it.first.chapter.id != null }
|
||||
pairs.asSequence()
|
||||
.filter { it.first.history.id == null && it.first.chapter.id != null }
|
||||
.sortedWith { f1, f2 ->
|
||||
if (abs(f1.second.date_fetch - f2.second.date_fetch) <=
|
||||
TimeUnit.HOURS.toMillis(12)
|
||||
@ -249,8 +274,8 @@ class RecentsPresenter(
|
||||
}.flatten()
|
||||
} else {
|
||||
if (viewType == VIEW_TYPE_ONLY_UPDATES) {
|
||||
val map = TreeMap<Date, MutableList<Pair<MangaChapterHistory, Chapter>>> {
|
||||
d1, d2 ->
|
||||
val map =
|
||||
TreeMap<Date, MutableList<Pair<MangaChapterHistory, Chapter>>> { d1, d2 ->
|
||||
d2
|
||||
.compareTo(d1)
|
||||
}
|
||||
@ -264,24 +289,41 @@ class RecentsPresenter(
|
||||
}
|
||||
} else pairs.map { RecentMangaItem(it.first, it.second, null) }
|
||||
}
|
||||
recentItems = if (page == 0 || !updatePageCount) {
|
||||
// Timber.d("setting some items")
|
||||
if (customViewType == null) {
|
||||
recentItems = if (isOnFirstPage || !updatePageCount) {
|
||||
newItems
|
||||
} else {
|
||||
recentItems + newItems
|
||||
}
|
||||
} else {
|
||||
heldItems[customViewType] = newItems
|
||||
}
|
||||
val newCount = itemCount + newItems.size
|
||||
val hasNewItems = newItems.isNotEmpty()
|
||||
if (updatePageCount && newCount < 25 && viewType != VIEW_TYPE_GROUP_ALL && query.isEmpty() && !limit) {
|
||||
page++
|
||||
// Timber.d("needs to retry. has New items: $hasNewItems, offset: $subUpdatesOffset")
|
||||
runRecents(oldQuery, true, retryCount + (if (hasNewItems) 0 else 1), newCount)
|
||||
return
|
||||
}
|
||||
if (!limit) {
|
||||
setDownloadedChapters(recentItems)
|
||||
if (customViewType == null) {
|
||||
withContext(Dispatchers.Main) {
|
||||
controller?.showLists(recentItems, hasNewItems, shouldMoveToTop)
|
||||
isLoading = false
|
||||
shouldMoveToTop = false
|
||||
}
|
||||
// scope.launchIO {
|
||||
// (0..3).map {
|
||||
// async {
|
||||
// if (this@RecentsPresenter.viewType != it) {
|
||||
// runRecents(oldQuery, customViewType = it)
|
||||
// }
|
||||
// }
|
||||
// }.awaitAll()
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -312,7 +354,7 @@ class RecentsPresenter(
|
||||
preferences.recentsViewType().set(pref)
|
||||
}
|
||||
viewType = pref
|
||||
page = 0
|
||||
resetOffsets()
|
||||
getRecents()
|
||||
}
|
||||
|
||||
@ -452,8 +494,11 @@ class RecentsPresenter(
|
||||
}
|
||||
|
||||
fun requestNext() {
|
||||
if (!isLoading) {
|
||||
isLoading = true
|
||||
getRecents(true)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private var lastRecents: List<RecentMangaItem>? = null
|
||||
@ -462,6 +507,7 @@ class RecentsPresenter(
|
||||
const val VIEW_TYPE_UNGROUP_ALL = 1
|
||||
const val VIEW_TYPE_ONLY_HISTORY = 2
|
||||
const val VIEW_TYPE_ONLY_UPDATES = 3
|
||||
var ENDLESS_LIMIT = 50
|
||||
|
||||
suspend fun getRecentManga(): List<Pair<Manga, Long>> {
|
||||
val presenter = RecentsPresenter(null)
|
||||
|
Loading…
Reference in New Issue
Block a user