diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 270980700..aaf78cb1a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -148,6 +148,7 @@ dependencies { implementation(androidx.paging.runtime) implementation(androidx.paging.compose) + implementation(libs.bundles.sqlite) implementation(androidx.sqlite) implementation(libs.sqldelight.android.driver) implementation(libs.sqldelight.coroutines) @@ -201,11 +202,6 @@ dependencies { implementation(libs.unifile) implementation(libs.junrar) - // Database - implementation(libs.bundles.sqlite) - implementation("com.github.inorichi.storio:storio-common:8be19de@aar") - implementation("com.github.inorichi.storio:storio-sqlite:8be19de@aar") - // Preferences implementation(libs.preferencektx) implementation(libs.flowpreferences) diff --git a/app/src/main/java/eu/kanade/data/AndroidDatabaseHandler.kt b/app/src/main/java/eu/kanade/data/AndroidDatabaseHandler.kt index 52656f2b7..468f8713e 100644 --- a/app/src/main/java/eu/kanade/data/AndroidDatabaseHandler.kt +++ b/app/src/main/java/eu/kanade/data/AndroidDatabaseHandler.kt @@ -91,9 +91,5 @@ class AndroidDatabaseHandler( // SY --> fun getLibraryQuery() = LibraryQuery(driver) - - fun rawQuery(query: (SqlDriver) -> Unit) { - return query(driver) - } // SY <-- } diff --git a/app/src/main/java/eu/kanade/data/manga/MangaMapper.kt b/app/src/main/java/eu/kanade/data/manga/MangaMapper.kt index dd6532040..3a2698dbc 100644 --- a/app/src/main/java/eu/kanade/data/manga/MangaMapper.kt +++ b/app/src/main/java/eu/kanade/data/manga/MangaMapper.kt @@ -1,7 +1,9 @@ package eu.kanade.data.manga +import eu.kanade.data.listOfStringsAndAdapter import eu.kanade.domain.chapter.model.Chapter import eu.kanade.domain.manga.model.Manga +import eu.kanade.tachiyomi.data.database.models.LibraryManga val mangaMapper: (Long, Long, String, String?, String?, String?, List?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, List?) -> Manga = { id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, _, initialized, viewer, chapterFlags, coverLastModified, dateAdded, filteredScanlators -> @@ -71,3 +73,30 @@ val mangaChapterMapper: (Long, Long, String, String?, String?, String?, List?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, List?, Long, Long, Long) -> LibraryManga = + { _id, source, url, artist, author, description, genre, title, status, thumbnail_url, favorite, last_update, next_update, initialized, viewer, chapter_flags, cover_last_modified, date_added, filtered_scanlators, unread_count, read_count, category -> + LibraryManga().apply { + this.id = _id + this.source = source + this.url = url + this.artist = artist + this.author = author + this.description = description + this.genre = genre?.joinToString() + this.title = title + this.status = status.toInt() + this.thumbnail_url = thumbnail_url + this.favorite = favorite + this.last_update = last_update ?: 0 + this.initialized = initialized + this.viewer_flags = viewer.toInt() + this.chapter_flags = chapter_flags.toInt() + this.cover_last_modified = cover_last_modified + this.date_added = date_added + this.filtered_scanlators = filtered_scanlators?.let(listOfStringsAndAdapter::encode) + this.unreadCount = unread_count.toInt() + this.readCount = read_count.toInt() + this.category = category.toInt() + } + } diff --git a/app/src/main/java/eu/kanade/data/manga/MangaMergeRepositoryImpl.kt b/app/src/main/java/eu/kanade/data/manga/MangaMergeRepositoryImpl.kt index 4a3830459..1d7a8df70 100644 --- a/app/src/main/java/eu/kanade/data/manga/MangaMergeRepositoryImpl.kt +++ b/app/src/main/java/eu/kanade/data/manga/MangaMergeRepositoryImpl.kt @@ -72,4 +72,57 @@ class MangaMergeRepositoryImpl( } } } + + override suspend fun insert(reference: MergedMangaReference): Long? { + return handler.awaitOneOrNull { + mergedQueries.insert( + infoManga = reference.isInfoManga, + getChapterUpdates = reference.getChapterUpdates, + chapterSortMode = reference.chapterSortMode.toLong(), + chapterPriority = reference.chapterPriority.toLong(), + downloadChapters = reference.downloadChapters, + mergeId = reference.mergeId!!, + mergeUrl = reference.mergeUrl, + mangaId = reference.mangaId, + mangaUrl = reference.mangaUrl, + mangaSource = reference.mangaSourceId, + ) + mergedQueries.selectLastInsertedRowId() + } + } + + override suspend fun insertAll(references: List) { + handler.await(true) { + references.forEach { reference -> + mergedQueries.insert( + infoManga = reference.isInfoManga, + getChapterUpdates = reference.getChapterUpdates, + chapterSortMode = reference.chapterSortMode.toLong(), + chapterPriority = reference.chapterPriority.toLong(), + downloadChapters = reference.downloadChapters, + mergeId = reference.mergeId!!, + mergeUrl = reference.mergeUrl, + mangaId = reference.mangaId, + mangaUrl = reference.mangaUrl, + mangaSource = reference.mangaSourceId, + ) + } + } + } + + override suspend fun deleteById(id: Long) { + handler.await { + mergedQueries.deleteById(id) + } + } + + override suspend fun deleteByMergeId(mergeId: Long) { + handler.await { + mergedQueries.deleteByMergeId(mergeId) + } + } + + override suspend fun getMergeMangaForDownloading(mergeId: Long): List { + return handler.awaitList { mergedQueries.selectMergedMangasForDownloadingById(mergeId, mangaMapper) } + } } diff --git a/app/src/main/java/eu/kanade/data/manga/MangaRepositoryImpl.kt b/app/src/main/java/eu/kanade/data/manga/MangaRepositoryImpl.kt index ad6b6cc1f..04927c13a 100644 --- a/app/src/main/java/eu/kanade/data/manga/MangaRepositoryImpl.kt +++ b/app/src/main/java/eu/kanade/data/manga/MangaRepositoryImpl.kt @@ -1,5 +1,6 @@ package eu.kanade.data.manga +import eu.kanade.data.AndroidDatabaseHandler import eu.kanade.data.DatabaseHandler import eu.kanade.data.listOfStringsAdapter import eu.kanade.data.listOfStringsAndAdapter @@ -7,6 +8,7 @@ import eu.kanade.data.toLong import eu.kanade.domain.manga.model.Manga import eu.kanade.domain.manga.model.MangaUpdate import eu.kanade.domain.manga.repository.MangaRepository +import eu.kanade.tachiyomi.data.database.models.LibraryManga import eu.kanade.tachiyomi.util.system.logcat import kotlinx.coroutines.flow.Flow import logcat.LogPriority @@ -19,26 +21,28 @@ class MangaRepositoryImpl( return handler.awaitOne { mangasQueries.getMangaById(id, mangaMapper) } } - override suspend fun subscribeMangaById(id: Long): Flow { - return handler.subscribeToOne { mangasQueries.getMangaById(id, mangaMapper) } - } - override suspend fun getMangaByIdAsFlow(id: Long): Flow { return handler.subscribeToOne { mangasQueries.getMangaById(id, mangaMapper) } } - override suspend fun getMangaByUrlAndSource(url: String, sourceId: Long): Manga? { + override suspend fun getMangaByUrlAndSourceId(url: String, sourceId: Long): Manga? { return handler.awaitOneOrNull { mangasQueries.getMangaByUrlAndSource(url, sourceId, mangaMapper) } } - override suspend fun subscribeMangaByUrlAndSource(url: String, sourceId: Long): Flow { - return handler.subscribeToOneOrNull { mangasQueries.getMangaByUrlAndSource(url, sourceId, mangaMapper) } - } - override suspend fun getFavorites(): List { return handler.awaitList { mangasQueries.getFavorites(mangaMapper) } } + override suspend fun getLibraryManga(): List { + return handler.awaitList { (handler as AndroidDatabaseHandler).getLibraryQuery() } + // return handler.awaitList { mangasQueries.getLibrary(libraryManga) } + } + + override fun getLibraryMangaAsFlow(): Flow> { + return handler.subscribeToList { (handler as AndroidDatabaseHandler).getLibraryQuery() } + // return handler.subscribeToList { mangasQueries.getLibrary(libraryManga) } + } + override fun getFavoritesBySourceId(sourceId: Long): Flow> { return handler.subscribeToList { mangasQueries.getFavoriteBySourceId(sourceId, mangaMapper) } } @@ -68,6 +72,31 @@ class MangaRepositoryImpl( } } + override suspend fun insert(manga: Manga): Long? { + return handler.awaitOneOrNull { + mangasQueries.insert( + source = manga.source, + url = manga.url, + artist = manga.artist, + author = manga.author, + description = manga.description, + genre = manga.genre, + title = manga.title, + status = manga.status, + thumbnail_url = manga.thumbnailUrl, + favorite = manga.favorite, + last_update = manga.lastUpdate, + next_update = null, + initialized = manga.initialized, + viewer = manga.viewerFlags, + chapter_flags = manga.chapterFlags, + cover_last_modified = manga.coverLastModified, + date_added = manga.dateAdded, + ) + mangasQueries.selectLastInsertedRowId() + } + } + override suspend fun update(update: MangaUpdate): Boolean { return try { partialUpdate(update) @@ -115,11 +144,15 @@ class MangaRepositoryImpl( } } - override suspend fun getMangaBySource(sourceId: Long): List { + override suspend fun getMangaBySourceId(sourceId: Long): List { return handler.awaitList { mangasQueries.getBySource(sourceId, mangaMapper) } } override suspend fun getAll(): List { return handler.awaitList { mangasQueries.getAll(mangaMapper) } } + + override suspend fun deleteManga(mangaId: Long) { + handler.await { mangasQueries.deleteById(mangaId) } + } } diff --git a/app/src/main/java/eu/kanade/domain/DomainModule.kt b/app/src/main/java/eu/kanade/domain/DomainModule.kt index 5f6e93ba2..804bb6b49 100644 --- a/app/src/main/java/eu/kanade/domain/DomainModule.kt +++ b/app/src/main/java/eu/kanade/domain/DomainModule.kt @@ -32,10 +32,13 @@ import eu.kanade.domain.history.interactor.UpsertHistory import eu.kanade.domain.history.repository.HistoryRepository import eu.kanade.domain.manga.interactor.GetDuplicateLibraryManga import eu.kanade.domain.manga.interactor.GetFavorites +import eu.kanade.domain.manga.interactor.GetLibraryManga import eu.kanade.domain.manga.interactor.GetManga import eu.kanade.domain.manga.interactor.GetMangaWithChapters +import eu.kanade.domain.manga.interactor.InsertManga import eu.kanade.domain.manga.interactor.ResetViewerFlags import eu.kanade.domain.manga.interactor.SetMangaChapterFlags +import eu.kanade.domain.manga.interactor.SetMangaViewerFlags import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.domain.manga.repository.MangaRepository import eu.kanade.domain.source.interactor.GetEnabledSources @@ -71,11 +74,14 @@ class DomainModule : InjektModule { addSingletonFactory { MangaRepositoryImpl(get()) } addFactory { GetDuplicateLibraryManga(get()) } addFactory { GetFavorites(get()) } + addFactory { GetLibraryManga(get()) } addFactory { GetMangaWithChapters(get(), get()) } addFactory { GetManga(get()) } addFactory { GetNextChapter(get()) } addFactory { ResetViewerFlags(get()) } addFactory { SetMangaChapterFlags(get()) } + addFactory { SetMangaViewerFlags(get()) } + addFactory { InsertManga(get()) } addFactory { UpdateManga(get()) } addFactory { SetMangaCategories(get()) } diff --git a/app/src/main/java/eu/kanade/domain/SYDomainModule.kt b/app/src/main/java/eu/kanade/domain/SYDomainModule.kt index 813f3b451..b7e3ed377 100644 --- a/app/src/main/java/eu/kanade/domain/SYDomainModule.kt +++ b/app/src/main/java/eu/kanade/domain/SYDomainModule.kt @@ -3,8 +3,12 @@ package eu.kanade.domain import eu.kanade.data.manga.FavoritesEntryRepositoryImpl import eu.kanade.data.manga.MangaMergeRepositoryImpl import eu.kanade.data.manga.MangaMetadataRepositoryImpl +import eu.kanade.domain.chapter.interactor.DeleteChapters import eu.kanade.domain.chapter.interactor.GetMergedChapterByMangaId +import eu.kanade.domain.manga.interactor.DeleteByMergeId import eu.kanade.domain.manga.interactor.DeleteFavoriteEntries +import eu.kanade.domain.manga.interactor.DeleteMangaById +import eu.kanade.domain.manga.interactor.DeleteMergeById import eu.kanade.domain.manga.interactor.GetAllManga import eu.kanade.domain.manga.interactor.GetExhFavoriteMangaWithMetadata import eu.kanade.domain.manga.interactor.GetFavoriteEntries @@ -13,12 +17,15 @@ import eu.kanade.domain.manga.interactor.GetIdsOfFavoriteMangaWithMetadata import eu.kanade.domain.manga.interactor.GetMangaBySource import eu.kanade.domain.manga.interactor.GetMergedManga import eu.kanade.domain.manga.interactor.GetMergedMangaById +import eu.kanade.domain.manga.interactor.GetMergedMangaForDownloading import eu.kanade.domain.manga.interactor.GetMergedReferencesById import eu.kanade.domain.manga.interactor.GetSearchTags import eu.kanade.domain.manga.interactor.GetSearchTitles import eu.kanade.domain.manga.interactor.InsertFavoriteEntries import eu.kanade.domain.manga.interactor.InsertFlatMetadata +import eu.kanade.domain.manga.interactor.InsertMergedReference import eu.kanade.domain.manga.interactor.SetMangaFilteredScanlators +import eu.kanade.domain.manga.interactor.UpdateMergedSettings import eu.kanade.domain.manga.repository.FavoritesEntryRepository import eu.kanade.domain.manga.repository.MangaMergeRepository import eu.kanade.domain.manga.repository.MangaMetadataRepository @@ -44,6 +51,8 @@ class SYDomainModule : InjektModule { addFactory { SetMangaFilteredScanlators(get()) } addFactory { GetAllManga(get()) } addFactory { GetMangaBySource(get()) } + addFactory { DeleteChapters(get()) } + addFactory { DeleteMangaById(get()) } addSingletonFactory { MangaMetadataRepositoryImpl(get()) } addFactory { GetFlatMetadataById(get()) } @@ -58,6 +67,11 @@ class SYDomainModule : InjektModule { addFactory { GetMergedMangaById(get()) } addFactory { GetMergedReferencesById(get()) } addFactory { GetMergedChapterByMangaId(get()) } + addFactory { InsertMergedReference(get()) } + addFactory { UpdateMergedSettings(get()) } + addFactory { DeleteByMergeId(get()) } + addFactory { DeleteMergeById(get()) } + addFactory { GetMergedMangaForDownloading(get()) } addSingletonFactory { FavoritesEntryRepositoryImpl(get()) } addFactory { GetFavoriteEntries(get()) } diff --git a/app/src/main/java/eu/kanade/domain/chapter/interactor/DeleteChapters.kt b/app/src/main/java/eu/kanade/domain/chapter/interactor/DeleteChapters.kt new file mode 100644 index 000000000..fb109aa1a --- /dev/null +++ b/app/src/main/java/eu/kanade/domain/chapter/interactor/DeleteChapters.kt @@ -0,0 +1,12 @@ +package eu.kanade.domain.chapter.interactor + +import eu.kanade.domain.chapter.repository.ChapterRepository + +class DeleteChapters( + private val chapterRepository: ChapterRepository, +) { + + suspend fun await(chapters: List) { + chapterRepository.removeChaptersWithIds(chapters) + } +} diff --git a/app/src/main/java/eu/kanade/domain/manga/interactor/DeleteByMergeId.kt b/app/src/main/java/eu/kanade/domain/manga/interactor/DeleteByMergeId.kt new file mode 100644 index 000000000..c39b6e986 --- /dev/null +++ b/app/src/main/java/eu/kanade/domain/manga/interactor/DeleteByMergeId.kt @@ -0,0 +1,12 @@ +package eu.kanade.domain.manga.interactor + +import eu.kanade.domain.manga.repository.MangaMergeRepository + +class DeleteByMergeId( + private val mangaMergeRepository: MangaMergeRepository, +) { + + suspend fun await(id: Long) { + return mangaMergeRepository.deleteByMergeId(id) + } +} diff --git a/app/src/main/java/eu/kanade/domain/manga/interactor/DeleteMangaById.kt b/app/src/main/java/eu/kanade/domain/manga/interactor/DeleteMangaById.kt new file mode 100644 index 000000000..78ea3eab1 --- /dev/null +++ b/app/src/main/java/eu/kanade/domain/manga/interactor/DeleteMangaById.kt @@ -0,0 +1,12 @@ +package eu.kanade.domain.manga.interactor + +import eu.kanade.domain.manga.repository.MangaRepository + +class DeleteMangaById( + private val mangaRepository: MangaRepository, +) { + + suspend fun await(id: Long) { + return mangaRepository.deleteManga(id) + } +} diff --git a/app/src/main/java/eu/kanade/domain/manga/interactor/DeleteMergeById.kt b/app/src/main/java/eu/kanade/domain/manga/interactor/DeleteMergeById.kt new file mode 100644 index 000000000..9d15efccf --- /dev/null +++ b/app/src/main/java/eu/kanade/domain/manga/interactor/DeleteMergeById.kt @@ -0,0 +1,12 @@ +package eu.kanade.domain.manga.interactor + +import eu.kanade.domain.manga.repository.MangaMergeRepository + +class DeleteMergeById( + private val mangaMergeRepository: MangaMergeRepository, +) { + + suspend fun await(id: Long) { + return mangaMergeRepository.deleteById(id) + } +} diff --git a/app/src/main/java/eu/kanade/domain/manga/interactor/GetLibraryManga.kt b/app/src/main/java/eu/kanade/domain/manga/interactor/GetLibraryManga.kt new file mode 100644 index 000000000..e7e56401c --- /dev/null +++ b/app/src/main/java/eu/kanade/domain/manga/interactor/GetLibraryManga.kt @@ -0,0 +1,18 @@ +package eu.kanade.domain.manga.interactor + +import eu.kanade.domain.manga.repository.MangaRepository +import eu.kanade.tachiyomi.data.database.models.LibraryManga +import kotlinx.coroutines.flow.Flow + +class GetLibraryManga( + private val mangaRepository: MangaRepository, +) { + + suspend fun await(): List { + return mangaRepository.getLibraryManga() + } + + fun subscribe(): Flow> { + return mangaRepository.getLibraryMangaAsFlow() + } +} diff --git a/app/src/main/java/eu/kanade/domain/manga/interactor/GetManga.kt b/app/src/main/java/eu/kanade/domain/manga/interactor/GetManga.kt index f4ccee492..da787116b 100644 --- a/app/src/main/java/eu/kanade/domain/manga/interactor/GetManga.kt +++ b/app/src/main/java/eu/kanade/domain/manga/interactor/GetManga.kt @@ -20,19 +20,10 @@ class GetManga( } suspend fun subscribe(id: Long): Flow { - return mangaRepository.subscribeMangaById(id) + return mangaRepository.getMangaByIdAsFlow(id) } suspend fun await(url: String, sourceId: Long): Manga? { - return try { - mangaRepository.getMangaByUrlAndSource(url, sourceId) - } catch (e: Exception) { - logcat(LogPriority.ERROR, e) - null - } - } - - suspend fun subscribe(url: String, sourceId: Long): Flow { - return mangaRepository.subscribeMangaByUrlAndSource(url, sourceId) + return mangaRepository.getMangaByUrlAndSourceId(url, sourceId) } } diff --git a/app/src/main/java/eu/kanade/domain/manga/interactor/GetMangaBySource.kt b/app/src/main/java/eu/kanade/domain/manga/interactor/GetMangaBySource.kt index db0616a9a..8fdea25af 100644 --- a/app/src/main/java/eu/kanade/domain/manga/interactor/GetMangaBySource.kt +++ b/app/src/main/java/eu/kanade/domain/manga/interactor/GetMangaBySource.kt @@ -8,6 +8,6 @@ class GetMangaBySource( ) { suspend fun await(sourceId: Long): List { - return mangaRepository.getMangaBySource(sourceId) + return mangaRepository.getMangaBySourceId(sourceId) } } diff --git a/app/src/main/java/eu/kanade/domain/manga/interactor/GetMangaWithChapters.kt b/app/src/main/java/eu/kanade/domain/manga/interactor/GetMangaWithChapters.kt index cd0375203..0386a11fc 100644 --- a/app/src/main/java/eu/kanade/domain/manga/interactor/GetMangaWithChapters.kt +++ b/app/src/main/java/eu/kanade/domain/manga/interactor/GetMangaWithChapters.kt @@ -14,7 +14,7 @@ class GetMangaWithChapters( suspend fun subscribe(id: Long): Flow>> { return combine( - mangaRepository.subscribeMangaById(id), + mangaRepository.getMangaByIdAsFlow(id), chapterRepository.getChapterByMangaIdAsFlow(id), ) { manga, chapters -> Pair(manga, chapters) diff --git a/app/src/main/java/eu/kanade/domain/manga/interactor/GetMergedMangaForDownloading.kt b/app/src/main/java/eu/kanade/domain/manga/interactor/GetMergedMangaForDownloading.kt new file mode 100644 index 000000000..69694fa0d --- /dev/null +++ b/app/src/main/java/eu/kanade/domain/manga/interactor/GetMergedMangaForDownloading.kt @@ -0,0 +1,13 @@ +package eu.kanade.domain.manga.interactor + +import eu.kanade.domain.manga.model.Manga +import eu.kanade.domain.manga.repository.MangaMergeRepository + +class GetMergedMangaForDownloading( + private val mangaMergeRepository: MangaMergeRepository, +) { + + suspend fun await(mergeId: Long): List { + return mangaMergeRepository.getMergeMangaForDownloading(mergeId) + } +} diff --git a/app/src/main/java/eu/kanade/domain/manga/interactor/InsertManga.kt b/app/src/main/java/eu/kanade/domain/manga/interactor/InsertManga.kt new file mode 100644 index 000000000..2477d91f2 --- /dev/null +++ b/app/src/main/java/eu/kanade/domain/manga/interactor/InsertManga.kt @@ -0,0 +1,13 @@ +package eu.kanade.domain.manga.interactor + +import eu.kanade.domain.manga.model.Manga +import eu.kanade.domain.manga.repository.MangaRepository + +class InsertManga( + private val mangaRepository: MangaRepository, +) { + + suspend fun await(manga: Manga): Long? { + return mangaRepository.insert(manga) + } +} diff --git a/app/src/main/java/eu/kanade/domain/manga/interactor/InsertMergedReference.kt b/app/src/main/java/eu/kanade/domain/manga/interactor/InsertMergedReference.kt new file mode 100644 index 000000000..254bd1c53 --- /dev/null +++ b/app/src/main/java/eu/kanade/domain/manga/interactor/InsertMergedReference.kt @@ -0,0 +1,17 @@ +package eu.kanade.domain.manga.interactor + +import eu.kanade.domain.manga.repository.MangaMergeRepository +import exh.merged.sql.models.MergedMangaReference + +class InsertMergedReference( + private val mangaMergedRepository: MangaMergeRepository, +) { + + suspend fun await(reference: MergedMangaReference): Long? { + return mangaMergedRepository.insert(reference) + } + + suspend fun awaitAll(references: List) { + mangaMergedRepository.insertAll(references) + } +} diff --git a/app/src/main/java/eu/kanade/domain/manga/interactor/SetMangaViewerFlags.kt b/app/src/main/java/eu/kanade/domain/manga/interactor/SetMangaViewerFlags.kt new file mode 100644 index 000000000..a9f743a11 --- /dev/null +++ b/app/src/main/java/eu/kanade/domain/manga/interactor/SetMangaViewerFlags.kt @@ -0,0 +1,33 @@ +package eu.kanade.domain.manga.interactor + +import eu.kanade.domain.manga.model.MangaUpdate +import eu.kanade.domain.manga.repository.MangaRepository +import eu.kanade.tachiyomi.ui.reader.setting.OrientationType +import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType + +class SetMangaViewerFlags( + private val mangaRepository: MangaRepository, +) { + + suspend fun awaitSetMangaReadingMode(id: Long, flag: Long) { + mangaRepository.update( + MangaUpdate( + id = id, + viewerFlags = flag.setFlag(flag, ReadingModeType.MASK.toLong()), + ), + ) + } + + suspend fun awaitSetOrientationType(id: Long, flag: Long) { + mangaRepository.update( + MangaUpdate( + id = id, + viewerFlags = flag.setFlag(flag, OrientationType.MASK.toLong()), + ), + ) + } + + private fun Long.setFlag(flag: Long, mask: Long): Long { + return this and mask.inv() or (flag and mask) + } +} diff --git a/app/src/main/java/eu/kanade/domain/manga/interactor/UpdateMergedSettings.kt b/app/src/main/java/eu/kanade/domain/manga/interactor/UpdateMergedSettings.kt new file mode 100644 index 000000000..be27221c6 --- /dev/null +++ b/app/src/main/java/eu/kanade/domain/manga/interactor/UpdateMergedSettings.kt @@ -0,0 +1,17 @@ +package eu.kanade.domain.manga.interactor + +import eu.kanade.domain.manga.model.MergeMangaSettingsUpdate +import eu.kanade.domain.manga.repository.MangaMergeRepository + +class UpdateMergedSettings( + private val mangaMergeRepository: MangaMergeRepository, +) { + + suspend fun await(mergeUpdate: MergeMangaSettingsUpdate): Boolean { + return mangaMergeRepository.updateSettings(mergeUpdate) + } + + suspend fun awaitAll(values: List): Boolean { + return mangaMergeRepository.updateAllSettings(values) + } +} diff --git a/app/src/main/java/eu/kanade/domain/manga/model/Manga.kt b/app/src/main/java/eu/kanade/domain/manga/model/Manga.kt index 30ef51985..b05d132a3 100644 --- a/app/src/main/java/eu/kanade/domain/manga/model/Manga.kt +++ b/app/src/main/java/eu/kanade/domain/manga/model/Manga.kt @@ -214,6 +214,28 @@ fun Manga.toMangaInfo(): MangaInfo = MangaInfo( // SY <-- ) +fun Manga.toMangaUpdate(): MangaUpdate { + return MangaUpdate( + id = id, + source = source, + favorite = favorite, + lastUpdate = lastUpdate, + dateAdded = dateAdded, + viewerFlags = viewerFlags, + chapterFlags = chapterFlags, + coverLastModified = coverLastModified, + url = url, + title = title, + artist = artist, + author = author, + description = description, + genre = genre, + status = status, + thumbnailUrl = thumbnailUrl, + initialized = initialized, + ) +} + fun Manga.isLocal(): Boolean = source == LocalSource.ID fun Manga.hasCustomCover(coverCache: CoverCache = Injekt.get()): Boolean { diff --git a/app/src/main/java/eu/kanade/domain/manga/repository/MangaMergeRepository.kt b/app/src/main/java/eu/kanade/domain/manga/repository/MangaMergeRepository.kt index c6c7f76e3..d279880a2 100644 --- a/app/src/main/java/eu/kanade/domain/manga/repository/MangaMergeRepository.kt +++ b/app/src/main/java/eu/kanade/domain/manga/repository/MangaMergeRepository.kt @@ -21,4 +21,14 @@ interface MangaMergeRepository { suspend fun updateSettings(update: MergeMangaSettingsUpdate): Boolean suspend fun updateAllSettings(values: List): Boolean + + suspend fun insert(reference: MergedMangaReference): Long? + + suspend fun insertAll(references: List) + + suspend fun deleteById(id: Long) + + suspend fun deleteByMergeId(mergeId: Long) + + suspend fun getMergeMangaForDownloading(mergeId: Long): List } diff --git a/app/src/main/java/eu/kanade/domain/manga/repository/MangaRepository.kt b/app/src/main/java/eu/kanade/domain/manga/repository/MangaRepository.kt index f091afdfa..9a93f5b0e 100644 --- a/app/src/main/java/eu/kanade/domain/manga/repository/MangaRepository.kt +++ b/app/src/main/java/eu/kanade/domain/manga/repository/MangaRepository.kt @@ -2,22 +2,23 @@ package eu.kanade.domain.manga.repository import eu.kanade.domain.manga.model.Manga import eu.kanade.domain.manga.model.MangaUpdate +import eu.kanade.tachiyomi.data.database.models.LibraryManga import kotlinx.coroutines.flow.Flow interface MangaRepository { suspend fun getMangaById(id: Long): Manga - suspend fun subscribeMangaById(id: Long): Flow - suspend fun getMangaByIdAsFlow(id: Long): Flow - suspend fun getMangaByUrlAndSource(url: String, sourceId: Long): Manga? - - suspend fun subscribeMangaByUrlAndSource(url: String, sourceId: Long): Flow + suspend fun getMangaByUrlAndSourceId(url: String, sourceId: Long): Manga? suspend fun getFavorites(): List + suspend fun getLibraryManga(): List + + fun getLibraryMangaAsFlow(): Flow> + fun getFavoritesBySourceId(sourceId: Long): Flow> suspend fun getDuplicateLibraryManga(title: String, sourceId: Long): Manga? @@ -26,11 +27,15 @@ interface MangaRepository { suspend fun setMangaCategories(mangaId: Long, categoryIds: List) + suspend fun insert(manga: Manga): Long? + suspend fun update(update: MangaUpdate): Boolean suspend fun updateAll(values: List): Boolean - suspend fun getMangaBySource(sourceId: Long): List + suspend fun getMangaBySourceId(sourceId: Long): List suspend fun getAll(): List + + suspend fun deleteManga(mangaId: Long) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt b/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt index 8370b3f34..82a6411d6 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt @@ -18,7 +18,6 @@ import eu.kanade.data.listOfStringsAdapter import eu.kanade.data.listOfStringsAndAdapter import eu.kanade.tachiyomi.data.cache.ChapterCache import eu.kanade.tachiyomi.data.cache.CoverCache -import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DbOpenCallback import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.library.CustomMangaManager @@ -89,8 +88,6 @@ class AppModule(val app: Application) : InjektModule { addSingletonFactory { PreferencesHelper(app) } - addSingletonFactory { DatabaseHelper(get()) } - addSingletonFactory { ChapterCache(app) } addSingletonFactory { CoverCache(app) } @@ -125,8 +122,6 @@ class AppModule(val app: Application) : InjektModule { get() - get() - get() // SY --> diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/AbstractBackupManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/AbstractBackupManager.kt index 8e4d3af6f..2106237ee 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/AbstractBackupManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/AbstractBackupManager.kt @@ -6,13 +6,16 @@ import eu.kanade.data.DatabaseHandler import eu.kanade.data.manga.mangaMapper import eu.kanade.data.toLong import eu.kanade.domain.manga.interactor.GetFavorites +import eu.kanade.domain.manga.interactor.GetFlatMetadataById import eu.kanade.domain.manga.interactor.GetMergedManga +import eu.kanade.domain.manga.interactor.InsertFlatMetadata import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.library.CustomMangaManager import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.source.SourceManager +import exh.metadata.metadata.base.FlatMetadata import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import data.Mangas as DbManga @@ -30,6 +33,8 @@ abstract class AbstractBackupManager(protected val context: Context) { // SY --> private val getMergedManga: GetMergedManga = Injekt.get() protected val customMangaManager: CustomMangaManager = Injekt.get() + private val insertFlatMetadata: InsertFlatMetadata = Injekt.get() + private val getFlatMetadataById: GetFlatMetadataById = Injekt.get() // SY <-- abstract suspend fun createBackup(uri: Uri, flags: Int, isAutoBackup: Boolean): String @@ -65,6 +70,10 @@ abstract class AbstractBackupManager(protected val context: Context) { protected suspend fun getMergedManga(): List { return getMergedManga.await() } + + protected suspend fun getFlatMetadata(mangaId: Long) = getFlatMetadataById.await(mangaId) + + protected suspend fun insertFlatMetadata(flatMetadata: FlatMetadata) = insertFlatMetadata.await(flatMetadata) // SY <-- /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupManager.kt index 13df390be..88c932fb0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupManager.kt @@ -42,8 +42,6 @@ import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.source.online.MetadataSource import eu.kanade.tachiyomi.util.system.logcat -import exh.metadata.metadata.base.awaitFlatMetadataForManga -import exh.metadata.metadata.base.awaitInsertFlatMetadata import exh.source.MERGED_SOURCE_ID import exh.source.getMainSource import exh.util.nullIfBlank @@ -197,7 +195,7 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) { val source = sourceManager.get(manga.source)?.getMainSource>() if (source != null) { - handler.awaitFlatMetadataForManga(manga.id)?.let { flatMetadata -> + getFlatMetadata(manga.id)?.let { flatMetadata -> mangaObject.flatMetadata = BackupFlatMetadata.copyFrom(flatMetadata) } } @@ -535,18 +533,17 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) { mergeId = mergeMangaId mangaId = mergedManga.id handler.await { - mergedQueries.insertMerged( - null, - isInfoManga, - getChapterUpdates, - chapterSortMode.toLong(), - chapterPriority.toLong(), - downloadChapters, - mergeId!!, - mergeUrl, - mangaId, - mangaUrl, - mangaSourceId, + mergedQueries.insert( + infoManga = isInfoManga, + getChapterUpdates = getChapterUpdates, + chapterSortMode = chapterSortMode.toLong(), + chapterPriority = chapterPriority.toLong(), + downloadChapters = downloadChapters, + mergeId = mergeId!!, + mergeUrl = mergeUrl, + mangaId = mangaId, + mangaUrl = mangaUrl, + mangaSource = mangaSourceId, ) } } @@ -555,8 +552,8 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) { } internal suspend fun restoreFlatMetadata(mangaId: Long, backupFlatMetadata: BackupFlatMetadata) { - if (handler.awaitFlatMetadataForManga(mangaId) == null) { - handler.awaitInsertFlatMetadata(backupFlatMetadata.getFlatMetadata(mangaId)) + if (getFlatMetadata(mangaId) == null) { + insertFlatMetadata(backupFlatMetadata.getFlatMetadata(mangaId)) } } // SY <-- diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/DatabaseHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/DatabaseHelper.kt deleted file mode 100755 index b050d1462..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/DatabaseHelper.kt +++ /dev/null @@ -1,53 +0,0 @@ -package eu.kanade.tachiyomi.data.database - -import androidx.sqlite.db.SupportSQLiteOpenHelper -import com.pushtorefresh.storio.sqlite.impl.DefaultStorIOSQLite -import eu.kanade.tachiyomi.data.database.mappers.CategoryTypeMapping -import eu.kanade.tachiyomi.data.database.mappers.ChapterTypeMapping -import eu.kanade.tachiyomi.data.database.mappers.HistoryTypeMapping -import eu.kanade.tachiyomi.data.database.mappers.MangaCategoryTypeMapping -import eu.kanade.tachiyomi.data.database.mappers.MangaTypeMapping -import eu.kanade.tachiyomi.data.database.mappers.TrackTypeMapping -import eu.kanade.tachiyomi.data.database.models.Category -import eu.kanade.tachiyomi.data.database.models.Chapter -import eu.kanade.tachiyomi.data.database.models.History -import eu.kanade.tachiyomi.data.database.models.Manga -import eu.kanade.tachiyomi.data.database.models.MangaCategory -import eu.kanade.tachiyomi.data.database.models.Track -import eu.kanade.tachiyomi.data.database.queries.ChapterQueries -import eu.kanade.tachiyomi.data.database.queries.MangaQueries -import exh.merged.sql.mappers.MergedMangaTypeMapping -import exh.merged.sql.models.MergedMangaReference -import exh.merged.sql.queries.MergedQueries - -/** - * This class provides operations to manage the database through its interfaces. - */ -class DatabaseHelper( - openHelper: SupportSQLiteOpenHelper, -) : - MangaQueries, - ChapterQueries, - /* SY --> */ - MergedQueries -/* SY <-- */ { - - override val db = DefaultStorIOSQLite.builder() - .sqliteOpenHelper(openHelper) - .addTypeMapping(Manga::class.java, MangaTypeMapping()) - .addTypeMapping(Chapter::class.java, ChapterTypeMapping()) - .addTypeMapping(Track::class.java, TrackTypeMapping()) - .addTypeMapping(Category::class.java, CategoryTypeMapping()) - .addTypeMapping(MangaCategory::class.java, MangaCategoryTypeMapping()) - .addTypeMapping(History::class.java, HistoryTypeMapping()) - // SY --> - .addTypeMapping(MergedMangaReference::class.java, MergedMangaTypeMapping()) - // SY <-- - .build() - - inline fun inTransaction(block: () -> Unit) = db.inTransaction(block) - - // SY --> - fun lowLevel() = db.lowLevel() - // SY <-- -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/DbExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/DbExtensions.kt deleted file mode 100755 index caaba0e10..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/DbExtensions.kt +++ /dev/null @@ -1,24 +0,0 @@ -package eu.kanade.tachiyomi.data.database - -import com.pushtorefresh.storio.sqlite.StorIOSQLite - -inline fun StorIOSQLite.inTransaction(block: () -> Unit) { - lowLevel().beginTransaction() - try { - block() - lowLevel().setTransactionSuccessful() - } finally { - lowLevel().endTransaction() - } -} - -inline fun StorIOSQLite.inTransactionReturn(block: () -> T): T { - lowLevel().beginTransaction() - try { - val result = block() - lowLevel().setTransactionSuccessful() - return result - } finally { - lowLevel().endTransaction() - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/DbProvider.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/DbProvider.kt deleted file mode 100755 index ff42ff75b..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/DbProvider.kt +++ /dev/null @@ -1,7 +0,0 @@ -package eu.kanade.tachiyomi.data.database - -import com.pushtorefresh.storio.sqlite.impl.DefaultStorIOSQLite - -interface DbProvider { - val db: DefaultStorIOSQLite -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/CategoryTypeMapping.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/CategoryTypeMapping.kt deleted file mode 100755 index dfc7d7709..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/CategoryTypeMapping.kt +++ /dev/null @@ -1,71 +0,0 @@ -package eu.kanade.tachiyomi.data.database.mappers - -import android.database.Cursor -import androidx.core.content.contentValuesOf -import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping -import com.pushtorefresh.storio.sqlite.operations.delete.DefaultDeleteResolver -import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver -import com.pushtorefresh.storio.sqlite.operations.put.DefaultPutResolver -import com.pushtorefresh.storio.sqlite.queries.DeleteQuery -import com.pushtorefresh.storio.sqlite.queries.InsertQuery -import com.pushtorefresh.storio.sqlite.queries.UpdateQuery -import eu.kanade.tachiyomi.data.database.models.Category -import eu.kanade.tachiyomi.data.database.models.CategoryImpl -import eu.kanade.tachiyomi.data.database.tables.CategoryTable.COL_FLAGS -import eu.kanade.tachiyomi.data.database.tables.CategoryTable.COL_ID -import eu.kanade.tachiyomi.data.database.tables.CategoryTable.COL_MANGA_ORDER -import eu.kanade.tachiyomi.data.database.tables.CategoryTable.COL_NAME -import eu.kanade.tachiyomi.data.database.tables.CategoryTable.COL_ORDER -import eu.kanade.tachiyomi.data.database.tables.CategoryTable.TABLE - -class CategoryTypeMapping : SQLiteTypeMapping( - CategoryPutResolver(), - CategoryGetResolver(), - CategoryDeleteResolver(), -) - -class CategoryPutResolver : DefaultPutResolver() { - - override fun mapToInsertQuery(obj: Category) = InsertQuery.builder() - .table(TABLE) - .build() - - override fun mapToUpdateQuery(obj: Category) = UpdateQuery.builder() - .table(TABLE) - .where("$COL_ID = ?") - .whereArgs(obj.id) - .build() - - override fun mapToContentValues(obj: Category) = - contentValuesOf( - COL_ID to obj.id, - COL_NAME to obj.name, - COL_ORDER to obj.order, - COL_FLAGS to obj.flags, - COL_MANGA_ORDER to obj.mangaOrder.joinToString("/"), - ) -} - -class CategoryGetResolver : DefaultGetResolver() { - - override fun mapFromCursor(cursor: Cursor): Category = CategoryImpl().apply { - id = cursor.getInt(cursor.getColumnIndexOrThrow(COL_ID)) - name = cursor.getString(cursor.getColumnIndexOrThrow(COL_NAME)) - order = cursor.getInt(cursor.getColumnIndexOrThrow(COL_ORDER)) - flags = cursor.getInt(cursor.getColumnIndexOrThrow(COL_FLAGS)) - - // SY --> - val orderString = cursor.getString(cursor.getColumnIndexOrThrow(COL_MANGA_ORDER)) - mangaOrder = orderString?.split("/")?.mapNotNull { it.toLongOrNull() }.orEmpty() - // SY <-- - } -} - -class CategoryDeleteResolver : DefaultDeleteResolver() { - - override fun mapToDeleteQuery(obj: Category) = DeleteQuery.builder() - .table(TABLE) - .where("$COL_ID = ?") - .whereArgs(obj.id) - .build() -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/ChapterTypeMapping.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/ChapterTypeMapping.kt deleted file mode 100755 index d56fe36d0..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/ChapterTypeMapping.kt +++ /dev/null @@ -1,88 +0,0 @@ -package eu.kanade.tachiyomi.data.database.mappers - -import android.database.Cursor -import androidx.core.content.contentValuesOf -import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping -import com.pushtorefresh.storio.sqlite.operations.delete.DefaultDeleteResolver -import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver -import com.pushtorefresh.storio.sqlite.operations.put.DefaultPutResolver -import com.pushtorefresh.storio.sqlite.queries.DeleteQuery -import com.pushtorefresh.storio.sqlite.queries.InsertQuery -import com.pushtorefresh.storio.sqlite.queries.UpdateQuery -import eu.kanade.tachiyomi.data.database.models.Chapter -import eu.kanade.tachiyomi.data.database.models.ChapterImpl -import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_BOOKMARK -import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_CHAPTER_NUMBER -import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_DATE_FETCH -import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_DATE_UPLOAD -import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_ID -import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_LAST_PAGE_READ -import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_MANGA_ID -import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_NAME -import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_READ -import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_SCANLATOR -import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_SOURCE_ORDER -import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_URL -import eu.kanade.tachiyomi.data.database.tables.ChapterTable.TABLE - -class ChapterTypeMapping : SQLiteTypeMapping( - ChapterPutResolver(), - ChapterGetResolver(), - ChapterDeleteResolver(), -) - -class ChapterPutResolver : DefaultPutResolver() { - - override fun mapToInsertQuery(obj: Chapter) = InsertQuery.builder() - .table(TABLE) - .build() - - override fun mapToUpdateQuery(obj: Chapter) = UpdateQuery.builder() - .table(TABLE) - .where("$COL_ID = ?") - .whereArgs(obj.id) - .build() - - override fun mapToContentValues(obj: Chapter) = - contentValuesOf( - COL_ID to obj.id, - COL_MANGA_ID to obj.manga_id, - COL_URL to obj.url, - COL_NAME to obj.name, - COL_READ to obj.read, - COL_SCANLATOR to obj.scanlator, - COL_BOOKMARK to obj.bookmark, - COL_DATE_FETCH to obj.date_fetch, - COL_DATE_UPLOAD to obj.date_upload, - COL_LAST_PAGE_READ to obj.last_page_read, - COL_CHAPTER_NUMBER to obj.chapter_number, - COL_SOURCE_ORDER to obj.source_order, - ) -} - -class ChapterGetResolver : DefaultGetResolver() { - - override fun mapFromCursor(cursor: Cursor): Chapter = ChapterImpl().apply { - id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_ID)) - manga_id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_MANGA_ID)) - url = cursor.getString(cursor.getColumnIndexOrThrow(COL_URL)) - name = cursor.getString(cursor.getColumnIndexOrThrow(COL_NAME)) - scanlator = cursor.getString(cursor.getColumnIndexOrThrow(COL_SCANLATOR)) - read = cursor.getInt(cursor.getColumnIndexOrThrow(COL_READ)) == 1 - bookmark = cursor.getInt(cursor.getColumnIndexOrThrow(COL_BOOKMARK)) == 1 - date_fetch = cursor.getLong(cursor.getColumnIndexOrThrow(COL_DATE_FETCH)) - date_upload = cursor.getLong(cursor.getColumnIndexOrThrow(COL_DATE_UPLOAD)) - last_page_read = cursor.getInt(cursor.getColumnIndexOrThrow(COL_LAST_PAGE_READ)) - chapter_number = cursor.getFloat(cursor.getColumnIndexOrThrow(COL_CHAPTER_NUMBER)) - source_order = cursor.getInt(cursor.getColumnIndexOrThrow(COL_SOURCE_ORDER)) - } -} - -class ChapterDeleteResolver : DefaultDeleteResolver() { - - override fun mapToDeleteQuery(obj: Chapter) = DeleteQuery.builder() - .table(TABLE) - .where("$COL_ID = ?") - .whereArgs(obj.id) - .build() -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/HistoryTypeMapping.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/HistoryTypeMapping.kt deleted file mode 100755 index 836eb3c13..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/HistoryTypeMapping.kt +++ /dev/null @@ -1,64 +0,0 @@ -package eu.kanade.tachiyomi.data.database.mappers - -import android.database.Cursor -import androidx.core.content.contentValuesOf -import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping -import com.pushtorefresh.storio.sqlite.operations.delete.DefaultDeleteResolver -import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver -import com.pushtorefresh.storio.sqlite.operations.put.DefaultPutResolver -import com.pushtorefresh.storio.sqlite.queries.DeleteQuery -import com.pushtorefresh.storio.sqlite.queries.InsertQuery -import com.pushtorefresh.storio.sqlite.queries.UpdateQuery -import eu.kanade.tachiyomi.data.database.models.History -import eu.kanade.tachiyomi.data.database.models.HistoryImpl -import eu.kanade.tachiyomi.data.database.tables.HistoryTable.COL_CHAPTER_ID -import eu.kanade.tachiyomi.data.database.tables.HistoryTable.COL_ID -import eu.kanade.tachiyomi.data.database.tables.HistoryTable.COL_LAST_READ -import eu.kanade.tachiyomi.data.database.tables.HistoryTable.COL_TIME_READ -import eu.kanade.tachiyomi.data.database.tables.HistoryTable.TABLE - -class HistoryTypeMapping : SQLiteTypeMapping( - HistoryPutResolver(), - HistoryGetResolver(), - HistoryDeleteResolver(), -) - -open class HistoryPutResolver : DefaultPutResolver() { - - override fun mapToInsertQuery(obj: History) = InsertQuery.builder() - .table(TABLE) - .build() - - override fun mapToUpdateQuery(obj: History) = UpdateQuery.builder() - .table(TABLE) - .where("$COL_ID = ?") - .whereArgs(obj.id) - .build() - - override fun mapToContentValues(obj: History) = - contentValuesOf( - COL_ID to obj.id, - COL_CHAPTER_ID to obj.chapter_id, - COL_LAST_READ to obj.last_read, - COL_TIME_READ to obj.time_read, - ) -} - -class HistoryGetResolver : DefaultGetResolver() { - - override fun mapFromCursor(cursor: Cursor): History = HistoryImpl().apply { - id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_ID)) - chapter_id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_CHAPTER_ID)) - last_read = cursor.getLong(cursor.getColumnIndexOrThrow(COL_LAST_READ)) - time_read = cursor.getLong(cursor.getColumnIndexOrThrow(COL_TIME_READ)) - } -} - -class HistoryDeleteResolver : DefaultDeleteResolver() { - - override fun mapToDeleteQuery(obj: History) = DeleteQuery.builder() - .table(TABLE) - .where("$COL_ID = ?") - .whereArgs(obj.id) - .build() -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/MangaCategoryTypeMapping.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/MangaCategoryTypeMapping.kt deleted file mode 100755 index abd807f2f..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/MangaCategoryTypeMapping.kt +++ /dev/null @@ -1,60 +0,0 @@ -package eu.kanade.tachiyomi.data.database.mappers - -import android.database.Cursor -import androidx.core.content.contentValuesOf -import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping -import com.pushtorefresh.storio.sqlite.operations.delete.DefaultDeleteResolver -import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver -import com.pushtorefresh.storio.sqlite.operations.put.DefaultPutResolver -import com.pushtorefresh.storio.sqlite.queries.DeleteQuery -import com.pushtorefresh.storio.sqlite.queries.InsertQuery -import com.pushtorefresh.storio.sqlite.queries.UpdateQuery -import eu.kanade.tachiyomi.data.database.models.MangaCategory -import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable.COL_CATEGORY_ID -import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable.COL_ID -import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable.COL_MANGA_ID -import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable.TABLE - -class MangaCategoryTypeMapping : SQLiteTypeMapping( - MangaCategoryPutResolver(), - MangaCategoryGetResolver(), - MangaCategoryDeleteResolver(), -) - -class MangaCategoryPutResolver : DefaultPutResolver() { - - override fun mapToInsertQuery(obj: MangaCategory) = InsertQuery.builder() - .table(TABLE) - .build() - - override fun mapToUpdateQuery(obj: MangaCategory) = UpdateQuery.builder() - .table(TABLE) - .where("$COL_ID = ?") - .whereArgs(obj.id) - .build() - - override fun mapToContentValues(obj: MangaCategory) = - contentValuesOf( - COL_ID to obj.id, - COL_MANGA_ID to obj.manga_id, - COL_CATEGORY_ID to obj.category_id, - ) -} - -class MangaCategoryGetResolver : DefaultGetResolver() { - - override fun mapFromCursor(cursor: Cursor): MangaCategory = MangaCategory().apply { - id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_ID)) - manga_id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_MANGA_ID)) - category_id = cursor.getInt(cursor.getColumnIndexOrThrow(COL_CATEGORY_ID)) - } -} - -class MangaCategoryDeleteResolver : DefaultDeleteResolver() { - - override fun mapToDeleteQuery(obj: MangaCategory) = DeleteQuery.builder() - .table(TABLE) - .where("$COL_ID = ?") - .whereArgs(obj.id) - .build() -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/MangaTypeMapping.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/MangaTypeMapping.kt deleted file mode 100755 index 234d17ac2..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/MangaTypeMapping.kt +++ /dev/null @@ -1,114 +0,0 @@ -package eu.kanade.tachiyomi.data.database.mappers - -import android.database.Cursor -import androidx.core.content.contentValuesOf -import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping -import com.pushtorefresh.storio.sqlite.operations.delete.DefaultDeleteResolver -import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver -import com.pushtorefresh.storio.sqlite.operations.put.DefaultPutResolver -import com.pushtorefresh.storio.sqlite.queries.DeleteQuery -import com.pushtorefresh.storio.sqlite.queries.InsertQuery -import com.pushtorefresh.storio.sqlite.queries.UpdateQuery -import eu.kanade.tachiyomi.data.database.models.Manga -import eu.kanade.tachiyomi.data.database.models.MangaImpl -import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_ARTIST -import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_AUTHOR -import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_CHAPTER_FLAGS -import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_COVER_LAST_MODIFIED -import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_DATE_ADDED -import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_DESCRIPTION -import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_FAVORITE -import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_FILTERED_SCANLATORS -import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_GENRE -import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_ID -import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_INITIALIZED -import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_LAST_UPDATE -import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_SOURCE -import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_STATUS -import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_THUMBNAIL_URL -import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_TITLE -import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_URL -import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_VIEWER -import eu.kanade.tachiyomi.data.database.tables.MangaTable.TABLE - -class MangaTypeMapping : SQLiteTypeMapping( - MangaPutResolver(), - MangaGetResolver(), - MangaDeleteResolver(), -) - -class MangaPutResolver : DefaultPutResolver() { - - override fun mapToInsertQuery(obj: Manga) = InsertQuery.builder() - .table(TABLE) - .build() - - override fun mapToUpdateQuery(obj: Manga) = UpdateQuery.builder() - .table(TABLE) - .where("$COL_ID = ?") - .whereArgs(obj.id) - .build() - - override fun mapToContentValues(obj: Manga) = - contentValuesOf( - COL_ID to obj.id, - COL_SOURCE to obj.source, - COL_URL to obj.url, - // SY --> - COL_ARTIST to obj.originalArtist, - COL_AUTHOR to obj.originalAuthor, - COL_DESCRIPTION to obj.originalDescription, - COL_GENRE to obj.originalGenre, - COL_TITLE to obj.originalTitle, - COL_STATUS to obj.originalStatus, - // SY <-- - COL_THUMBNAIL_URL to obj.thumbnail_url, - COL_FAVORITE to obj.favorite, - COL_LAST_UPDATE to obj.last_update, - COL_INITIALIZED to obj.initialized, - COL_VIEWER to obj.viewer_flags, - COL_CHAPTER_FLAGS to obj.chapter_flags, - COL_COVER_LAST_MODIFIED to obj.cover_last_modified, - COL_DATE_ADDED to obj.date_added, - COL_FILTERED_SCANLATORS to obj.filtered_scanlators, - ) -} - -interface BaseMangaGetResolver { - fun mapBaseFromCursor(manga: Manga, cursor: Cursor) = manga.apply { - id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_ID)) - source = cursor.getLong(cursor.getColumnIndexOrThrow(COL_SOURCE)) - url = cursor.getString(cursor.getColumnIndexOrThrow(COL_URL)) - artist = cursor.getString(cursor.getColumnIndexOrThrow(COL_ARTIST)) - author = cursor.getString(cursor.getColumnIndexOrThrow(COL_AUTHOR)) - description = cursor.getString(cursor.getColumnIndexOrThrow(COL_DESCRIPTION)) - genre = cursor.getString(cursor.getColumnIndexOrThrow(COL_GENRE)) - title = cursor.getString(cursor.getColumnIndexOrThrow(COL_TITLE)) - status = cursor.getInt(cursor.getColumnIndexOrThrow(COL_STATUS)) - thumbnail_url = cursor.getString(cursor.getColumnIndexOrThrow(COL_THUMBNAIL_URL)) - favorite = cursor.getInt(cursor.getColumnIndexOrThrow(COL_FAVORITE)) == 1 - last_update = cursor.getLong(cursor.getColumnIndexOrThrow(COL_LAST_UPDATE)) - initialized = cursor.getInt(cursor.getColumnIndexOrThrow(COL_INITIALIZED)) == 1 - viewer_flags = cursor.getInt(cursor.getColumnIndexOrThrow(COL_VIEWER)) - chapter_flags = cursor.getInt(cursor.getColumnIndexOrThrow(COL_CHAPTER_FLAGS)) - cover_last_modified = cursor.getLong(cursor.getColumnIndexOrThrow(COL_COVER_LAST_MODIFIED)) - date_added = cursor.getLong(cursor.getColumnIndexOrThrow(COL_DATE_ADDED)) - filtered_scanlators = cursor.getString(cursor.getColumnIndexOrThrow(COL_FILTERED_SCANLATORS)) - } -} - -open class MangaGetResolver : DefaultGetResolver(), BaseMangaGetResolver { - - override fun mapFromCursor(cursor: Cursor): Manga { - return mapBaseFromCursor(MangaImpl(), cursor) - } -} - -class MangaDeleteResolver : DefaultDeleteResolver() { - - override fun mapToDeleteQuery(obj: Manga) = DeleteQuery.builder() - .table(TABLE) - .where("$COL_ID = ?") - .whereArgs(obj.id) - .build() -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/TrackTypeMapping.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/TrackTypeMapping.kt deleted file mode 100755 index 764f2325a..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/TrackTypeMapping.kt +++ /dev/null @@ -1,91 +0,0 @@ -package eu.kanade.tachiyomi.data.database.mappers - -import android.database.Cursor -import androidx.core.content.contentValuesOf -import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping -import com.pushtorefresh.storio.sqlite.operations.delete.DefaultDeleteResolver -import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver -import com.pushtorefresh.storio.sqlite.operations.put.DefaultPutResolver -import com.pushtorefresh.storio.sqlite.queries.DeleteQuery -import com.pushtorefresh.storio.sqlite.queries.InsertQuery -import com.pushtorefresh.storio.sqlite.queries.UpdateQuery -import eu.kanade.tachiyomi.data.database.models.Track -import eu.kanade.tachiyomi.data.database.models.TrackImpl -import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_FINISH_DATE -import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_ID -import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_LAST_CHAPTER_READ -import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_LIBRARY_ID -import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_MANGA_ID -import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_MEDIA_ID -import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_SCORE -import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_START_DATE -import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_STATUS -import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_SYNC_ID -import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_TITLE -import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_TOTAL_CHAPTERS -import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_TRACKING_URL -import eu.kanade.tachiyomi.data.database.tables.TrackTable.TABLE - -class TrackTypeMapping : SQLiteTypeMapping( - TrackPutResolver(), - TrackGetResolver(), - TrackDeleteResolver(), -) - -class TrackPutResolver : DefaultPutResolver() { - - override fun mapToInsertQuery(obj: Track) = InsertQuery.builder() - .table(TABLE) - .build() - - override fun mapToUpdateQuery(obj: Track) = UpdateQuery.builder() - .table(TABLE) - .where("$COL_ID = ?") - .whereArgs(obj.id) - .build() - - override fun mapToContentValues(obj: Track) = - contentValuesOf( - COL_ID to obj.id, - COL_MANGA_ID to obj.manga_id, - COL_SYNC_ID to obj.sync_id, - COL_MEDIA_ID to obj.media_id, - COL_LIBRARY_ID to obj.library_id, - COL_TITLE to obj.title, - COL_LAST_CHAPTER_READ to obj.last_chapter_read, - COL_TOTAL_CHAPTERS to obj.total_chapters, - COL_STATUS to obj.status, - COL_TRACKING_URL to obj.tracking_url, - COL_SCORE to obj.score, - COL_START_DATE to obj.started_reading_date, - COL_FINISH_DATE to obj.finished_reading_date, - ) -} - -class TrackGetResolver : DefaultGetResolver() { - - override fun mapFromCursor(cursor: Cursor): Track = TrackImpl().apply { - id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_ID)) - manga_id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_MANGA_ID)) - sync_id = cursor.getInt(cursor.getColumnIndexOrThrow(COL_SYNC_ID)) - media_id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_MEDIA_ID)) - library_id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_LIBRARY_ID)) - title = cursor.getString(cursor.getColumnIndexOrThrow(COL_TITLE)) - last_chapter_read = cursor.getFloat(cursor.getColumnIndexOrThrow(COL_LAST_CHAPTER_READ)) - total_chapters = cursor.getInt(cursor.getColumnIndexOrThrow(COL_TOTAL_CHAPTERS)) - status = cursor.getInt(cursor.getColumnIndexOrThrow(COL_STATUS)) - score = cursor.getFloat(cursor.getColumnIndexOrThrow(COL_SCORE)) - tracking_url = cursor.getString(cursor.getColumnIndexOrThrow(COL_TRACKING_URL)) - started_reading_date = cursor.getLong(cursor.getColumnIndexOrThrow(COL_START_DATE)) - finished_reading_date = cursor.getLong(cursor.getColumnIndexOrThrow(COL_FINISH_DATE)) - } -} - -class TrackDeleteResolver : DefaultDeleteResolver() { - - override fun mapToDeleteQuery(obj: Track) = DeleteQuery.builder() - .table(TABLE) - .where("$COL_ID = ?") - .whereArgs(obj.id) - .build() -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/ChapterQueries.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/ChapterQueries.kt deleted file mode 100755 index 4a14dda8d..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/ChapterQueries.kt +++ /dev/null @@ -1,37 +0,0 @@ -package eu.kanade.tachiyomi.data.database.queries - -import com.pushtorefresh.storio.sqlite.queries.Query -import eu.kanade.tachiyomi.data.database.DbProvider -import eu.kanade.tachiyomi.data.database.models.Chapter -import eu.kanade.tachiyomi.data.database.models.Manga -import eu.kanade.tachiyomi.data.database.resolvers.ChapterProgressPutResolver -import eu.kanade.tachiyomi.data.database.tables.ChapterTable - -interface ChapterQueries : DbProvider { - // SY --> - fun getChapters(manga: Manga) = getChapters(manga.id) - - fun getChapters(mangaId: Long?) = db.get() - .listOfObjects(Chapter::class.java) - .withQuery( - Query.builder() - .table(ChapterTable.TABLE) - .where("${ChapterTable.COL_MANGA_ID} = ?") - .whereArgs(mangaId) - .build(), - ) - .prepare() - // SY <-- - - fun deleteChapters(chapters: List) = db.delete().objects(chapters).prepare() - - fun updateChapterProgress(chapter: Chapter) = db.put() - .`object`(chapter) - .withPutResolver(ChapterProgressPutResolver()) - .prepare() - - fun updateChaptersProgress(chapters: List) = db.put() - .objects(chapters) - .withPutResolver(ChapterProgressPutResolver()) - .prepare() -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/MangaQueries.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/MangaQueries.kt deleted file mode 100755 index fd8fe29bd..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/MangaQueries.kt +++ /dev/null @@ -1,79 +0,0 @@ -package eu.kanade.tachiyomi.data.database.queries - -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.models.LibraryManga -import eu.kanade.tachiyomi.data.database.models.Manga -import eu.kanade.tachiyomi.data.database.resolvers.LibraryMangaGetResolver -import eu.kanade.tachiyomi.data.database.resolvers.MangaFlagsPutResolver -import eu.kanade.tachiyomi.data.database.tables.CategoryTable -import eu.kanade.tachiyomi.data.database.tables.ChapterTable -import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable -import eu.kanade.tachiyomi.data.database.tables.MangaTable - -interface MangaQueries : DbProvider { - - fun getLibraryMangas() = db.get() - .listOfObjects(LibraryManga::class.java) - .withQuery( - RawQuery.builder() - .query(libraryQuery) - .observesTables(MangaTable.TABLE, ChapterTable.TABLE, MangaCategoryTable.TABLE, CategoryTable.TABLE) - .build(), - ) - .withGetResolver(LibraryMangaGetResolver.INSTANCE) - .prepare() - - fun getFavoriteMangas() = db.get() - .listOfObjects(Manga::class.java) - .withQuery( - Query.builder() - .table(MangaTable.TABLE) - .where("${MangaTable.COL_FAVORITE} = ?") - .whereArgs(1) - .build(), - ) - .prepare() - - fun getManga(url: String, sourceId: Long) = db.get() - .`object`(Manga::class.java) - .withQuery( - Query.builder() - .table(MangaTable.TABLE) - .where("${MangaTable.COL_URL} = ? AND ${MangaTable.COL_SOURCE} = ?") - .whereArgs(url, sourceId) - .build(), - ) - .prepare() - - fun getManga(id: Long) = db.get() - .`object`(Manga::class.java) - .withQuery( - Query.builder() - .table(MangaTable.TABLE) - .where("${MangaTable.COL_ID} = ?") - .whereArgs(id) - .build(), - ) - .prepare() - - fun insertManga(manga: Manga) = db.put().`object`(manga).prepare() - - fun updateChapterFlags(manga: Manga) = db.put() - .`object`(manga) - .withPutResolver(MangaFlagsPutResolver(MangaTable.COL_CHAPTER_FLAGS, Manga::chapter_flags)) - .prepare() - - fun updateChapterFlags(manga: List) = db.put() - .objects(manga) - .withPutResolver(MangaFlagsPutResolver(MangaTable.COL_CHAPTER_FLAGS, Manga::chapter_flags)) - .prepare() - - fun updateViewerFlags(manga: Manga) = db.put() - .`object`(manga) - .withPutResolver(MangaFlagsPutResolver(MangaTable.COL_VIEWER, Manga::viewer_flags)) - .prepare() - - fun deleteManga(manga: Manga) = db.delete().`object`(manga).prepare() -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/RawQueries.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/RawQueries.kt deleted file mode 100755 index dfaf45990..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/RawQueries.kt +++ /dev/null @@ -1,131 +0,0 @@ -package eu.kanade.tachiyomi.data.database.queries - -import exh.source.MERGED_SOURCE_ID -import eu.kanade.tachiyomi.data.database.tables.ChapterTable as Chapter -import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable as MangaCategory -import eu.kanade.tachiyomi.data.database.tables.MangaTable as Manga -import exh.merged.sql.tables.MergedTable as Merged - -// SY --> -/** - * Query to get the manga merged into a merged manga - */ -fun getMergedMangaQuery() = - """ - SELECT ${Manga.TABLE}.* - FROM ( - SELECT ${Merged.COL_MANGA_ID} FROM ${Merged.TABLE} WHERE ${Merged.COL_MERGE_ID} = ? - ) AS M - JOIN ${Manga.TABLE} - ON ${Manga.TABLE}.${Manga.COL_ID} = M.${Merged.COL_MANGA_ID} -""" - -/** - * Query to get the manga merged into a merged manga - */ -fun getMergedMangaForDownloadingQuery() = - """ - SELECT ${Manga.TABLE}.* - FROM ( - SELECT ${Merged.COL_MANGA_ID} FROM ${Merged.TABLE} WHERE ${Merged.COL_MERGE_ID} = ? AND ${Merged.COL_DOWNLOAD_CHAPTERS} = 1 - ) AS M - JOIN ${Manga.TABLE} - ON ${Manga.TABLE}.${Manga.COL_ID} = M.${Merged.COL_MANGA_ID} -""" - -/** - * Query to get all the manga that are merged into other manga - */ -fun getAllMergedMangaQuery() = - """ - SELECT ${Manga.TABLE}.* - FROM ( - SELECT ${Merged.COL_MANGA_ID} FROM ${Merged.TABLE} - ) AS M - JOIN ${Manga.TABLE} - ON ${Manga.TABLE}.${Manga.COL_ID} = M.${Merged.COL_MANGA_ID} -""" - -/** - * Query to get the manga merged into a merged manga using the Url - */ -fun getMergedMangaFromUrlQuery() = - """ - SELECT ${Manga.TABLE}.* - FROM ( - SELECT ${Merged.COL_MANGA_ID} FROM ${Merged.TABLE} WHERE ${Merged.COL_MERGE_URL} = ? - ) AS M - JOIN ${Manga.TABLE} - ON ${Manga.TABLE}.${Manga.COL_ID} = M.${Merged.COL_MANGA_ID} -""" - -/** - * Query to get the chapters of all manga in a merged manga - */ -fun getMergedChaptersQuery() = - """ - SELECT ${Chapter.TABLE}.* - FROM ( - SELECT ${Merged.COL_MANGA_ID} FROM ${Merged.TABLE} WHERE ${Merged.COL_MERGE_ID} = ? - ) AS M - JOIN ${Chapter.TABLE} - ON ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} = M.${Merged.COL_MANGA_ID} -""" - -/** - * Query to get the manga from the library, with their categories, read and unread count. - */ -val libraryQuery = - """ - SELECT M.*, COALESCE(MC.${MangaCategory.COL_CATEGORY_ID}, 0) AS ${Manga.COL_CATEGORY} - FROM ( - SELECT ${Manga.TABLE}.*, COALESCE(C.unreadCount, 0) AS ${Manga.COMPUTED_COL_UNREAD_COUNT}, COALESCE(R.readCount, 0) AS ${Manga.COMPUTED_COL_READ_COUNT} - FROM ${Manga.TABLE} - LEFT JOIN ( - SELECT ${Chapter.TABLE}.${Chapter.COL_MANGA_ID}, COUNT(*) AS unreadCount - FROM ${Chapter.TABLE} - WHERE ${Chapter.COL_READ} = 0 - GROUP BY ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} - ) AS C - ON ${Manga.TABLE}.${Manga.COL_ID} = C.${Chapter.COL_MANGA_ID} - LEFT JOIN ( - SELECT ${Chapter.COL_MANGA_ID}, COUNT(*) AS readCount - FROM ${Chapter.TABLE} - WHERE ${Chapter.COL_READ} = 1 - GROUP BY ${Chapter.COL_MANGA_ID} - ) AS R - ON ${Manga.TABLE}.${Manga.COL_ID} = R.${Chapter.COL_MANGA_ID} - WHERE ${Manga.COL_FAVORITE} = 1 AND ${Manga.COL_SOURCE} <> $MERGED_SOURCE_ID - GROUP BY ${Manga.TABLE}.${Manga.COL_ID} - UNION - SELECT ${Manga.TABLE}.*, COALESCE(C.unreadCount, 0) AS ${Manga.COMPUTED_COL_UNREAD_COUNT}, COALESCE(R.readCount, 0) AS ${Manga.COMPUTED_COL_READ_COUNT} - FROM ${Manga.TABLE} - LEFT JOIN ( - SELECT ${Merged.TABLE}.${Merged.COL_MERGE_ID}, COUNT(*) as unreadCount - FROM ${Merged.TABLE} - JOIN ${Chapter.TABLE} - ON ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} = ${Merged.TABLE}.${Merged.COL_MANGA_ID} - WHERE ${Chapter.TABLE}.${Chapter.COL_READ} = 0 - GROUP BY ${Merged.TABLE}.${Merged.COL_MERGE_ID} - ) AS C - ON ${Manga.TABLE}.${Manga.COL_ID} = C.${Merged.COL_MERGE_ID} - LEFT JOIN ( - SELECT ${Merged.TABLE}.${Merged.COL_MERGE_ID}, COUNT(*) as readCount - FROM ${Merged.TABLE} - JOIN ${Chapter.TABLE} - ON ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} = ${Merged.TABLE}.${Merged.COL_MANGA_ID} - WHERE ${Chapter.TABLE}.${Chapter.COL_READ} = 1 - GROUP BY ${Merged.TABLE}.${Merged.COL_MERGE_ID} - ) AS R - ON ${Manga.TABLE}.${Manga.COL_ID} = R.${Merged.COL_MERGE_ID} - WHERE ${Manga.COL_FAVORITE} = 1 AND ${Manga.COL_SOURCE} = $MERGED_SOURCE_ID - GROUP BY ${Manga.TABLE}.${Manga.COL_ID} - ORDER BY ${Manga.COL_TITLE} - ) AS M - LEFT JOIN ( - SELECT * FROM ${MangaCategory.TABLE} - ) AS MC - ON MC.${MangaCategory.COL_MANGA_ID} = M.${Manga.COL_ID}; -""" - -// SY <-- diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/ChapterProgressPutResolver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/ChapterProgressPutResolver.kt deleted file mode 100755 index 27a6838cc..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/ChapterProgressPutResolver.kt +++ /dev/null @@ -1,34 +0,0 @@ -package eu.kanade.tachiyomi.data.database.resolvers - -import androidx.core.content.contentValuesOf -import com.pushtorefresh.storio.sqlite.StorIOSQLite -import com.pushtorefresh.storio.sqlite.operations.put.PutResolver -import com.pushtorefresh.storio.sqlite.operations.put.PutResult -import com.pushtorefresh.storio.sqlite.queries.UpdateQuery -import eu.kanade.tachiyomi.data.database.inTransactionReturn -import eu.kanade.tachiyomi.data.database.models.Chapter -import eu.kanade.tachiyomi.data.database.tables.ChapterTable - -class ChapterProgressPutResolver : PutResolver() { - - override fun performPut(db: StorIOSQLite, chapter: Chapter) = db.inTransactionReturn { - val updateQuery = mapToUpdateQuery(chapter) - val contentValues = mapToContentValues(chapter) - - val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues) - PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table()) - } - - fun mapToUpdateQuery(chapter: Chapter) = UpdateQuery.builder() - .table(ChapterTable.TABLE) - .where("${ChapterTable.COL_ID} = ?") - .whereArgs(chapter.id) - .build() - - fun mapToContentValues(chapter: Chapter) = - contentValuesOf( - ChapterTable.COL_READ to chapter.read, - ChapterTable.COL_BOOKMARK to chapter.bookmark, - ChapterTable.COL_LAST_PAGE_READ to chapter.last_page_read, - ) -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/HistoryChapterIdPutResolver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/HistoryChapterIdPutResolver.kt deleted file mode 100644 index f5c529610..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/HistoryChapterIdPutResolver.kt +++ /dev/null @@ -1,32 +0,0 @@ -package eu.kanade.tachiyomi.data.database.resolvers - -import androidx.core.content.contentValuesOf -import com.pushtorefresh.storio.sqlite.StorIOSQLite -import com.pushtorefresh.storio.sqlite.operations.put.PutResolver -import com.pushtorefresh.storio.sqlite.operations.put.PutResult -import com.pushtorefresh.storio.sqlite.queries.UpdateQuery -import eu.kanade.tachiyomi.data.database.inTransactionReturn -import eu.kanade.tachiyomi.data.database.models.History -import eu.kanade.tachiyomi.data.database.tables.HistoryTable - -class HistoryChapterIdPutResolver : PutResolver() { - - override fun performPut(db: StorIOSQLite, history: History) = db.inTransactionReturn { - val updateQuery = mapToUpdateQuery(history) - val contentValues = mapToContentValues(history) - - val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues) - PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table()) - } - - fun mapToUpdateQuery(history: History) = UpdateQuery.builder() - .table(HistoryTable.TABLE) - .where("${HistoryTable.COL_ID} = ?") - .whereArgs(history.id) - .build() - - fun mapToContentValues(history: History) = - contentValuesOf( - HistoryTable.COL_CHAPTER_ID to history.chapter_id, - ) -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/HistoryUpsertResolver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/HistoryUpsertResolver.kt deleted file mode 100755 index 908aca16d..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/HistoryUpsertResolver.kt +++ /dev/null @@ -1,52 +0,0 @@ -package eu.kanade.tachiyomi.data.database.resolvers - -import androidx.annotation.NonNull -import androidx.core.content.contentValuesOf -import com.pushtorefresh.storio.sqlite.StorIOSQLite -import com.pushtorefresh.storio.sqlite.operations.put.PutResult -import com.pushtorefresh.storio.sqlite.queries.Query -import com.pushtorefresh.storio.sqlite.queries.UpdateQuery -import eu.kanade.tachiyomi.data.database.inTransactionReturn -import eu.kanade.tachiyomi.data.database.mappers.HistoryPutResolver -import eu.kanade.tachiyomi.data.database.models.History -import eu.kanade.tachiyomi.data.database.tables.HistoryTable - -class HistoryUpsertResolver : HistoryPutResolver() { - - /** - * Updates last_read time of chapter - */ - override fun performPut(@NonNull db: StorIOSQLite, @NonNull history: History): PutResult = db.inTransactionReturn { - val updateQuery = mapToUpdateQuery(history) - - val cursor = db.lowLevel().query( - Query.builder() - .table(updateQuery.table()) - .where(updateQuery.where()) - .whereArgs(updateQuery.whereArgs()) - .build(), - ) - - cursor.use { putCursor -> - if (putCursor.count == 0) { - val insertQuery = mapToInsertQuery(history) - val insertedId = db.lowLevel().insert(insertQuery, mapToContentValues(history)) - PutResult.newInsertResult(insertedId, insertQuery.table()) - } else { - val numberOfRowsUpdated = db.lowLevel().update(updateQuery, mapToUpdateContentValues(history)) - PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table()) - } - } - } - - override fun mapToUpdateQuery(obj: History) = UpdateQuery.builder() - .table(HistoryTable.TABLE) - .where("${HistoryTable.COL_CHAPTER_ID} = ?") - .whereArgs(obj.chapter_id) - .build() - - private fun mapToUpdateContentValues(history: History) = - contentValuesOf( - HistoryTable.COL_LAST_READ to history.last_read, - ) -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/LibraryMangaGetResolver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/LibraryMangaGetResolver.kt deleted file mode 100755 index 2435b80cd..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/LibraryMangaGetResolver.kt +++ /dev/null @@ -1,25 +0,0 @@ -package eu.kanade.tachiyomi.data.database.resolvers - -import android.database.Cursor -import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver -import eu.kanade.tachiyomi.data.database.mappers.BaseMangaGetResolver -import eu.kanade.tachiyomi.data.database.models.LibraryManga -import eu.kanade.tachiyomi.data.database.tables.MangaTable - -class LibraryMangaGetResolver : DefaultGetResolver(), BaseMangaGetResolver { - - companion object { - val INSTANCE = LibraryMangaGetResolver() - } - - override fun mapFromCursor(cursor: Cursor): LibraryManga { - val manga = LibraryManga() - - mapBaseFromCursor(manga, cursor) - manga.unreadCount = cursor.getInt(cursor.getColumnIndexOrThrow(MangaTable.COMPUTED_COL_UNREAD_COUNT)) - manga.category = cursor.getInt(cursor.getColumnIndexOrThrow(MangaTable.COL_CATEGORY)) - manga.readCount = cursor.getInt(cursor.getColumnIndexOrThrow(MangaTable.COMPUTED_COL_READ_COUNT)) - - return manga - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaChapterGetResolver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaChapterGetResolver.kt deleted file mode 100755 index a6305b1ba..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaChapterGetResolver.kt +++ /dev/null @@ -1,27 +0,0 @@ -package eu.kanade.tachiyomi.data.database.resolvers - -import android.database.Cursor -import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver -import eu.kanade.tachiyomi.data.database.mappers.ChapterGetResolver -import eu.kanade.tachiyomi.data.database.mappers.MangaGetResolver -import eu.kanade.tachiyomi.data.database.models.MangaChapter - -class MangaChapterGetResolver : DefaultGetResolver() { - - companion object { - val INSTANCE = MangaChapterGetResolver() - } - - private val mangaGetResolver = MangaGetResolver() - - private val chapterGetResolver = ChapterGetResolver() - - override fun mapFromCursor(cursor: Cursor): MangaChapter { - val manga = mangaGetResolver.mapFromCursor(cursor) - val chapter = chapterGetResolver.mapFromCursor(cursor) - manga.id = chapter.manga_id - manga.url = cursor.getString(cursor.getColumnIndexOrThrow("mangaUrl")) - - return MangaChapter(manga, chapter) - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaFavoritePutResolver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaFavoritePutResolver.kt deleted file mode 100644 index 0389d4854..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaFavoritePutResolver.kt +++ /dev/null @@ -1,33 +0,0 @@ -package eu.kanade.tachiyomi.data.database.resolvers - -import androidx.core.content.contentValuesOf -import com.pushtorefresh.storio.sqlite.StorIOSQLite -import com.pushtorefresh.storio.sqlite.operations.put.PutResolver -import com.pushtorefresh.storio.sqlite.operations.put.PutResult -import com.pushtorefresh.storio.sqlite.queries.UpdateQuery -import eu.kanade.tachiyomi.data.database.inTransactionReturn -import eu.kanade.tachiyomi.data.database.models.Manga -import eu.kanade.tachiyomi.data.database.tables.MangaTable - -class MangaFavoritePutResolver : PutResolver() { - - override fun performPut(db: StorIOSQLite, manga: Manga) = db.inTransactionReturn { - val updateQuery = mapToUpdateQuery(manga) - val contentValues = mapToContentValues(manga) - - val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues) - PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table()) - } - - fun mapToUpdateQuery(manga: Manga) = UpdateQuery.builder() - .table(MangaTable.TABLE) - .where("${MangaTable.COL_ID} = ?") - .whereArgs(manga.id) - .build() - - fun mapToContentValues(manga: Manga) = - contentValuesOf( - MangaTable.COL_FAVORITE to manga.favorite, - MangaTable.COL_DATE_ADDED to manga.date_added, - ) -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaFilteredScanlatorsPutResolver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaFilteredScanlatorsPutResolver.kt deleted file mode 100644 index 72691c649..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaFilteredScanlatorsPutResolver.kt +++ /dev/null @@ -1,32 +0,0 @@ -package eu.kanade.tachiyomi.data.database.resolvers - -import androidx.core.content.contentValuesOf -import com.pushtorefresh.storio.sqlite.StorIOSQLite -import com.pushtorefresh.storio.sqlite.operations.put.PutResolver -import com.pushtorefresh.storio.sqlite.operations.put.PutResult -import com.pushtorefresh.storio.sqlite.queries.UpdateQuery -import eu.kanade.tachiyomi.data.database.inTransactionReturn -import eu.kanade.tachiyomi.data.database.models.Manga -import eu.kanade.tachiyomi.data.database.tables.MangaTable - -// [EXH] -class MangaFilteredScanlatorsPutResolver : PutResolver() { - - override fun performPut(db: StorIOSQLite, manga: Manga) = db.inTransactionReturn { - val updateQuery = mapToUpdateQuery(manga) - val contentValues = mapToContentValues(manga) - - val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues) - PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table()) - } - - fun mapToUpdateQuery(manga: Manga) = UpdateQuery.builder() - .table(MangaTable.TABLE) - .where("${MangaTable.COL_ID} = ?") - .whereArgs(manga.id) - .build() - - fun mapToContentValues(manga: Manga) = contentValuesOf( - MangaTable.COL_FILTERED_SCANLATORS to manga.filtered_scanlators, - ) -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaFlagsPutResolver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaFlagsPutResolver.kt deleted file mode 100755 index a90784d82..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaFlagsPutResolver.kt +++ /dev/null @@ -1,33 +0,0 @@ -package eu.kanade.tachiyomi.data.database.resolvers - -import androidx.core.content.contentValuesOf -import com.pushtorefresh.storio.sqlite.StorIOSQLite -import com.pushtorefresh.storio.sqlite.operations.put.PutResolver -import com.pushtorefresh.storio.sqlite.operations.put.PutResult -import com.pushtorefresh.storio.sqlite.queries.UpdateQuery -import eu.kanade.tachiyomi.data.database.inTransactionReturn -import eu.kanade.tachiyomi.data.database.models.Manga -import eu.kanade.tachiyomi.data.database.tables.MangaTable -import kotlin.reflect.KProperty1 - -class MangaFlagsPutResolver(private val colName: String, private val fieldGetter: KProperty1) : PutResolver() { - - override fun performPut(db: StorIOSQLite, manga: Manga) = db.inTransactionReturn { - val updateQuery = mapToUpdateQuery(manga) - val contentValues = mapToContentValues(manga) - - val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues) - PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table()) - } - - fun mapToUpdateQuery(manga: Manga) = UpdateQuery.builder() - .table(MangaTable.TABLE) - .where("${MangaTable.COL_ID} = ?") - .whereArgs(manga.id) - .build() - - fun mapToContentValues(manga: Manga) = - contentValuesOf( - colName to fieldGetter.get(manga), - ) -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaInfoPutResolver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaInfoPutResolver.kt deleted file mode 100644 index 0d7df08d7..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaInfoPutResolver.kt +++ /dev/null @@ -1,50 +0,0 @@ -package eu.kanade.tachiyomi.data.database.resolvers - -import androidx.core.content.contentValuesOf -import com.pushtorefresh.storio.sqlite.StorIOSQLite -import com.pushtorefresh.storio.sqlite.operations.put.PutResolver -import com.pushtorefresh.storio.sqlite.operations.put.PutResult -import com.pushtorefresh.storio.sqlite.queries.UpdateQuery -import eu.kanade.tachiyomi.data.database.inTransactionReturn -import eu.kanade.tachiyomi.data.database.models.Manga -import eu.kanade.tachiyomi.data.database.tables.MangaTable -import exh.util.nullIfZero - -class MangaInfoPutResolver(val reset: Boolean = false) : PutResolver() { - - override fun performPut(db: StorIOSQLite, manga: Manga) = db.inTransactionReturn { - val updateQuery = mapToUpdateQuery(manga) - val contentValues = if (reset) resetToContentValues(manga) else mapToContentValues(manga) - - val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues) - PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table()) - } - - fun mapToUpdateQuery(manga: Manga) = UpdateQuery.builder() - .table(MangaTable.TABLE) - .where("${MangaTable.COL_ID} = ?") - .whereArgs(manga.id) - .build() - - fun mapToContentValues(manga: Manga) = contentValuesOf( - MangaTable.COL_TITLE to manga.originalTitle, - MangaTable.COL_GENRE to manga.originalGenre, - MangaTable.COL_AUTHOR to manga.originalAuthor, - MangaTable.COL_ARTIST to manga.originalArtist, - MangaTable.COL_DESCRIPTION to manga.originalDescription, - MangaTable.COL_STATUS to manga.originalStatus, - ) - - private fun resetToContentValues(manga: Manga) = contentValuesOf( - MangaTable.COL_TITLE to manga.title.split(splitter).last(), - MangaTable.COL_GENRE to manga.genre?.split(splitter)?.lastOrNull(), - MangaTable.COL_AUTHOR to manga.author?.split(splitter)?.lastOrNull(), - MangaTable.COL_ARTIST to manga.artist?.split(splitter)?.lastOrNull(), - MangaTable.COL_DESCRIPTION to manga.description?.split(splitter)?.lastOrNull(), - MangaTable.COL_STATUS to manga.status.nullIfZero()?.toString()?.split(splitter)?.lastOrNull(), - ) - - companion object { - const val splitter = "▒ ▒∩▒" - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaMigrationPutResolver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaMigrationPutResolver.kt deleted file mode 100644 index b15af8e0f..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaMigrationPutResolver.kt +++ /dev/null @@ -1,35 +0,0 @@ -package eu.kanade.tachiyomi.data.database.resolvers - -import androidx.core.content.contentValuesOf -import com.pushtorefresh.storio.sqlite.StorIOSQLite -import com.pushtorefresh.storio.sqlite.operations.put.PutResolver -import com.pushtorefresh.storio.sqlite.operations.put.PutResult -import com.pushtorefresh.storio.sqlite.queries.UpdateQuery -import eu.kanade.tachiyomi.data.database.inTransactionReturn -import eu.kanade.tachiyomi.data.database.models.Manga -import eu.kanade.tachiyomi.data.database.tables.MangaTable - -class MangaMigrationPutResolver : PutResolver() { - - override fun performPut(db: StorIOSQLite, manga: Manga) = db.inTransactionReturn { - val updateQuery = mapToUpdateQuery(manga) - val contentValues = mapToContentValues(manga) - - val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues) - PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table()) - } - - fun mapToUpdateQuery(manga: Manga) = UpdateQuery.builder() - .table(MangaTable.TABLE) - .where("${MangaTable.COL_ID} = ?") - .whereArgs(manga.id) - .build() - - fun mapToContentValues(manga: Manga) = contentValuesOf( - MangaTable.COL_FAVORITE to manga.favorite, - MangaTable.COL_DATE_ADDED to manga.date_added, - MangaTable.COL_TITLE to manga.title, - MangaTable.COL_CHAPTER_FLAGS to manga.chapter_flags, - MangaTable.COL_VIEWER to manga.viewer_flags, - ) -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaThumbnailPutResolver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaThumbnailPutResolver.kt deleted file mode 100644 index e1a1462de..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaThumbnailPutResolver.kt +++ /dev/null @@ -1,32 +0,0 @@ -package eu.kanade.tachiyomi.data.database.resolvers - -import androidx.core.content.contentValuesOf -import com.pushtorefresh.storio.sqlite.StorIOSQLite -import com.pushtorefresh.storio.sqlite.operations.put.PutResolver -import com.pushtorefresh.storio.sqlite.operations.put.PutResult -import com.pushtorefresh.storio.sqlite.queries.UpdateQuery -import eu.kanade.tachiyomi.data.database.inTransactionReturn -import eu.kanade.tachiyomi.data.database.models.Manga -import eu.kanade.tachiyomi.data.database.tables.MangaTable - -// SY -class MangaThumbnailPutResolver : PutResolver() { - - override fun performPut(db: StorIOSQLite, manga: Manga) = db.inTransactionReturn { - val updateQuery = mapToUpdateQuery(manga) - val contentValues = mapToContentValues(manga) - - val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues) - PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table()) - } - - fun mapToUpdateQuery(manga: Manga) = UpdateQuery.builder() - .table(MangaTable.TABLE) - .where("${MangaTable.COL_ID} = ?") - .whereArgs(manga.id) - .build() - - fun mapToContentValues(manga: Manga) = contentValuesOf( - MangaTable.COL_THUMBNAIL_URL to manga.thumbnail_url, - ) -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaUrlPutResolver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaUrlPutResolver.kt deleted file mode 100644 index 81d0546bb..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaUrlPutResolver.kt +++ /dev/null @@ -1,32 +0,0 @@ -package eu.kanade.tachiyomi.data.database.resolvers - -import androidx.core.content.contentValuesOf -import com.pushtorefresh.storio.sqlite.StorIOSQLite -import com.pushtorefresh.storio.sqlite.operations.put.PutResolver -import com.pushtorefresh.storio.sqlite.operations.put.PutResult -import com.pushtorefresh.storio.sqlite.queries.UpdateQuery -import eu.kanade.tachiyomi.data.database.inTransactionReturn -import eu.kanade.tachiyomi.data.database.models.Manga -import eu.kanade.tachiyomi.data.database.tables.MangaTable - -// [EXH] -class MangaUrlPutResolver : PutResolver() { - - override fun performPut(db: StorIOSQLite, manga: Manga) = db.inTransactionReturn { - val updateQuery = mapToUpdateQuery(manga) - val contentValues = mapToContentValues(manga) - - val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues) - PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table()) - } - - fun mapToUpdateQuery(manga: Manga) = UpdateQuery.builder() - .table(MangaTable.TABLE) - .where("${MangaTable.COL_ID} = ?") - .whereArgs(manga.id) - .build() - - fun mapToContentValues(manga: Manga) = contentValuesOf( - MangaTable.COL_URL to manga.url, - ) -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/CategoryTable.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/CategoryTable.kt deleted file mode 100755 index 80a88ca55..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/CategoryTable.kt +++ /dev/null @@ -1,18 +0,0 @@ -package eu.kanade.tachiyomi.data.database.tables - -object CategoryTable { - - const val TABLE = "categories" - - const val COL_ID = "_id" - - const val COL_NAME = "name" - - const val COL_ORDER = "sort" - - const val COL_FLAGS = "flags" - - // SY --> - const val COL_MANGA_ORDER = "manga_order" - // SY <-- -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/ChapterTable.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/ChapterTable.kt deleted file mode 100755 index 8914e6f3c..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/ChapterTable.kt +++ /dev/null @@ -1,30 +0,0 @@ -package eu.kanade.tachiyomi.data.database.tables - -object ChapterTable { - - const val TABLE = "chapters" - - const val COL_ID = "_id" - - const val COL_MANGA_ID = "manga_id" - - const val COL_URL = "url" - - const val COL_NAME = "name" - - const val COL_READ = "read" - - const val COL_SCANLATOR = "scanlator" - - const val COL_BOOKMARK = "bookmark" - - const val COL_DATE_FETCH = "date_fetch" - - const val COL_DATE_UPLOAD = "date_upload" - - const val COL_LAST_PAGE_READ = "last_page_read" - - const val COL_CHAPTER_NUMBER = "chapter_number" - - const val COL_SOURCE_ORDER = "source_order" -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/HistoryTable.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/HistoryTable.kt deleted file mode 100755 index e3eab5dee..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/HistoryTable.kt +++ /dev/null @@ -1,29 +0,0 @@ -package eu.kanade.tachiyomi.data.database.tables - -object HistoryTable { - - /** - * Table name - */ - const val TABLE = "history" - - /** - * Id column name - */ - const val COL_ID = "_id" - - /** - * Chapter id column name - */ - const val COL_CHAPTER_ID = "chapter_id" - - /** - * Last read column name - */ - const val COL_LAST_READ = "last_read" - - /** - * Time read column name - */ - const val COL_TIME_READ = "time_read" -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/MangaCategoryTable.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/MangaCategoryTable.kt deleted file mode 100755 index d39b32adf..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/MangaCategoryTable.kt +++ /dev/null @@ -1,12 +0,0 @@ -package eu.kanade.tachiyomi.data.database.tables - -object MangaCategoryTable { - - const val TABLE = "mangas_categories" - - const val COL_ID = "_id" - - const val COL_MANGA_ID = "manga_id" - - const val COL_CATEGORY_ID = "category_id" -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/MangaTable.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/MangaTable.kt deleted file mode 100755 index 3e42dea7a..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/MangaTable.kt +++ /dev/null @@ -1,54 +0,0 @@ -package eu.kanade.tachiyomi.data.database.tables - -object MangaTable { - - const val TABLE = "mangas" - - const val COL_ID = "_id" - - const val COL_SOURCE = "source" - - const val COL_URL = "url" - - const val COL_ARTIST = "artist" - - const val COL_AUTHOR = "author" - - const val COL_DESCRIPTION = "description" - - const val COL_GENRE = "genre" - - const val COL_TITLE = "title" - - const val COL_STATUS = "status" - - const val COL_THUMBNAIL_URL = "thumbnail_url" - - const val COL_FAVORITE = "favorite" - - const val COL_LAST_UPDATE = "last_update" - - // Not actually used anymore - const val COL_NEXT_UPDATE = "next_update" - - const val COL_DATE_ADDED = "date_added" - - const val COL_INITIALIZED = "initialized" - - const val COL_VIEWER = "viewer" - - const val COL_CHAPTER_FLAGS = "chapter_flags" - - // SY --> - const val COL_FILTERED_SCANLATORS = "filtered_scanlators" - // SY <-- - - const val COL_CATEGORY = "category" - - const val COL_COVER_LAST_MODIFIED = "cover_last_modified" - - // Not an actual value but computed when created - const val COMPUTED_COL_UNREAD_COUNT = "unread_count" - - const val COMPUTED_COL_READ_COUNT = "read_count" -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/TrackTable.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/TrackTable.kt deleted file mode 100755 index 05ee195f3..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/TrackTable.kt +++ /dev/null @@ -1,32 +0,0 @@ -package eu.kanade.tachiyomi.data.database.tables - -object TrackTable { - - const val TABLE = "manga_sync" - - const val COL_ID = "_id" - - const val COL_MANGA_ID = "manga_id" - - const val COL_SYNC_ID = "sync_id" - - const val COL_MEDIA_ID = "remote_id" - - const val COL_LIBRARY_ID = "library_id" - - const val COL_TITLE = "title" - - const val COL_LAST_CHAPTER_READ = "last_chapter_read" - - const val COL_STATUS = "status" - - const val COL_SCORE = "score" - - const val COL_TOTAL_CHAPTERS = "total_chapters" - - const val COL_TRACKING_URL = "remote_url" - - const val COL_START_DATE = "start_date" - - const val COL_FINISH_DATE = "finish_date" -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt index 4f9aaad2d..3adf7b7f5 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt @@ -5,7 +5,6 @@ import com.hippo.unifile.UniFile import com.jakewharton.rxrelay.BehaviorRelay import eu.kanade.domain.category.interactor.GetCategories import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.download.model.Download @@ -34,7 +33,6 @@ import uy.kohesive.injekt.injectLazy */ class DownloadManager( private val context: Context, - private val db: DatabaseHelper = Injekt.get(), private val getCategories: GetCategories = Injekt.get(), ) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt index 45a263930..ee9648c50 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt @@ -14,18 +14,21 @@ import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay import eu.kanade.domain.chapter.model.toDbChapter import eu.kanade.domain.manga.interactor.GetFavorites +import eu.kanade.domain.manga.interactor.GetLibraryManga import eu.kanade.domain.manga.interactor.GetManga +import eu.kanade.domain.manga.interactor.GetMergedMangaForDownloading import eu.kanade.domain.manga.interactor.InsertFlatMetadata +import eu.kanade.domain.manga.interactor.InsertManga import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.domain.manga.model.toDbManga import eu.kanade.domain.manga.model.toMangaInfo +import eu.kanade.domain.manga.model.toMangaUpdate import eu.kanade.domain.track.interactor.GetTracks import eu.kanade.domain.track.interactor.InsertTrack import eu.kanade.domain.track.model.toDbTrack import eu.kanade.domain.track.model.toDomainTrack import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.cache.CoverCache -import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.LibraryManga import eu.kanade.tachiyomi.data.database.models.Manga @@ -47,6 +50,7 @@ import eu.kanade.tachiyomi.data.track.TrackStatus import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.UnmeteredSource import eu.kanade.tachiyomi.source.model.SManga +import eu.kanade.tachiyomi.source.model.toMangaInfo import eu.kanade.tachiyomi.source.model.toSChapter import eu.kanade.tachiyomi.source.model.toSManga import eu.kanade.tachiyomi.source.online.all.MergedSource @@ -67,7 +71,6 @@ import exh.source.LIBRARY_UPDATE_EXCLUDED_SOURCES import exh.source.MERGED_SOURCE_ID import exh.source.isMdBasedSource import exh.source.mangaDexSourceIds -import exh.util.executeOnIO import exh.util.nullIfBlank import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineScope @@ -102,12 +105,12 @@ import eu.kanade.domain.manga.model.Manga as DomainManga * destroyed. */ class LibraryUpdateService( - val db: DatabaseHelper = Injekt.get(), val sourceManager: SourceManager = Injekt.get(), val preferences: PreferencesHelper = Injekt.get(), val downloadManager: DownloadManager = Injekt.get(), val trackManager: TrackManager = Injekt.get(), val coverCache: CoverCache = Injekt.get(), + private val getLibraryManga: GetLibraryManga = Injekt.get(), private val getManga: GetManga = Injekt.get(), private val updateManga: UpdateManga = Injekt.get(), private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(), @@ -119,6 +122,8 @@ class LibraryUpdateService( // SY --> private val getFavorites: GetFavorites = Injekt.get(), private val insertFlatMetadata: InsertFlatMetadata = Injekt.get(), + private val insertManga: InsertManga = Injekt.get(), + private val getMergedMangaForDownloading: GetMergedMangaForDownloading = Injekt.get(), // SY <-- ) : Service() { @@ -301,7 +306,7 @@ class LibraryUpdateService( * @param categoryId the ID of the category to update, or -1 if no category specified. */ fun addMangaToQueue(categoryId: Long, group: Int, groupExtra: String?) { - val libraryManga = db.getLibraryMangas().executeAsBlocking() + val libraryManga = runBlocking { getLibraryManga.await() } // SY --> val groupLibraryUpdateType = preferences.groupLibraryUpdateType().get() // SY <-- @@ -499,12 +504,12 @@ class LibraryUpdateService( // may don't like it and they could ban the user. // SY --> if (manga.source == MERGED_SOURCE_ID) { - val downloadingManga = db.getMergedMangasForDownloading(manga.id!!).executeAsBlocking() - .associateBy { it.id!! } + val downloadingManga = runBlocking { getMergedMangaForDownloading.await(manga.id!!) } + .associateBy { it.id } chapters.groupBy { it.manga_id } .forEach { downloadManager.downloadChapters( - downloadingManga[it.key] ?: return@forEach, + downloadingManga[it.key]?.toDbManga() ?: return@forEach, chapters, false, ) @@ -593,7 +598,14 @@ class LibraryUpdateService( mangaWithNotif.prepUpdateCover(coverCache, sManga, true) sManga.thumbnail_url?.let { mangaWithNotif.thumbnail_url = it - db.insertManga(mangaWithNotif).executeAsBlocking() + try { + updateManga.await( + mangaWithNotif.toDomainManga()!! + .toMangaUpdate(), + ) + } catch (e: Exception) { + logcat(LogPriority.ERROR) { "Manga don't exist anymore" } + } } } catch (e: Throwable) { // Ignore errors and continue @@ -714,24 +726,29 @@ class LibraryUpdateService( count++ notifier.showProgressNotification(listOf(networkManga), count, size) - var dbManga = db.getManga(networkManga.url, mangaDex.id) - .executeOnIO() + var dbManga = getManga.await(networkManga.url, mangaDex.id) + if (dbManga == null) { - dbManga = Manga.create( + val newManga = Manga.create( networkManga.url, networkManga.title, mangaDex.id, ) - dbManga.date_added = System.currentTimeMillis() + newManga.favorite = true + newManga.date_added = System.currentTimeMillis() + newManga.id = -1 + val result = runBlocking { + val id = insertManga.await(newManga.toDomainManga()!!) + getManga.await(id!!) + } + dbManga = result ?: return + } else if (!dbManga.favorite) { + updateManga.awaitUpdateFavorite(dbManga.id, true) } - dbManga.copyFrom(networkManga) - dbManga.favorite = true - val id = db.insertManga(dbManga).executeOnIO().insertedId() - if (id != null) { - metadata.mangaId = id - insertFlatMetadata.await(metadata) - } + updateManga.awaitUpdateFromSource(dbManga, networkManga.toMangaInfo(), true) + metadata.mangaId = dbManga.id + insertFlatMetadata.await(metadata) } notifier.cancelProgressNotification() diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MergedSource.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MergedSource.kt index 287c85c94..cc94ef820 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MergedSource.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MergedSource.kt @@ -4,7 +4,11 @@ import eu.kanade.domain.category.interactor.GetCategories import eu.kanade.domain.chapter.interactor.GetMergedChapterByMangaId import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource import eu.kanade.domain.chapter.model.toDbChapter -import eu.kanade.tachiyomi.data.database.DatabaseHelper +import eu.kanade.domain.manga.interactor.GetManga +import eu.kanade.domain.manga.interactor.GetMergedReferencesById +import eu.kanade.domain.manga.interactor.InsertManga +import eu.kanade.domain.manga.model.toDbManga +import eu.kanade.domain.manga.model.toMangaInfo import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.toDomainManga @@ -22,7 +26,6 @@ import eu.kanade.tachiyomi.source.model.toSManga import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.util.lang.withIOContext import eu.kanade.tachiyomi.util.shouldDownloadNewChapters -import exh.log.xLogW import exh.merged.sql.models.MergedMangaReference import exh.source.MERGED_SOURCE_ID import kotlinx.coroutines.CancellationException @@ -42,8 +45,10 @@ import eu.kanade.domain.chapter.model.Chapter as DomainChapter import eu.kanade.domain.manga.model.Manga as DomainManga class MergedSource : HttpSource() { - private val db: DatabaseHelper by injectLazy() + private val getManga: GetManga by injectLazy() + private val getMergedReferencesById: GetMergedReferencesById by injectLazy() private val getMergedChaptersByMangaId: GetMergedChapterByMangaId by injectLazy() + private val insertManga: InsertManga by injectLazy() private val getCategories: GetCategories by injectLazy() private val sourceManager: SourceManager by injectLazy() private val downloadManager: DownloadManager by injectLazy() @@ -74,9 +79,8 @@ class MergedSource : HttpSource() { override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo { return withIOContext { - val mergedManga = db.getManga(manga.key, id).executeAsBlocking() - ?: throw Exception("merged manga not in db") - val mangaReferences = db.getMergedMangaReferences(mergedManga.id!!).executeAsBlocking() + val mergedManga = getManga.await(manga.key, id) ?: throw Exception("merged manga not in db") + val mangaReferences = getMergedReferencesById.await(mergedManga.id) .apply { if (isEmpty()) { throw IllegalArgumentException( @@ -93,7 +97,7 @@ class MergedSource : HttpSource() { val mangaInfoReference = mangaReferences.firstOrNull { it.isInfoManga } ?: mangaReferences.firstOrNull { it.mangaId != it.mergeId } val dbManga = mangaInfoReference?.run { - db.getManga(mangaUrl, mangaSourceId).executeAsBlocking()?.toMangaInfo() + getManga.await(mangaUrl, mangaSourceId)?.toMangaInfo() } (dbManga ?: mergedManga.toMangaInfo()).copy( key = manga.key, @@ -102,8 +106,8 @@ class MergedSource : HttpSource() { } // TODO more chapter dedupe - fun transformMergedChapters(mangaId: Long, chapterList: List, editScanlators: Boolean, dedupe: Boolean): List { - val mangaReferences = db.getMergedMangaReferences(mangaId).executeAsBlocking() + suspend fun transformMergedChapters(mangaId: Long, chapterList: List, editScanlators: Boolean, dedupe: Boolean): List { + val mangaReferences = getMergedReferencesById.await(mangaId) val chapters = if (editScanlators) { val sources = mangaReferences.map { sourceManager.getOrStub(it.mangaSourceId) to it.mangaId } chapterList.map { chapter -> @@ -127,7 +131,11 @@ class MergedSource : HttpSource() { } fun getChaptersAsBlocking(mangaId: Long, editScanlators: Boolean = false, dedupe: Boolean = true): List { - return transformMergedChapters(mangaId, runBlocking { getMergedChaptersByMangaId.await(mangaId) }, editScanlators, dedupe) + return runBlocking { getChapters(mangaId, editScanlators, dedupe) } + } + + suspend fun getChapters(mangaId: Long, editScanlators: Boolean = false, dedupe: Boolean = true): List { + return transformMergedChapters(mangaId, getMergedChaptersByMangaId.await(mangaId), editScanlators, dedupe) } private fun dedupeChapterList(mangaReferences: List, chapterList: List): List { @@ -165,7 +173,7 @@ class MergedSource : HttpSource() { suspend fun fetchChaptersAndSync(manga: DomainManga, downloadChapters: Boolean = true): Pair, List> { val syncChaptersWithSource = Injekt.get() - val mangaReferences = db.getMergedMangaReferences(manga.id).executeAsBlocking() + val mangaReferences = getMergedReferencesById.await(manga.id) if (mangaReferences.isEmpty()) { throw IllegalArgumentException("Manga references are empty, chapters unavailable, merge is likely corrupted") } @@ -183,15 +191,15 @@ class MergedSource : HttpSource() { values.map { try { val (source, loadedManga, reference) = - it.load(db, sourceManager) + it.load(sourceManager, getManga, insertManga) if (loadedManga != null && reference.getChapterUpdates) { val chapterList = source.getChapterList(loadedManga.toMangaInfo()) .map(ChapterInfo::toSChapter) val results = - syncChaptersWithSource.await(chapterList, loadedManga.toDomainManga()!!, source) + syncChaptersWithSource.await(chapterList, loadedManga, source) if (ifDownloadNewChapters && reference.downloadChapters) { downloadManager.downloadChapters( - loadedManga, + loadedManga.toDbManga(), results.first.map(DomainChapter::toDbChapter), ) } @@ -218,26 +226,25 @@ class MergedSource : HttpSource() { } } - suspend fun MergedMangaReference.load(db: DatabaseHelper, sourceManager: SourceManager): LoadedMangaSource { - var manga = db.getManga(mangaUrl, mangaSourceId).executeAsBlocking() + suspend fun MergedMangaReference.load(sourceManager: SourceManager, getManga: GetManga, insertManga: InsertManga): LoadedMangaSource { + var manga = getManga.await(mangaUrl, mangaSourceId) val source = sourceManager.getOrStub(manga?.source ?: mangaSourceId) if (manga == null) { - manga = Manga.create(mangaSourceId).apply { + val newManga = Manga.create(mangaSourceId).apply { url = mangaUrl } - manga.copyFrom(source.getMangaDetails(manga.toMangaInfo()).toSManga()) - try { - manga.id = db.insertManga(manga).executeAsBlocking().insertedId() - mangaId = manga.id - db.insertNewMergedMangaId(this).executeAsBlocking() - } catch (e: Exception) { - xLogW("Error inserting merged manga id", e) + newManga.copyFrom(source.getMangaDetails(newManga.toMangaInfo()).toSManga()) + newManga.id = -1 + val result = run { + val id = insertManga.await(newManga.toDomainManga()!!) + getManga.await(id!!) } + manga = result } return LoadedMangaSource(source, manga, this) } - data class LoadedMangaSource(val source: Source, val manga: Manga?, val reference: MergedMangaReference) + data class LoadedMangaSource(val source: Source, val manga: DomainManga?, val reference: MergedMangaReference) override val lang = "all" override val supportsLatest = false diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/feed/FeedPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/feed/FeedPresenter.kt index 079cd4180..0b620bedb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/feed/FeedPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/feed/FeedPresenter.kt @@ -4,8 +4,13 @@ import android.os.Bundle import eu.kanade.data.DatabaseHandler import eu.kanade.data.exh.feedSavedSearchMapper import eu.kanade.data.exh.savedSearchMapper -import eu.kanade.tachiyomi.data.database.DatabaseHelper +import eu.kanade.domain.manga.interactor.GetManga +import eu.kanade.domain.manga.interactor.InsertManga +import eu.kanade.domain.manga.interactor.UpdateManga +import eu.kanade.domain.manga.model.toDbManga +import eu.kanade.domain.manga.model.toMangaUpdate import eu.kanade.tachiyomi.data.database.models.Manga +import eu.kanade.tachiyomi.data.database.models.toDomainManga import eu.kanade.tachiyomi.data.database.models.toMangaInfo import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.source.CatalogueSource @@ -23,6 +28,7 @@ import exh.savedsearches.models.FeedSavedSearch import exh.savedsearches.models.SavedSearch import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.runBlocking import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import logcat.LogPriority @@ -40,14 +46,16 @@ import xyz.nulldev.ts.api.http.serializer.FilterSerializer * Function calls should be done from here. UI calls should be done from the controller. * * @param sourceManager manages the different sources. - * @param database manages the database calls. + * @param handler manages the database calls. * @param preferences manages the preference calls. */ open class FeedPresenter( val sourceManager: SourceManager = Injekt.get(), - val database: DatabaseHandler = Injekt.get(), - val db: DatabaseHelper = Injekt.get(), + val handler: DatabaseHandler = Injekt.get(), val preferences: PreferencesHelper = Injekt.get(), + private val getManga: GetManga = Injekt.get(), + private val insertManga: InsertManga = Injekt.get(), + private val updateManga: UpdateManga = Injekt.get(), ) : BasePresenter() { /** @@ -68,7 +76,7 @@ open class FeedPresenter( override fun onCreate(savedState: Bundle?) { super.onCreate(savedState) - database.subscribeToList { feed_saved_searchQueries.selectAllGlobal() } + handler.subscribeToList { feed_saved_searchQueries.selectAllGlobal() } .onEach { getFeed() } @@ -82,7 +90,7 @@ open class FeedPresenter( } suspend fun hasTooManyFeeds(): Boolean { - return database.awaitOne { feed_saved_searchQueries.countGlobal() } > 10 + return handler.awaitOne { feed_saved_searchQueries.countGlobal() } > 10 } fun getEnabledSources(): List { @@ -97,12 +105,12 @@ open class FeedPresenter( } suspend fun getSourceSavedSearches(source: CatalogueSource): List { - return database.awaitList { saved_searchQueries.selectBySource(source.id, savedSearchMapper) } + return handler.awaitList { saved_searchQueries.selectBySource(source.id, savedSearchMapper) } } fun createFeed(source: CatalogueSource, savedSearch: SavedSearch?) { launchIO { - database.await { + handler.await { feed_saved_searchQueries.insertFeedSavedSearch( _id = null, source = source.id, @@ -115,17 +123,17 @@ open class FeedPresenter( fun deleteFeed(feed: FeedSavedSearch) { launchIO { - database.await { + handler.await { feed_saved_searchQueries.deleteById(feed.id ?: return@await) } } } private suspend fun getSourcesToGetFeed(): List> { - val savedSearches = database.awaitList { + val savedSearches = handler.awaitList { feed_saved_searchQueries.selectGlobalFeedSavedSearch(savedSearchMapper) }.associateBy { it.id } - return database.awaitList { feed_saved_searchQueries.selectAllGlobal(feedSavedSearchMapper) } + return handler.awaitList { feed_saved_searchQueries.selectAllGlobal(feedSavedSearchMapper) } .map { it to savedSearches[it.savedSearch] } } @@ -263,7 +271,7 @@ open class FeedPresenter( val networkManga = source.getMangaDetails(manga.toMangaInfo()) manga.copyFrom(networkManga.toSManga()) manga.initialized = true - db.insertManga(manga).executeAsBlocking() + updateManga.await(manga.toDomainManga()!!.toMangaUpdate()) manga } .onErrorResumeNext { Observable.just(manga) } @@ -276,15 +284,22 @@ open class FeedPresenter( * @param sManga the manga from the source. * @return a manga from the database. */ - protected open fun networkToLocalManga(sManga: SManga, sourceId: Long): Manga { - var localManga = db.getManga(sManga.url, sourceId).executeAsBlocking() + private fun networkToLocalManga(sManga: SManga, sourceId: Long): Manga { + var localManga = runBlocking { getManga.await(sManga.url, sourceId) } if (localManga == null) { val newManga = Manga.create(sManga.url, sManga.title, sourceId) newManga.copyFrom(sManga) - val result = db.insertManga(newManga).executeAsBlocking() - newManga.id = result.insertedId() - localManga = newManga + newManga.id = -1 + val result = runBlocking { + val id = insertManga.await(newManga.toDomainManga()!!) + getManga.await(id!!) + } + localManga = result + } else if (!localManga.favorite) { + // if the manga isn't a favorite, set its display title from source + // if it later becomes a favorite, updated title will go to db + localManga = localManga.copy(ogTitle = sManga.title) } - return localManga + return localManga?.toDbManga()!! } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SearchController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SearchController.kt index 61373e4d3..4e1e4af54 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SearchController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SearchController.kt @@ -5,8 +5,9 @@ import android.view.Menu import android.view.MenuInflater import androidx.appcompat.widget.SearchView import androidx.core.os.bundleOf +import eu.kanade.domain.manga.interactor.GetManga +import eu.kanade.domain.manga.model.toDbManga import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.SourceManager @@ -17,6 +18,7 @@ import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchPresenter import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.runBlocking import reactivecircus.flowbinding.appcompat.QueryTextEvent import reactivecircus.flowbinding.appcompat.queryTextEvents import uy.kohesive.injekt.Injekt @@ -34,7 +36,11 @@ class SearchController( ) { constructor(targetController: MigrationListController?, mangaId: Long, sources: LongArray) : this( - Injekt.get().getManga(mangaId).executeAsBlocking(), + runBlocking { + Injekt.get() + .await(mangaId) + ?.toDbManga() + }, sources.map { Injekt.get().getOrStub(it) }.filterIsInstance(), ) { this.targetController = targetController diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt index 7189c8bb5..57aa2b02b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt @@ -9,11 +9,14 @@ import eu.kanade.domain.category.interactor.SetMangaCategories import eu.kanade.domain.chapter.interactor.GetChapterByMangaId import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay import eu.kanade.domain.manga.interactor.GetDuplicateLibraryManga +import eu.kanade.domain.manga.interactor.GetManga +import eu.kanade.domain.manga.interactor.InsertManga +import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.domain.manga.model.toDbManga +import eu.kanade.domain.manga.model.toMangaUpdate import eu.kanade.domain.track.interactor.InsertTrack import eu.kanade.domain.track.model.toDomainTrack import eu.kanade.tachiyomi.data.cache.CoverCache -import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.toDomainManga import eu.kanade.tachiyomi.data.database.models.toMangaInfo @@ -87,14 +90,16 @@ open class BrowseSourcePresenter( private val savedSearch: Long? = null, // SY <-- private val sourceManager: SourceManager = Injekt.get(), - private val db: DatabaseHelper = Injekt.get(), private val database: DatabaseHandler = Injekt.get(), private val prefs: PreferencesHelper = Injekt.get(), private val coverCache: CoverCache = Injekt.get(), + private val getManga: GetManga = Injekt.get(), private val getDuplicateLibraryManga: GetDuplicateLibraryManga = Injekt.get(), private val getCategories: GetCategories = Injekt.get(), private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(), private val setMangaCategories: SetMangaCategories = Injekt.get(), + private val insertManga: InsertManga = Injekt.get(), + private val updateManga: UpdateManga = Injekt.get(), private val insertTrack: InsertTrack = Injekt.get(), private val syncChaptersWithTrackServiceTwoWay: SyncChaptersWithTrackServiceTwoWay = Injekt.get(), ) : BasePresenter() { @@ -278,19 +283,22 @@ open class BrowseSourcePresenter( * @return a manga from the database. */ private fun networkToLocalManga(sManga: SManga, sourceId: Long): Manga { - var localManga = db.getManga(sManga.url, sourceId).executeAsBlocking() + var localManga = runBlocking { getManga.await(sManga.url, sourceId) } if (localManga == null) { val newManga = Manga.create(sManga.url, sManga.title, sourceId) newManga.copyFrom(sManga) - val result = db.insertManga(newManga).executeAsBlocking() - newManga.id = result.insertedId() - localManga = newManga + newManga.id = -1 + val result = runBlocking { + val id = insertManga.await(newManga.toDomainManga()!!) + getManga.await(id!!) + } + localManga = result } else if (!localManga.favorite) { // if the manga isn't a favorite, set its display title from source // if it later becomes a favorite, updated title will go to db - localManga.title = sManga.title + localManga = localManga.copy(ogTitle = sManga.title) } - return localManga + return localManga?.toDbManga()!! } /** @@ -325,7 +333,11 @@ open class BrowseSourcePresenter( val networkManga = source.getMangaDetails(manga.toMangaInfo()) manga.copyFrom(networkManga.toSManga()) manga.initialized = true - db.insertManga(manga).executeAsBlocking() + updateManga.await( + manga + .toDomainManga() + ?.toMangaUpdate()!!, + ) } catch (e: Exception) { logcat(LogPriority.ERROR, e) } @@ -352,7 +364,13 @@ open class BrowseSourcePresenter( autoAddTrack(manga) } - db.insertManga(manga).executeAsBlocking() + runBlocking { + updateManga.await( + manga + .toDomainManga() + ?.toMangaUpdate()!!, + ) + } } private fun autoAddTrack(manga: Manga) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/feed/SourceFeedPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/feed/SourceFeedPresenter.kt index 2151f9dfc..5b76c7e31 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/feed/SourceFeedPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/feed/SourceFeedPresenter.kt @@ -5,8 +5,13 @@ import eu.davidea.flexibleadapter.items.IFlexible import eu.kanade.data.DatabaseHandler import eu.kanade.data.exh.feedSavedSearchMapper import eu.kanade.data.exh.savedSearchMapper -import eu.kanade.tachiyomi.data.database.DatabaseHelper +import eu.kanade.domain.manga.interactor.GetManga +import eu.kanade.domain.manga.interactor.InsertManga +import eu.kanade.domain.manga.interactor.UpdateManga +import eu.kanade.domain.manga.model.toDbManga +import eu.kanade.domain.manga.model.toMangaUpdate import eu.kanade.tachiyomi.data.database.models.Manga +import eu.kanade.tachiyomi.data.database.models.toDomainManga import eu.kanade.tachiyomi.data.database.models.toMangaInfo import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.source.CatalogueSource @@ -28,6 +33,7 @@ import exh.savedsearches.models.SavedSearch import kotlinx.coroutines.CancellationException import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.runBlocking import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonArray @@ -40,7 +46,6 @@ import rx.subjects.PublishSubject import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import xyz.nulldev.ts.api.http.serializer.FilterSerializer -import java.lang.RuntimeException sealed class SourceFeed { object Latest : SourceFeed() @@ -53,14 +58,16 @@ sealed class SourceFeed { * Function calls should be done from here. UI calls should be done from the controller. * * @param source the source. - * @param database manages the database calls. + * @param handler manages the database calls. * @param preferences manages the preference calls. */ open class SourceFeedPresenter( val source: CatalogueSource, - val database: DatabaseHandler = Injekt.get(), - val db: DatabaseHelper = Injekt.get(), + val handler: DatabaseHandler = Injekt.get(), val preferences: PreferencesHelper = Injekt.get(), + private val getManga: GetManga = Injekt.get(), + private val insertManga: InsertManga = Injekt.get(), + private val updateManga: UpdateManga = Injekt.get(), ) : BasePresenter() { /** @@ -98,7 +105,7 @@ open class SourceFeedPresenter( sourceFilters = source.getFilterList() - database.subscribeToList { feed_saved_searchQueries.selectSourceFeedSavedSearch(source.id, savedSearchMapper) } + handler.subscribeToList { feed_saved_searchQueries.selectSourceFeedSavedSearch(source.id, savedSearchMapper) } .onEach { getFeed() } @@ -113,19 +120,19 @@ open class SourceFeedPresenter( suspend fun hasTooManyFeeds(): Boolean { return withIOContext { - database.awaitList { + handler.awaitList { feed_saved_searchQueries.selectSourceFeedSavedSearch(source.id) }.size > 10 } } suspend fun getSourceSavedSearches(): List { - return database.awaitList { saved_searchQueries.selectBySource(source.id, savedSearchMapper) } + return handler.awaitList { saved_searchQueries.selectBySource(source.id, savedSearchMapper) } } fun createFeed(savedSearchId: Long) { launchIO { - database.await { + handler.await { feed_saved_searchQueries.insertFeedSavedSearch( _id = null, source = source.id, @@ -138,12 +145,12 @@ open class SourceFeedPresenter( fun deleteFeed(feed: FeedSavedSearch) { launchIO { - database.await { feed_saved_searchQueries.deleteById(feed.id ?: return@await) } + handler.await { feed_saved_searchQueries.deleteById(feed.id ?: return@await) } } } private suspend fun getSourcesToGetFeed(): List { - val savedSearches = database.awaitList { feed_saved_searchQueries.selectSourceFeedSavedSearch(source.id, savedSearchMapper) } + val savedSearches = handler.awaitList { feed_saved_searchQueries.selectSourceFeedSavedSearch(source.id, savedSearchMapper) } .associateBy { it.id!! } return listOfNotNull( @@ -151,7 +158,7 @@ open class SourceFeedPresenter( SourceFeed.Latest } else null, SourceFeed.Browse, - ) + database.awaitList { feed_saved_searchQueries.selectBySource(source.id, feedSavedSearchMapper) } + ) + handler.awaitList { feed_saved_searchQueries.selectBySource(source.id, feedSavedSearchMapper) } .map { SourceFeed.SourceSavedSearch(it, savedSearches[it.savedSearch]!!) } } @@ -284,7 +291,7 @@ open class SourceFeedPresenter( val networkManga = source.getMangaDetails(manga.toMangaInfo()) manga.copyFrom(networkManga.toSManga()) manga.initialized = true - db.insertManga(manga).executeAsBlocking() + updateManga.await(manga.toDomainManga()!!.toMangaUpdate()) manga } .onErrorResumeNext { Observable.just(manga) } @@ -297,21 +304,28 @@ open class SourceFeedPresenter( * @param sManga the manga from the source. * @return a manga from the database. */ - protected open fun networkToLocalManga(sManga: SManga, sourceId: Long): Manga { - var localManga = db.getManga(sManga.url, sourceId).executeAsBlocking() + private fun networkToLocalManga(sManga: SManga, sourceId: Long): Manga { + var localManga = runBlocking { getManga.await(sManga.url, sourceId) } if (localManga == null) { val newManga = Manga.create(sManga.url, sManga.title, sourceId) newManga.copyFrom(sManga) - val result = db.insertManga(newManga).executeAsBlocking() - newManga.id = result.insertedId() - localManga = newManga + newManga.id = -1 + val result = runBlocking { + val id = insertManga.await(newManga.toDomainManga()!!) + getManga.await(id!!) + } + localManga = result + } else if (!localManga.favorite) { + // if the manga isn't a favorite, set its display title from source + // if it later becomes a favorite, updated title will go to db + localManga = localManga.copy(ogTitle = sManga.title) } - return localManga + return localManga?.toDbManga()!! } suspend fun loadSearch(searchId: Long): EXHSavedSearch? { return withIOContext { - val search = database.awaitOneOrNull { + val search = handler.awaitOneOrNull { saved_searchQueries.selectById(searchId, savedSearchMapper) } ?: return@withIOContext null EXHSavedSearch( @@ -334,7 +348,7 @@ open class SourceFeedPresenter( suspend fun loadSearches(): List { return withIOContext { - database.awaitList { saved_searchQueries.selectBySource(source.id, savedSearchMapper) }.map { + handler.awaitList { saved_searchQueries.selectBySource(source.id, savedSearchMapper) }.map { val filtersJson = it.filtersJson ?: return@map EXHSavedSearch( id = it.id!!, name = it.name, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchPresenter.kt index 04048d7a3..ef4cdab9c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchPresenter.kt @@ -1,8 +1,13 @@ package eu.kanade.tachiyomi.ui.browse.source.globalsearch import android.os.Bundle -import eu.kanade.tachiyomi.data.database.DatabaseHelper +import eu.kanade.domain.manga.interactor.GetManga +import eu.kanade.domain.manga.interactor.InsertManga +import eu.kanade.domain.manga.interactor.UpdateManga +import eu.kanade.domain.manga.model.toDbManga +import eu.kanade.domain.manga.model.toMangaUpdate import eu.kanade.tachiyomi.data.database.models.Manga +import eu.kanade.tachiyomi.data.database.models.toDomainManga import eu.kanade.tachiyomi.data.database.models.toMangaInfo import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.extension.ExtensionManager @@ -16,6 +21,7 @@ import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter import eu.kanade.tachiyomi.util.lang.runAsObservable import eu.kanade.tachiyomi.util.system.logcat +import kotlinx.coroutines.runBlocking import logcat.LogPriority import rx.Observable import rx.Subscription @@ -39,8 +45,10 @@ open class GlobalSearchPresenter( private val initialExtensionFilter: String? = null, private val sourcesToUse: List? = null, val sourceManager: SourceManager = Injekt.get(), - val db: DatabaseHelper = Injekt.get(), val preferences: PreferencesHelper = Injekt.get(), + private val getManga: GetManga = Injekt.get(), + private val insertManga: InsertManga = Injekt.get(), + private val updateManga: UpdateManga = Injekt.get(), ) : BasePresenter() { /** @@ -250,7 +258,7 @@ open class GlobalSearchPresenter( val networkManga = source.getMangaDetails(manga.toMangaInfo()) manga.copyFrom(networkManga.toSManga()) manga.initialized = true - db.insertManga(manga).executeAsBlocking() + runBlocking { updateManga.await(manga.toDomainManga()!!.toMangaUpdate()) } return manga } @@ -262,18 +270,21 @@ open class GlobalSearchPresenter( * @return a manga from the database. */ protected open fun networkToLocalManga(sManga: SManga, sourceId: Long): Manga { - var localManga = db.getManga(sManga.url, sourceId).executeAsBlocking() + var localManga = runBlocking { getManga.await(sManga.url, sourceId) } if (localManga == null) { val newManga = Manga.create(sManga.url, sManga.title, sourceId) newManga.copyFrom(sManga) - val result = db.insertManga(newManga).executeAsBlocking() - newManga.id = result.insertedId() - localManga = newManga + newManga.id = -1 + val result = runBlocking { + val id = insertManga.await(newManga.toDomainManga()!!) + getManga.await(id!!) + } + localManga = result } else if (!localManga.favorite) { // if the manga isn't a favorite, set its display title from source // if it later becomes a favorite, updated title will go to db - localManga.title = sManga.title + localManga = localManga.copy(ogTitle = sManga.title) } - return localManga + return localManga!!.toDbManga() } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/category/sources/SourceCategoryPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/category/sources/SourceCategoryPresenter.kt index 58dc9e431..cf93bf6a8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/category/sources/SourceCategoryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/category/sources/SourceCategoryPresenter.kt @@ -1,7 +1,6 @@ package eu.kanade.tachiyomi.ui.category.sources import android.os.Bundle -import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import kotlinx.coroutines.flow.launchIn @@ -14,9 +13,7 @@ import uy.kohesive.injekt.api.get /** * Presenter of [SourceCategoryController]. Used to manage the categories of the library. */ -class SourceCategoryPresenter( - private val db: DatabaseHelper = Injekt.get(), -) : BasePresenter() { +class SourceCategoryPresenter : BasePresenter() { /** * List containing categories. 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 c75079a65..a9099a988 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt @@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.ui.library import android.os.Bundle import com.jakewharton.rxrelay.BehaviorRelay import eu.kanade.core.util.asObservable -import eu.kanade.data.AndroidDatabaseHandler import eu.kanade.data.DatabaseHandler import eu.kanade.domain.category.interactor.GetCategories import eu.kanade.domain.category.interactor.SetMangaCategories @@ -13,6 +12,7 @@ import eu.kanade.domain.chapter.interactor.GetMergedChapterByMangaId import eu.kanade.domain.chapter.interactor.UpdateChapter import eu.kanade.domain.chapter.model.ChapterUpdate import eu.kanade.domain.chapter.model.toDbChapter +import eu.kanade.domain.manga.interactor.GetLibraryManga import eu.kanade.domain.manga.interactor.GetMergedMangaById import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.domain.manga.model.Manga @@ -74,6 +74,7 @@ typealias LibraryMap = Map> */ class LibraryPresenter( private val handler: DatabaseHandler = Injekt.get(), + private val getLibraryManga: GetLibraryManga = Injekt.get(), private val getTracks: GetTracks = Injekt.get(), private val getCategories: GetCategories = Injekt.get(), private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(), @@ -561,39 +562,7 @@ class LibraryPresenter( val defaultLibraryDisplayMode = preferences.libraryDisplayMode() val shouldSetFromCategory = preferences.categorizedDisplaySettings() - // TODO: Move this to domain/data layer - return handler - .subscribeToList { - // SY --> - (handler as AndroidDatabaseHandler).getLibraryQuery() - /*mangasQueries.getLibrary { _id: Long, source: Long, url: String, artist: String?, author: String?, description: String?, genre: List?, title: String, status: Long, thumbnail_url: String?, favorite: Boolean, last_update: Long?, next_update: Long?, initialized: Boolean, viewer: Long, chapter_flags: Long, cover_last_modified: Long, date_added: Long, filteredScanlators: List?, unread_count: Long, read_count: Long, category: Long -> - LibraryManga().apply { - this.id = _id - this.source = source - this.url = url - this.artist = artist - this.author = author - this.description = description - this.genre = genre?.joinToString() - this.title = title - this.status = status.toInt() - this.thumbnail_url = thumbnail_url - this.favorite = favorite - this.last_update = last_update ?: 0 - this.initialized = initialized - this.viewer_flags = viewer.toInt() - this.chapter_flags = chapter_flags.toInt() - this.cover_last_modified = cover_last_modified - this.date_added = date_added - this.filtered_scanlators = filteredScanlators?.let(listOfStringsAndAdapter::encode) - this.unreadCount = unread_count.toInt() - this.readCount = read_count.toInt() - this.category = category.toInt() - } - }*/ - // SY <-- - } - .asObservable() + return getLibraryManga.subscribe().asObservable() .map { list -> list.map { libraryManga -> // Display mode based on user preference: take it from global library setting or category diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt index 58223b42f..2e4eb21bc 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt @@ -237,7 +237,7 @@ class MangaController : private fun openMergedSettingsDialog() { EditMergedSettingsDialog( this, - presenter.manga!!.toDbManga(), + presenter.manga ?: return, ).showDialog(router) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt index 35063d004..e30b35938 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt @@ -12,16 +12,22 @@ import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay import eu.kanade.domain.chapter.interactor.UpdateChapter import eu.kanade.domain.chapter.model.ChapterUpdate import eu.kanade.domain.chapter.model.toDbChapter +import eu.kanade.domain.manga.interactor.DeleteByMergeId +import eu.kanade.domain.manga.interactor.DeleteMangaById import eu.kanade.domain.manga.interactor.GetDuplicateLibraryManga import eu.kanade.domain.manga.interactor.GetFlatMetadataById import eu.kanade.domain.manga.interactor.GetManga import eu.kanade.domain.manga.interactor.GetMangaWithChapters import eu.kanade.domain.manga.interactor.GetMergedMangaById import eu.kanade.domain.manga.interactor.GetMergedReferencesById +import eu.kanade.domain.manga.interactor.InsertManga +import eu.kanade.domain.manga.interactor.InsertMergedReference import eu.kanade.domain.manga.interactor.SetMangaChapterFlags import eu.kanade.domain.manga.interactor.SetMangaFilteredScanlators import eu.kanade.domain.manga.interactor.UpdateManga +import eu.kanade.domain.manga.interactor.UpdateMergedSettings import eu.kanade.domain.manga.model.MangaUpdate +import eu.kanade.domain.manga.model.MergeMangaSettingsUpdate import eu.kanade.domain.manga.model.TriStateFilter import eu.kanade.domain.manga.model.isLocal import eu.kanade.domain.manga.model.toDbManga @@ -32,7 +38,6 @@ import eu.kanade.domain.track.interactor.InsertTrack import eu.kanade.domain.track.model.toDbTrack import eu.kanade.domain.track.model.toDomainTrack import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.database.models.toDomainChapter @@ -127,6 +132,11 @@ class MangaPresenter( private val getMergedChapterByMangaId: GetMergedChapterByMangaId = Injekt.get(), private val getMergedMangaById: GetMergedMangaById = Injekt.get(), private val getMergedReferencesById: GetMergedReferencesById = Injekt.get(), + private val insertMergedReference: InsertMergedReference = Injekt.get(), + private val updateMergedSettings: UpdateMergedSettings = Injekt.get(), + private val insertManga: InsertManga = Injekt.get(), + private val deleteMangaById: DeleteMangaById = Injekt.get(), + private val deleteByMergeId: DeleteByMergeId = Injekt.get(), private val getFlatMetadata: GetFlatMetadataById = Injekt.get(), // SY <-- private val getDuplicateLibraryManga: GetDuplicateLibraryManga = Injekt.get(), @@ -223,7 +233,7 @@ class MangaPresenter( presenterScope.launchIO { if (!getMangaAndChapters.awaitManga(mangaId).favorite) { - ChapterSettingsHelper.applySettingDefaults(mangaId, setMangaChapterFlags) + ChapterSettingsHelper.applySettingDefaults(mangaId) } getMangaAndChapters.subscribe(mangaId) @@ -431,8 +441,6 @@ class MangaPresenter( } suspend fun smartSearchMerge(context: Context, manga: DomainManga, originalMangaId: Long): DomainManga { - val db = Injekt.get() - val originalManga = getManga.await(originalMangaId) ?: throw IllegalArgumentException(context.getString(R.string.merge_unknown_manga, originalMangaId)) if (originalManga.source == MERGED_SOURCE_ID) { @@ -474,7 +482,7 @@ class MangaPresenter( } // todo - db.insertMergedMangas(mangaReferences).executeAsBlocking() + insertMergedReference.awaitAll(mangaReferences) return originalManga } else { @@ -494,8 +502,10 @@ class MangaPresenter( throw IllegalArgumentException(context.getString(R.string.merge_duplicate)) } else if (!existingManga.favorite) { withContext(NonCancellable) { - db.deleteManga(existingManga!!.toDbManga()).executeAsBlocking() - db.deleteMangaForMergedManga(existingManga!!.id).executeAsBlocking() + existingManga?.id?.let { + deleteByMergeId.await(it) + deleteMangaById.await(it) + } } } existingManga = getManga.await(mergedManga.url, mergedManga.source) @@ -503,13 +513,13 @@ class MangaPresenter( // Reload chapters immediately mergedManga.initialized = false - - val newId = db.insertManga(mergedManga).executeAsBlocking().insertedId() - if (newId != null) mergedManga.id = newId + mergedManga.id = -1 + val newId = insertManga.await(mergedManga.toDomainManga()!!) + mergedManga.id = newId ?: throw NullPointerException("Invalid new manga id") getCategories.await(originalMangaId) .let { - setMangaCategories.await(mergedManga.id!!, it.map { it.id }) + setMangaCategories.await(newId, it.map { it.id }) } val originalMangaReference = MergedMangaReference( @@ -554,7 +564,7 @@ class MangaPresenter( mangaSourceId = MERGED_SOURCE_ID, ) - db.insertMergedMangas(listOf(originalMangaReference, newMangaReference, mergedMangaReference)).executeAsBlocking() + insertMergedReference.awaitAll(listOf(originalMangaReference, newMangaReference, mergedMangaReference)) return mergedManga.toDomainManga()!! } @@ -562,14 +572,21 @@ class MangaPresenter( // Note that if the manga are merged in a different order, this won't trigger, but I don't care lol } - fun updateMergeSettings(mergeReference: MergedMangaReference?, mergedMangaReferences: List) { + fun updateMergeSettings(mergedMangaReferences: List) { launchIO { - // todo - val db = Injekt.get() - mergeReference?.let { - db.updateMergeMangaSettings(it).executeAsBlocking() + if (mergedMangaReferences.isNotEmpty()) { + updateMergedSettings.awaitAll( + mergedMangaReferences.map { + MergeMangaSettingsUpdate( + it.id!!, + it.isInfoManga, + it.getChapterUpdates, + it.chapterPriority, + it.downloadChapters, + ) + }, + ) } - if (mergedMangaReferences.isNotEmpty()) db.updateMergedMangaSettings(mergedMangaReferences).executeAsBlocking() } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/merged/EditMergedMangaItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/merged/EditMergedMangaItem.kt index 863e88cce..f1d15320a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/merged/EditMergedMangaItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/merged/EditMergedMangaItem.kt @@ -5,8 +5,8 @@ import androidx.recyclerview.widget.RecyclerView import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.items.AbstractFlexibleItem import eu.davidea.flexibleadapter.items.IFlexible +import eu.kanade.domain.manga.model.Manga import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.databinding.EditMergedSettingsItemBinding import exh.merged.sql.models.MergedMangaReference diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/merged/EditMergedSettingsDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/merged/EditMergedSettingsDialog.kt index 177812c77..82c58419b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/merged/EditMergedSettingsDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/merged/EditMergedSettingsDialog.kt @@ -7,15 +7,22 @@ import androidx.core.os.bundleOf import androidx.recyclerview.widget.ConcatAdapter import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.dialog.MaterialAlertDialogBuilder +import eu.kanade.domain.manga.interactor.DeleteMergeById +import eu.kanade.domain.manga.interactor.GetManga +import eu.kanade.domain.manga.interactor.GetMergedMangaById +import eu.kanade.domain.manga.interactor.GetMergedReferencesById +import eu.kanade.domain.manga.model.Manga import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.database.DatabaseHelper -import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.databinding.EditMergedSettingsDialogBinding import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.ui.manga.MangaController +import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.system.toast import exh.merged.sql.models.MergedMangaReference import exh.source.MERGED_SOURCE_ID +import kotlinx.coroutines.runBlocking +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy class EditMergedSettingsDialog : DialogController, EditMergedMangaAdapter.EditMergedMangaItemListener { @@ -27,13 +34,15 @@ class EditMergedSettingsDialog : DialogController, EditMergedMangaAdapter.EditMe lateinit var binding: EditMergedSettingsDialogBinding - private val db: DatabaseHelper by injectLazy() + private val getMergedMangaById: GetMergedMangaById by injectLazy() + private val getMergedReferencesById: GetMergedReferencesById by injectLazy() + private val deleteMergeById: DeleteMergeById by injectLazy() private val mangaController get() = targetController as MangaController constructor(target: MangaController, manga: Manga) : super( - bundleOf(KEY_MANGA to manga.id!!), + bundleOf(KEY_MANGA to manga.id), ) { targetController = target this.manga = manga @@ -41,8 +50,7 @@ class EditMergedSettingsDialog : DialogController, EditMergedMangaAdapter.EditMe @Suppress("unused") constructor(bundle: Bundle) : super(bundle) { - manga = db.getManga(bundle.getLong(KEY_MANGA)) - .executeAsBlocking()!! + manga = runBlocking { Injekt.get().await(bundle.getLong(KEY_MANGA))!! } } private var mergedHeaderAdapter: EditMergedSettingsHeaderAdapter? = null @@ -62,8 +70,8 @@ class EditMergedSettingsDialog : DialogController, EditMergedMangaAdapter.EditMe } fun onViewCreated() { - val mergedManga = db.getMergedMangas(manga.id!!).executeAsBlocking() - val mergedReferences = db.getMergedMangaReferences(manga.id!!).executeAsBlocking() + val mergedManga = runBlocking { getMergedMangaById.await(manga.id) } + val mergedReferences = runBlocking { getMergedReferencesById.await(manga.id) } if (mergedReferences.isEmpty() || mergedReferences.size == 1) { activity?.toast(R.string.merged_references_invalid) router.popCurrentController() @@ -85,7 +93,7 @@ class EditMergedSettingsDialog : DialogController, EditMergedMangaAdapter.EditMe } private fun onPositiveButtonClick() { - mangaController.presenter.updateMergeSettings(mergeReference, mergedMangas.map { it.second }) + mangaController.presenter.updateMergeSettings(listOfNotNull(mergeReference) + mergedMangas.map { it.second }) } override fun onItemReleased(position: Int) { @@ -105,7 +113,9 @@ class EditMergedSettingsDialog : DialogController, EditMergedMangaAdapter.EditMe .setTitle(R.string.delete_merged_manga) .setMessage(R.string.delete_merged_manga_desc) .setPositiveButton(android.R.string.ok) { _, _ -> - db.deleteMergedManga(mergeMangaReference).executeAsBlocking() + launchIO { + deleteMergeById.await(mergeMangaReference.id!!) + } dialog?.dismiss() mangaController.router.popController(mangaController) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt index bef8ff8e5..72b59e591 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt @@ -14,12 +14,14 @@ import eu.kanade.domain.history.interactor.UpsertHistory import eu.kanade.domain.history.model.HistoryUpdate import eu.kanade.domain.manga.interactor.GetFlatMetadataById import eu.kanade.domain.manga.interactor.GetManga +import eu.kanade.domain.manga.interactor.GetMergedManga +import eu.kanade.domain.manga.interactor.GetMergedReferencesById +import eu.kanade.domain.manga.interactor.SetMangaViewerFlags import eu.kanade.domain.manga.model.isLocal import eu.kanade.domain.manga.model.toDbManga import eu.kanade.domain.track.interactor.GetTracks import eu.kanade.domain.track.interactor.InsertTrack import eu.kanade.domain.track.model.toDbTrack -import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.toDomainManga @@ -86,7 +88,6 @@ import java.util.concurrent.TimeUnit * Presenter used by the activity to perform background operations. */ class ReaderPresenter( - private val db: DatabaseHelper = Injekt.get(), private val sourceManager: SourceManager = Injekt.get(), private val downloadManager: DownloadManager = Injekt.get(), private val preferences: PreferencesHelper = Injekt.get(), @@ -97,8 +98,11 @@ class ReaderPresenter( private val insertTrack: InsertTrack = Injekt.get(), private val upsertHistory: UpsertHistory = Injekt.get(), private val updateChapter: UpdateChapter = Injekt.get(), + private val setMangaViewerFlags: SetMangaViewerFlags = Injekt.get(), // SY --> - private val getFlatMetadataById: GetFlatMetadataById, + private val getFlatMetadataById: GetFlatMetadataById = Injekt.get(), + private val getMergedManga: GetMergedManga = Injekt.get(), + private val getMergedReferencesById: GetMergedReferencesById = Injekt.get(), // SY <-- ) : BasePresenter() { @@ -314,8 +318,8 @@ class ReaderPresenter( val context = Injekt.get() val source = sourceManager.getOrStub(manga.source) - val mergedReferences = if (source is MergedSource) db.getMergedMangaReferences(manga.id!!).executeAsBlocking() else emptyList() - mergedManga = if (source is MergedSource) db.getMergedMangas(manga.id!!).executeAsBlocking().associateBy { it.id!! } else emptyMap() + val mergedReferences = if (source is MergedSource) runBlocking { getMergedReferencesById.await(manga.id!!) } else emptyList() + mergedManga = if (source is MergedSource) runBlocking { getMergedManga.await() }.map { it.toDbManga() }.associateBy { it.id!! } else emptyMap() loader = ChapterLoader(context, downloadManager, manga, source, sourceManager, mergedReferences, mergedManga ?: emptyMap()) Observable.just(manga).subscribeLatestCache(ReaderActivity::setManga) @@ -648,7 +652,14 @@ class ReaderPresenter( fun toggleBookmark(chapterId: Long, bookmarked: Boolean) { val chapter = chapterList.find { it.chapter.id == chapterId }?.chapter ?: return chapter.bookmark = bookmarked - db.updateChapterProgress(chapter).executeAsBlocking() + launchIO { + updateChapter.await( + ChapterUpdate( + id = chapter.id!!.toLong(), + bookmark = bookmarked, + ), + ) + } } // SY <-- @@ -677,7 +688,9 @@ class ReaderPresenter( fun setMangaReadingMode(readingModeType: Int) { val manga = manga ?: return manga.readingModeType = readingModeType - db.updateViewerFlags(manga).executeAsBlocking() + runBlocking { + setMangaViewerFlags.awaitSetMangaReadingMode(manga.id!!.toLong(), readingModeType.toLong()) + } Observable.timer(250, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()) .subscribeFirst({ view, _ -> @@ -712,7 +725,9 @@ class ReaderPresenter( fun setMangaOrientationType(rotationType: Int) { val manga = manga ?: return manga.orientationType = rotationType - db.updateViewerFlags(manga).executeAsBlocking() + runBlocking { + setMangaViewerFlags.awaitSetOrientationType(manga.id!!.toLong(), rotationType.toLong()) + } logcat(LogPriority.INFO) { "Manga orientation is ${manga.orientationType}" } diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterSettingsHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterSettingsHelper.kt index fafe771a8..88706dacf 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterSettingsHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterSettingsHelper.kt @@ -1,7 +1,7 @@ package eu.kanade.tachiyomi.util.chapter +import eu.kanade.domain.manga.interactor.GetFavorites import eu.kanade.domain.manga.interactor.SetMangaChapterFlags -import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.util.lang.launchIO @@ -10,7 +10,8 @@ import uy.kohesive.injekt.injectLazy object ChapterSettingsHelper { private val prefs: PreferencesHelper by injectLazy() - private val db: DatabaseHelper by injectLazy() + private val getFavorites: GetFavorites by injectLazy() + private val setMangaChapterFlags: SetMangaChapterFlags by injectLazy() /** * Updates the global Chapter Settings in Preferences. @@ -23,19 +24,20 @@ object ChapterSettingsHelper { * Updates a single manga's Chapter Settings to match what's set in Preferences. */ fun applySettingDefaults(manga: Manga) { - with(manga) { - readFilter = prefs.filterChapterByRead() - downloadedFilter = prefs.filterChapterByDownloaded() - bookmarkedFilter = prefs.filterChapterByBookmarked() - sorting = prefs.sortChapterBySourceOrNumber() - displayMode = prefs.displayChapterByNameOrNumber() - setChapterOrder(prefs.sortChapterByAscendingOrDescending()) + launchIO { + setMangaChapterFlags.awaitSetAllFlags( + mangaId = manga.id!!, + unreadFilter = prefs.filterChapterByRead().toLong(), + downloadedFilter = prefs.filterChapterByDownloaded().toLong(), + bookmarkedFilter = prefs.filterChapterByBookmarked().toLong(), + sortingMode = prefs.sortChapterBySourceOrNumber().toLong(), + sortingDirection = prefs.sortChapterByAscendingOrDescending().toLong(), + displayMode = prefs.displayChapterByNameOrNumber().toLong(), + ) } - - db.updateChapterFlags(manga).executeAsBlocking() } - suspend fun applySettingDefaults(mangaId: Long, setMangaChapterFlags: SetMangaChapterFlags) { + suspend fun applySettingDefaults(mangaId: Long) { setMangaChapterFlags.awaitSetAllFlags( mangaId = mangaId, unreadFilter = prefs.filterChapterByRead().toLong(), @@ -52,21 +54,18 @@ object ChapterSettingsHelper { */ fun updateAllMangasWithGlobalDefaults() { launchIO { - val updatedMangas = db.getFavoriteMangas() - .executeAsBlocking() + getFavorites.await() .map { manga -> - with(manga) { - readFilter = prefs.filterChapterByRead() - downloadedFilter = prefs.filterChapterByDownloaded() - bookmarkedFilter = prefs.filterChapterByBookmarked() - sorting = prefs.sortChapterBySourceOrNumber() - displayMode = prefs.displayChapterByNameOrNumber() - setChapterOrder(prefs.sortChapterByAscendingOrDescending()) - } - manga + setMangaChapterFlags.awaitSetAllFlags( + mangaId = manga.id, + unreadFilter = prefs.filterChapterByRead().toLong(), + downloadedFilter = prefs.filterChapterByDownloaded().toLong(), + bookmarkedFilter = prefs.filterChapterByBookmarked().toLong(), + sortingMode = prefs.sortChapterBySourceOrNumber().toLong(), + sortingDirection = prefs.sortChapterByAscendingOrDescending().toLong(), + displayMode = prefs.displayChapterByNameOrNumber().toLong(), + ) } - - db.updateChapterFlags(updatedMangas).executeAsBlocking() } } } diff --git a/app/src/main/java/exh/EXHMigrations.kt b/app/src/main/java/exh/EXHMigrations.kt index 3041ba7e2..b51ac72f8 100644 --- a/app/src/main/java/exh/EXHMigrations.kt +++ b/app/src/main/java/exh/EXHMigrations.kt @@ -2,21 +2,21 @@ package exh -import android.content.Context import androidx.core.content.edit import androidx.preference.PreferenceManager -import com.pushtorefresh.storio.sqlite.queries.Query import eu.kanade.data.DatabaseHandler +import eu.kanade.data.chapter.chapterMapper +import eu.kanade.domain.chapter.interactor.DeleteChapters +import eu.kanade.domain.chapter.interactor.UpdateChapter +import eu.kanade.domain.chapter.model.ChapterUpdate import eu.kanade.domain.manga.interactor.GetManga import eu.kanade.domain.manga.interactor.GetMangaBySource +import eu.kanade.domain.manga.interactor.InsertMergedReference import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.domain.manga.model.MangaUpdate import eu.kanade.tachiyomi.BuildConfig import eu.kanade.tachiyomi.data.backup.BackupCreatorJob -import eu.kanade.tachiyomi.data.database.DatabaseHelper -import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Manga -import eu.kanade.tachiyomi.data.database.tables.ChapterTable import eu.kanade.tachiyomi.data.library.LibraryUpdateJob import eu.kanade.tachiyomi.data.preference.MANGA_NON_COMPLETED import eu.kanade.tachiyomi.data.preference.PreferenceKeys @@ -39,7 +39,6 @@ import eu.kanade.tachiyomi.util.preference.minusAssign import eu.kanade.tachiyomi.util.system.DeviceUtil import exh.eh.EHentaiUpdateWorker import exh.log.xLogE -import exh.log.xLogW import exh.merged.sql.models.MergedMangaReference import exh.source.BlacklistedSources import exh.source.EH_SOURCE_ID @@ -69,12 +68,14 @@ import java.net.URISyntaxException import eu.kanade.domain.manga.model.Manga as DomainManga object EXHMigrations { - private val db: DatabaseHelper by injectLazy() private val handler: DatabaseHandler by injectLazy() private val sourceManager: SourceManager by injectLazy() private val getManga: GetManga by injectLazy() private val getMangaBySource: GetMangaBySource by injectLazy() private val updateManga: UpdateManga by injectLazy() + private val updateChapter: UpdateChapter by injectLazy() + private val deleteChapters: DeleteChapters by injectLazy() + private val insertMergedReference: InsertMergedReference by injectLazy() /** * Performs a migration when the application is updated. @@ -125,89 +126,73 @@ object EXHMigrations { updateSourceId(NHentai.otherId, 6907) } if (oldVersion under 7) { - db.inTransaction { - val mergedMangas = runBlocking { getMangaBySource.await(MERGED_SOURCE_ID) } + val mergedMangas = runBlocking { getMangaBySource.await(MERGED_SOURCE_ID) } - if (mergedMangas.isNotEmpty()) { - val mangaConfigs = mergedMangas.mapNotNull { mergedManga -> readMangaConfig(mergedManga)?.let { mergedManga to it } } - if (mangaConfigs.isNotEmpty()) { - val mangaToUpdate = mutableListOf() - val mergedMangaReferences = mutableListOf() - mangaConfigs.onEach { mergedManga -> - val newFirst = mergedManga.second.children.firstOrNull()?.url?.let { - if (runBlocking { getManga.await(it, MERGED_SOURCE_ID) } != null) return@onEach - mangaToUpdate += MangaUpdate(id = mergedManga.first.id, url = it) - mergedManga.first.copy(url = it) - } ?: mergedManga.first + if (mergedMangas.isNotEmpty()) { + val mangaConfigs = mergedMangas.mapNotNull { mergedManga -> readMangaConfig(mergedManga)?.let { mergedManga to it } } + if (mangaConfigs.isNotEmpty()) { + val mangaToUpdate = mutableListOf() + val mergedMangaReferences = mutableListOf() + mangaConfigs.onEach { mergedManga -> + val newFirst = mergedManga.second.children.firstOrNull()?.url?.let { + if (runBlocking { getManga.await(it, MERGED_SOURCE_ID) } != null) return@onEach + mangaToUpdate += MangaUpdate(id = mergedManga.first.id, url = it) + mergedManga.first.copy(url = it) + } ?: mergedManga.first + mergedMangaReferences += MergedMangaReference( + id = null, + isInfoManga = false, + getChapterUpdates = false, + chapterSortMode = 0, + chapterPriority = 0, + downloadChapters = false, + mergeId = newFirst.id, + mergeUrl = newFirst.url, + mangaId = newFirst.id, + mangaUrl = newFirst.url, + mangaSourceId = MERGED_SOURCE_ID, + ) + mergedManga.second.children.distinct().forEachIndexed { index, mangaSource -> + val load = mangaSource.load() ?: return@forEachIndexed mergedMangaReferences += MergedMangaReference( id = null, - isInfoManga = false, - getChapterUpdates = false, + isInfoManga = index == 0, + getChapterUpdates = true, chapterSortMode = 0, chapterPriority = 0, - downloadChapters = false, - mergeId = mergedManga.first.id, - mergeUrl = mergedManga.first.url, - mangaId = mergedManga.first.id, - mangaUrl = mergedManga.first.url, - mangaSourceId = MERGED_SOURCE_ID, + downloadChapters = true, + mergeId = newFirst.id, + mergeUrl = newFirst.url, + mangaId = load.manga.id, + mangaUrl = load.manga.url, + mangaSourceId = load.source.id, ) - mergedManga.second.children.distinct().forEachIndexed { index, mangaSource -> - val load = mangaSource.load(db, sourceManager) ?: return@forEachIndexed - mergedMangaReferences += MergedMangaReference( - id = null, - isInfoManga = index == 0, - getChapterUpdates = true, - chapterSortMode = 0, - chapterPriority = 0, - downloadChapters = true, - mergeId = mergedManga.first.id, - mergeUrl = mergedManga.first.url, - mangaId = load.manga.id!!, - mangaUrl = load.manga.url, - mangaSourceId = load.source.id, - ) - } } - runBlocking { - updateManga.awaitAll(mangaToUpdate) - } - db.insertMergedMangas(mergedMangaReferences).executeAsBlocking() + } + runBlocking { + updateManga.awaitAll(mangaToUpdate) + insertMergedReference.awaitAll(mergedMangaReferences) + } - val loadedMangaList = mangaConfigs.map { it.second.children }.flatten().mapNotNull { it.load(db, sourceManager) }.distinct() - val chapters = db.db.get() - .listOfObjects(Chapter::class.java) - .withQuery( - Query.builder() - .table(ChapterTable.TABLE) - .where("${ChapterTable.COL_MANGA_ID} IN (${mergedMangas.joinToString { it.id.toString() }})") - .build(), + val loadedMangaList = mangaConfigs.map { it.second.children }.flatten().mapNotNull { it.load() }.distinct() + val chapters = runBlocking { handler.awaitList { ehQueries.getChaptersByMangaIds(mergedMangas.map { it.id }, chapterMapper) } } + val mergedMangaChapters = runBlocking { handler.awaitList { ehQueries.getChaptersByMangaIds(loadedMangaList.map { it.manga.id }, chapterMapper) } } + + val mergedMangaChaptersMatched = mergedMangaChapters.mapNotNull { chapter -> loadedMangaList.firstOrNull { it.manga.id == chapter.id }?.let { it to chapter } } + val parsedChapters = chapters.filter { it.read || it.lastPageRead != 0L }.mapNotNull { chapter -> readUrlConfig(chapter.url)?.let { chapter to it } } + val chaptersToUpdate = mutableListOf() + parsedChapters.forEach { parsedChapter -> + mergedMangaChaptersMatched.firstOrNull { it.second.url == parsedChapter.second.url && it.first.source.id == parsedChapter.second.source && it.first.manga.url == parsedChapter.second.mangaUrl }?.let { + chaptersToUpdate += ChapterUpdate( + it.second.id, + read = parsedChapter.first.read, + lastPageRead = parsedChapter.first.lastPageRead, ) - .prepare() - .executeAsBlocking() - val mergedMangaChapters = db.db.get() - .listOfObjects(Chapter::class.java) - .withQuery( - Query.builder() - .table(ChapterTable.TABLE) - .where("${ChapterTable.COL_MANGA_ID} IN (${loadedMangaList.filter { it.manga.id != null }.joinToString { it.manga.id.toString() }})") - .build(), - ) - .prepare() - .executeAsBlocking() - val mergedMangaChaptersMatched = mergedMangaChapters.mapNotNull { chapter -> loadedMangaList.firstOrNull { it.manga.id == chapter.id }?.let { it to chapter } } - val parsedChapters = chapters.filter { it.read || it.last_page_read != 0 }.mapNotNull { chapter -> readUrlConfig(chapter.url)?.let { chapter to it } } - val chaptersToUpdate = mutableListOf() - parsedChapters.forEach { parsedChapter -> - mergedMangaChaptersMatched.firstOrNull { it.second.url == parsedChapter.second.url && it.first.source.id == parsedChapter.second.source && it.first.manga.url == parsedChapter.second.mangaUrl }?.let { - chaptersToUpdate += it.second.apply { - read = parsedChapter.first.read - last_page_read = parsedChapter.first.last_page_read - } - } } - db.deleteChapters(mergedMangaChapters).executeAsBlocking() - db.updateChaptersProgress(chaptersToUpdate).executeAsBlocking() + } + runBlocking { + deleteChapters.await(mergedMangaChapters.map { it.id }) + updateChapter.awaitAll(chaptersToUpdate) } } } @@ -471,18 +456,6 @@ object EXHMigrations { } } - private fun backupDatabase(context: Context, oldMigrationVersion: Int) { - val backupLocation = File(File(context.filesDir, "exh_db_bck"), "$oldMigrationVersion.bck.db") - if (backupLocation.exists()) return // Do not backup same version twice - - val dbLocation = context.getDatabasePath(db.lowLevel().sqliteOpenHelper().databaseName) - try { - dbLocation.copyTo(backupLocation, overwrite = true) - } catch (t: Throwable) { - xLogW("Failed to backup database!") - } - } - private fun getUrlWithoutDomain(orig: String): String { return try { val uri = URI(orig) @@ -536,8 +509,8 @@ object EXHMigrations { @SerialName("u") val url: String, ) { - fun load(db: DatabaseHelper, sourceManager: SourceManager): LoadedMangaSource? { - val manga = db.getManga(url, source).executeAsBlocking() ?: return null + fun load(): LoadedMangaSource? { + val manga = runBlocking { getManga.await(url, source) } ?: return null val source = sourceManager.getOrStub(source) return LoadedMangaSource(source, manga) } @@ -551,7 +524,7 @@ object EXHMigrations { } } - private data class LoadedMangaSource(val source: Source, val manga: Manga) + private data class LoadedMangaSource(val source: Source, val manga: DomainManga) private fun updateSourceId(newId: Long, oldId: Long) { runBlocking { diff --git a/app/src/main/java/exh/debug/DebugFunctions.kt b/app/src/main/java/exh/debug/DebugFunctions.kt index f662e9144..5fe675f95 100644 --- a/app/src/main/java/exh/debug/DebugFunctions.kt +++ b/app/src/main/java/exh/debug/DebugFunctions.kt @@ -2,7 +2,6 @@ package exh.debug import android.app.Application import androidx.work.WorkManager -import eu.kanade.data.AndroidDatabaseHandler import eu.kanade.data.DatabaseHandler import eu.kanade.domain.manga.interactor.GetAllManga import eu.kanade.domain.manga.interactor.GetExhFavoriteMangaWithMetadata @@ -12,7 +11,6 @@ import eu.kanade.domain.manga.interactor.GetSearchMetadata import eu.kanade.domain.manga.interactor.InsertFlatMetadata import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.domain.manga.model.toMangaInfo -import eu.kanade.tachiyomi.data.database.tables.MangaTable import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.online.all.NHentai @@ -110,16 +108,7 @@ object DebugFunctions { } fun addAllMangaInDatabaseToLibrary() { - (handler as AndroidDatabaseHandler).rawQuery { - it.execute( - null, - """ - UPDATE ${MangaTable.TABLE} - SET ${MangaTable.COL_FAVORITE} = 1 - """.trimIndent(), - 0, - ) - } + runBlocking { handler.await { ehQueries.addAllMangaInDatabaseToLibrary() } } } fun countMangaInDatabaseInLibrary() = runBlocking { getFavorites.await().size } @@ -200,16 +189,8 @@ object DebugFunctions { fun cancelAllScheduledJobs() = app.jobScheduler.cancelAll() private fun convertSources(from: Long, to: Long) { - (handler as AndroidDatabaseHandler).rawQuery { - it.execute( - null, - """ - UPDATE ${MangaTable.TABLE} - SET ${MangaTable.COL_SOURCE} = $to - WHERE ${MangaTable.COL_SOURCE} = $from - """.trimIndent(), - 0, - ) + runBlocking { + handler.await { ehQueries.migrateSource(to, from) } } } @@ -292,60 +273,20 @@ object DebugFunctions { }*/ fun fixReaderViewerBackupBug() { - (handler as AndroidDatabaseHandler).rawQuery { - it.execute( - null, - """ - UPDATE ${MangaTable.TABLE} - SET ${MangaTable.COL_VIEWER} = 0 - WHERE ${MangaTable.COL_VIEWER} = -1 - """.trimIndent(), - 0, - ) - } + runBlocking { handler.await { ehQueries.fixReaderViewerBackupBug() } } } fun resetReaderViewerForAllManga() { - (handler as AndroidDatabaseHandler).rawQuery { - it.execute( - null, - """ - UPDATE ${MangaTable.TABLE} - SET ${MangaTable.COL_VIEWER} = 0 - """.trimIndent(), - 0, - ) - } + runBlocking { handler.await { ehQueries.resetReaderViewerForAllManga() } } } fun migrateAllNhentaiToOtherLang() { - val sources = nHentaiSourceIds.toMutableList() - .also { it.remove(NHentai.otherId) } - .joinToString(separator = ",") + val sources = nHentaiSourceIds - NHentai.otherId - (handler as AndroidDatabaseHandler).rawQuery { - it.execute( - null, - """ - UPDATE ${MangaTable.TABLE} - SET ${MangaTable.COL_SOURCE} = ${NHentai.otherId} - WHERE ${MangaTable.COL_FAVORITE} = 1 AND ${MangaTable.COL_SOURCE} in ($sources) - """.trimIndent(), - 0, - ) - } + runBlocking { handler.await { ehQueries.migrateAllNhentaiToOtherLang(NHentai.otherId, sources) } } } fun resetFilteredScanlatorsForAllManga() { - (handler as AndroidDatabaseHandler).rawQuery { - it.execute( - null, - """ - UPDATE ${MangaTable.TABLE} - SET ${MangaTable.COL_FILTERED_SCANLATORS} = NULL - """.trimIndent(), - 0, - ) - } + runBlocking { handler.await { ehQueries.resetFilteredScanlatorsForAllManga() } } } } diff --git a/app/src/main/java/exh/eh/EHentaiUpdateWorker.kt b/app/src/main/java/exh/eh/EHentaiUpdateWorker.kt index 34e8bcd45..4d92c12dd 100644 --- a/app/src/main/java/exh/eh/EHentaiUpdateWorker.kt +++ b/app/src/main/java/exh/eh/EHentaiUpdateWorker.kt @@ -12,11 +12,13 @@ import androidx.work.WorkerParameters import com.elvishew.xlog.Logger import com.elvishew.xlog.XLog import eu.kanade.data.DatabaseHandler -import eu.kanade.data.manga.mangaMapper import eu.kanade.domain.chapter.interactor.GetChapterByMangaId import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource import eu.kanade.domain.chapter.model.Chapter import eu.kanade.domain.chapter.model.toDbChapter +import eu.kanade.domain.manga.interactor.GetExhFavoriteMangaWithMetadata +import eu.kanade.domain.manga.interactor.GetFlatMetadataById +import eu.kanade.domain.manga.interactor.InsertFlatMetadata import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.domain.manga.model.Manga import eu.kanade.domain.manga.model.toDbManga @@ -33,11 +35,6 @@ import exh.debug.DebugToggles import exh.eh.EHentaiUpdateWorkerConstants.UPDATES_PER_ITERATION import exh.log.xLog import exh.metadata.metadata.EHentaiSearchMetadata -import exh.metadata.metadata.base.awaitFlatMetadataForManga -import exh.metadata.metadata.base.awaitInsertFlatMetadata -import exh.source.EH_SOURCE_ID -import exh.source.EXH_SOURCE_ID -import exh.source.isEhBasedManga import exh.util.cancellable import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.mapNotNull @@ -53,7 +50,6 @@ import kotlin.time.Duration.Companion.days class EHentaiUpdateWorker(private val context: Context, workerParams: WorkerParameters) : CoroutineWorker(context, workerParams) { - private val handler: DatabaseHandler by injectLazy() private val prefs: PreferencesHelper by injectLazy() private val sourceManager: SourceManager by injectLazy() private val updateHelper: EHentaiUpdateHelper by injectLazy() @@ -61,6 +57,9 @@ class EHentaiUpdateWorker(private val context: Context, workerParams: WorkerPara private val updateManga: UpdateManga by injectLazy() private val syncChaptersWithSource: SyncChaptersWithSource by injectLazy() private val getChapterByMangaId: GetChapterByMangaId by injectLazy() + private val getFlatMetadataById: GetFlatMetadataById by injectLazy() + private val insertFlatMetadata: InsertFlatMetadata by injectLazy() + private val getExhFavoriteMangaWithMetadata: GetExhFavoriteMangaWithMetadata by injectLazy() private val updateNotifier by lazy { LibraryUpdateNotifier(context) } @@ -84,16 +83,12 @@ class EHentaiUpdateWorker(private val context: Context, workerParams: WorkerPara val startTime = System.currentTimeMillis() logger.d("Finding manga with metadata...") - val metadataManga = handler.awaitList { mangasQueries.getEhMangaWithMetadata(EH_SOURCE_ID, EXH_SOURCE_ID, mangaMapper) } + val metadataManga = getExhFavoriteMangaWithMetadata.await() logger.d("Filtering manga and raising metadata...") val curTime = System.currentTimeMillis() val allMeta = metadataManga.asFlow().cancellable().mapNotNull { manga -> - if (!manga.isEhBasedManga()) { - return@mapNotNull null - } - - val meta = handler.awaitFlatMetadataForManga(manga.id) + val meta = getFlatMetadataById.await(manga.id) ?: return@mapNotNull null val raisedMeta = meta.raise() @@ -221,12 +216,12 @@ class EHentaiUpdateWorker(private val context: Context, workerParams: WorkerPara return new to getChapterByMangaId.await(manga.id) } catch (t: Throwable) { if (t is EHentai.GalleryNotFoundException) { - val meta = handler.awaitFlatMetadataForManga(manga.id)?.raise() + val meta = getFlatMetadataById.await(manga.id)?.raise() if (meta != null) { // Age dead galleries logger.d("Aged %s - notfound", manga.id) meta.aged = true - handler.awaitInsertFlatMetadata(meta.flatten()) + insertFlatMetadata.await(meta) } throw GalleryNotUpdatedException(false, t) } diff --git a/app/src/main/java/exh/merged/sql/mappers/MergedMangaTypeMapping.kt b/app/src/main/java/exh/merged/sql/mappers/MergedMangaTypeMapping.kt deleted file mode 100644 index 309d815c6..000000000 --- a/app/src/main/java/exh/merged/sql/mappers/MergedMangaTypeMapping.kt +++ /dev/null @@ -1,84 +0,0 @@ -package exh.merged.sql.mappers - -import android.database.Cursor -import androidx.core.content.contentValuesOf -import androidx.core.database.getLongOrNull -import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping -import com.pushtorefresh.storio.sqlite.operations.delete.DefaultDeleteResolver -import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver -import com.pushtorefresh.storio.sqlite.operations.put.DefaultPutResolver -import com.pushtorefresh.storio.sqlite.queries.DeleteQuery -import com.pushtorefresh.storio.sqlite.queries.InsertQuery -import com.pushtorefresh.storio.sqlite.queries.UpdateQuery -import exh.merged.sql.models.MergedMangaReference -import exh.merged.sql.tables.MergedTable.COL_CHAPTER_PRIORITY -import exh.merged.sql.tables.MergedTable.COL_CHAPTER_SORT_MODE -import exh.merged.sql.tables.MergedTable.COL_DOWNLOAD_CHAPTERS -import exh.merged.sql.tables.MergedTable.COL_GET_CHAPTER_UPDATES -import exh.merged.sql.tables.MergedTable.COL_ID -import exh.merged.sql.tables.MergedTable.COL_IS_INFO_MANGA -import exh.merged.sql.tables.MergedTable.COL_MANGA_ID -import exh.merged.sql.tables.MergedTable.COL_MANGA_SOURCE -import exh.merged.sql.tables.MergedTable.COL_MANGA_URL -import exh.merged.sql.tables.MergedTable.COL_MERGE_ID -import exh.merged.sql.tables.MergedTable.COL_MERGE_URL -import exh.merged.sql.tables.MergedTable.TABLE - -class MergedMangaTypeMapping : SQLiteTypeMapping( - MergedMangaPutResolver(), - MergedMangaGetResolver(), - MergedMangaDeleteResolver(), -) - -class MergedMangaPutResolver : DefaultPutResolver() { - - override fun mapToInsertQuery(obj: MergedMangaReference) = InsertQuery.builder() - .table(TABLE) - .build() - - override fun mapToUpdateQuery(obj: MergedMangaReference) = UpdateQuery.builder() - .table(TABLE) - .where("$COL_ID = ?") - .whereArgs(obj.id) - .build() - - override fun mapToContentValues(obj: MergedMangaReference) = contentValuesOf( - COL_ID to obj.id, - COL_IS_INFO_MANGA to obj.isInfoManga, - COL_GET_CHAPTER_UPDATES to obj.getChapterUpdates, - COL_CHAPTER_SORT_MODE to obj.chapterSortMode, - COL_CHAPTER_PRIORITY to obj.chapterPriority, - COL_DOWNLOAD_CHAPTERS to obj.downloadChapters, - COL_MERGE_ID to obj.mergeId, - COL_MERGE_URL to obj.mergeUrl, - COL_MANGA_ID to obj.mangaId, - COL_MANGA_URL to obj.mangaUrl, - COL_MANGA_SOURCE to obj.mangaSourceId, - ) -} - -class MergedMangaGetResolver : DefaultGetResolver() { - - override fun mapFromCursor(cursor: Cursor): MergedMangaReference = MergedMangaReference( - id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_ID)), - isInfoManga = cursor.getInt(cursor.getColumnIndexOrThrow(COL_IS_INFO_MANGA)) == 1, - getChapterUpdates = cursor.getInt(cursor.getColumnIndexOrThrow(COL_GET_CHAPTER_UPDATES)) == 1, - chapterSortMode = cursor.getInt(cursor.getColumnIndexOrThrow(COL_CHAPTER_SORT_MODE)), - chapterPriority = cursor.getInt(cursor.getColumnIndexOrThrow(COL_CHAPTER_PRIORITY)), - downloadChapters = cursor.getInt(cursor.getColumnIndexOrThrow(COL_DOWNLOAD_CHAPTERS)) == 1, - mergeId = cursor.getLong(cursor.getColumnIndexOrThrow(COL_MERGE_ID)), - mergeUrl = cursor.getString(cursor.getColumnIndexOrThrow(COL_MERGE_URL)), - mangaId = cursor.getLongOrNull(cursor.getColumnIndexOrThrow(COL_MANGA_ID)), - mangaUrl = cursor.getString(cursor.getColumnIndexOrThrow(COL_MANGA_URL)), - mangaSourceId = cursor.getLong(cursor.getColumnIndexOrThrow(COL_MANGA_SOURCE)), - ) -} - -class MergedMangaDeleteResolver : DefaultDeleteResolver() { - - override fun mapToDeleteQuery(obj: MergedMangaReference) = DeleteQuery.builder() - .table(TABLE) - .where("$COL_ID = ?") - .whereArgs(obj.id) - .build() -} diff --git a/app/src/main/java/exh/merged/sql/queries/MergedQueries.kt b/app/src/main/java/exh/merged/sql/queries/MergedQueries.kt deleted file mode 100644 index f15a12e4c..000000000 --- a/app/src/main/java/exh/merged/sql/queries/MergedQueries.kt +++ /dev/null @@ -1,69 +0,0 @@ -package exh.merged.sql.queries - -import com.pushtorefresh.storio.sqlite.queries.DeleteQuery -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.models.Manga -import eu.kanade.tachiyomi.data.database.queries.getMergedMangaForDownloadingQuery -import eu.kanade.tachiyomi.data.database.queries.getMergedMangaQuery -import exh.merged.sql.models.MergedMangaReference -import exh.merged.sql.resolvers.MergeMangaSettingsPutResolver -import exh.merged.sql.resolvers.MergedMangaIdPutResolver -import exh.merged.sql.resolvers.MergedMangaSettingsPutResolver -import exh.merged.sql.tables.MergedTable - -interface MergedQueries : DbProvider { - fun getMergedMangaReferences(mergedMangaId: Long) = db.get() - .listOfObjects(MergedMangaReference::class.java) - .withQuery( - Query.builder() - .table(MergedTable.TABLE) - .where("${MergedTable.COL_MERGE_ID} = ?") - .whereArgs(mergedMangaId) - .build(), - ) - .prepare() - - fun deleteMangaForMergedManga(mergedMangaId: Long) = db.delete() - .byQuery( - DeleteQuery.builder() - .table(MergedTable.TABLE) - .where("${MergedTable.COL_MERGE_ID} = ?") - .whereArgs(mergedMangaId) - .build(), - ) - .prepare() - - fun getMergedMangas(mergedMangaId: Long) = db.get() - .listOfObjects(Manga::class.java) - .withQuery( - RawQuery.builder() - .query(getMergedMangaQuery()) - .args(mergedMangaId) - .build(), - ) - .prepare() - - fun getMergedMangasForDownloading(mergedMangaId: Long) = db.get() - .listOfObjects(Manga::class.java) - .withQuery( - RawQuery.builder() - .query(getMergedMangaForDownloadingQuery()) - .args(mergedMangaId) - .build(), - ) - .prepare() - - fun insertMergedManga(mergedManga: MergedMangaReference) = db.put().`object`(mergedManga).prepare() - - fun insertNewMergedMangaId(mergedManga: MergedMangaReference) = db.put().`object`(mergedManga).withPutResolver(MergedMangaIdPutResolver()).prepare() - - fun insertMergedMangas(mergedManga: List) = db.put().objects(mergedManga).prepare() - - fun updateMergedMangaSettings(mergedManga: List) = db.put().objects(mergedManga).withPutResolver(MergedMangaSettingsPutResolver()).prepare() - - fun updateMergeMangaSettings(mergeManga: MergedMangaReference) = db.put().`object`(mergeManga).withPutResolver(MergeMangaSettingsPutResolver()).prepare() - - fun deleteMergedManga(mergedManga: MergedMangaReference) = db.delete().`object`(mergedManga).prepare() -} diff --git a/app/src/main/java/exh/merged/sql/resolvers/MergeMangaSettingsPutResolver.kt b/app/src/main/java/exh/merged/sql/resolvers/MergeMangaSettingsPutResolver.kt deleted file mode 100644 index 9448f6d67..000000000 --- a/app/src/main/java/exh/merged/sql/resolvers/MergeMangaSettingsPutResolver.kt +++ /dev/null @@ -1,31 +0,0 @@ -package exh.merged.sql.resolvers - -import androidx.core.content.contentValuesOf -import com.pushtorefresh.storio.sqlite.StorIOSQLite -import com.pushtorefresh.storio.sqlite.operations.put.PutResolver -import com.pushtorefresh.storio.sqlite.operations.put.PutResult -import com.pushtorefresh.storio.sqlite.queries.UpdateQuery -import eu.kanade.tachiyomi.data.database.inTransactionReturn -import exh.merged.sql.models.MergedMangaReference -import exh.merged.sql.tables.MergedTable - -class MergeMangaSettingsPutResolver(val reset: Boolean = false) : PutResolver() { - - override fun performPut(db: StorIOSQLite, mergedMangaReference: MergedMangaReference) = db.inTransactionReturn { - val updateQuery = mapToUpdateQuery(mergedMangaReference) - val contentValues = mapToContentValues(mergedMangaReference) - - val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues) - PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table()) - } - - fun mapToUpdateQuery(mergedMangaReference: MergedMangaReference) = UpdateQuery.builder() - .table(MergedTable.TABLE) - .where("${MergedTable.COL_ID} = ?") - .whereArgs(mergedMangaReference.id) - .build() - - fun mapToContentValues(mergedMangaReference: MergedMangaReference) = contentValuesOf( - MergedTable.COL_CHAPTER_SORT_MODE to mergedMangaReference.chapterSortMode, - ) -} diff --git a/app/src/main/java/exh/merged/sql/resolvers/MergedMangaIdPutResolver.kt b/app/src/main/java/exh/merged/sql/resolvers/MergedMangaIdPutResolver.kt deleted file mode 100644 index aaf67f85a..000000000 --- a/app/src/main/java/exh/merged/sql/resolvers/MergedMangaIdPutResolver.kt +++ /dev/null @@ -1,31 +0,0 @@ -package exh.merged.sql.resolvers - -import androidx.core.content.contentValuesOf -import com.pushtorefresh.storio.sqlite.StorIOSQLite -import com.pushtorefresh.storio.sqlite.operations.put.PutResolver -import com.pushtorefresh.storio.sqlite.operations.put.PutResult -import com.pushtorefresh.storio.sqlite.queries.UpdateQuery -import eu.kanade.tachiyomi.data.database.inTransactionReturn -import exh.merged.sql.models.MergedMangaReference -import exh.merged.sql.tables.MergedTable - -class MergedMangaIdPutResolver : PutResolver() { - - override fun performPut(db: StorIOSQLite, mergedMangaReference: MergedMangaReference) = db.inTransactionReturn { - val updateQuery = mapToUpdateQuery(mergedMangaReference) - val contentValues = mapToContentValues(mergedMangaReference) - - val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues) - PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table()) - } - - fun mapToUpdateQuery(mergedMangaReference: MergedMangaReference) = UpdateQuery.builder() - .table(MergedTable.TABLE) - .where("${MergedTable.COL_ID} = ?") - .whereArgs(mergedMangaReference.id) - .build() - - fun mapToContentValues(mergedMangaReference: MergedMangaReference) = contentValuesOf( - MergedTable.COL_MANGA_ID to mergedMangaReference.mangaId, - ) -} diff --git a/app/src/main/java/exh/merged/sql/resolvers/MergedMangaSettingsPutResolver.kt b/app/src/main/java/exh/merged/sql/resolvers/MergedMangaSettingsPutResolver.kt deleted file mode 100644 index b20cf39e3..000000000 --- a/app/src/main/java/exh/merged/sql/resolvers/MergedMangaSettingsPutResolver.kt +++ /dev/null @@ -1,34 +0,0 @@ -package exh.merged.sql.resolvers - -import androidx.core.content.contentValuesOf -import com.pushtorefresh.storio.sqlite.StorIOSQLite -import com.pushtorefresh.storio.sqlite.operations.put.PutResolver -import com.pushtorefresh.storio.sqlite.operations.put.PutResult -import com.pushtorefresh.storio.sqlite.queries.UpdateQuery -import eu.kanade.tachiyomi.data.database.inTransactionReturn -import exh.merged.sql.models.MergedMangaReference -import exh.merged.sql.tables.MergedTable - -class MergedMangaSettingsPutResolver(val reset: Boolean = false) : PutResolver() { - - override fun performPut(db: StorIOSQLite, mergedMangaReference: MergedMangaReference) = db.inTransactionReturn { - val updateQuery = mapToUpdateQuery(mergedMangaReference) - val contentValues = mapToContentValues(mergedMangaReference) - - val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues) - PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table()) - } - - fun mapToUpdateQuery(mergedMangaReference: MergedMangaReference) = UpdateQuery.builder() - .table(MergedTable.TABLE) - .where("${MergedTable.COL_ID} = ?") - .whereArgs(mergedMangaReference.id) - .build() - - fun mapToContentValues(mergedMangaReference: MergedMangaReference) = contentValuesOf( - MergedTable.COL_GET_CHAPTER_UPDATES to mergedMangaReference.getChapterUpdates, - MergedTable.COL_DOWNLOAD_CHAPTERS to mergedMangaReference.downloadChapters, - MergedTable.COL_IS_INFO_MANGA to mergedMangaReference.isInfoManga, - MergedTable.COL_CHAPTER_PRIORITY to mergedMangaReference.chapterPriority, - ) -} diff --git a/app/src/main/java/exh/merged/sql/tables/MergedTable.kt b/app/src/main/java/exh/merged/sql/tables/MergedTable.kt deleted file mode 100644 index 5648c188f..000000000 --- a/app/src/main/java/exh/merged/sql/tables/MergedTable.kt +++ /dev/null @@ -1,28 +0,0 @@ -package exh.merged.sql.tables - -object MergedTable { - - const val TABLE = "merged" - - const val COL_ID = "_id" - - const val COL_IS_INFO_MANGA = "info_manga" - - const val COL_GET_CHAPTER_UPDATES = "get_chapter_updates" - - const val COL_CHAPTER_SORT_MODE = "chapter_sort_mode" - - const val COL_CHAPTER_PRIORITY = "chapter_priority" - - const val COL_DOWNLOAD_CHAPTERS = "download_chapters" - - const val COL_MERGE_ID = "merge_id" - - const val COL_MERGE_URL = "merge_url" - - const val COL_MANGA_ID = "manga_id" - - const val COL_MANGA_URL = "manga_url" - - const val COL_MANGA_SOURCE = "manga_source" -} diff --git a/app/src/main/java/exh/metadata/metadata/base/FlatMetadata.kt b/app/src/main/java/exh/metadata/metadata/base/FlatMetadata.kt index 609423123..3c06a3e72 100644 --- a/app/src/main/java/exh/metadata/metadata/base/FlatMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/base/FlatMetadata.kt @@ -1,9 +1,5 @@ package exh.metadata.metadata.base -import eu.kanade.data.DatabaseHandler -import eu.kanade.data.exh.searchMetadataMapper -import eu.kanade.data.exh.searchTagMapper -import eu.kanade.data.exh.searchTitleMapper import exh.metadata.sql.models.SearchMetadata import exh.metadata.sql.models.SearchTag import exh.metadata.sql.models.SearchTitle @@ -27,35 +23,3 @@ data class FlatMetadata( fillBaseFields(this@FlatMetadata) } } - -@Deprecated("Replace with GetFlatMetadataById") -suspend fun DatabaseHandler.awaitFlatMetadataForManga(mangaId: Long): FlatMetadata? { - return await { - val meta = search_metadataQueries.selectByMangaId(mangaId, searchMetadataMapper).executeAsOneOrNull() - if (meta != null) { - val tags = search_tagsQueries.selectByMangaId(mangaId, searchTagMapper).executeAsList() - val titles = search_titlesQueries.selectByMangaId(mangaId, searchTitleMapper).executeAsList() - - FlatMetadata(meta, tags, titles) - } else null - } -} - -@Deprecated("Replace with InsertFlatMetadata") -suspend fun DatabaseHandler.awaitInsertFlatMetadata(flatMetadata: FlatMetadata) { - require(flatMetadata.metadata.mangaId != -1L) - - await(true) { - flatMetadata.metadata.run { - search_metadataQueries.upsert(mangaId, uploader, extra, indexedExtra, extraVersion) - } - search_tagsQueries.deleteByManga(flatMetadata.metadata.mangaId) - flatMetadata.tags.forEach { - search_tagsQueries.insert(it.mangaId, it.namespace, it.name, it.type) - } - search_titlesQueries.deleteByManga(flatMetadata.metadata.mangaId) - flatMetadata.titles.forEach { - search_titlesQueries.insert(it.mangaId, it.title, it.type) - } - } -} diff --git a/app/src/main/java/exh/savedsearches/mappers/FeedSavedSearchTypeMapping.kt b/app/src/main/java/exh/savedsearches/mappers/FeedSavedSearchTypeMapping.kt deleted file mode 100644 index aa960ad0d..000000000 --- a/app/src/main/java/exh/savedsearches/mappers/FeedSavedSearchTypeMapping.kt +++ /dev/null @@ -1,76 +0,0 @@ -package exh.savedsearches.mappers - -import android.database.Cursor -import androidx.core.content.contentValuesOf -import androidx.core.database.getLongOrNull -import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping -import com.pushtorefresh.storio.sqlite.operations.delete.DefaultDeleteResolver -import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver -import com.pushtorefresh.storio.sqlite.operations.put.DefaultPutResolver -import com.pushtorefresh.storio.sqlite.queries.DeleteQuery -import com.pushtorefresh.storio.sqlite.queries.InsertQuery -import com.pushtorefresh.storio.sqlite.queries.UpdateQuery -import exh.savedsearches.mappers.FeedSavedSearchTable.COL_GLOBAL -import exh.savedsearches.mappers.FeedSavedSearchTable.COL_ID -import exh.savedsearches.mappers.FeedSavedSearchTable.COL_SAVED_SEARCH_ID -import exh.savedsearches.mappers.FeedSavedSearchTable.COL_SOURCE -import exh.savedsearches.mappers.FeedSavedSearchTable.TABLE -import exh.savedsearches.models.FeedSavedSearch - -private object FeedSavedSearchTable { - - const val TABLE = "feed_saved_search" - - const val COL_ID = "_id" - - const val COL_SOURCE = "source" - - const val COL_SAVED_SEARCH_ID = "saved_search" - - const val COL_GLOBAL = "global" -} - -class FeedSavedSearchTypeMapping : SQLiteTypeMapping( - FeedSavedSearchPutResolver(), - FeedSavedSearchGetResolver(), - FeedSavedSearchDeleteResolver(), -) - -class FeedSavedSearchPutResolver : DefaultPutResolver() { - - override fun mapToInsertQuery(obj: FeedSavedSearch) = InsertQuery.builder() - .table(TABLE) - .build() - - override fun mapToUpdateQuery(obj: FeedSavedSearch) = UpdateQuery.builder() - .table(TABLE) - .where("$COL_ID = ?") - .whereArgs(obj.id) - .build() - - override fun mapToContentValues(obj: FeedSavedSearch) = contentValuesOf( - COL_ID to obj.id, - COL_SOURCE to obj.source, - COL_SAVED_SEARCH_ID to obj.savedSearch, - COL_GLOBAL to obj.global, - ) -} - -class FeedSavedSearchGetResolver : DefaultGetResolver() { - - override fun mapFromCursor(cursor: Cursor): FeedSavedSearch = FeedSavedSearch( - id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_ID)), - source = cursor.getLong(cursor.getColumnIndexOrThrow(COL_SOURCE)), - savedSearch = cursor.getLongOrNull(cursor.getColumnIndexOrThrow(COL_SAVED_SEARCH_ID)), - global = cursor.getInt(cursor.getColumnIndexOrThrow(COL_GLOBAL)) == 1, - ) -} - -class FeedSavedSearchDeleteResolver : DefaultDeleteResolver() { - - override fun mapToDeleteQuery(obj: FeedSavedSearch) = DeleteQuery.builder() - .table(TABLE) - .where("$COL_ID = ?") - .whereArgs(obj.id) - .build() -} diff --git a/app/src/main/java/exh/savedsearches/mappers/SavedSearchTypeMapping.kt b/app/src/main/java/exh/savedsearches/mappers/SavedSearchTypeMapping.kt deleted file mode 100644 index 2ef01c587..000000000 --- a/app/src/main/java/exh/savedsearches/mappers/SavedSearchTypeMapping.kt +++ /dev/null @@ -1,81 +0,0 @@ -package exh.savedsearches.mappers - -import android.database.Cursor -import androidx.core.content.contentValuesOf -import androidx.core.database.getStringOrNull -import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping -import com.pushtorefresh.storio.sqlite.operations.delete.DefaultDeleteResolver -import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver -import com.pushtorefresh.storio.sqlite.operations.put.DefaultPutResolver -import com.pushtorefresh.storio.sqlite.queries.DeleteQuery -import com.pushtorefresh.storio.sqlite.queries.InsertQuery -import com.pushtorefresh.storio.sqlite.queries.UpdateQuery -import exh.savedsearches.mappers.SavedSearchTable.COL_FILTERS_JSON -import exh.savedsearches.mappers.SavedSearchTable.COL_ID -import exh.savedsearches.mappers.SavedSearchTable.COL_NAME -import exh.savedsearches.mappers.SavedSearchTable.COL_QUERY -import exh.savedsearches.mappers.SavedSearchTable.COL_SOURCE -import exh.savedsearches.mappers.SavedSearchTable.TABLE -import exh.savedsearches.models.SavedSearch - -private object SavedSearchTable { - - const val TABLE = "saved_search" - - const val COL_ID = "_id" - - const val COL_SOURCE = "source" - - const val COL_NAME = "name" - - const val COL_QUERY = "query" - - const val COL_FILTERS_JSON = "filters_json" -} - -class SavedSearchTypeMapping : SQLiteTypeMapping( - SavedSearchPutResolver(), - SavedSearchGetResolver(), - SavedSearchDeleteResolver(), -) - -class SavedSearchPutResolver : DefaultPutResolver() { - - override fun mapToInsertQuery(obj: SavedSearch) = InsertQuery.builder() - .table(TABLE) - .build() - - override fun mapToUpdateQuery(obj: SavedSearch) = UpdateQuery.builder() - .table(TABLE) - .where("$COL_ID = ?") - .whereArgs(obj.id) - .build() - - override fun mapToContentValues(obj: SavedSearch) = contentValuesOf( - COL_ID to obj.id, - COL_SOURCE to obj.source, - COL_NAME to obj.name, - COL_QUERY to obj.query, - COL_FILTERS_JSON to obj.filtersJson, - ) -} - -class SavedSearchGetResolver : DefaultGetResolver() { - - override fun mapFromCursor(cursor: Cursor): SavedSearch = SavedSearch( - id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_ID)), - source = cursor.getLong(cursor.getColumnIndexOrThrow(COL_SOURCE)), - name = cursor.getString(cursor.getColumnIndexOrThrow(COL_NAME)), - query = cursor.getStringOrNull(cursor.getColumnIndexOrThrow(COL_QUERY)), - filtersJson = cursor.getStringOrNull(cursor.getColumnIndexOrThrow(COL_FILTERS_JSON)), - ) -} - -class SavedSearchDeleteResolver : DefaultDeleteResolver() { - - override fun mapToDeleteQuery(obj: SavedSearch) = DeleteQuery.builder() - .table(TABLE) - .where("$COL_ID = ?") - .whereArgs(obj.id) - .build() -} diff --git a/app/src/main/java/exh/smartsearch/SmartSearchEngine.kt b/app/src/main/java/exh/smartsearch/SmartSearchEngine.kt index 3d2c7bde3..fc4a1cba2 100644 --- a/app/src/main/java/exh/smartsearch/SmartSearchEngine.kt +++ b/app/src/main/java/exh/smartsearch/SmartSearchEngine.kt @@ -1,13 +1,14 @@ package exh.smartsearch -import eu.kanade.data.DatabaseHandler -import eu.kanade.tachiyomi.data.database.DatabaseHelper +import eu.kanade.domain.manga.interactor.GetManga +import eu.kanade.domain.manga.interactor.InsertManga +import eu.kanade.domain.manga.model.toDbManga import eu.kanade.tachiyomi.data.database.models.Manga +import eu.kanade.tachiyomi.data.database.models.toDomainManga import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.util.lang.awaitSingle -import exh.util.executeOnIO import info.debatty.java.stringsimilarity.NormalizedLevenshtein import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async @@ -18,8 +19,8 @@ import java.util.Locale class SmartSearchEngine( private val extraSearchParams: String? = null, ) { - private val db: DatabaseHelper by injectLazy() - private val handler: DatabaseHandler by injectLazy() + private val getManga: GetManga by injectLazy() + private val insertManga: InsertManga by injectLazy() private val normalizedLevenshtein = NormalizedLevenshtein() @@ -172,15 +173,22 @@ class SmartSearchEngine( * @return a manga from the database. */ suspend fun networkToLocalManga(sManga: SManga, sourceId: Long): Manga { - var localManga = db.getManga(sManga.url, sourceId).executeOnIO() + var localManga = getManga.await(sManga.url, sourceId) if (localManga == null) { val newManga = Manga.create(sManga.url, sManga.title, sourceId) newManga.copyFrom(sManga) - val result = db.insertManga(newManga).executeOnIO() - newManga.id = result.insertedId() - localManga = newManga + newManga.id = -1 + val result = run { + val id = insertManga.await(newManga.toDomainManga()!!) + getManga.await(id!!) + } + localManga = result + } else if (!localManga.favorite) { + // if the manga isn't a favorite, set its display title from source + // if it later becomes a favorite, updated title will go to db + localManga = localManga.copy(ogTitle = sManga.title) } - return localManga + return localManga?.toDbManga()!! } companion object { diff --git a/app/src/main/java/exh/ui/metadata/MetadataViewPresenter.kt b/app/src/main/java/exh/ui/metadata/MetadataViewPresenter.kt index 98e43bc05..2aad9c6eb 100644 --- a/app/src/main/java/exh/ui/metadata/MetadataViewPresenter.kt +++ b/app/src/main/java/exh/ui/metadata/MetadataViewPresenter.kt @@ -1,14 +1,13 @@ package exh.ui.metadata import android.os.Bundle -import eu.kanade.data.DatabaseHandler +import eu.kanade.domain.manga.interactor.GetFlatMetadataById import eu.kanade.domain.manga.model.Manga import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.online.MetadataSource import eu.kanade.tachiyomi.util.lang.launchIO import exh.metadata.metadata.base.RaisedSearchMetadata -import exh.metadata.metadata.base.awaitFlatMetadataForManga import exh.source.getMainSource import exh.ui.base.CoroutinePresenter import kotlinx.coroutines.flow.MutableStateFlow @@ -19,7 +18,7 @@ class MetadataViewPresenter( val manga: Manga, val source: Source, val preferences: PreferencesHelper = Injekt.get(), - private val db: DatabaseHandler = Injekt.get(), + private val getFlatMetadataById: GetFlatMetadataById = Injekt.get(), ) : CoroutinePresenter() { val meta = MutableStateFlow(null) @@ -28,7 +27,7 @@ class MetadataViewPresenter( super.onCreate(savedState) launchIO { - val flatMetadata = db.awaitFlatMetadataForManga(manga.id) ?: return@launchIO + val flatMetadata = getFlatMetadataById.await(manga.id) ?: return@launchIO val mainSource = source.getMainSource>() if (mainSource != null) { meta.value = flatMetadata.raise(mainSource.metaClass) diff --git a/app/src/main/java/exh/util/DatabaseExtensions.kt b/app/src/main/java/exh/util/DatabaseExtensions.kt deleted file mode 100644 index da5b016f0..000000000 --- a/app/src/main/java/exh/util/DatabaseExtensions.kt +++ /dev/null @@ -1,24 +0,0 @@ -package exh.util - -import android.database.Cursor -import com.pushtorefresh.storio.operations.PreparedOperation -import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetCursor -import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetListOfObjects -import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetObject -import com.pushtorefresh.storio.sqlite.operations.put.PreparedPutCollectionOfObjects -import com.pushtorefresh.storio.sqlite.operations.put.PreparedPutObject -import com.pushtorefresh.storio.sqlite.operations.put.PutResult -import com.pushtorefresh.storio.sqlite.operations.put.PutResults -import eu.kanade.tachiyomi.util.lang.withIOContext - -suspend fun PreparedGetListOfObjects.executeOnIO(): List = withIOContext { executeAsBlocking() } - -suspend fun PreparedGetObject.executeOnIO(): T? = withIOContext { executeAsBlocking() } - -suspend fun PreparedPutObject.executeOnIO(): PutResult = withIOContext { executeAsBlocking() } - -suspend fun PreparedPutCollectionOfObjects.executeOnIO(): PutResults = withIOContext { executeAsBlocking() } - -suspend fun PreparedGetCursor.executeOnIO(): Cursor = withIOContext { executeAsBlocking() } - -suspend fun PreparedOperation.executeOnIO(): T? = withIOContext { executeAsBlocking() } diff --git a/app/src/main/sqldelight/data/eh.sq b/app/src/main/sqldelight/data/eh.sq index e90bab0d1..412c8895b 100644 --- a/app/src/main/sqldelight/data/eh.sq +++ b/app/src/main/sqldelight/data/eh.sq @@ -4,4 +4,29 @@ DELETE FROM manga_sync WHERE sync_id = :syncId; migrateSource: UPDATE mangas SET source = :newId -WHERE source = :oldId; \ No newline at end of file +WHERE source = :oldId; + +getChaptersByMangaIds: +SELECT * FROM chapters WHERE manga_id IN :mangaIds; + +resetFilteredScanlatorsForAllManga: +UPDATE mangas +SET filtered_scanlators = NULL; + +migrateAllNhentaiToOtherLang: +UPDATE mangas +SET source = :nh +WHERE favorite = 1 AND source IN :sources; + +resetReaderViewerForAllManga: +UPDATE mangas +SET viewer = 0; + +fixReaderViewerBackupBug: +UPDATE mangas +SET viewer = 0 +WHERE viewer = -1; + +addAllMangaInDatabaseToLibrary: +UPDATE mangas +SET favorite = 1; \ No newline at end of file diff --git a/app/src/main/sqldelight/data/mangas.sq b/app/src/main/sqldelight/data/mangas.sq index 1d9916e03..fb53bd4ea 100644 --- a/app/src/main/sqldelight/data/mangas.sq +++ b/app/src/main/sqldelight/data/mangas.sq @@ -166,6 +166,44 @@ WHERE favorite = 0 AND source IN :sourceIdsAND AND _id NOT IN ( SELECT manga_id FROM chapters WHERE read = 1 OR last_page_read != 0 ); +INSERT INTO mangas( + source, + url, + artist, + author, + description, + genre, + title, + status, + thumbnail_url, + favorite, + last_update, + next_update, + initialized, + viewer, + chapter_flags, + cover_last_modified, + date_added +) VALUES ( + :source, + :url, + :artist, + :author, + :description, + :genre, + :title, + :status, + :thumbnailUrl, + :favorite, + :lastUpdate, + 0, + :initialized, + :viewerFlags, + :chapterFlags, + :coverLastModified, + :dateAdded +); + update: UPDATE mangas SET source = coalesce(:source, source), @@ -208,6 +246,9 @@ SELECT * FROM mangas WHERE source = :sourceId; getAll: SELECT * FROM mangas; +deleteById: +DELETE FROM mangas WHERE _id = :id; + selectLastInsertRow: SELECT * FROM mangas diff --git a/app/src/main/sqldelight/data/merged.sq b/app/src/main/sqldelight/data/merged.sq index 26fd6e8e5..b92fed9dd 100644 --- a/app/src/main/sqldelight/data/merged.sq +++ b/app/src/main/sqldelight/data/merged.sq @@ -73,9 +73,31 @@ FROM ( JOIN chapters ON chapters.manga_id = M.manga_id; -insertMerged: -INSERT INTO merged (_id, info_manga, get_chapter_updates, chapter_sort_mode, chapter_priority, download_chapters, merge_id, merge_url, manga_id, manga_url, manga_source) -VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?); +insert: +INSERT INTO merged( + info_manga, + get_chapter_updates, + chapter_sort_mode, + chapter_priority, + download_chapters, + merge_id, + merge_url, + manga_id, + manga_url, + manga_source +) +VALUES ( + :infoManga, + :getChapterUpdates, + :chapterSortMode, + :chapterPriority, + :downloadChapters, + :mergeId, + :mergeUrl, + :mangaId, + :mangaUrl, + :mangaSource +); updateSettingsById: UPDATE merged @@ -89,5 +111,8 @@ WHERE _id = :id; deleteById: DELETE FROM merged WHERE _id = ?; -deleteBy: +deleteAll: DELETE FROM merged; + +selectLastInsertedRowId: +SELECT last_insert_rowid(); \ No newline at end of file