From a2a0a7e79eba6f1a59a94a1a2053c681c91a560a Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 21 Jun 2024 10:15:15 +0700 Subject: [PATCH] chore(recents): Use sql query to filter scanlators pt.2 --- .../data/database/queries/RawQueries.kt | 70 ++++++++++++------- .../tachiyomi/ui/recents/RecentsPresenter.kt | 3 +- .../tachiyomi/util/chapter/ChapterFilter.kt | 11 --- .../util/chapter/ChapterSourceSync.kt | 12 +++- .../sqldelight/tachiyomi/data/chapters.sq | 55 +++++++++++++++ 5 files changed, 113 insertions(+), 38 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/RawQueries.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/RawQueries.kt index 19a5d7d39e..f6068ec5a6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/RawQueries.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/RawQueries.kt @@ -40,6 +40,7 @@ fun limitAndOffset(endless: Boolean, isResuming: Boolean, offset: Int): String { } } +// TODO: Migrate to SQLDelight /** * 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 @@ -52,18 +53,27 @@ fun getRecentHistoryUngrouped( isResuming: Boolean, ) = """ - 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} - AND ${History.TABLE}.${History.COL_LAST_READ} > 0 - AND lower(${Manga.TABLE}.${Manga.COL_TITLE}) LIKE '%$search%' - ORDER BY ${History.TABLE}.${History.COL_LAST_READ} DESC + SELECT + M.url AS mangaUrl, + M.*, + C.*, + H.* + 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 + AND H.history_last_read > 0 + LEFT JOIN scanlators_view AS S + ON C.manga_id = S.manga_id + AND ifnull(C.scanlator, 'N/A') = ifnull(S.name, '//') + WHERE lower(M.title) LIKE '%$search%' + AND S.name IS NULL + ORDER BY H.history_last_read DESC ${limitAndOffset(true, isResuming, offset)} """ +// TODO: Migrate to SQLDelight /** * 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 @@ -76,22 +86,34 @@ fun getRecentMangasLimitQuery( isResuming: Boolean, ) = """ - 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} + SELECT + M.url AS mangaUrl, + M.*, + C.*, + H.* + 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 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} - AND max_last_read.${History.COL_CHAPTER_ID} = ${History.TABLE}.${History.COL_CHAPTER_ID} - AND max_last_read.${History.COL_LAST_READ} > 0 - AND lower(${Manga.TABLE}.${Manga.COL_TITLE}) LIKE '%$search%' - ORDER BY max_last_read.${History.COL_LAST_READ} DESC + SELECT + C2.manga_id AS manga_id, + C2._id AS history_chapter_id, + MAX(H2.history_last_read) AS history_last_read + FROM chapters AS C2 JOIN history AS H2 + ON C2._id = H2.history_chapter_id + GROUP BY C2.manga_id + ) AS max_last_read + ON C.manga_id = max_last_read.manga_id + AND max_last_read.history_chapter_id = H.history_chapter_id + AND max_last_read.history_last_read > 0 + LEFT JOIN scanlators_view AS S + ON C.manga_id = S.manga_id + AND ifnull(C.scanlator, 'N/A') = ifnull(S.name, '//') + WHERE lower(M.title) LIKE '%$search%' + AND S.name IS NULL + ORDER BY max_last_read.history_last_read DESC ${limitAndOffset(true, isResuming, offset)} """ diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentsPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentsPresenter.kt index 5d3308b9a4..710ac27497 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentsPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recents/RecentsPresenter.kt @@ -17,7 +17,6 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.ui.base.presenter.BaseCoroutinePresenter import eu.kanade.tachiyomi.util.chapter.ChapterFilter -import eu.kanade.tachiyomi.util.chapter.ChapterFilter.Companion.filterChaptersByScanlators import eu.kanade.tachiyomi.util.chapter.ChapterSort import eu.kanade.tachiyomi.util.system.executeOnIO import eu.kanade.tachiyomi.util.system.launchIO @@ -205,7 +204,7 @@ class RecentsPresenter( val manga = mchs.first().manga val chapters = mchs.map { mch -> ChapterHistory(mch.chapter, mch.history) - }.filterChaptersByScanlators(manga) + } extraCount += mchs.size - chapters.size if (chapters.isEmpty()) return@mapNotNull null val lastAmount = if (groupChaptersHistory == GroupType.ByDay) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterFilter.kt b/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterFilter.kt index f8dba036df..ba5ef6c351 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterFilter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterFilter.kt @@ -81,15 +81,4 @@ class ChapterFilter(val preferences: PreferencesHelper = Injekt.get(), val downl return filteredChapters } - - companion object { - /** filters chapters for scanlators */ - @Deprecated("Filter it from SQL instead if possible") - fun List.filterChaptersByScanlators(manga: Manga): List { - return manga.filtered_scanlators?.let { filteredScanlatorString -> - val filteredScanlators = ChapterUtil.getScanlators(filteredScanlatorString) - filter { ChapterUtil.getScanlators(it.scanlator).none { group -> filteredScanlators.contains(group) } } - } ?: this - } - } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterSourceSync.kt b/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterSourceSync.kt index 805b48c999..7b5a72dfe2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterSourceSync.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterSourceSync.kt @@ -6,7 +6,6 @@ import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.online.HttpSource -import eu.kanade.tachiyomi.util.chapter.ChapterFilter.Companion.filterChaptersByScanlators import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy @@ -203,6 +202,17 @@ suspend fun syncChaptersWithSource( ) } +private fun List.filterChaptersByScanlators(manga: Manga): List { + if (manga.filtered_scanlators == null) return this + + return this.filter { chapter -> + ChapterUtil.getScanlators(chapter.scanlator) + .none { group -> + ChapterUtil.getScanlators(manga.filtered_scanlators).contains(group) + } + } +} + // checks if the chapter in db needs updated private fun shouldUpdateDbChapter(dbChapter: Chapter, sourceChapter: Chapter): Boolean { return dbChapter.scanlator != sourceChapter.scanlator || diff --git a/data/src/commonMain/sqldelight/tachiyomi/data/chapters.sq b/data/src/commonMain/sqldelight/tachiyomi/data/chapters.sq index 5e2043e006..e1e25e063d 100644 --- a/data/src/commonMain/sqldelight/tachiyomi/data/chapters.sq +++ b/data/src/commonMain/sqldelight/tachiyomi/data/chapters.sq @@ -52,6 +52,61 @@ AND ( ORDER BY C.date_fetch DESC LIMIT :limit OFFSET :offset; +getRecentsUngrouped: +SELECT + M.url AS mangaUrl, + M.*, + C.*, + H.* +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 +AND H.history_last_read > 0 +LEFT JOIN scanlators_view AS S +ON C.manga_id = S.manga_id +AND ifnull(C.scanlator, 'N/A') = ifnull(S.name, '//') -- I assume if it's N/A it shouldn't be filtered +WHERE lower(M.title) LIKE :search +AND ( + :apply_filter = 0 OR S.name IS NULL +) +ORDER BY H.history_last_read DESC +LIMIT :limit OFFSET :offset; + +getRecentsBySeries: +SELECT + M.url AS mangaUrl, + M.*, + C.*, + H.* +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 +JOIN ( + SELECT + C2.manga_id AS manga_id, + C2._id AS history_chapter_id, + MAX(H2.history_last_read) AS history_last_read + FROM chapters AS C2 JOIN history AS H2 + ON C2._id = H2.history_chapter_id + GROUP BY C2.manga_id +) AS max_last_read +ON C.manga_id = max_last_read.manga_id +AND max_last_read.history_chapter_id = H.history_chapter_id +AND max_last_read.history_last_read > 0 +LEFT JOIN scanlators_view AS S +ON C.manga_id = S.manga_id +AND ifnull(C.scanlator, 'N/A') = ifnull(S.name, '//') -- I assume if it's N/A it shouldn't be filtered +WHERE lower(M.title) LIKE :search +AND ( + :apply_filter = 0 OR S.name IS NULL +) +ORDER BY max_last_read.history_last_read DESC +LIMIT :limit OFFSET :offset; + getScanlatorsByMangaId: SELECT scanlator FROM chapters