refactor: Use SQL to get lastRead and lastFetch instead

Following Android's SQLite best practice, nesting sql instead of nesting functions.
This commit is contained in:
Ahmad Ansori Palembani 2024-06-17 10:12:58 +07:00
parent 1ddc488b17
commit 8d9e5813a0
Signed by: null2264
GPG key ID: BA64F8B60AF3EFB6
6 changed files with 70 additions and 78 deletions

View file

@ -1,19 +1,18 @@
package eu.kanade.tachiyomi.data.database.models
import eu.kanade.tachiyomi.data.database.updateStrategyAdapter
import eu.kanade.tachiyomi.source.model.UpdateStrategy
import kotlin.math.roundToInt
class LibraryManga : MangaImpl() {
var unread: Int = 0
var read: Int = 0
var category: Int = 0
var bookmarkCount: Int = 0
var totalChapters: Int = 0
data class LibraryManga(
var unread: Int = 0,
var read: Int = 0,
var category: Int = 0,
var bookmarkCount: Int = 0,
var totalChapters: Int = 0,
var latestUpdate: Int = 0,
var lastRead: Int = 0,
var lastFetch: Int = 0,
) : MangaImpl() {
val hasRead
get() = read > 0
@ -55,7 +54,10 @@ class LibraryManga : MangaImpl() {
total: Long,
readCount: Double,
bookmarkCount: Double,
categoryId: Long
categoryId: Long,
latestUpdate: Long,
lastRead: Long,
lastFetch: Long,
): LibraryManga = createBlank(categoryId.toInt()).apply {
this.id = id
this.source = source
@ -80,6 +82,9 @@ class LibraryManga : MangaImpl() {
this.unread = maxOf((total - readCount).roundToInt(), 0)
this.totalChapters = readCount.roundToInt()
this.bookmarkCount = bookmarkCount.roundToInt()
this.latestUpdate = latestUpdate.toInt()
this.lastRead = lastRead.toInt()
this.lastFetch = lastFetch.toInt()
}
}
}

View file

@ -185,26 +185,6 @@ interface MangaQueries : DbProvider {
)
.prepare()
fun getLastReadManga() = db.get()
.listOfObjects(Manga::class.java)
.withQuery(
RawQuery.builder()
.query(getLastReadMangaQuery())
.observesTables(MangaTable.TABLE)
.build(),
)
.prepare()
fun getLastFetchedManga() = db.get()
.listOfObjects(Manga::class.java)
.withQuery(
RawQuery.builder()
.query(getLastFetchedMangaQuery())
.observesTables(MangaTable.TABLE)
.build(),
)
.prepare()
fun getTotalChapterManga() = db.get().listOfObjects(Manga::class.java)
.withQuery(RawQuery.builder().query(getTotalChapterMangaQuery()).observesTables(MangaTable.TABLE).build()).prepare()

View file

@ -46,6 +46,7 @@ import eu.kanade.tachiyomi.util.mapStatus
import eu.kanade.tachiyomi.util.system.executeOnIO
import eu.kanade.tachiyomi.util.system.launchIO
import eu.kanade.tachiyomi.util.system.launchUI
import eu.kanade.tachiyomi.util.system.withIOContext
import eu.kanade.tachiyomi.util.system.withUIContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -75,9 +76,10 @@ class LibraryPresenter(
private val trackManager: TrackManager = Injekt.get(),
) : BaseCoroutinePresenter<LibraryController>(), DownloadQueue.DownloadListener {
private val getLibraryManga: GetLibraryManga by injectLazy()
private val getChapters: GetChapters by injectLazy()
private val libraryManga: List<LibraryManga> = emptyList()
private val context = preferences.context
private val viewContext
get() = view?.view?.context
@ -169,8 +171,8 @@ class LibraryPresenter(
Date().time >= preferences.lastLibrarySuggestion().get() + TimeUnit.HOURS.toMillis(2)
) {
// Doing this instead of a job in case the app isn't used often
presenterScope.launchIO {
setSearchSuggestion(preferences, getLibraryManga, sourceManager)
presenterScope.launch {
withIOContext { setSearchSuggestion(preferences, getLibraryManga, sourceManager) }
withUIContext { view?.setTitle() }
}
}
@ -195,7 +197,7 @@ class LibraryPresenter(
categories = lastCategories ?: db.getCategories().executeAsBlocking().toMutableList()
}
presenterScope.launch {
val (library, hiddenItems) = withContext(Dispatchers.IO) { getLibraryFromDB() }
val (library, hiddenItems) = withIOContext { getLibraryFromDB() }
setDownloadCount(library)
setUnreadBadge(library)
setSourceLanguage(library)
@ -598,16 +600,6 @@ class LibraryPresenter(
* @param itemList the map to sort.
*/
private fun applySort(itemList: List<LibraryItem>): List<LibraryItem> {
val lastReadManga by lazy {
var counter = 0
db.getLastReadManga().executeAsBlocking().associate { it.id!! to counter++ }
}
val lastFetchedManga by lazy {
var counter = 0
db.getLastFetchedManga().executeAsBlocking().associate { it.id!! to counter++ }
}
val sortFn: (LibraryItem, LibraryItem) -> Int = { i1, i2 ->
if (i1.header.category.id == i2.header.category.id) {
val category = i1.header.category
@ -630,21 +622,13 @@ class LibraryPresenter(
else -> i1.manga.unread.compareTo(i2.manga.unread)
}
LibrarySort.LastRead -> {
val manga1LastRead =
lastReadManga[i1.manga.id!!] ?: lastReadManga.size
val manga2LastRead =
lastReadManga[i2.manga.id!!] ?: lastReadManga.size
manga1LastRead.compareTo(manga2LastRead)
i1.manga.lastRead.compareTo(i2.manga.lastRead)
}
LibrarySort.TotalChapters -> {
i1.manga.totalChapters.compareTo(i2.manga.totalChapters)
}
LibrarySort.DateFetched -> {
val manga1LastRead =
lastFetchedManga[i1.manga.id!!] ?: lastFetchedManga.size
val manga2LastRead =
lastFetchedManga[i2.manga.id!!] ?: lastFetchedManga.size
manga1LastRead.compareTo(manga2LastRead)
i1.manga.lastFetch.compareTo(i2.manga.lastFetch)
}
LibrarySort.DateAdded -> i2.manga.date_added.compareTo(i1.manga.date_added)
LibrarySort.DragAndDrop -> {

View file

@ -29,23 +29,3 @@ CREATE INDEX library_favorite_index ON mangas(favorite) WHERE favorite = 1;
findAll:
SELECT *
FROM mangas;
getLastRead:
SELECT M.*, max(H.history_last_read) AS max
FROM mangas AS M
JOIN chapters AS C
ON M._id = C.manga_id
JOIN history AS H
ON C._id = H.history_chapter_id
WHERE M.favorite = 1
GROUP BY M._id
ORDER BY max DESC;
getLastFetched:
SELECT M.*, max(C.date_fetch) AS max
FROM mangas AS M
JOIN chapters AS C
ON M._id = C.manga_id
WHERE M.favorite = 1
GROUP BY M._id
ORDER BY max DESC;

View file

@ -0,0 +1,35 @@
DROP VIEW IF EXISTS library_view;
CREATE VIEW library_view AS
SELECT
M.*,
coalesce(C.total, 0) AS total,
coalesce(C.read_count, 0) AS has_read,
coalesce(C.bookmark_count, 0) AS bookmark_count,
coalesce(MC.category_id, 0) AS category,
coalesce(C.latestUpload, 0) AS latestUpload,
coalesce(C.lastRead, 0) AS lastRead,
coalesce(C.lastFetch, 0) AS lastFetch
FROM mangas AS M
LEFT JOIN (
SELECT
chapters.manga_id,
count(*) AS total,
sum(read) AS read_count,
sum(bookmark) AS bookmark_count,
coalesce(max(chapters.date_upload), 0) AS latestUpload,
coalesce(max(history.history_last_read), 0) AS lastRead,
coalesce(max(chapters.date_fetch), 0) AS lastFetch
FROM chapters
LEFT JOIN scanlators_view AS filtered_scanlators
ON chapters.manga_id = filtered_scanlators.manga_id
AND ifnull(chapters.scanlator, 'N/A') = ifnull(filtered_scanlators.name, '/<INVALID>/')
LEFT JOIN history
ON chapters._id = history.history_chapter_id
WHERE filtered_scanlators.name IS NULL
GROUP BY chapters.manga_id
) AS C
ON M._id = C.manga_id
LEFT JOIN (SELECT * FROM mangas_categories) AS MC
ON MC.manga_id = M._id
WHERE M.favorite = 1
ORDER BY M.title;

View file

@ -4,18 +4,26 @@ SELECT
coalesce(C.total, 0) AS total,
coalesce(C.read_count, 0) AS has_read,
coalesce(C.bookmark_count, 0) AS bookmark_count,
coalesce(MC.category_id, 0) AS category
coalesce(MC.category_id, 0) AS category,
coalesce(C.latestUpload, 0) AS latestUpload,
coalesce(C.lastRead, 0) AS lastRead,
coalesce(C.lastFetch, 0) AS lastFetch
FROM mangas AS M
LEFT JOIN (
SELECT
chapters.manga_id,
count(*) AS total,
sum(read) AS read_count,
sum(bookmark) AS bookmark_count
sum(bookmark) AS bookmark_count,
coalesce(max(chapters.date_upload), 0) AS latestUpload,
coalesce(max(history.history_last_read), 0) AS lastRead,
coalesce(max(chapters.date_fetch), 0) AS lastFetch
FROM chapters
LEFT JOIN scanlators_view AS filtered_scanlators
ON chapters.manga_id = filtered_scanlators.manga_id
AND ifnull(chapters.scanlator, 'N/A') = ifnull(filtered_scanlators.name, '/<INVALID>/') -- I assume if it's N/A it shouldn't be filtered
LEFT JOIN history
ON chapters._id = history.history_chapter_id
WHERE filtered_scanlators.name IS NULL
GROUP BY chapters.manga_id
) AS C