From 17b07cd8364c6a8692faebbf7675c2a31557c0e8 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Fri, 29 Nov 2024 17:05:59 +0700 Subject: [PATCH] refactor(db): Migrate last history queries (that can be migrated) to SQLDelight --- .../data/database/queries/HistoryQueries.kt | 60 +------------------ .../kanade/tachiyomi/ui/main/MainActivity.kt | 17 +++--- .../ui/manga/MangaDetailsPresenter.kt | 8 ++- .../stats/details/StatsDetailsPresenter.kt | 12 +++- .../sqldelight/tachiyomi/data/history.sq | 11 ++++ 5 files changed, 36 insertions(+), 72 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/HistoryQueries.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/HistoryQueries.kt index cacfe9435f..240ffbb545 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/HistoryQueries.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/HistoryQueries.kt @@ -4,70 +4,12 @@ import com.pushtorefresh.storio.sqlite.queries.RawQuery import eu.kanade.tachiyomi.data.database.DbProvider import eu.kanade.tachiyomi.data.database.inTransactionReturn import eu.kanade.tachiyomi.data.database.models.History -import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory import eu.kanade.tachiyomi.data.database.resolvers.HistoryUpsertResolver -import eu.kanade.tachiyomi.data.database.resolvers.MangaChapterHistoryGetResolver import eu.kanade.tachiyomi.data.database.tables.HistoryTable -import eu.kanade.tachiyomi.util.lang.sqLite interface HistoryQueries : DbProvider { - /** - * Insert history into database - * @param history object containing history information - */ -// fun insertHistory(history: History) = db.put().`object`(history).prepare() - -// /** -// * Returns history of recent manga containing last read chapter in 25s -// * @param date recent date range -// * @offset offset the db by -// */ -// fun getRecentManga(date: Date, offset: Int = 0, search: String = "") = db.get() -// .listOfObjects(MangaChapterHistory::class.java) -// .withQuery( -// RawQuery.builder() -// .query(getRecentMangasQuery(offset, search.sqLite)) -// .args(date.time) -// .observesTables(HistoryTable.TABLE) -// .build() -// ) -// .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 getHistoryUngrouped(search: String = "", offset: Int, isResuming: Boolean) = db.get() - .listOfObjects(MangaChapterHistory::class.java) - .withQuery( - RawQuery.builder() - .query(getRecentHistoryUngrouped(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 - * @param endDate end date of the period - * @offset offset the db by - */ - fun getHistoryPerPeriod(startDate: Long, endDate: Long) = db.get() - .listOfObjects(MangaChapterHistory::class.java) - .withQuery( - RawQuery.builder() - .query(getHistoryPerPeriodQuery(startDate, endDate)) - .observesTables(HistoryTable.TABLE) - .build(), - ) - .withGetResolver(MangaChapterHistoryGetResolver.INSTANCE) - .prepare() - + // FIXME: Migrate to SQLDelight, on halt: in StorIO transaction fun getHistoryByMangaId(mangaId: Long) = db.get() .listOfObjects(History::class.java) .withQuery( diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt index 50d2a7cc66..3058db10ed 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt @@ -106,7 +106,6 @@ import eu.kanade.tachiyomi.util.showNotificationPermissionPrompt import eu.kanade.tachiyomi.util.system.contextCompatDrawable import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.util.system.e -import eu.kanade.tachiyomi.util.system.executeOnIO import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.util.system.hasSideNavBar import eu.kanade.tachiyomi.util.system.ignoredSystemInsets @@ -134,6 +133,10 @@ import eu.kanade.tachiyomi.util.view.setTitle import eu.kanade.tachiyomi.util.view.snack import eu.kanade.tachiyomi.util.view.withFadeInTransaction import eu.kanade.tachiyomi.util.view.withFadeTransaction +import kotlin.collections.set +import kotlin.math.abs +import kotlin.math.min +import kotlin.math.roundToLong import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.flow.launchIn @@ -142,15 +145,12 @@ import kotlinx.coroutines.withContext import uy.kohesive.injekt.injectLazy import yokai.core.migration.Migrator import yokai.domain.base.BasePreferences +import yokai.domain.recents.interactor.GetRecents import yokai.i18n.MR import yokai.presentation.core.Constants import yokai.presentation.extension.repo.ExtensionRepoController import yokai.presentation.onboarding.OnboardingController import yokai.util.lang.getString -import kotlin.collections.set -import kotlin.math.abs -import kotlin.math.min -import kotlin.math.roundToLong import android.R as AR @SuppressLint("ResourceType") @@ -170,7 +170,10 @@ open class MainActivity : BaseActivity() { private val downloadManager: DownloadManager by injectLazy() private val mangaShortcutManager: MangaShortcutManager by injectLazy() private val extensionManager: ExtensionManager by injectLazy() + private val db: DatabaseHelper by injectLazy() + private val getRecents: GetRecents by injectLazy() + private val hideBottomNav get() = router.backstackSize > 1 && router.backstack[1].controller !is DialogController private val hideAppBar @@ -408,8 +411,7 @@ open class MainActivity : BaseActivity() { } BasePreferences.LongTapRecents.LAST_READ -> { lifecycleScope.launchUI { - val lastReadChapter = - db.getHistoryUngrouped("", 0, true).executeOnIO().maxByOrNull { it.history.last_read } + val lastReadChapter = getRecents.awaitUngrouped(true, true, "", 0).maxByOrNull { it.history.last_read } lastReadChapter ?: return@launchUI val manga = lastReadChapter.manga @@ -1031,6 +1033,7 @@ open class MainActivity : BaseActivity() { requestColourProfile.launch(arrayOf("*/*")) } + @SuppressLint("MissingSuperCall") override fun onNewIntent(intent: Intent) { if (!handleIntentAction(intent)) { super.onNewIntent(intent) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaDetailsPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaDetailsPresenter.kt index 38a0dc8b87..9c314ca080 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaDetailsPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaDetailsPresenter.kt @@ -88,6 +88,7 @@ import yokai.domain.category.interactor.GetCategories import yokai.domain.chapter.interactor.GetAvailableScanlators import yokai.domain.chapter.interactor.GetChapter import yokai.domain.chapter.interactor.UpdateChapter +import yokai.domain.history.interactor.GetHistory import yokai.domain.library.custom.model.CustomMangaInfo import yokai.domain.manga.interactor.GetManga import yokai.domain.manga.interactor.UpdateManga @@ -117,6 +118,7 @@ class MangaDetailsPresenter( private val updateManga: UpdateManga by injectLazy() private val deleteTrack: DeleteTrack by injectLazy() private val getTrack: GetTrack by injectLazy() + private val getHistory: GetHistory by injectLazy() private val networkPreferences: NetworkPreferences by injectLazy() @@ -263,7 +265,7 @@ class MangaDetailsPresenter( private fun getHistory() { presenterScope.launchIO { - allHistory = db.getHistoryByMangaId(mangaId).executeAsBlocking() + allHistory = getHistory.awaitAllByMangaId(mangaId) } } @@ -1139,8 +1141,8 @@ class MangaDetailsPresenter( updateRemote(track, item.service) } - fun getSuggestedDate(readingDate: TrackingBottomSheet.ReadingDate): Long? { - val chapters = db.getHistoryByMangaId(manga.id ?: 0L).executeAsBlocking() + suspend fun getSuggestedDate(readingDate: TrackingBottomSheet.ReadingDate): Long? { + val chapters = getHistory.awaitAllByMangaId(manga.id ?: 0L) val date = when (readingDate) { TrackingBottomSheet.ReadingDate.Start -> chapters.minOfOrNull { it.last_read } TrackingBottomSheet.ReadingDate.Finish -> chapters.maxOfOrNull { it.last_read } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/more/stats/details/StatsDetailsPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/more/stats/details/StatsDetailsPresenter.kt index 6527409ef2..345ede076c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/more/stats/details/StatsDetailsPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/more/stats/details/StatsDetailsPresenter.kt @@ -38,6 +38,7 @@ import kotlinx.coroutines.runBlocking import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy +import yokai.data.DatabaseHandler import yokai.domain.category.interactor.GetCategories import yokai.domain.chapter.interactor.GetChapter import yokai.domain.history.interactor.GetHistory @@ -52,6 +53,7 @@ class StatsDetailsPresenter( val trackManager: TrackManager = Injekt.get(), private val sourceManager: SourceManager = Injekt.get(), ) : BaseCoroutinePresenter() { + private val handler: DatabaseHandler by injectLazy() private val getCategories: GetCategories by injectLazy() private val getChapter: GetChapter by injectLazy() private val getLibraryManga: GetLibraryManga by injectLazy() @@ -588,15 +590,19 @@ class StatsDetailsPresenter( return runBlocking { getCategories.await() }.toMutableList() } - private fun List.getReadDuration(): Long { - return sumOf { manga -> db.getHistoryByMangaId(manga.id!!).executeAsBlocking().sumOf { it.time_read } } + private suspend fun List.getReadDuration(): Long { + return sumOf { manga -> getHistory.awaitAllByMangaId(manga.id!!).sumOf { it.time_read } } } /** * Get the manga and history grouped by day during the selected period */ fun getMangaHistoryGroupedByDay(): Map> { - val history = db.getHistoryPerPeriod(startDate.timeInMillis, endDate.timeInMillis).executeAsBlocking() + val history = runBlocking { + handler.awaitList { + historyQueries.getPerPeriod(startDate.timeInMillis, endDate.timeInMillis, MangaChapterHistory::mapper) + } + } val calendar = Calendar.getInstance().apply { timeInMillis = startDate.timeInMillis } diff --git a/data/src/commonMain/sqldelight/tachiyomi/data/history.sq b/data/src/commonMain/sqldelight/tachiyomi/data/history.sq index 2daeafd44f..cf4a9bb91b 100644 --- a/data/src/commonMain/sqldelight/tachiyomi/data/history.sq +++ b/data/src/commonMain/sqldelight/tachiyomi/data/history.sq @@ -45,6 +45,17 @@ WHERE chapters.url = :chapterUrl AND history.history_chapter_id = chapters._id; getTotalReadDuration: SELECT sum(history_time_read) FROM history; +getPerPeriod: +SELECT mangas.*, chapters.*, history.* +FROM mangas +JOIN chapters +ON mangas._id = chapters.manga_id +JOIN history +ON chapters._id = history.history_chapter_id +AND history.history_last_read >= :startDate +AND history.history_last_read <= :endDate +ORDER BY history.history_last_read DESC; + getRecentsUngrouped: SELECT M.*,