Tweak library view (#8240)

- Move category join to improve performance
- Move bookmark calculation into query
- Move unread calculation into domain

(cherry picked from commit 8d97b980e354d50a7682e87677ef336833b760fe)

# Conflicts:
#	app/build.gradle.kts
#	app/src/main/java/eu/kanade/data/manga/MangaMapper.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt
#	app/src/main/sqldelight/migrations/22.sqm
#	app/src/main/sqldelight/view/libraryView.sq
This commit is contained in:
Andreas 2022-10-18 22:33:26 +02:00 committed by Jobobby04
parent a31e8282cb
commit fed8ef09af
6 changed files with 34 additions and 48 deletions

View File

@ -34,12 +34,13 @@ private val mapper = { cursor: SqlCursor ->
cursor.getString(18)?.let(listOfStringsAndAdapter::decode), cursor.getString(18)?.let(listOfStringsAndAdapter::decode),
updateStrategyAdapter.decode(cursor.getLong(19)!!), updateStrategyAdapter.decode(cursor.getLong(19)!!),
), ),
unreadCount = cursor.getLong(20)!!, totalChapters = cursor.getLong(20)!!,
readCount = cursor.getLong(21)!!, readCount = cursor.getLong(21)!!,
latestUpload = cursor.getLong(22)!!, latestUpload = cursor.getLong(22)!!,
chapterFetchedAt = cursor.getLong(23)!!, chapterFetchedAt = cursor.getLong(23)!!,
lastRead = cursor.getLong(24)!!, lastRead = cursor.getLong(24)!!,
category = cursor.getLong(25)!!, bookmarkCount = cursor.getLong(25)!!,
category = cursor.getLong(26)!!,
) )
} }
@ -50,15 +51,14 @@ class LibraryQuery(val driver: SqlDriver) : Query<LibraryManga>(copyOnWriteList(
""" """
SELECT SELECT
M.*, M.*,
coalesce(C.total - C.readCount, 0) AS unreadCount, coalesce(C.total, 0) AS totalCount,
coalesce(C.readCount, 0) AS readCount, coalesce(C.readCount, 0) AS readCount,
coalesce(C.latestUpload, 0) AS latestUpload, coalesce(C.latestUpload, 0) AS latestUpload,
coalesce(C.fetchedAt, 0) AS chapterFetchedAt, coalesce(C.fetchedAt, 0) AS chapterFetchedAt,
coalesce(C.lastRead, 0) AS lastRead, coalesce(C.lastRead, 0) AS lastRead,
COALESCE(MC.category_id, 0) AS category coalesce(C.bookmarkCount, 0) AS bookmarkCount,
coalesce(MC.category_id, 0) AS category
FROM mangas M FROM mangas M
LEFT JOIN mangas_categories AS MC
ON MC.manga_id = M._id
LEFT JOIN( LEFT JOIN(
SELECT SELECT
chapters.manga_id, chapters.manga_id,
@ -66,23 +66,27 @@ class LibraryQuery(val driver: SqlDriver) : Query<LibraryManga>(copyOnWriteList(
sum(read) AS readCount, sum(read) AS readCount,
coalesce(max(chapters.date_upload), 0) AS latestUpload, coalesce(max(chapters.date_upload), 0) AS latestUpload,
coalesce(max(history.last_read), 0) AS lastRead, coalesce(max(history.last_read), 0) AS lastRead,
coalesce(max(chapters.date_fetch), 0) AS fetchedAt coalesce(max(chapters.date_fetch), 0) AS fetchedAt,
sum(chapters.bookmark) AS bookmarkCount
FROM chapters FROM chapters
LEFT JOIN history LEFT JOIN history
ON chapters._id = history.chapter_id ON chapters._id = history.chapter_id
GROUP BY chapters.manga_id GROUP BY chapters.manga_id
) AS C ) AS C
ON M._id = C.manga_id ON M._id = C.manga_id
LEFT JOIN mangas_categories AS MC
ON MC.manga_id = M._id
WHERE M.favorite = 1 AND M.source <> $MERGED_SOURCE_ID WHERE M.favorite = 1 AND M.source <> $MERGED_SOURCE_ID
UNION UNION
SELECT SELECT
M.*, M.*,
coalesce(C.total - C.readCount, 0) AS unreadCount, coalesce(C.total, 0) AS totalCount,
coalesce(C.readCount, 0) AS readCount, coalesce(C.readCount, 0) AS readCount,
coalesce(C.latestUpload, 0) AS latestUpload, coalesce(C.latestUpload, 0) AS latestUpload,
coalesce(C.fetchedAt, 0) AS chapterFetchedAt, coalesce(C.fetchedAt, 0) AS chapterFetchedAt,
coalesce(C.lastRead, 0) AS lastRead, coalesce(C.lastRead, 0) AS lastRead,
COALESCE(MC.category_id, 0) AS category coalesce(C.bookmarkCount, 0) AS bookmarkCount,
coalesce(MC.category_id, 0) AS category
FROM mangas M FROM mangas M
LEFT JOIN ( LEFT JOIN (
SELECT merged.manga_id,merged.merge_id SELECT merged.manga_id,merged.merge_id
@ -90,8 +94,6 @@ class LibraryQuery(val driver: SqlDriver) : Query<LibraryManga>(copyOnWriteList(
GROUP BY merged.merge_id GROUP BY merged.merge_id
) as ME ) as ME
ON ME.merge_id = M._id ON ME.merge_id = M._id
LEFT JOIN mangas_categories AS MC
ON MC.manga_id = M._id
LEFT JOIN( LEFT JOIN(
SELECT SELECT
ME.merge_id, ME.merge_id,
@ -99,7 +101,8 @@ class LibraryQuery(val driver: SqlDriver) : Query<LibraryManga>(copyOnWriteList(
sum(read) AS readCount, sum(read) AS readCount,
coalesce(max(chapters.date_upload), 0) AS latestUpload, coalesce(max(chapters.date_upload), 0) AS latestUpload,
coalesce(max(history.last_read), 0) AS lastRead, coalesce(max(history.last_read), 0) AS lastRead,
coalesce(max(chapters.date_fetch), 0) AS fetchedAt coalesce(max(chapters.date_fetch), 0) AS fetchedAt,
sum(chapters.bookmark) AS bookmarkCount
FROM chapters FROM chapters
LEFT JOIN history LEFT JOIN history
ON chapters._id = history.chapter_id ON chapters._id = history.chapter_id
@ -108,6 +111,8 @@ class LibraryQuery(val driver: SqlDriver) : Query<LibraryManga>(copyOnWriteList(
GROUP BY ME.merge_id GROUP BY ME.merge_id
) AS C ) AS C
ON ME.merge_id = C.merge_id ON ME.merge_id = C.merge_id
LEFT JOIN mangas_categories AS MC
ON MC.manga_id = M._id
WHERE M.favorite = 1 AND M.source = $MERGED_SOURCE_ID; WHERE M.favorite = 1 AND M.source = $MERGED_SOURCE_ID;
""".trimIndent(), """.trimIndent(),
1, 1,

View File

@ -33,8 +33,8 @@ val mangaMapper: (Long, Long, String, String?, String?, String?, List<String>?,
) )
} }
val libraryManga: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, List<String>?, UpdateStrategy, Long, Long, Long, Long, Long, Long) -> LibraryManga = val libraryManga: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, List<String>?, UpdateStrategy, Long, Long, Long, Long, Long, Long, Long) -> LibraryManga =
{ id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, nextUpdate, initialized, viewerFlags, chapterFlags, coverLastModified, dateAdded, filteredScanlators, updateStrategy, unreadCount, readCount, latestUpload, chapterFetchedAt, lastRead, category -> { id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, nextUpdate, initialized, viewerFlags, chapterFlags, coverLastModified, dateAdded, filteredScanlators, updateStrategy, totalCount, readCount, latestUpload, chapterFetchedAt, lastRead, bookmarkCount, category ->
LibraryManga( LibraryManga(
manga = mangaMapper( manga = mangaMapper(
id, id,
@ -59,8 +59,9 @@ val libraryManga: (Long, Long, String, String?, String?, String?, List<String>?,
updateStrategy, updateStrategy,
), ),
category = category, category = category,
unreadCount = unreadCount, totalChapters = totalCount,
readCount = readCount, readCount = readCount,
bookmarkCount = bookmarkCount,
latestUpload = latestUpload, latestUpload = latestUpload,
chapterFetchedAt = chapterFetchedAt, chapterFetchedAt = chapterFetchedAt,
lastRead = lastRead, lastRead = lastRead,

View File

@ -19,7 +19,6 @@ import eu.kanade.domain.category.interactor.SetMangaCategories
import eu.kanade.domain.category.interactor.SetSortModeForCategory import eu.kanade.domain.category.interactor.SetSortModeForCategory
import eu.kanade.domain.category.interactor.UpdateCategory import eu.kanade.domain.category.interactor.UpdateCategory
import eu.kanade.domain.category.repository.CategoryRepository import eu.kanade.domain.category.repository.CategoryRepository
import eu.kanade.domain.chapter.interactor.GetBookmarkedChaptersByMangaId
import eu.kanade.domain.chapter.interactor.GetChapter import eu.kanade.domain.chapter.interactor.GetChapter
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
import eu.kanade.domain.chapter.interactor.SetMangaDefaultChapterFlags import eu.kanade.domain.chapter.interactor.SetMangaDefaultChapterFlags
@ -111,7 +110,6 @@ class DomainModule : InjektModule {
addSingletonFactory<ChapterRepository> { ChapterRepositoryImpl(get()) } addSingletonFactory<ChapterRepository> { ChapterRepositoryImpl(get()) }
addFactory { GetChapter(get()) } addFactory { GetChapter(get()) }
addFactory { GetChapterByMangaId(get()) } addFactory { GetChapterByMangaId(get()) }
addFactory { GetBookmarkedChaptersByMangaId(get()) }
addFactory { UpdateChapter(get()) } addFactory { UpdateChapter(get()) }
addFactory { SetReadStatus(get(), get(), get(), get(), get()) } addFactory { SetReadStatus(get(), get(), get(), get(), get()) }
addFactory { ShouldUpdateDbChapter() } addFactory { ShouldUpdateDbChapter() }

View File

@ -1,20 +0,0 @@
package eu.kanade.domain.chapter.interactor
import eu.kanade.domain.chapter.model.Chapter
import eu.kanade.domain.chapter.repository.ChapterRepository
import eu.kanade.tachiyomi.util.system.logcat
import logcat.LogPriority
class GetBookmarkedChaptersByMangaId(
private val chapterRepository: ChapterRepository,
) {
suspend fun await(mangaId: Long): List<Chapter> {
return try {
chapterRepository.getBookmarkedChaptersByMangaId(mangaId)
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
emptyList()
}
}
}

View File

@ -5,15 +5,20 @@ import eu.kanade.domain.manga.model.Manga
data class LibraryManga( data class LibraryManga(
val manga: Manga, val manga: Manga,
val category: Long, val category: Long,
val unreadCount: Long, val totalChapters: Long,
val readCount: Long, val readCount: Long,
val bookmarkCount: Long,
val latestUpload: Long, val latestUpload: Long,
val chapterFetchedAt: Long, val chapterFetchedAt: Long,
val lastRead: Long, val lastRead: Long,
) { ) {
val id: Long = manga.id val id: Long = manga.id
val totalChapters = readCount + unreadCount val unreadCount
get() = totalChapters - readCount
val hasBookmarks
get() = bookmarkCount > 0
val hasStarted = readCount > 0 val hasStarted = readCount > 0
} }

View File

@ -22,7 +22,6 @@ import eu.kanade.domain.base.BasePreferences
import eu.kanade.domain.category.interactor.GetCategories import eu.kanade.domain.category.interactor.GetCategories
import eu.kanade.domain.category.interactor.SetMangaCategories import eu.kanade.domain.category.interactor.SetMangaCategories
import eu.kanade.domain.category.model.Category import eu.kanade.domain.category.model.Category
import eu.kanade.domain.chapter.interactor.GetBookmarkedChaptersByMangaId
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
import eu.kanade.domain.chapter.interactor.GetMergedChapterByMangaId import eu.kanade.domain.chapter.interactor.GetMergedChapterByMangaId
import eu.kanade.domain.chapter.interactor.SetReadStatus import eu.kanade.domain.chapter.interactor.SetReadStatus
@ -126,7 +125,6 @@ class LibraryPresenter(
private val getLibraryManga: GetLibraryManga = Injekt.get(), private val getLibraryManga: GetLibraryManga = Injekt.get(),
private val getTracks: GetTracks = Injekt.get(), private val getTracks: GetTracks = Injekt.get(),
private val getCategories: GetCategories = Injekt.get(), private val getCategories: GetCategories = Injekt.get(),
private val getBookmarkedChaptersByMangaId: GetBookmarkedChaptersByMangaId = Injekt.get(),
private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(), private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
private val setReadStatus: SetReadStatus = Injekt.get(), private val setReadStatus: SetReadStatus = Injekt.get(),
private val updateManga: UpdateManga = Injekt.get(), private val updateManga: UpdateManga = Injekt.get(),
@ -315,14 +313,13 @@ class LibraryPresenter(
val filterFnBookmarked: (LibraryItem) -> Boolean = bookmarked@{ item -> val filterFnBookmarked: (LibraryItem) -> Boolean = bookmarked@{ item ->
if (filterBookmarked == State.IGNORE.value) return@bookmarked true if (filterBookmarked == State.IGNORE.value) return@bookmarked true
return@bookmarked runBlocking {
val isBookmarked = getBookmarkedChaptersByMangaId.await(item.libraryManga.manga.id).isNotEmpty()
return@runBlocking if (filterBookmarked == State.INCLUDE.value) { val hasBookmarks = item.libraryManga.hasBookmarks
isBookmarked
return@bookmarked if (filterBookmarked == State.INCLUDE.value) {
hasBookmarks
} else { } else {
!isBookmarked !hasBookmarks
}
} }
} }