Steps to optimize recents loading

especially those with insanely large libraries
This commit is contained in:
Jays2Kings 2021-04-12 22:05:53 -04:00
parent 2ec4db3c10
commit 2f09ac8cb5
6 changed files with 229 additions and 260 deletions

View File

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

View File

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

View File

@ -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()
)
.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)
.query(
getRecentRead(
search.sqLite,
includeRead,
endless,
offset,
isResuming
)
)
// .args(date.time, startDate.time)
.observesTables(HistoryTable.TABLE)
.build()
)

View File

@ -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,56 +42,59 @@ 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} < ?
WHERE ${Manga.COL_FAVORITE} = 1
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}
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})
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
GROUP BY ${Chapter.TABLE}.${Chapter.COL_MANGA_ID}) AS newest_chapter
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_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() =

View File

@ -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
refresh()
if (!presenter.isLoading) {
refresh()
}
setBottomPadding()
binding.downloadBottomSheet.dlBottomSheet.update()
}

View File

@ -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) {
finished = false
shouldMoveToTop = true
}
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 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()
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) {
db.getAllRecents(
query,
showRead,
isEndless,
if (isCustom) ENDLESS_LIMIT else historyOffset,
!updatePageCount && !isOnFirstPage
)
} else {
db.getRecentsWithUnread(startCal.time, cal.time, query, isUngrouped && !limit)
.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(
query,
if (isCustom) ENDLESS_LIMIT else updatesOffset,
!updatePageCount && !isOnFirstPage
).executeAsBlocking().map {
MangaChapterHistory(it.manga, it.chapter, HistoryImpl())
}
} else db.getRecentMangaLimit(
startCal.time,
cal.time,
if (viewType == VIEW_TYPE_ONLY_HISTORY) 200 else 8,
query
).executeOnIO()
} else emptyList()
val rUpdates = when {
viewType == VIEW_TYPE_ONLY_UPDATES -> db.getRecentChapters(startCal.time, calWeek.time, query).executeOnIO().map {
MangaChapterHistory(it.manga, it.chapter, HistoryImpl())
viewType != VIEW_TYPE_ONLY_HISTORY -> db.getUpdatedManga(
query,
isEndless,
if (isCustom) ENDLESS_LIMIT else updatesOffset,
!updatePageCount && !isOnFirstPage
).executeAsBlocking()
else -> emptyList()
}
viewType != VIEW_TYPE_ONLY_HISTORY -> db.getUpdatedManga(startCal.time, calWeek.time, query, isUngrouped && !limit).executeOnIO()
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(
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)
}
rUpdates.forEach {
it.history.last_read = it.chapter.date_fetch
}
val nAdditions = if (viewType < VIEW_TYPE_ONLY_HISTORY) {
db.getRecentlyAdded(startCal.time, calDay.time, query, isUngrouped && !limit).executeOnIO()
} else emptyList()
nAdditions.forEach {
it.history.last_read = it.manga.date_added
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,11 +274,11 @@ class RecentsPresenter(
}.flatten()
} else {
if (viewType == VIEW_TYPE_ONLY_UPDATES) {
val map = TreeMap<Date, MutableList<Pair<MangaChapterHistory, Chapter>>> {
d1, d2 ->
d2
.compareTo(d1)
}
val map =
TreeMap<Date, MutableList<Pair<MangaChapterHistory, Chapter>>> { d1, d2 ->
d2
.compareTo(d1)
}
val byDay =
pairs.groupByTo(map, { getMapKey(it.first.history.last_read) })
byDay.flatMap {
@ -264,23 +289,40 @@ class RecentsPresenter(
}
} else pairs.map { RecentMangaItem(it.first, it.second, null) }
}
recentItems = if (page == 0 || !updatePageCount) {
newItems
// Timber.d("setting some items")
if (customViewType == null) {
recentItems = if (isOnFirstPage || !updatePageCount) {
newItems
} else {
recentItems + newItems
}
} else {
recentItems + newItems
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)
withContext(Dispatchers.Main) {
controller?.showLists(recentItems, hasNewItems, shouldMoveToTop)
shouldMoveToTop = false
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,7 +494,10 @@ class RecentsPresenter(
}
fun requestNext() {
getRecents(true)
if (!isLoading) {
isLoading = true
getRecents(true)
}
}
companion object {
@ -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)