mirror of
https://github.com/null2264/yokai.git
synced 2025-06-21 02:34:39 +00:00
refactor(recents): Fully migrate recents to use SQLDelight
This commit is contained in:
parent
79929b395e
commit
354ed7ce8a
10 changed files with 354 additions and 86 deletions
|
@ -39,16 +39,18 @@ interface History : Serializable {
|
|||
this.chapter_id = chapter.id!!
|
||||
}
|
||||
|
||||
fun create(): History = HistoryImpl()
|
||||
|
||||
fun mapper(
|
||||
id: Long,
|
||||
chapterId: Long,
|
||||
lastRead: Long,
|
||||
timeRead: Long
|
||||
) = HistoryImpl().apply {
|
||||
lastRead: Long?,
|
||||
timeRead: Long?,
|
||||
): History = HistoryImpl().apply {
|
||||
this.id = id
|
||||
this.chapter_id = chapterId
|
||||
this.last_read = lastRead
|
||||
this.time_read = timeRead
|
||||
this.last_read = lastRead ?: 0L
|
||||
this.time_read = timeRead ?: 0L
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,100 @@ data class MangaChapterHistory(val manga: Manga, val chapter: Chapter, val histo
|
|||
|
||||
companion object {
|
||||
fun createBlank() = MangaChapterHistory(MangaImpl(), ChapterImpl(), HistoryImpl())
|
||||
|
||||
fun mapper(
|
||||
// manga
|
||||
mangaId: Long,
|
||||
source: Long,
|
||||
mangaUrl: String,
|
||||
artist: String?,
|
||||
author: String?,
|
||||
description: String?,
|
||||
genre: String?,
|
||||
title: String,
|
||||
status: Long,
|
||||
thumbnailUrl: String?,
|
||||
favorite: Boolean,
|
||||
lastUpdate: Long?,
|
||||
initialized: Boolean,
|
||||
viewer: Long,
|
||||
hideTitle: Boolean,
|
||||
chapterFlags: Long,
|
||||
dateAdded: Long?,
|
||||
filteredScanlators: String?,
|
||||
updateStrategy: Long,
|
||||
coverLastModified: Long,
|
||||
// chapter
|
||||
chapterId: Long?,
|
||||
_mangaId: Long?,
|
||||
chapterUrl: String?,
|
||||
name: String?,
|
||||
scanlator: String?,
|
||||
read: Boolean?,
|
||||
bookmark: Boolean?,
|
||||
lastPageRead: Long?,
|
||||
pagesLeft: Long?,
|
||||
chapterNumber: Double?,
|
||||
sourceOrder: Long?,
|
||||
dateFetch: Long?,
|
||||
dateUpload: Long?,
|
||||
// history
|
||||
historyId: Long?,
|
||||
historyChapterId: Long?,
|
||||
historyLastRead: Long?,
|
||||
historyTimeRead: Long?,
|
||||
) = MangaChapterHistory(
|
||||
Manga.mapper(
|
||||
id = mangaId,
|
||||
source = source,
|
||||
url = mangaUrl,
|
||||
artist = artist,
|
||||
author = author,
|
||||
description = description,
|
||||
genre = genre,
|
||||
title = title,
|
||||
status = status,
|
||||
thumbnailUrl = thumbnailUrl,
|
||||
favorite = favorite,
|
||||
lastUpdate = lastUpdate,
|
||||
initialized = initialized,
|
||||
viewerFlags = viewer,
|
||||
hideTitle = hideTitle,
|
||||
chapterFlags = chapterFlags,
|
||||
dateAdded = dateAdded,
|
||||
filteredScanlators = filteredScanlators,
|
||||
updateStrategy = updateStrategy,
|
||||
coverLastModified = coverLastModified,
|
||||
),
|
||||
chapterId?.let {
|
||||
Chapter.mapper(
|
||||
id = chapterId,
|
||||
mangaId = _mangaId!!,
|
||||
url = chapterUrl!!,
|
||||
name = name!!,
|
||||
scanlator = scanlator!!,
|
||||
read = read!!,
|
||||
bookmark = bookmark!!,
|
||||
lastPageRead = lastPageRead!!,
|
||||
pagesLeft = pagesLeft!!,
|
||||
chapterNumber = chapterNumber!!,
|
||||
sourceOrder = sourceOrder!!,
|
||||
dateFetch = dateFetch!!,
|
||||
dateUpload = dateUpload!!,
|
||||
)
|
||||
} ?: Chapter.create(),
|
||||
historyId?.let {
|
||||
History.mapper(
|
||||
id = historyId,
|
||||
chapterId = historyChapterId!!,
|
||||
lastRead = historyLastRead,
|
||||
timeRead = historyTimeRead,
|
||||
)
|
||||
} ?: History.create().apply {
|
||||
historyLastRead?.let { last_read = it }
|
||||
historyTimeRead?.let { time_read = it }
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,22 +52,6 @@ interface HistoryQueries : DbProvider {
|
|||
.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 getRecentMangaLimit(search: String = "", offset: Int, isResuming: Boolean) = db.get()
|
||||
.listOfObjects(MangaChapterHistory::class.java)
|
||||
.withQuery(
|
||||
RawQuery.builder()
|
||||
.query(getRecentMangasLimitQuery(search.sqLite, offset, isResuming))
|
||||
.observesTables(HistoryTable.TABLE)
|
||||
.build(),
|
||||
)
|
||||
.withGetResolver(MangaChapterHistoryGetResolver.INSTANCE)
|
||||
.prepare()
|
||||
|
||||
/**
|
||||
* Returns history of manga read during period
|
||||
* @param startDate start date of the period
|
||||
|
@ -85,37 +69,6 @@ interface HistoryQueries : DbProvider {
|
|||
.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 getAllRecentsTypes(
|
||||
search: String = "",
|
||||
includeRead: Boolean,
|
||||
endless: Boolean,
|
||||
offset: Int,
|
||||
isResuming: Boolean,
|
||||
) = db.get()
|
||||
.listOfObjects(MangaChapterHistory::class.java)
|
||||
.withQuery(
|
||||
RawQuery.builder()
|
||||
.query(
|
||||
getAllRecentsType(
|
||||
search.sqLite,
|
||||
includeRead,
|
||||
endless,
|
||||
offset,
|
||||
isResuming,
|
||||
),
|
||||
)
|
||||
// .args(date.time, startDate.time)
|
||||
.observesTables(HistoryTable.TABLE)
|
||||
.build(),
|
||||
)
|
||||
.withGetResolver(MangaChapterHistoryGetResolver.INSTANCE)
|
||||
.prepare()
|
||||
|
||||
fun getHistoryByMangaId(mangaId: Long) = db.get()
|
||||
.listOfObjects(History::class.java)
|
||||
.withQuery(
|
||||
|
|
|
@ -17,7 +17,6 @@ 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.ChapterSort
|
||||
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.toast
|
||||
|
@ -41,9 +40,9 @@ import uy.kohesive.injekt.Injekt
|
|||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import yokai.domain.chapter.interactor.GetChapter
|
||||
import yokai.domain.chapter.interactor.RecentChapter
|
||||
import yokai.domain.chapter.interactor.UpdateChapter
|
||||
import yokai.domain.recents.RecentsPreferences
|
||||
import yokai.domain.recents.interactor.GetRecents
|
||||
import yokai.domain.ui.UiPreferences
|
||||
import yokai.i18n.MR
|
||||
|
||||
|
@ -56,7 +55,7 @@ class RecentsPresenter(
|
|||
private val chapterFilter: ChapterFilter = Injekt.get(),
|
||||
) : BaseCoroutinePresenter<RecentsController>(), DownloadQueue.DownloadListener {
|
||||
private val getChapter: GetChapter by injectLazy()
|
||||
private val recentChapter: RecentChapter by injectLazy()
|
||||
private val getRecents: GetRecents by injectLazy()
|
||||
private val updateChapter: UpdateChapter by injectLazy()
|
||||
|
||||
private var recentsJob: Job? = null
|
||||
|
@ -172,26 +171,29 @@ class RecentsPresenter(
|
|||
var extraCount = 0
|
||||
val cReading: List<MangaChapterHistory> = when (viewType) {
|
||||
RecentsViewType.GroupedAll, RecentsViewType.UngroupedAll -> {
|
||||
db.getAllRecentsTypes(
|
||||
query,
|
||||
getRecents.awaitAll(
|
||||
showRead,
|
||||
true,
|
||||
isEndless,
|
||||
if (isCustom) ENDLESS_LIMIT else pageOffset,
|
||||
!updatePageCount && !isOnFirstPage,
|
||||
).executeOnIO()
|
||||
query,
|
||||
(if (isCustom) ENDLESS_LIMIT else pageOffset).toLong(),
|
||||
)
|
||||
}
|
||||
RecentsViewType.History -> {
|
||||
val items = if (groupChaptersHistory == GroupType.BySeries) {
|
||||
db.getRecentMangaLimit(
|
||||
query,
|
||||
if (isCustom) ENDLESS_LIMIT else pageOffset,
|
||||
getRecents.awaitBySeries(
|
||||
true,
|
||||
!updatePageCount && !isOnFirstPage,
|
||||
query,
|
||||
(if (isCustom) ENDLESS_LIMIT else pageOffset).toLong(),
|
||||
)
|
||||
} else {
|
||||
db.getHistoryUngrouped(
|
||||
query,
|
||||
if (isCustom) ENDLESS_LIMIT else pageOffset,
|
||||
getRecents.awaitUngrouped(
|
||||
true,
|
||||
!updatePageCount && !isOnFirstPage,
|
||||
query,
|
||||
(if (isCustom) ENDLESS_LIMIT else pageOffset).toLong(),
|
||||
)
|
||||
}
|
||||
if (groupChaptersHistory.isByTime) {
|
||||
|
@ -203,7 +205,7 @@ class RecentsPresenter(
|
|||
)
|
||||
val dayOfWeek = Calendar.getInstance().get(Calendar.DAY_OF_WEEK) % 7 + 1
|
||||
dateFormat.calendar.firstDayOfWeek = dayOfWeek
|
||||
items.executeOnIO().groupBy {
|
||||
items.groupBy {
|
||||
val date = it.history.last_read
|
||||
it.manga.id to if (date <= 0L) "-1" else dateFormat.format(Date(date))
|
||||
}
|
||||
|
@ -235,14 +237,14 @@ class RecentsPresenter(
|
|||
}
|
||||
}
|
||||
} else {
|
||||
items.executeOnIO()
|
||||
items
|
||||
}
|
||||
}
|
||||
RecentsViewType.Updates -> {
|
||||
dateFormat.applyPattern("yyyy-MM-dd")
|
||||
dateFormat.calendar.firstDayOfWeek =
|
||||
Calendar.getInstance().get(Calendar.DAY_OF_WEEK)
|
||||
recentChapter.await(
|
||||
getRecents.awaitUpdates(
|
||||
true,
|
||||
!updatePageCount && !isOnFirstPage,
|
||||
query,
|
||||
|
|
|
@ -8,6 +8,7 @@ import uy.kohesive.injekt.api.get
|
|||
import yokai.data.category.CategoryRepositoryImpl
|
||||
import yokai.data.chapter.ChapterRepositoryImpl
|
||||
import yokai.data.extension.repo.ExtensionRepoRepositoryImpl
|
||||
import yokai.data.history.HistoryRepositoryImpl
|
||||
import yokai.data.library.custom.CustomMangaRepositoryImpl
|
||||
import yokai.data.manga.MangaRepositoryImpl
|
||||
import yokai.domain.category.CategoryRepository
|
||||
|
@ -17,7 +18,7 @@ import yokai.domain.chapter.interactor.DeleteChapter
|
|||
import yokai.domain.chapter.interactor.GetAvailableScanlators
|
||||
import yokai.domain.chapter.interactor.GetChapter
|
||||
import yokai.domain.chapter.interactor.InsertChapter
|
||||
import yokai.domain.chapter.interactor.RecentChapter
|
||||
import yokai.domain.recents.interactor.GetRecents
|
||||
import yokai.domain.chapter.interactor.UpdateChapter
|
||||
import yokai.domain.extension.interactor.TrustExtension
|
||||
import yokai.domain.extension.repo.ExtensionRepoRepository
|
||||
|
@ -27,6 +28,7 @@ import yokai.domain.extension.repo.interactor.GetExtensionRepo
|
|||
import yokai.domain.extension.repo.interactor.GetExtensionRepoCount
|
||||
import yokai.domain.extension.repo.interactor.ReplaceExtensionRepo
|
||||
import yokai.domain.extension.repo.interactor.UpdateExtensionRepo
|
||||
import yokai.domain.history.HistoryRepository
|
||||
import yokai.domain.library.custom.CustomMangaRepository
|
||||
import yokai.domain.library.custom.interactor.CreateCustomManga
|
||||
import yokai.domain.library.custom.interactor.DeleteCustomManga
|
||||
|
@ -67,9 +69,12 @@ class DomainModule : InjektModule {
|
|||
addFactory { GetAvailableScanlators(get()) }
|
||||
addFactory { GetChapter(get()) }
|
||||
addFactory { InsertChapter(get()) }
|
||||
addFactory { RecentChapter(get()) }
|
||||
addFactory { UpdateChapter(get()) }
|
||||
|
||||
addSingletonFactory<HistoryRepository> { HistoryRepositoryImpl(get()) }
|
||||
|
||||
addFactory { GetRecents(get(), get()) }
|
||||
|
||||
addSingletonFactory<CategoryRepository> { CategoryRepositoryImpl(get()) }
|
||||
addFactory { GetCategories(get()) }
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package yokai.data.history
|
||||
|
||||
import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
|
||||
import eu.kanade.tachiyomi.util.system.toInt
|
||||
import yokai.data.DatabaseHandler
|
||||
import yokai.domain.history.HistoryRepository
|
||||
|
||||
class HistoryRepositoryImpl(private val handler: DatabaseHandler) : HistoryRepository {
|
||||
override suspend fun getRecentsUngrouped(
|
||||
filterScanlators: Boolean,
|
||||
search: String,
|
||||
limit: Long,
|
||||
offset: Long,
|
||||
): List<MangaChapterHistory> =
|
||||
handler.awaitList { historyQueries.getRecentsUngrouped(search, filterScanlators.toInt().toLong(), limit, offset, MangaChapterHistory::mapper) }
|
||||
|
||||
override suspend fun getRecentsBySeries(
|
||||
filterScanlators: Boolean,
|
||||
search: String,
|
||||
limit: Long,
|
||||
offset: Long,
|
||||
): List<MangaChapterHistory> =
|
||||
handler.awaitList { historyQueries.getRecentsBySeries(search, filterScanlators.toInt().toLong(), limit, offset, MangaChapterHistory::mapper) }
|
||||
|
||||
override suspend fun getRecentsAll(
|
||||
includeRead: Boolean,
|
||||
filterScanlators: Boolean,
|
||||
search: String,
|
||||
limit: Long,
|
||||
offset: Long
|
||||
): List<MangaChapterHistory> =
|
||||
handler.awaitList { historyQueries.getRecentsAll(includeRead.toInt().toLong(), search, filterScanlators.toInt().toLong(), limit, offset, MangaChapterHistory::mapper) }
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package yokai.domain.chapter.interactor
|
||||
|
||||
import eu.kanade.tachiyomi.data.database.models.MangaChapter
|
||||
import yokai.domain.chapter.ChapterRepository
|
||||
import yokai.util.limitAndOffset
|
||||
|
||||
class RecentChapter(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
) {
|
||||
suspend fun await(filterScanlators: Boolean, isResuming: Boolean, search: String = "", offset: Long = 0L): List<MangaChapter> {
|
||||
val (limit, actualOffset) = limitAndOffset(true, isResuming, offset)
|
||||
|
||||
return chapterRepository.getRecents(filterScanlators, search, limit, actualOffset)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package yokai.domain.history
|
||||
|
||||
import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
|
||||
|
||||
interface HistoryRepository {
|
||||
suspend fun getRecentsUngrouped(filterScanlators: Boolean, search: String = "", limit: Long = 25L, offset: Long = 0L): List<MangaChapterHistory>
|
||||
suspend fun getRecentsBySeries(filterScanlators: Boolean, search: String = "", limit: Long = 25L, offset: Long = 0L): List<MangaChapterHistory>
|
||||
suspend fun getRecentsAll(includeRead: Boolean, filterScanlators: Boolean, search: String = "", limit: Long = 25L, offset: Long = 0L): List<MangaChapterHistory>
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package yokai.domain.recents.interactor
|
||||
|
||||
import eu.kanade.tachiyomi.data.database.models.MangaChapter
|
||||
import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
|
||||
import yokai.domain.chapter.ChapterRepository
|
||||
import yokai.domain.history.HistoryRepository
|
||||
import yokai.util.limitAndOffset
|
||||
|
||||
class GetRecents(
|
||||
private val chapterRepository: ChapterRepository,
|
||||
private val historyRepository: HistoryRepository,
|
||||
) {
|
||||
suspend fun awaitUpdates(
|
||||
filterScanlators: Boolean,
|
||||
isResuming: Boolean,
|
||||
search: String = "",
|
||||
offset: Long = 0L,
|
||||
): List<MangaChapter> {
|
||||
val (limit, actualOffset) = limitAndOffset(true, isResuming, offset)
|
||||
|
||||
return chapterRepository.getRecents(filterScanlators, search, limit, actualOffset)
|
||||
}
|
||||
|
||||
suspend fun awaitUngrouped(
|
||||
filterScanlators: Boolean,
|
||||
isResuming: Boolean,
|
||||
search: String = "",
|
||||
offset: Long = 0L,
|
||||
): List<MangaChapterHistory> {
|
||||
val (limit, actualOffset) = limitAndOffset(true, isResuming, offset)
|
||||
|
||||
return historyRepository.getRecentsUngrouped(filterScanlators, search, limit, actualOffset)
|
||||
}
|
||||
|
||||
suspend fun awaitBySeries(
|
||||
filterScanlators: Boolean,
|
||||
isResuming: Boolean,
|
||||
search: String = "",
|
||||
offset: Long = 0L,
|
||||
): List<MangaChapterHistory> {
|
||||
val (limit, actualOffset) = limitAndOffset(true, isResuming, offset)
|
||||
|
||||
return historyRepository.getRecentsBySeries(filterScanlators, search, limit, actualOffset)
|
||||
}
|
||||
|
||||
suspend fun awaitAll(
|
||||
includeRead: Boolean,
|
||||
filterScanlators: Boolean,
|
||||
isEndless: Boolean,
|
||||
isResuming: Boolean,
|
||||
search: String = "",
|
||||
offset: Long = 0L,
|
||||
): List<MangaChapterHistory> {
|
||||
val (limit, actualOffset) = limitAndOffset(isEndless, isResuming, offset)
|
||||
|
||||
return historyRepository.getRecentsAll(includeRead, filterScanlators, search, limit, actualOffset)
|
||||
}
|
||||
}
|
|
@ -32,7 +32,6 @@ LIMIT :limit OFFSET :offset;
|
|||
|
||||
getRecentsBySeries:
|
||||
SELECT
|
||||
M.url AS mangaUrl,
|
||||
M.*,
|
||||
C.*,
|
||||
H.*
|
||||
|
@ -62,3 +61,131 @@ AND (
|
|||
)
|
||||
ORDER BY max_last_read.history_last_read DESC
|
||||
LIMIT :limit OFFSET :offset;
|
||||
|
||||
getRecentsAll: -- AKA insanity
|
||||
SELECT * FROM (
|
||||
SELECT
|
||||
M.*,
|
||||
C.*,
|
||||
H.*
|
||||
FROM (
|
||||
SELECT mangas.*
|
||||
FROM mangas
|
||||
LEFT JOIN (
|
||||
SELECT manga_id, COUNT(*) AS unread
|
||||
FROM chapters
|
||||
WHERE read = 0
|
||||
GROUP BY manga_id
|
||||
) AS C
|
||||
ON _id = C.manga_id
|
||||
WHERE (
|
||||
:include_read = 0 OR C.unread > 0
|
||||
)
|
||||
GROUP BY _id
|
||||
ORDER BY title
|
||||
) 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
|
||||
chapters.manga_id AS manga_id,
|
||||
chapters._id AS history_chapter_id,
|
||||
MAX(history.history_last_read) AS history_last_read
|
||||
FROM chapters JOIN history
|
||||
ON chapters._id = history.history_chapter_id
|
||||
GROUP BY chapters.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, '/<INVALID>/') -- 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
|
||||
)
|
||||
)
|
||||
|
||||
UNION --
|
||||
|
||||
SELECT * FROM (
|
||||
SELECT
|
||||
M.*,
|
||||
C.*,
|
||||
NULL AS history_id,
|
||||
NULL AS history_chapter_id,
|
||||
C.date_fetch AS history_last_read,
|
||||
NULL AS history_time_read
|
||||
FROM (
|
||||
SELECT mangas.*
|
||||
FROM mangas
|
||||
LEFT JOIN (
|
||||
SELECT manga_id, COUNT(*) AS unread
|
||||
FROM chapters
|
||||
WHERE read = 0
|
||||
GROUP BY manga_id
|
||||
) AS C2
|
||||
ON _id = C2.manga_id
|
||||
WHERE (
|
||||
:include_read = 0 OR C2.unread > 0
|
||||
)
|
||||
GROUP BY _id
|
||||
ORDER BY title
|
||||
) 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
|
||||
chapters.manga_id,
|
||||
chapters._id AS history_chapter_id,
|
||||
max(chapters.date_upload)
|
||||
FROM chapters JOIN mangas
|
||||
ON mangas._id = chapters.manga_id
|
||||
WHERE chapters.read = 0
|
||||
GROUP BY chapters.manga_id
|
||||
) AS newest_chapter
|
||||
LEFT JOIN scanlators_view AS S
|
||||
ON C.manga_id = S.manga_id
|
||||
AND ifnull(C.scanlator, 'N/A') = ifnull(S.name, '/<INVALID>/') -- I assume if it's N/A it shouldn't be filtered
|
||||
WHERE M.favorite = 1
|
||||
AND newest_chapter.history_chapter_id = H.history_chapter_id
|
||||
AND C.date_fetch > M.date_added
|
||||
AND lower(M.title) LIKE '%' || :search || '%'
|
||||
AND (
|
||||
:apply_filter = 0 OR S.name IS NULL
|
||||
)
|
||||
)
|
||||
|
||||
UNION --
|
||||
|
||||
SELECT * FROM (
|
||||
SELECT
|
||||
M.*,
|
||||
NULL AS _id,
|
||||
NULL AS manga_id,
|
||||
NULL AS url,
|
||||
NULL AS name,
|
||||
NULL AS read,
|
||||
NULL AS scanlator,
|
||||
NULL AS bookmark,
|
||||
NULL AS date_fetch,
|
||||
NULL AS date_upload,
|
||||
NULL AS last_page_read,
|
||||
NULL AS pages_left,
|
||||
NULL AS chapter_number,
|
||||
NULL AS source_order,
|
||||
NULL AS history_id,
|
||||
NULL AS history_chapter_id,
|
||||
M.date_added AS history_last_read,
|
||||
NULL AS history_time_read
|
||||
FROM mangas AS M
|
||||
WHERE M.favorite = 1
|
||||
AND lower(M.title) LIKE '%' || :search || '%'
|
||||
)
|
||||
ORDER BY history_last_read DESC
|
||||
LIMIT :limit OFFSET :offset;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue