refactor(recents): Migrate getRecentChapters to SQLDelight

This commit is contained in:
Ahmad Ansori Palembani 2024-08-16 19:46:14 +07:00
parent eb8727afcf
commit a6ef46a90f
Signed by: null2264
GPG key ID: BA64F8B60AF3EFB6
10 changed files with 139 additions and 31 deletions

View file

@ -2,4 +2,78 @@ package eu.kanade.tachiyomi.data.database.models
import eu.kanade.tachiyomi.domain.manga.models.Manga import eu.kanade.tachiyomi.domain.manga.models.Manga
class MangaChapter(val manga: Manga, val chapter: Chapter) class MangaChapter(val manga: Manga, val chapter: Chapter) {
companion object {
fun mapper(
mangaId: Long,
source: Long,
mangaUrl: String,
artist: String?,
author: String?,
description: String?,
genre: String?,
title: String,
status: Long,
thumbnailUrl: String?,
favorite: Long,
lastUpdate: Long?,
initialized: Boolean,
viewer: Long,
hideTitle: Long,
chapterFlags: Long,
dateAdded: Long?,
filteredScanlators: String?,
updateStrategy: Long,
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,
) = MangaChapter(
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,
),
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,
),
)
}
}

View file

@ -1,16 +1,12 @@
package eu.kanade.tachiyomi.data.database.queries package eu.kanade.tachiyomi.data.database.queries
import com.pushtorefresh.storio.sqlite.queries.Query import com.pushtorefresh.storio.sqlite.queries.Query
import com.pushtorefresh.storio.sqlite.queries.RawQuery
import eu.kanade.tachiyomi.data.database.DbProvider import eu.kanade.tachiyomi.data.database.DbProvider
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.MangaChapter
import eu.kanade.tachiyomi.data.database.resolvers.ChapterKnownBackupPutResolver import eu.kanade.tachiyomi.data.database.resolvers.ChapterKnownBackupPutResolver
import eu.kanade.tachiyomi.data.database.resolvers.ChapterProgressPutResolver import eu.kanade.tachiyomi.data.database.resolvers.ChapterProgressPutResolver
import eu.kanade.tachiyomi.data.database.resolvers.MangaChapterGetResolver
import eu.kanade.tachiyomi.data.database.tables.ChapterTable import eu.kanade.tachiyomi.data.database.tables.ChapterTable
import eu.kanade.tachiyomi.domain.manga.models.Manga import eu.kanade.tachiyomi.domain.manga.models.Manga
import eu.kanade.tachiyomi.util.lang.sqLite
interface ChapterQueries : DbProvider { interface ChapterQueries : DbProvider {
@ -27,17 +23,6 @@ interface ChapterQueries : DbProvider {
) )
.prepare() .prepare()
fun getRecentChapters(search: String = "", offset: Int, isResuming: Boolean) = db.get()
.listOfObjects(MangaChapter::class.java)
.withQuery(
RawQuery.builder()
.query(getRecentsQuery(search.sqLite, offset, isResuming))
.observesTables(ChapterTable.TABLE)
.build(),
)
.withGetResolver(MangaChapterGetResolver.INSTANCE)
.prepare()
fun getChapter(id: Long) = db.get() fun getChapter(id: Long) = db.get()
.`object`(Chapter::class.java) .`object`(Chapter::class.java)
.withQuery( .withQuery(

View file

@ -22,6 +22,14 @@ import eu.kanade.tachiyomi.util.system.launchIO
import eu.kanade.tachiyomi.util.system.launchUI import eu.kanade.tachiyomi.util.system.launchUI
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.system.withUIContext import eu.kanade.tachiyomi.util.system.withUIContext
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
import java.util.TreeMap
import java.util.concurrent.TimeUnit
import kotlin.math.abs
import kotlin.math.roundToInt
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.drop
@ -33,14 +41,10 @@ import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import yokai.domain.chapter.interactor.GetChapter import yokai.domain.chapter.interactor.GetChapter
import yokai.domain.chapter.interactor.RecentChapter
import yokai.domain.recents.RecentsPreferences import yokai.domain.recents.RecentsPreferences
import yokai.domain.ui.UiPreferences import yokai.domain.ui.UiPreferences
import yokai.i18n.MR import yokai.i18n.MR
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.*
import kotlin.math.abs
import kotlin.math.roundToInt
class RecentsPresenter( class RecentsPresenter(
val uiPreferences: UiPreferences = Injekt.get(), val uiPreferences: UiPreferences = Injekt.get(),
@ -51,6 +55,7 @@ class RecentsPresenter(
private val chapterFilter: ChapterFilter = Injekt.get(), private val chapterFilter: ChapterFilter = Injekt.get(),
) : BaseCoroutinePresenter<RecentsController>(), DownloadQueue.DownloadListener { ) : BaseCoroutinePresenter<RecentsController>(), DownloadQueue.DownloadListener {
private val getChapter: GetChapter by injectLazy() private val getChapter: GetChapter by injectLazy()
private val recentChapter: RecentChapter by injectLazy()
private var recentsJob: Job? = null private var recentsJob: Job? = null
var recentItems = listOf<RecentMangaItem>() var recentItems = listOf<RecentMangaItem>()
@ -235,11 +240,12 @@ class RecentsPresenter(
dateFormat.applyPattern("yyyy-MM-dd") dateFormat.applyPattern("yyyy-MM-dd")
dateFormat.calendar.firstDayOfWeek = dateFormat.calendar.firstDayOfWeek =
Calendar.getInstance().get(Calendar.DAY_OF_WEEK) Calendar.getInstance().get(Calendar.DAY_OF_WEEK)
db.getRecentChapters( recentChapter.await(
query, true,
if (isCustom) ENDLESS_LIMIT else pageOffset,
!updatePageCount && !isOnFirstPage, !updatePageCount && !isOnFirstPage,
).executeOnIO().groupBy { query,
(if (isCustom) ENDLESS_LIMIT else pageOffset).toLong(),
).groupBy {
val date = it.chapter.date_fetch val date = it.chapter.date_fetch
it.manga.id to if (date <= 0L) "-1" else dateFormat.format(Date(date)) it.manga.id to if (date <= 0L) "-1" else dateFormat.format(Date(date))
} }

View file

@ -17,6 +17,7 @@ import yokai.domain.chapter.interactor.DeleteChapter
import yokai.domain.chapter.interactor.GetAvailableScanlators import yokai.domain.chapter.interactor.GetAvailableScanlators
import yokai.domain.chapter.interactor.GetChapter import yokai.domain.chapter.interactor.GetChapter
import yokai.domain.chapter.interactor.InsertChapter import yokai.domain.chapter.interactor.InsertChapter
import yokai.domain.chapter.interactor.RecentChapter
import yokai.domain.chapter.interactor.UpdateChapter import yokai.domain.chapter.interactor.UpdateChapter
import yokai.domain.extension.interactor.TrustExtension import yokai.domain.extension.interactor.TrustExtension
import yokai.domain.extension.repo.ExtensionRepoRepository import yokai.domain.extension.repo.ExtensionRepoRepository
@ -66,6 +67,7 @@ class DomainModule : InjektModule {
addFactory { GetAvailableScanlators(get()) } addFactory { GetAvailableScanlators(get()) }
addFactory { GetChapter(get()) } addFactory { GetChapter(get()) }
addFactory { InsertChapter(get()) } addFactory { InsertChapter(get()) }
addFactory { RecentChapter(get()) }
addFactory { UpdateChapter(get()) } addFactory { UpdateChapter(get()) }
addSingletonFactory<CategoryRepository> { CategoryRepositoryImpl(get()) } addSingletonFactory<CategoryRepository> { CategoryRepositoryImpl(get()) }

View file

@ -2,6 +2,7 @@ package yokai.data.chapter
import co.touchlab.kermit.Logger import co.touchlab.kermit.Logger
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.MangaChapter
import eu.kanade.tachiyomi.util.system.toInt import eu.kanade.tachiyomi.util.system.toInt
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import yokai.data.DatabaseHandler import yokai.data.DatabaseHandler
@ -15,6 +16,9 @@ class ChapterRepositoryImpl(private val handler: DatabaseHandler) : ChapterRepos
override fun getChaptersAsFlow(mangaId: Long, filterScanlators: Boolean): Flow<List<Chapter>> = override fun getChaptersAsFlow(mangaId: Long, filterScanlators: Boolean): Flow<List<Chapter>> =
handler.subscribeToList { chaptersQueries.getChaptersByMangaId(mangaId, filterScanlators.toInt().toLong(), Chapter::mapper) } handler.subscribeToList { chaptersQueries.getChaptersByMangaId(mangaId, filterScanlators.toInt().toLong(), Chapter::mapper) }
override suspend fun getRecents(filterScanlators: Boolean, search: String, limit: Long, offset: Long): List<MangaChapter> =
handler.awaitList { chaptersQueries.getRecents(search, filterScanlators.toInt().toLong(), limit, offset, MangaChapter::mapper) }
override suspend fun getScanlatorsByChapter(mangaId: Long): List<String> = override suspend fun getScanlatorsByChapter(mangaId: Long): List<String> =
handler.awaitList { chaptersQueries.getScanlatorsByMangaId(mangaId) { it.orEmpty() } } handler.awaitList { chaptersQueries.getScanlatorsByMangaId(mangaId) { it.orEmpty() } }

View file

@ -1,6 +1,7 @@
package yokai.domain.chapter package yokai.domain.chapter
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.MangaChapter
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import yokai.domain.chapter.models.ChapterUpdate import yokai.domain.chapter.models.ChapterUpdate
@ -8,6 +9,8 @@ interface ChapterRepository {
suspend fun getChapters(mangaId: Long, filterScanlators: Boolean): List<Chapter> suspend fun getChapters(mangaId: Long, filterScanlators: Boolean): List<Chapter>
fun getChaptersAsFlow(mangaId: Long, filterScanlators: Boolean): Flow<List<Chapter>> fun getChaptersAsFlow(mangaId: Long, filterScanlators: Boolean): Flow<List<Chapter>>
suspend fun getRecents(filterScanlators: Boolean, search: String = "", limit: Long = 25L, offset: Long = 0L): List<MangaChapter>
suspend fun getScanlatorsByChapter(mangaId: Long): List<String> suspend fun getScanlatorsByChapter(mangaId: Long): List<String>
fun getScanlatorsByChapterAsFlow(mangaId: Long): Flow<List<String>> fun getScanlatorsByChapterAsFlow(mangaId: Long): Flow<List<String>>

View file

@ -0,0 +1,21 @@
package yokai.domain.chapter.interactor
import eu.kanade.tachiyomi.data.database.models.MangaChapter
import eu.kanade.tachiyomi.util.lang.sqLite
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.sqLite}%",
limit,
actualOffset,
)
}
}

View file

@ -0,0 +1,17 @@
package yokai.util
import eu.kanade.tachiyomi.ui.recents.RecentsPresenter
fun limitAndOffset(isEndless: Boolean, isResuming: Boolean, offset: Long): Pair<Long, Long> {
return when {
isResuming && isEndless && offset > 0 -> {
offset to 0L
}
isEndless -> {
RecentsPresenter.ENDLESS_LIMIT.toLong() to offset
}
else -> {
RecentsPresenter.SHORT_LIMIT.toLong() to 0L
}
}
}

View file

@ -34,7 +34,6 @@ AND (
getRecents: getRecents:
SELECT SELECT
M.url AS mangaUrl,
M.*, M.*,
C.* C.*
FROM mangas AS M FROM mangas AS M
@ -54,7 +53,6 @@ LIMIT :limit OFFSET :offset;
getRecentsUngrouped: getRecentsUngrouped:
SELECT SELECT
M.url AS mangaUrl,
M.*, M.*,
C.*, C.*,
H.* H.*

View file

@ -1,10 +1,8 @@
import kotlin.Long;
CREATE TABLE history( CREATE TABLE history(
history_id INTEGER NOT NULL PRIMARY KEY, history_id INTEGER NOT NULL PRIMARY KEY,
history_chapter_id INTEGER NOT NULL UNIQUE, history_chapter_id INTEGER NOT NULL UNIQUE,
history_last_read INTEGER AS Long, history_last_read INTEGER,
history_time_read INTEGER AS Long, history_time_read INTEGER,
FOREIGN KEY(history_chapter_id) REFERENCES chapters (_id) FOREIGN KEY(history_chapter_id) REFERENCES chapters (_id)
ON DELETE CASCADE ON DELETE CASCADE
); );