diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/restore/restorers/MangaBackupRestorer.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/restore/restorers/MangaBackupRestorer.kt index 49b06ea1f4..dca557065a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/restore/restorers/MangaBackupRestorer.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/restore/restorers/MangaBackupRestorer.kt @@ -22,6 +22,8 @@ import yokai.domain.category.interactor.GetCategories import yokai.domain.chapter.interactor.GetChapter import yokai.domain.chapter.interactor.InsertChapter import yokai.domain.chapter.interactor.UpdateChapter +import yokai.domain.history.interactor.GetHistory +import yokai.domain.history.interactor.UpsertHistory import yokai.domain.library.custom.model.CustomMangaInfo import yokai.domain.manga.interactor.GetManga import yokai.domain.manga.interactor.InsertManga @@ -37,6 +39,8 @@ class MangaBackupRestorer( private val getManga: GetManga = Injekt.get(), private val insertManga: InsertManga = Injekt.get(), private val updateManga: UpdateManga = Injekt.get(), + private val getHistory: GetHistory = Injekt.get(), + private val upsertHistory: UpsertHistory = Injekt.get(), ) { suspend fun restoreManga( backupManga: BackupManga, @@ -202,7 +206,7 @@ class MangaBackupRestorer( // List containing history to be updated val historyToBeUpdated = ArrayList(history.size) for ((url, lastRead, readDuration) in history) { - val dbHistory = db.getHistoryByChapterUrl(url).executeAsBlocking() + val dbHistory = getHistory.awaitByChapterUrl(url) // Check if history already in database and update if (dbHistory != null) { dbHistory.apply { @@ -221,7 +225,7 @@ class MangaBackupRestorer( } } } - db.upsertHistoryLastRead(historyToBeUpdated).executeAsBlocking() + upsertHistory.awaitBulk(historyToBeUpdated) } /** 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 582d6670b7..6349d58a50 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 @@ -92,32 +92,12 @@ interface HistoryQueries : DbProvider { return cursor.getLong(0) } - fun getHistoryByChapterUrl(chapterUrl: String) = db.get() - .`object`(History::class.java) - .withQuery( - RawQuery.builder() - .query(getHistoryByChapterUrl()) - .args(chapterUrl) - .observesTables(HistoryTable.TABLE) - .build(), - ) - .prepare() - - /** - * Updates the history last read. - * Inserts history object if not yet in database - * @param history history object - */ - fun upsertHistoryLastRead(history: History) = db.put() - .`object`(history) - .withPutResolver(HistoryUpsertResolver()) - .prepare() - /** * Updates the history last read. * Inserts history object if not yet in database * @param historyList history object list */ + // FIXME: Migrate to SQLDelight, on halt: in StorIO transaction fun upsertHistoryLastRead(historyList: List) = db.inTransactionReturn { db.put() .objects(historyList) @@ -125,14 +105,6 @@ interface HistoryQueries : DbProvider { .prepare() } - fun deleteHistory() = db.delete() - .byQuery( - DeleteQuery.builder() - .table(HistoryTable.TABLE) - .build(), - ) - .prepare() - fun deleteHistoryNoLastRead() = db.delete() .byQuery( DeleteQuery.builder() 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 ef8b06dd37..df28c90f3e 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 @@ -18,6 +18,7 @@ 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.launchIO +import eu.kanade.tachiyomi.util.system.launchNonCancellableIO import eu.kanade.tachiyomi.util.system.launchUI import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.withUIContext @@ -39,8 +40,11 @@ import kotlinx.coroutines.withContext import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy +import yokai.data.DatabaseHandler import yokai.domain.chapter.interactor.GetChapter import yokai.domain.chapter.interactor.UpdateChapter +import yokai.domain.history.interactor.GetHistory +import yokai.domain.history.interactor.UpsertHistory import yokai.domain.recents.RecentsPreferences import yokai.domain.recents.interactor.GetRecents import yokai.domain.ui.UiPreferences @@ -54,9 +58,13 @@ class RecentsPresenter( val db: DatabaseHelper = Injekt.get(), private val chapterFilter: ChapterFilter = Injekt.get(), ) : BaseCoroutinePresenter(), DownloadQueue.DownloadListener { + private val handler: DatabaseHandler by injectLazy() + private val getChapter: GetChapter by injectLazy() private val getRecents: GetRecents by injectLazy() private val updateChapter: UpdateChapter by injectLazy() + private val getHistory: GetHistory by injectLazy() + private val upsertHistory: UpsertHistory by injectLazy() private var recentsJob: Job? = null var recentItems = listOf() @@ -635,7 +643,7 @@ class RecentsPresenter( lastRead: Int? = null, pagesLeft: Int? = null, ) { - presenterScope.launch(Dispatchers.IO) { + presenterScope.launchNonCancellableIO { chapter.apply { this.read = read if (!read) { @@ -654,10 +662,12 @@ class RecentsPresenter( * @param history history belonging to chapter */ fun removeFromHistory(history: History) { - history.last_read = 0L - history.time_read = 0L - db.upsertHistoryLastRead(history).executeAsBlocking() - getRecents() + presenterScope.launchNonCancellableIO { + history.last_read = 0L + history.time_read = 0L + upsertHistory.await(history) + getRecents() + } } /** @@ -665,13 +675,16 @@ class RecentsPresenter( * @param mangaId id of manga */ fun removeAllFromHistory(mangaId: Long) { - val history = db.getHistoryByMangaId(mangaId).executeAsBlocking() - history.forEach { - it.last_read = 0L - it.time_read = 0L + presenterScope.launchNonCancellableIO { + val histories = getHistory.awaitAllByMangaId(mangaId).map { + it.apply { + last_read = 0L + time_read = 0L + } + } + upsertHistory.awaitBulk(histories) + getRecents() } - db.upsertHistoryLastRead(history).executeAsBlocking() - getRecents() } fun requestNext() { @@ -682,8 +695,8 @@ class RecentsPresenter( } fun deleteAllHistory() { - presenterScope.launchIO { - db.deleteHistory().executeAsBlocking() + presenterScope.launchNonCancellableIO { + handler.await { historyQueries.deleteAll() } withUIContext { view?.activity?.toast(MR.strings.clear_history_completed) getRecents() diff --git a/app/src/main/java/yokai/data/history/HistoryRepositoryImpl.kt b/app/src/main/java/yokai/data/history/HistoryRepositoryImpl.kt index da274def36..c05ec382be 100644 --- a/app/src/main/java/yokai/data/history/HistoryRepositoryImpl.kt +++ b/app/src/main/java/yokai/data/history/HistoryRepositoryImpl.kt @@ -13,9 +13,26 @@ class HistoryRepositoryImpl(private val handler: DatabaseHandler) : HistoryRepos historyQueries.selectLastInsertedRowId() } + override suspend fun bulkUpsert(histories: List) = + handler.await(true) { + histories.forEach { history -> + historyQueries.upsert( + history.chapter_id, + history.last_read, + history.time_read, + ) + } + } + override suspend fun getByChapterUrl(chapterUrl: String): History? = handler.awaitOneOrNull { historyQueries.getByChapterUrl(chapterUrl, History::mapper) } + override suspend fun getByMangaId(mangaId: Long): History? = + handler.awaitOneOrNull { historyQueries.getByMangaId(mangaId, History::mapper) } + + override suspend fun getAllByMangaId(mangaId: Long): List = + handler.awaitList { historyQueries.getByMangaId(mangaId, History::mapper) } + override suspend fun getRecentsUngrouped( filterScanlators: Boolean, search: String, diff --git a/app/src/main/java/yokai/domain/history/HistoryRepository.kt b/app/src/main/java/yokai/domain/history/HistoryRepository.kt index 78b69a0d46..5d01e79984 100644 --- a/app/src/main/java/yokai/domain/history/HistoryRepository.kt +++ b/app/src/main/java/yokai/domain/history/HistoryRepository.kt @@ -5,7 +5,10 @@ import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory interface HistoryRepository { suspend fun upsert(chapterId: Long, lastRead: Long, timeRead: Long): Long? + suspend fun bulkUpsert(histories: List) suspend fun getByChapterUrl(chapterUrl: String): History? + suspend fun getByMangaId(mangaId: Long): History? + suspend fun getAllByMangaId(mangaId: Long): List suspend fun getRecentsUngrouped(filterScanlators: Boolean, search: String = "", limit: Long = 25L, offset: Long = 0L): List suspend fun getRecentsBySeries(filterScanlators: Boolean, search: String = "", limit: Long = 25L, offset: Long = 0L): List diff --git a/app/src/main/java/yokai/domain/history/interactor/GetHistory.kt b/app/src/main/java/yokai/domain/history/interactor/GetHistory.kt index 9b2be8ba15..74aec313ac 100644 --- a/app/src/main/java/yokai/domain/history/interactor/GetHistory.kt +++ b/app/src/main/java/yokai/domain/history/interactor/GetHistory.kt @@ -6,4 +6,6 @@ class GetHistory( private val historyRepository: HistoryRepository ) { suspend fun awaitByChapterUrl(chapterUrl: String) = historyRepository.getByChapterUrl(chapterUrl) + suspend fun awaitByMangaId(mangaId: Long) = historyRepository.getByMangaId(mangaId) + suspend fun awaitAllByMangaId(mangaId: Long) = historyRepository.getAllByMangaId(mangaId) } diff --git a/app/src/main/java/yokai/domain/history/interactor/UpsertHistory.kt b/app/src/main/java/yokai/domain/history/interactor/UpsertHistory.kt index 353dd7c1cf..965ccad50b 100644 --- a/app/src/main/java/yokai/domain/history/interactor/UpsertHistory.kt +++ b/app/src/main/java/yokai/domain/history/interactor/UpsertHistory.kt @@ -11,4 +11,7 @@ class UpsertHistory( suspend fun await(history: History) = historyRepository.upsert(history.chapter_id, history.last_read, history.time_read) + + suspend fun awaitBulk(histories: List) = + historyRepository.bulkUpsert(histories) } diff --git a/data/src/commonMain/sqldelight/tachiyomi/data/history.sq b/data/src/commonMain/sqldelight/tachiyomi/data/history.sq index e4ff7b822a..4f00d5fd13 100644 --- a/data/src/commonMain/sqldelight/tachiyomi/data/history.sq +++ b/data/src/commonMain/sqldelight/tachiyomi/data/history.sq @@ -22,6 +22,16 @@ WHERE history_chapter_id = history_chapter_id; selectLastInsertedRowId: SELECT last_insert_rowid(); +deleteAll: +DELETE FROM history; + +getByMangaId: +SELECT history.* +FROM history +JOIN chapters +ON history.history_chapter_id = chapters._id +WHERE chapters.manga_id = :mangaId AND history.history_chapter_id = chapters._id; + getByChapterUrl: SELECT history.* FROM history