From c18380209662ac6b391e58355047102fd996fe1c Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani Date: Thu, 28 Nov 2024 20:53:26 +0700 Subject: [PATCH] refactor(db): Migrate GetTrack to SQLDelight --- .../create/creators/MangaBackupCreator.kt | 14 +++++---- .../restore/restorers/MangaBackupRestorer.kt | 4 ++- .../tachiyomi/data/database/models/Track.kt | 30 +++++++++++++++++++ .../data/database/queries/TrackQueries.kt | 7 ++--- .../data/library/LibraryUpdateJob.kt | 5 ++-- .../data/track/DelayedTrackingUpdateJob.kt | 10 +++++-- .../tachiyomi/ui/library/LibraryPresenter.kt | 16 +++++----- .../ui/manga/MangaDetailsPresenter.kt | 8 +++-- .../tachiyomi/ui/migration/MigrationFlags.kt | 5 +++- .../tachiyomi/ui/more/stats/StatsPresenter.kt | 7 +++-- .../stats/details/StatsDetailsPresenter.kt | 4 ++- .../tachiyomi/ui/reader/ReaderViewModel.kt | 10 +++---- .../kanade/tachiyomi/util/MangaExtensions.kt | 15 +++++----- .../util/chapter/ChapterTrackSync.kt | 4 ++- .../main/java/yokai/core/di/DomainModule.kt | 10 +++++-- .../data/category/CategoryRepositoryImpl.kt | 3 ++ .../yokai/data/manga/MangaRepositoryImpl.kt | 3 ++ .../yokai/data/track/TrackRepositoryImpl.kt | 10 +++++++ .../domain/category/CategoryRepository.kt | 1 + .../category/interactor/GetCategories.kt | 1 + .../yokai/domain/manga/MangaRepository.kt | 1 + .../yokai/domain/manga/interactor/GetManga.kt | 1 + .../yokai/domain/track/TrackRepository.kt | 7 +++++ .../yokai/domain/track/interactor/GetTrack.kt | 9 ++++++ .../sqldelight/tachiyomi/data/categories.sq | 5 ++++ .../sqldelight/tachiyomi/data/manga_sync.sq | 12 +++++--- 26 files changed, 154 insertions(+), 48 deletions(-) create mode 100644 app/src/main/java/yokai/data/track/TrackRepositoryImpl.kt create mode 100644 app/src/main/java/yokai/domain/track/TrackRepository.kt create mode 100644 app/src/main/java/yokai/domain/track/interactor/GetTrack.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/creators/MangaBackupCreator.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/creators/MangaBackupCreator.kt index cfefeed412..9ecc98211d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/creators/MangaBackupCreator.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/create/creators/MangaBackupCreator.kt @@ -5,19 +5,23 @@ import eu.kanade.tachiyomi.data.backup.models.BackupChapter import eu.kanade.tachiyomi.data.backup.models.BackupHistory import eu.kanade.tachiyomi.data.backup.models.BackupManga import eu.kanade.tachiyomi.data.backup.models.BackupTracking -import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.library.CustomMangaManager import eu.kanade.tachiyomi.domain.manga.models.Manga import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import yokai.data.DatabaseHandler +import yokai.domain.category.interactor.GetCategories import yokai.domain.chapter.interactor.GetChapter +import yokai.domain.history.interactor.GetHistory +import yokai.domain.track.interactor.GetTrack class MangaBackupCreator( - private val db: DatabaseHelper = Injekt.get(), private val customMangaManager: CustomMangaManager = Injekt.get(), private val handler: DatabaseHandler = Injekt.get(), + private val getCategories: GetCategories = Injekt.get(), private val getChapter: GetChapter = Injekt.get(), + private val getHistory: GetHistory = Injekt.get(), + private val getTrack: GetTrack = Injekt.get(), ) { suspend operator fun invoke(mangas: List, options: BackupOptions): List { return mangas.map { @@ -55,7 +59,7 @@ class MangaBackupCreator( // Check if user wants category information in backup if (options.categories) { // Backup categories for this manga - val categoriesForManga = db.getCategoriesForManga(manga).executeAsBlocking() + val categoriesForManga = getCategories.awaitByMangaId(manga.id!!) if (categoriesForManga.isNotEmpty()) { mangaObject.categories = categoriesForManga.mapNotNull { it.order } } @@ -63,7 +67,7 @@ class MangaBackupCreator( // Check if user wants track information in backup if (options.tracking) { - val tracks = db.getTracks(manga).executeAsBlocking() + val tracks = getTrack.awaitAllByMangaId(manga.id!!) if (tracks.isNotEmpty()) { mangaObject.tracking = tracks.map { BackupTracking.copyFrom(it) } } @@ -71,7 +75,7 @@ class MangaBackupCreator( // Check if user wants history information in backup if (options.history) { - val historyForManga = db.getHistoryByMangaId(manga.id!!).executeAsBlocking() + val historyForManga = getHistory.awaitAllByMangaId(manga.id!!) if (historyForManga.isNotEmpty()) { val history = historyForManga.mapNotNull { history -> val url = getChapter.awaitById(history.chapter_id)?.url 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 dca557065a..d3397fc4a8 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 @@ -28,6 +28,7 @@ import yokai.domain.library.custom.model.CustomMangaInfo import yokai.domain.manga.interactor.GetManga import yokai.domain.manga.interactor.InsertManga import yokai.domain.manga.interactor.UpdateManga +import yokai.domain.track.interactor.GetTrack class MangaBackupRestorer( private val db: DatabaseHelper = Injekt.get(), @@ -41,6 +42,7 @@ class MangaBackupRestorer( private val updateManga: UpdateManga = Injekt.get(), private val getHistory: GetHistory = Injekt.get(), private val upsertHistory: UpsertHistory = Injekt.get(), + private val getTrack: GetTrack = Injekt.get(), ) { suspend fun restoreManga( backupManga: BackupManga, @@ -239,7 +241,7 @@ class MangaBackupRestorer( tracks.map { it.manga_id = manga.id!! } // Get tracks from database - val dbTracks = db.getTracks(manga).executeAsBlocking() + val dbTracks = getTrack.awaitAllByMangaId(manga.id!!) val trackToUpdate = mutableListOf() tracks.forEach { track -> diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Track.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Track.kt index b80c47dd6a..ea938fcc48 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Track.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Track.kt @@ -42,5 +42,35 @@ interface Track : Serializable { fun create(serviceId: Long): Track = TrackImpl().apply { sync_id = serviceId } + + fun mapper( + id: Long, + mangaId: Long, + syncId: Long, + remoteId: Long, + libraryId: Long?, + title: String, + lastChapterRead: Double, + totalChapters: Long, + status: Long, + score: Double, + remoteUrl: String, + startDate: Long, + finishDate: Long, + ) = TrackImpl().apply { + this.id = id + this.manga_id = mangaId + this.sync_id = syncId + this.media_id = remoteId + this.library_id = libraryId + this.title = title + this.last_chapter_read = lastChapterRead.toFloat() + this.total_chapters = totalChapters + this.score = score.toFloat() + this.status = status.toInt() + this.started_reading_date = startDate + this.finished_reading_date = finishDate + this.tracking_url = remoteUrl + } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/TrackQueries.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/TrackQueries.kt index 88de11fbfb..f77400e719 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/TrackQueries.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/TrackQueries.kt @@ -10,15 +10,14 @@ import eu.kanade.tachiyomi.domain.manga.models.Manga interface TrackQueries : DbProvider { - fun getTracks(manga: Manga) = getTracks(manga.id) - - fun getTracks(mangaId: Long?) = db.get() + // FIXME: Migrate to SQLDelight, on halt: in StorIO transaction + fun getTracks(manga: Manga) = db.get() .listOfObjects(Track::class.java) .withQuery( Query.builder() .table(TrackTable.TABLE) .where("${TrackTable.COL_MANGA_ID} = ?") - .whereArgs(mangaId) + .whereArgs(manga.id) .build(), ) .prepare() diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt index 05d6f03079..c133764014 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt @@ -85,6 +85,7 @@ import yokai.domain.chapter.interactor.GetChapter import yokai.domain.manga.interactor.GetLibraryManga import yokai.domain.manga.interactor.UpdateManga import yokai.domain.manga.models.cover +import yokai.domain.track.interactor.GetTrack import yokai.i18n.MR import yokai.util.lang.getString @@ -103,6 +104,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet private val mangaShortcutManager: MangaShortcutManager = Injekt.get() private val getLibraryManga: GetLibraryManga = Injekt.get() private val updateManga: UpdateManga = Injekt.get() + private val getTrack: GetTrack = Injekt.get() private var extraDeferredJobs = mutableListOf>() @@ -302,7 +304,6 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet * Method that updates the metadata of the connected tracking services. It's called in a * background thread, so it's safe to do heavy operations or network calls here. */ - private suspend fun updateTrackings(mangaToUpdate: List) { // Initialize the variables holding the progress of the updates. var count = 0 @@ -312,7 +313,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet mangaToUpdate.forEach { manga -> notifier.showProgressNotification(manga, count++, mangaToUpdate.size) - val tracks = db.getTracks(manga).executeAsBlocking() + val tracks = getTrack.awaitAllByMangaId(manga.id!!) tracks.forEach { track -> val service = trackManager.getService(track.sync_id) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/DelayedTrackingUpdateJob.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/DelayedTrackingUpdateJob.kt index 5c788b9d2c..b0320c25c5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/DelayedTrackingUpdateJob.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/DelayedTrackingUpdateJob.kt @@ -18,10 +18,16 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get +import uy.kohesive.injekt.injectLazy +import yokai.domain.manga.interactor.GetManga +import yokai.domain.track.interactor.GetTrack class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters) : CoroutineWorker(context, workerParams) { + private val getManga: GetManga by injectLazy() + private val getTrack: GetTrack by injectLazy() + override suspend fun doWork(): Result { val preferences = Injekt.get() val db = Injekt.get() @@ -40,8 +46,8 @@ class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters) withContext(Dispatchers.IO) { trackings.forEach { val mangaId = it.key - val manga = db.getManga(mangaId).executeAsBlocking() ?: return@withContext - val trackList = db.getTracks(manga).executeAsBlocking() + val manga = getManga.awaitById(mangaId) ?: return@withContext + val trackList = getTrack.awaitAllByMangaId(manga.id) it.value.map { tC -> val trackChapter = tC.second val service = trackManager.getService(trackChapter.first) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt index 5eff21edce..cf0470e922 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt @@ -73,6 +73,7 @@ import yokai.domain.manga.interactor.GetLibraryManga import yokai.domain.manga.interactor.GetManga import yokai.domain.manga.interactor.UpdateManga import yokai.domain.manga.models.MangaUpdate +import yokai.domain.track.interactor.GetTrack import yokai.i18n.MR import yokai.util.isLewd import yokai.util.lang.getString @@ -94,6 +95,7 @@ class LibraryPresenter( private val getChapter: GetChapter by injectLazy() private val updateChapter: UpdateChapter by injectLazy() private val updateManga: UpdateManga by injectLazy() + private val getTrack: GetTrack by injectLazy() private val context = preferences.context private val viewContext @@ -423,7 +425,7 @@ class LibraryPresenter( return filteredItems } - private fun matchesFilters( + private suspend fun matchesFilters( item: LibraryItem, filterPrefs: ItemPreferences, filterTrackers: String, @@ -475,7 +477,7 @@ class LibraryPresenter( return true } - private fun matchesCustomFilters( + private suspend fun matchesCustomFilters( item: LibraryItem, customFilters: FilteredLibraryController, filterTrackers: String, @@ -498,7 +500,7 @@ class LibraryPresenter( } val trackingScore = customFilters.filterTrackingScore if (trackingScore > 0 || trackingScore == -1) { - val tracks = db.getTracks(item.manga).executeAsBlocking() + val tracks = getTrack.awaitAllByMangaId(item.manga.id!!) val hasTrack = loggedServices.any { service -> tracks.any { it.sync_id == service.id } @@ -556,14 +558,14 @@ class LibraryPresenter( return service?.get10PointScore(this.score) } - private fun matchesFilterTracking( + private suspend fun matchesFilterTracking( item: LibraryItem, filterTracked: Int, filterTrackers: String, ): Boolean { // Filter for tracked (or per tracked service) if (filterTracked != STATE_IGNORE) { - val tracks = db.getTracks(item.manga).executeAsBlocking() + val tracks = getTrack.awaitAllByMangaId(item.manga.id!!) val hasTrack = loggedServices.any { service -> tracks.any { it.sync_id == service.id } @@ -992,7 +994,7 @@ class LibraryPresenter( ) } - private fun getDynamicLibraryItems( + private suspend fun getDynamicLibraryItems( libraryManga: List, sortingMode: Int, isAscending: Boolean, @@ -1031,7 +1033,7 @@ class LibraryPresenter( } } BY_TRACK_STATUS -> { - val tracks = db.getTracks(manga).executeAsBlocking() + val tracks = getTrack.awaitAllByMangaId(manga.id!!) val track = tracks.find { track -> loggedServices.any { it.id == track?.sync_id } } 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 9f9f42a843..70bdb69e2b 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 @@ -94,6 +94,7 @@ import yokai.domain.manga.interactor.UpdateManga import yokai.domain.manga.models.MangaUpdate import yokai.domain.manga.models.cover import yokai.domain.storage.StorageManager +import yokai.domain.track.interactor.GetTrack import yokai.i18n.MR import yokai.util.lang.getString @@ -112,6 +113,7 @@ class MangaDetailsPresenter( private val getManga: GetManga by injectLazy() private val updateChapter: UpdateChapter by injectLazy() private val updateManga: UpdateManga by injectLazy() + private val getTrack: GetTrack by injectLazy() private val networkPreferences: NetworkPreferences by injectLazy() @@ -176,7 +178,9 @@ class MangaDetailsPresenter( downloadManager.addListener(this) - tracks = db.getTracks(manga).executeAsBlocking() + runBlocking { + tracks = getTrack.awaitAllByMangaId(manga.id!!) + } } /** @@ -1008,7 +1012,7 @@ class MangaDetailsPresenter( } suspend fun fetchTracks() { - tracks = withContext(Dispatchers.IO) { db.getTracks(manga).executeAsBlocking() } + tracks = withContext(Dispatchers.IO) { getTrack.awaitAllByMangaId(manga.id!!) } setTrackItems() withContext(Dispatchers.Main) { view?.refreshTracking(trackList) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/MigrationFlags.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/MigrationFlags.kt index e860955b87..b0a96b556a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/MigrationFlags.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/MigrationFlags.kt @@ -7,7 +7,9 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.library.CustomMangaManager import eu.kanade.tachiyomi.domain.manga.models.Manga import eu.kanade.tachiyomi.util.system.toInt +import kotlinx.coroutines.runBlocking import uy.kohesive.injekt.injectLazy +import yokai.domain.track.interactor.GetTrack import yokai.i18n.MR import yokai.util.lang.getString @@ -21,6 +23,7 @@ object MigrationFlags { private val coverCache: CoverCache by injectLazy() private val db: DatabaseHelper by injectLazy() private val customMangaManager: CustomMangaManager by injectLazy() + private val getTrack: GetTrack by injectLazy() val titles get() = arrayOf(MR.strings.chapters, MR.strings.categories, MR.strings.tracking, MR.strings.custom_manga_info) val flags get() = arrayOf(CHAPTERS, CATEGORIES, TRACK, CUSTOM_MANGA_INFO) @@ -61,7 +64,7 @@ object MigrationFlags { fun flags(manga: Manga?): Array { val flags = arrayOf(CHAPTERS, CATEGORIES).toMutableList() if (manga != null) { - if (db.getTracks(manga).executeAsBlocking().isNotEmpty()) { + if (runBlocking { getTrack.awaitAllByMangaId(manga.id) }.isNotEmpty()) { flags.add(TRACK) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/more/stats/StatsPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/more/stats/StatsPresenter.kt index 50b1bae8f1..c54cda1f3d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/more/stats/StatsPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/more/stats/StatsPresenter.kt @@ -14,12 +14,14 @@ import eu.kanade.tachiyomi.domain.manga.models.Manga import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.model.SManga +import eu.kanade.tachiyomi.ui.base.presenter.BaseCoroutinePresenter import eu.kanade.tachiyomi.ui.more.stats.StatsHelper.getReadDuration import kotlinx.coroutines.runBlocking import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy import yokai.domain.manga.interactor.GetLibraryManga +import yokai.domain.track.interactor.GetTrack import yokai.i18n.MR import yokai.util.lang.getString @@ -32,8 +34,9 @@ class StatsPresenter( private val trackManager: TrackManager = Injekt.get(), private val downloadManager: DownloadManager = Injekt.get(), private val sourceManager: SourceManager = Injekt.get(), -) { +): BaseCoroutinePresenter() { private val getLibraryManga: GetLibraryManga by injectLazy() + private val getTrack: GetTrack by injectLazy() private val libraryMangas = getLibrary() val mangaDistinct = libraryMangas.distinct() @@ -43,7 +46,7 @@ class StatsPresenter( } fun getTracks(manga: Manga): MutableList { - return db.getTracks(manga).executeAsBlocking() + return runBlocking { getTrack.awaitAllByMangaId(manga.id) }.toMutableList() } fun getLoggedTrackers(): List { 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 4146f77214..4cb2695961 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 @@ -39,6 +39,7 @@ import yokai.util.lang.getString import java.util.* import java.util.concurrent.* import kotlin.math.roundToInt +import yokai.domain.track.interactor.GetTrack class StatsDetailsPresenter( private val db: DatabaseHelper = Injekt.get(), @@ -47,6 +48,7 @@ class StatsDetailsPresenter( private val sourceManager: SourceManager = Injekt.get(), ) : BaseCoroutinePresenter() { private val getLibraryManga: GetLibraryManga by injectLazy() + private val getTrack: GetTrack by injectLazy() private val context get() = view?.view?.context ?: prefs.context @@ -557,7 +559,7 @@ class StatsDetailsPresenter( } fun getTracks(manga: Manga): MutableList { - return db.getTracks(manga).executeAsBlocking() + return runBlocking { getTrack.awaitAllByMangaId(manga.id) }.toMutableList() } fun getLibrary(): MutableList { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt index 1d313f41d3..fa8433ff23 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt @@ -88,6 +88,7 @@ import yokai.domain.manga.interactor.InsertManga import yokai.domain.manga.interactor.UpdateManga import yokai.domain.manga.models.MangaUpdate import yokai.domain.storage.StorageManager +import yokai.domain.track.interactor.GetTrack import yokai.i18n.MR import yokai.util.lang.getString @@ -113,6 +114,7 @@ class ReaderViewModel( private val updateManga: UpdateManga by injectLazy() private val getHistory: GetHistory by injectLazy() private val upsertHistory: UpsertHistory by injectLazy() + private val getTrack: GetTrack by injectLazy() private val mutableState = MutableStateFlow(State()) val state = mutableState.asStateFlow() @@ -178,11 +180,7 @@ class ReaderViewModel( private var scope = CoroutineScope(Job() + Dispatchers.Default) private var hasTrackers: Boolean = false - private val checkTrackers: (Manga) -> Unit = { manga -> - val tracks = db.getTracks(manga).executeAsBlocking() - - hasTrackers = tracks.size > 0 - } + private suspend fun checkTrackers(manga: Manga) = getTrack.awaitAllByMangaId(manga.id).isNotEmpty() init { var secondRun = false @@ -251,7 +249,7 @@ class ReaderViewModel( chapterId = initialChapterId } - checkTrackers(manga) + hasTrackers = checkTrackers(manga) NotificationReceiver.dismissNotification( preferences.context, diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/MangaExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/MangaExtensions.kt index f52326de3f..8d70315b47 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/MangaExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/MangaExtensions.kt @@ -42,9 +42,12 @@ import eu.kanade.tachiyomi.util.view.withFadeTransaction import eu.kanade.tachiyomi.widget.TriStateCheckBox import java.util.Date import java.util.Locale +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import yokai.domain.chapter.interactor.GetChapter +import yokai.domain.manga.interactor.GetManga import yokai.i18n.MR import yokai.util.lang.getString import android.R as AR @@ -144,20 +147,16 @@ fun Manga.addOrRemoveToFavorites( onMangaAdded: (Pair?) -> Unit, onMangaMoved: () -> Unit, onMangaDeleted: () -> Unit, + getManga: GetManga = Injekt.get() ): Snackbar? { if (!favorite) { if (checkForDupes) { - // TODO - /* - val duplicateManga = runBlocking(Dispatchers.IO) { handler.awaitOne { - mangasQueries.findDuplicateFavorite( + val duplicateManga = runBlocking(Dispatchers.IO) { + getManga.awaitDuplicateFavorite( this@addOrRemoveToFavorites.title, this@addOrRemoveToFavorites.source, - Manga::mapper, ) - } } - */ - val duplicateManga = db.getDuplicateLibraryManga(this).executeAsBlocking() + } if (duplicateManga != null) { showAddDuplicateDialog( this, diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterTrackSync.kt b/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterTrackSync.kt index cff59008dc..45fbf39873 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterTrackSync.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterTrackSync.kt @@ -19,6 +19,7 @@ import kotlinx.coroutines.delay import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import yokai.domain.chapter.interactor.UpdateChapter +import yokai.domain.track.interactor.GetTrack /** * Helper method for syncing a remote track with the local chapters, and back @@ -98,9 +99,10 @@ suspend fun updateTrackChapterRead( mangaId: Long?, newChapterRead: Float, retryWhenOnline: Boolean = false, + getTrack: GetTrack = Injekt.get() ): List> { val trackManager = Injekt.get() - val trackList = db.getTracks(mangaId).executeAsBlocking() + val trackList = getTrack.awaitAllByMangaId(mangaId) val failures = mutableListOf>() trackList.map { track -> val service = trackManager.getService(track.sync_id) diff --git a/app/src/main/java/yokai/core/di/DomainModule.kt b/app/src/main/java/yokai/core/di/DomainModule.kt index 6f91628b87..a6ce9c2a8e 100644 --- a/app/src/main/java/yokai/core/di/DomainModule.kt +++ b/app/src/main/java/yokai/core/di/DomainModule.kt @@ -7,6 +7,7 @@ import yokai.data.extension.repo.ExtensionRepoRepositoryImpl import yokai.data.history.HistoryRepositoryImpl import yokai.data.library.custom.CustomMangaRepositoryImpl import yokai.data.manga.MangaRepositoryImpl +import yokai.data.track.TrackRepositoryImpl import yokai.domain.category.CategoryRepository import yokai.domain.category.interactor.GetCategories import yokai.domain.chapter.ChapterRepository @@ -37,10 +38,15 @@ import yokai.domain.manga.interactor.GetManga import yokai.domain.manga.interactor.InsertManga import yokai.domain.manga.interactor.UpdateManga import yokai.domain.recents.interactor.GetRecents +import yokai.domain.track.TrackRepository +import yokai.domain.track.interactor.GetTrack fun domainModule() = module { factory { TrustExtension(get(), get()) } + single { CategoryRepositoryImpl(get()) } + factory { GetCategories(get()) } + single { ExtensionRepoRepositoryImpl(get()) } factory { CreateExtensionRepo(get()) } factory { DeleteExtensionRepo(get()) } @@ -74,6 +80,6 @@ fun domainModule() = module { factory { GetRecents(get(), get()) } - single { CategoryRepositoryImpl(get()) } - factory { GetCategories(get()) } + single { TrackRepositoryImpl(get()) } + factory { GetTrack(get()) } } diff --git a/app/src/main/java/yokai/data/category/CategoryRepositoryImpl.kt b/app/src/main/java/yokai/data/category/CategoryRepositoryImpl.kt index d5ccd8e35f..f910a258c9 100644 --- a/app/src/main/java/yokai/data/category/CategoryRepositoryImpl.kt +++ b/app/src/main/java/yokai/data/category/CategoryRepositoryImpl.kt @@ -9,6 +9,9 @@ class CategoryRepositoryImpl(private val handler: DatabaseHandler) : CategoryRep override suspend fun getAll(): List = handler.awaitList { categoriesQueries.findAll(Category::mapper) } + override suspend fun getAllByMangaId(mangaId: Long): List = + handler.awaitList { categoriesQueries.findAllByMangaId(mangaId, Category::mapper) } + override fun getAllAsFlow(): Flow> = handler.subscribeToList { categoriesQueries.findAll(Category::mapper) } } diff --git a/app/src/main/java/yokai/data/manga/MangaRepositoryImpl.kt b/app/src/main/java/yokai/data/manga/MangaRepositoryImpl.kt index f8e3d0e2ff..84ef9e1a3d 100644 --- a/app/src/main/java/yokai/data/manga/MangaRepositoryImpl.kt +++ b/app/src/main/java/yokai/data/manga/MangaRepositoryImpl.kt @@ -35,6 +35,9 @@ class MangaRepositoryImpl(private val handler: DatabaseHandler) : MangaRepositor override fun getLibraryMangaAsFlow(): Flow> = handler.subscribeToList { library_viewQueries.findAll(LibraryManga::mapper) } + override suspend fun getDuplicateFavorite(title: String, source: Long): Manga? = + handler.awaitOneOrNull { mangasQueries.findDuplicateFavorite(title, source, Manga::mapper) } + override suspend fun update(update: MangaUpdate): Boolean { return try { partialUpdate(update) diff --git a/app/src/main/java/yokai/data/track/TrackRepositoryImpl.kt b/app/src/main/java/yokai/data/track/TrackRepositoryImpl.kt new file mode 100644 index 0000000000..0c6dc2ee2d --- /dev/null +++ b/app/src/main/java/yokai/data/track/TrackRepositoryImpl.kt @@ -0,0 +1,10 @@ +package yokai.data.track + +import eu.kanade.tachiyomi.data.database.models.Track +import yokai.data.DatabaseHandler +import yokai.domain.track.TrackRepository + +class TrackRepositoryImpl(private val handler: DatabaseHandler) : TrackRepository { + override suspend fun getAllByMangaId(mangaId: Long): List = + handler.awaitList { manga_syncQueries.getAllByMangaId(mangaId, Track::mapper) } +} diff --git a/app/src/main/java/yokai/domain/category/CategoryRepository.kt b/app/src/main/java/yokai/domain/category/CategoryRepository.kt index d64a0eb6d7..11a9ace577 100644 --- a/app/src/main/java/yokai/domain/category/CategoryRepository.kt +++ b/app/src/main/java/yokai/domain/category/CategoryRepository.kt @@ -5,5 +5,6 @@ import kotlinx.coroutines.flow.Flow interface CategoryRepository { suspend fun getAll(): List + suspend fun getAllByMangaId(mangaId: Long): List fun getAllAsFlow(): Flow> } diff --git a/app/src/main/java/yokai/domain/category/interactor/GetCategories.kt b/app/src/main/java/yokai/domain/category/interactor/GetCategories.kt index f5902d8c7c..b9347170b6 100644 --- a/app/src/main/java/yokai/domain/category/interactor/GetCategories.kt +++ b/app/src/main/java/yokai/domain/category/interactor/GetCategories.kt @@ -6,5 +6,6 @@ class GetCategories( private val categoryRepository: CategoryRepository, ) { suspend fun await() = categoryRepository.getAll() + suspend fun awaitByMangaId(mangaId: Long) = categoryRepository.getAllByMangaId(mangaId) fun subscribe() = categoryRepository.getAllAsFlow() } diff --git a/app/src/main/java/yokai/domain/manga/MangaRepository.kt b/app/src/main/java/yokai/domain/manga/MangaRepository.kt index 715495c888..7d86f341b4 100644 --- a/app/src/main/java/yokai/domain/manga/MangaRepository.kt +++ b/app/src/main/java/yokai/domain/manga/MangaRepository.kt @@ -11,6 +11,7 @@ interface MangaRepository { suspend fun getMangaById(id: Long): Manga? suspend fun getFavorites(): List suspend fun getReadNotFavorites(): List + suspend fun getDuplicateFavorite(title: String, source: Long): Manga? fun getMangaListAsFlow(): Flow> suspend fun getLibraryManga(): List fun getLibraryMangaAsFlow(): Flow> diff --git a/app/src/main/java/yokai/domain/manga/interactor/GetManga.kt b/app/src/main/java/yokai/domain/manga/interactor/GetManga.kt index 22211f69ed..588044c9ed 100644 --- a/app/src/main/java/yokai/domain/manga/interactor/GetManga.kt +++ b/app/src/main/java/yokai/domain/manga/interactor/GetManga.kt @@ -12,4 +12,5 @@ class GetManga ( suspend fun awaitById(id: Long) = mangaRepository.getMangaById(id) suspend fun awaitFavorites() = mangaRepository.getFavorites() suspend fun awaitReadNotFavorites() = mangaRepository.getReadNotFavorites() + suspend fun awaitDuplicateFavorite(title: String, source: Long) = mangaRepository.getDuplicateFavorite(title, source) } diff --git a/app/src/main/java/yokai/domain/track/TrackRepository.kt b/app/src/main/java/yokai/domain/track/TrackRepository.kt new file mode 100644 index 0000000000..89332a1df6 --- /dev/null +++ b/app/src/main/java/yokai/domain/track/TrackRepository.kt @@ -0,0 +1,7 @@ +package yokai.domain.track + +import eu.kanade.tachiyomi.data.database.models.Track + +interface TrackRepository { + suspend fun getAllByMangaId(mangaId: Long): List +} diff --git a/app/src/main/java/yokai/domain/track/interactor/GetTrack.kt b/app/src/main/java/yokai/domain/track/interactor/GetTrack.kt new file mode 100644 index 0000000000..46bea69cc3 --- /dev/null +++ b/app/src/main/java/yokai/domain/track/interactor/GetTrack.kt @@ -0,0 +1,9 @@ +package yokai.domain.track.interactor + +import yokai.domain.track.TrackRepository + +class GetTrack( + private val trackRepository: TrackRepository, +) { + suspend fun awaitAllByMangaId(mangaId: Long?) = mangaId?.let { trackRepository.getAllByMangaId(it) } ?: listOf() +} diff --git a/data/src/commonMain/sqldelight/tachiyomi/data/categories.sq b/data/src/commonMain/sqldelight/tachiyomi/data/categories.sq index f51171eda6..d8a03606b7 100644 --- a/data/src/commonMain/sqldelight/tachiyomi/data/categories.sq +++ b/data/src/commonMain/sqldelight/tachiyomi/data/categories.sq @@ -10,3 +10,8 @@ findAll: SELECT * FROM categories ORDER BY sort; + +findAllByMangaId: +SELECT categories.* FROM categories +JOIN mangas_categories ON categories._id = mangas_categories.category_id +WHERE mangas_categories.manga_id = :mangaId; diff --git a/data/src/commonMain/sqldelight/tachiyomi/data/manga_sync.sq b/data/src/commonMain/sqldelight/tachiyomi/data/manga_sync.sq index 7e95fbb802..e6f9e330f3 100644 --- a/data/src/commonMain/sqldelight/tachiyomi/data/manga_sync.sq +++ b/data/src/commonMain/sqldelight/tachiyomi/data/manga_sync.sq @@ -1,5 +1,4 @@ import kotlin.Float; -import kotlin.Long; CREATE TABLE manga_sync( _id INTEGER NOT NULL PRIMARY KEY, @@ -11,11 +10,16 @@ CREATE TABLE manga_sync( last_chapter_read REAL NOT NULL, total_chapters INTEGER NOT NULL, status INTEGER NOT NULL, - score REAL AS Float NOT NULL, + score REAL NOT NULL, remote_url TEXT NOT NULL, - start_date INTEGER AS Long NOT NULL, - finish_date INTEGER AS Long NOT NULL, + start_date INTEGER NOT NULL, + finish_date INTEGER NOT NULL, UNIQUE (manga_id, sync_id) ON CONFLICT REPLACE, FOREIGN KEY(manga_id) REFERENCES mangas (_id) ON DELETE CASCADE ); + +getAllByMangaId: +SELECT * +FROM manga_sync +WHERE manga_id = :mangaId;