From 17951cfd68159d083df54c3e03094d8d66fe02ec Mon Sep 17 00:00:00 2001 From: Andreas Date: Sun, 3 Jul 2022 16:17:41 +0200 Subject: [PATCH] Use SQLDelight for all Manga related queries (#7447) --- app/build.gradle.kts | 6 +- .../java/eu/kanade/data/manga/MangaMapper.kt | 27 +++++ .../kanade/data/manga/MangaRepositoryImpl.kt | 42 ++++++- .../java/eu/kanade/domain/DomainModule.kt | 10 +- .../manga/interactor/GetLibraryManga.kt | 18 +++ .../{GetMangaById.kt => GetManga.kt} | 8 +- .../manga/interactor/GetMangaWithChapters.kt | 2 +- .../domain/manga/interactor/InsertManga.kt | 13 +++ .../manga/interactor/SetMangaViewerFlags.kt | 33 ++++++ .../eu/kanade/domain/manga/model/Manga.kt | 22 ++++ .../manga/repository/MangaRepository.kt | 11 +- .../java/eu/kanade/tachiyomi/AppModule.kt | 5 - .../tachiyomi/data/database/DatabaseHelper.kt | 27 ----- .../tachiyomi/data/database/DbExtensions.kt | 24 ---- .../tachiyomi/data/database/DbProvider.kt | 7 -- .../database/mappers/ChapterTypeMapping.kt | 88 -------------- .../mappers/MangaCategoryTypeMapping.kt | 60 ---------- .../data/database/mappers/MangaTypeMapping.kt | 109 ------------------ .../data/database/queries/MangaQueries.kt | 77 ------------- .../data/database/queries/RawQueries.kt | 37 ------ .../resolvers/ChapterProgressPutResolver.kt | 34 ------ .../resolvers/LibraryMangaGetResolver.kt | 25 ---- .../resolvers/MangaFlagsPutResolver.kt | 33 ------ .../data/database/tables/CategoryTable.kt | 6 - .../data/database/tables/ChapterTable.kt | 30 ----- .../database/tables/MangaCategoryTable.kt | 12 -- .../data/database/tables/MangaTable.kt | 50 -------- .../data/download/DownloadManager.kt | 2 - .../tachiyomi/data/download/DownloadStore.kt | 6 +- .../tachiyomi/data/download/model/Download.kt | 6 +- .../data/library/LibraryUpdateService.kt | 25 ++-- .../data/notification/NotificationReceiver.kt | 10 +- .../track/job/DelayedTrackingUpdateJob.kt | 6 +- .../migration/search/SearchController.kt | 12 +- .../source/browse/BrowseSourcePresenter.kt | 38 ++++-- .../globalsearch/GlobalSearchPresenter.kt | 29 +++-- .../tachiyomi/ui/library/LibraryPresenter.kt | 33 +----- .../tachiyomi/ui/manga/MangaPresenter.kt | 2 +- .../ui/manga/info/MangaFullCoverDialog.kt | 6 +- .../tachiyomi/ui/reader/ReaderPresenter.kt | 18 +-- .../util/chapter/ChapterSettingsHelper.kt | 49 ++++---- app/src/main/sqldelight/data/mangas.sq | 38 ++++++ 42 files changed, 343 insertions(+), 753 deletions(-) create mode 100644 app/src/main/java/eu/kanade/domain/manga/interactor/GetLibraryManga.kt rename app/src/main/java/eu/kanade/domain/manga/interactor/{GetMangaById.kt => GetManga.kt} (73%) create mode 100644 app/src/main/java/eu/kanade/domain/manga/interactor/InsertManga.kt create mode 100644 app/src/main/java/eu/kanade/domain/manga/interactor/SetMangaViewerFlags.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/database/DatabaseHelper.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/database/DbExtensions.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/database/DbProvider.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/ChapterTypeMapping.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/MangaCategoryTypeMapping.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/MangaTypeMapping.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/database/queries/MangaQueries.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/database/queries/RawQueries.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/ChapterProgressPutResolver.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/LibraryMangaGetResolver.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaFlagsPutResolver.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/database/tables/CategoryTable.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/database/tables/ChapterTable.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/database/tables/MangaCategoryTable.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/database/tables/MangaTable.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 49bedae8b..2fbfc6161 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -165,6 +165,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) @@ -218,11 +219,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/manga/MangaMapper.kt b/app/src/main/java/eu/kanade/data/manga/MangaMapper.kt index 153c47a8f..4d2ad1f95 100644 --- a/app/src/main/java/eu/kanade/data/manga/MangaMapper.kt +++ b/app/src/main/java/eu/kanade/data/manga/MangaMapper.kt @@ -2,6 +2,7 @@ package eu.kanade.data.manga 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) -> Manga = { id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, _, initialized, viewer, chapterFlags, coverLastModified, dateAdded -> @@ -61,3 +62,29 @@ val mangaChapterMapper: (Long, Long, String, String?, String?, String?, List?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, 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, 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.unreadCount = unread_count.toInt() + this.readCount = read_count.toInt() + this.category = category.toInt() + } + } 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 f9ecbf735..27aeb793e 100644 --- a/app/src/main/java/eu/kanade/data/manga/MangaRepositoryImpl.kt +++ b/app/src/main/java/eu/kanade/data/manga/MangaRepositoryImpl.kt @@ -6,6 +6,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 @@ -18,18 +19,26 @@ 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 getMangaByUrlAndSourceId(url: String, sourceId: Long): Manga? { + return handler.awaitOneOrNull { mangasQueries.getMangaByUrlAndSource(url, sourceId, mangaMapper) } + } + override suspend fun getFavorites(): List { return handler.awaitList { mangasQueries.getFavorites(mangaMapper) } } + override suspend fun getLibraryManga(): List { + return handler.awaitList { mangasQueries.getLibrary(libraryManga) } + } + + override fun getLibraryMangaAsFlow(): Flow> { + return handler.subscribeToList { mangasQueries.getLibrary(libraryManga) } + } + override fun getFavoritesBySourceId(sourceId: Long): Flow> { return handler.subscribeToList { mangasQueries.getFavoriteBySourceId(sourceId, mangaMapper) } } @@ -59,6 +68,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) diff --git a/app/src/main/java/eu/kanade/domain/DomainModule.kt b/app/src/main/java/eu/kanade/domain/DomainModule.kt index 971bde777..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.GetMangaById +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 { GetMangaById(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/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/GetMangaById.kt b/app/src/main/java/eu/kanade/domain/manga/interactor/GetManga.kt similarity index 73% rename from app/src/main/java/eu/kanade/domain/manga/interactor/GetMangaById.kt rename to app/src/main/java/eu/kanade/domain/manga/interactor/GetManga.kt index a641fceb9..da787116b 100644 --- a/app/src/main/java/eu/kanade/domain/manga/interactor/GetMangaById.kt +++ b/app/src/main/java/eu/kanade/domain/manga/interactor/GetManga.kt @@ -6,7 +6,7 @@ import eu.kanade.tachiyomi.util.system.logcat import kotlinx.coroutines.flow.Flow import logcat.LogPriority -class GetMangaById( +class GetManga( private val mangaRepository: MangaRepository, ) { @@ -20,6 +20,10 @@ class GetMangaById( } suspend fun subscribe(id: Long): Flow { - return mangaRepository.subscribeMangaById(id) + return mangaRepository.getMangaByIdAsFlow(id) + } + + suspend fun await(url: String, sourceId: Long): Manga? { + return mangaRepository.getMangaByUrlAndSourceId(url, 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/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/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/model/Manga.kt b/app/src/main/java/eu/kanade/domain/manga/model/Manga.kt index acf51d85d..4911fab5b 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 @@ -175,6 +175,28 @@ fun Manga.toMangaInfo(): MangaInfo = MangaInfo( title = title, ) +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/MangaRepository.kt b/app/src/main/java/eu/kanade/domain/manga/repository/MangaRepository.kt index 97c35de42..72fcef773 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,18 +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 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? @@ -22,6 +27,8 @@ 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 diff --git a/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt b/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt index 0b2715756..a5c3aad2f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt @@ -15,7 +15,6 @@ import eu.kanade.data.dateAdapter import eu.kanade.data.listOfStringsAdapter 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.preference.PreferencesHelper @@ -76,8 +75,6 @@ class AppModule(val app: Application) : InjektModule { addSingletonFactory { PreferencesHelper(app) } - addSingletonFactory { DatabaseHelper(get()) } - addSingletonFactory { ChapterCache(app) } addSingletonFactory { CoverCache(app) } @@ -106,8 +103,6 @@ class AppModule(val app: Application) : InjektModule { get() - get() - get() } } 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 100644 index 19535f6d2..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/DatabaseHelper.kt +++ /dev/null @@ -1,27 +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.ChapterTypeMapping -import eu.kanade.tachiyomi.data.database.mappers.MangaCategoryTypeMapping -import eu.kanade.tachiyomi.data.database.mappers.MangaTypeMapping -import eu.kanade.tachiyomi.data.database.models.Chapter -import eu.kanade.tachiyomi.data.database.models.Manga -import eu.kanade.tachiyomi.data.database.models.MangaCategory -import eu.kanade.tachiyomi.data.database.queries.MangaQueries - -/** - * This class provides operations to manage the database through its interfaces. - */ -class DatabaseHelper( - openHelper: SupportSQLiteOpenHelper, -) : - MangaQueries { - - override val db = DefaultStorIOSQLite.builder() - .sqliteOpenHelper(openHelper) - .addTypeMapping(Manga::class.java, MangaTypeMapping()) - .addTypeMapping(Chapter::class.java, ChapterTypeMapping()) - .addTypeMapping(MangaCategory::class.java, MangaCategoryTypeMapping()) - .build() -} 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 100644 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 100644 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/ChapterTypeMapping.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/ChapterTypeMapping.kt deleted file mode 100644 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/MangaCategoryTypeMapping.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/MangaCategoryTypeMapping.kt deleted file mode 100644 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 100644 index 00d305653..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/MangaTypeMapping.kt +++ /dev/null @@ -1,109 +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_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, - COL_ARTIST to obj.artist, - COL_AUTHOR to obj.author, - COL_DESCRIPTION to obj.description, - COL_GENRE to obj.genre, - COL_TITLE to obj.title, - COL_STATUS to obj.status, - 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, - ) -} - -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)) - } -} - -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/queries/MangaQueries.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/MangaQueries.kt deleted file mode 100644 index edaddecb9..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/MangaQueries.kt +++ /dev/null @@ -1,77 +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() -} 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 100644 index 3933b5be9..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/RawQueries.kt +++ /dev/null @@ -1,37 +0,0 @@ -package eu.kanade.tachiyomi.data.database.queries - -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 - -/** - * 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.COL_MANGA_ID}, COUNT(*) AS unreadCount - FROM ${Chapter.TABLE} - WHERE ${Chapter.COL_READ} = 0 - GROUP BY ${Chapter.COL_MANGA_ID} - ) AS C - ON ${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.COL_ID} = R.${Chapter.COL_MANGA_ID} - WHERE ${Manga.COL_FAVORITE} = 1 - GROUP BY ${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} -""" 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 100644 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/LibraryMangaGetResolver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/LibraryMangaGetResolver.kt deleted file mode 100644 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/MangaFlagsPutResolver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaFlagsPutResolver.kt deleted file mode 100644 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/tables/CategoryTable.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/CategoryTable.kt deleted file mode 100644 index 43677bd91..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/CategoryTable.kt +++ /dev/null @@ -1,6 +0,0 @@ -package eu.kanade.tachiyomi.data.database.tables - -object CategoryTable { - - const val TABLE = "categories" -} 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 100644 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/MangaCategoryTable.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/MangaCategoryTable.kt deleted file mode 100644 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 100644 index 5c32e16bc..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/MangaTable.kt +++ /dev/null @@ -1,50 +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" - - 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/download/DownloadManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt index c27414260..74e337e48 100644 --- 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 @@ -32,7 +31,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/download/DownloadStore.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadStore.kt index 443620ff4..9c92fd054 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadStore.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadStore.kt @@ -4,7 +4,7 @@ import android.content.Context import androidx.core.content.edit import eu.kanade.domain.chapter.interactor.GetChapter import eu.kanade.domain.chapter.model.toDbChapter -import eu.kanade.domain.manga.interactor.GetMangaById +import eu.kanade.domain.manga.interactor.GetManga import eu.kanade.domain.manga.model.toDbManga import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.download.model.Download @@ -34,7 +34,7 @@ class DownloadStore( private val json: Json by injectLazy() - private val getMangaById: GetMangaById by injectLazy() + private val getManga: GetManga by injectLazy() private val getChapter: GetChapter by injectLazy() /** @@ -96,7 +96,7 @@ class DownloadStore( val cachedManga = mutableMapOf() for ((mangaId, chapterId) in objs) { val manga = cachedManga.getOrPut(mangaId) { - runBlocking { getMangaById.await(mangaId)?.toDbManga() } + runBlocking { getManga.await(mangaId)?.toDbManga() } } ?: continue val source = sourceManager.get(manga.source) as? HttpSource ?: continue val chapter = runBlocking { getChapter.await(chapterId) }?.toDbChapter() ?: continue diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/model/Download.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/model/Download.kt index 2b8a38451..0ea7a6333 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/model/Download.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/model/Download.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.data.download.model import eu.kanade.domain.chapter.interactor.GetChapter import eu.kanade.domain.chapter.model.toDbChapter -import eu.kanade.domain.manga.interactor.GetMangaById +import eu.kanade.domain.manga.interactor.GetManga import eu.kanade.domain.manga.model.toDbManga import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Manga @@ -69,11 +69,11 @@ data class Download( suspend fun fromChapterId( chapterId: Long, getChapter: GetChapter = Injekt.get(), - getMangaById: GetMangaById = Injekt.get(), + getManga: GetManga = Injekt.get(), sourceManager: SourceManager = Injekt.get(), ): Download? { val chapter = getChapter.await(chapterId) ?: return null - val manga = getMangaById.await(chapter.mangaId) ?: return null + val manga = getManga.await(chapter.mangaId) ?: return null val source = sourceManager.get(manga.source) as? HttpSource ?: return null return Download(source, manga.toDbManga(), chapter.toDbChapter()) 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 5373e3dcb..abafc364e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt @@ -13,16 +13,17 @@ import eu.kanade.domain.chapter.interactor.GetChapterByMangaId 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.GetMangaById +import eu.kanade.domain.manga.interactor.GetLibraryManga +import eu.kanade.domain.manga.interactor.GetManga import eu.kanade.domain.manga.interactor.UpdateManga 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 @@ -61,6 +62,7 @@ import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.cancel import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking import kotlinx.coroutines.supervisorScope import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.withPermit @@ -84,13 +86,13 @@ 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 getMangaById: GetMangaById = 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(), private val getCategories: GetCategories = Injekt.get(), @@ -255,7 +257,7 @@ class LibraryUpdateService( * @param categoryId the ID of the category to update, or -1 if no category specified. */ fun addMangaToQueue(categoryId: Long) { - val libraryManga = db.getLibraryMangas().executeAsBlocking() + val libraryManga = runBlocking { getLibraryManga.await() } val listToUpdate = if (categoryId != -1L) { libraryManga.filter { it.category.toLong() == categoryId } @@ -323,7 +325,7 @@ class LibraryUpdateService( } // Don't continue to update if manga not in library - manga.id?.let { getMangaById.await(it) } ?: return@forEach + manga.id?.let { getManga.await(it) } ?: return@forEach withUpdateNotification( currentlyUpdatingManga, @@ -434,7 +436,7 @@ class LibraryUpdateService( .map { it.toSChapter() } // Get manga from database to account for if it was removed during the update - val dbManga = getMangaById.await(manga.id) + val dbManga = getManga.await(manga.id) ?: return Pair(emptyList(), emptyList()) // [dbmanga] was used so that manga data doesn't get overwritten @@ -471,7 +473,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 diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt index 9ed42985d..59ad5aff4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt @@ -11,7 +11,7 @@ import eu.kanade.domain.chapter.interactor.GetChapter import eu.kanade.domain.chapter.interactor.UpdateChapter import eu.kanade.domain.chapter.model.toChapterUpdate import eu.kanade.domain.chapter.model.toDbChapter -import eu.kanade.domain.manga.interactor.GetMangaById +import eu.kanade.domain.manga.interactor.GetManga import eu.kanade.domain.manga.model.toDbManga import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.backup.BackupRestoreService @@ -46,7 +46,7 @@ import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID */ class NotificationReceiver : BroadcastReceiver() { - private val getMangaById: GetMangaById by injectLazy() + private val getManga: GetManga by injectLazy() private val getChapter: GetChapter by injectLazy() private val updateChapter: UpdateChapter by injectLazy() private val downloadManager: DownloadManager by injectLazy() @@ -178,7 +178,7 @@ class NotificationReceiver : BroadcastReceiver() { * @param chapterId id of chapter */ private fun openChapter(context: Context, mangaId: Long, chapterId: Long) { - val manga = runBlocking { getMangaById.await(mangaId) } + val manga = runBlocking { getManga.await(mangaId) } val chapter = runBlocking { getChapter.await(chapterId) } if (manga != null && chapter != null) { val intent = ReaderActivity.newIntent(context, manga.id, chapter.id).apply { @@ -248,7 +248,7 @@ class NotificationReceiver : BroadcastReceiver() { .map { val chapter = it.copy(read = true) if (preferences.removeAfterMarkedAsRead()) { - val manga = getMangaById.await(mangaId) + val manga = getManga.await(mangaId) if (manga != null) { val source = sourceManager.get(manga.source) if (source != null) { @@ -270,7 +270,7 @@ class NotificationReceiver : BroadcastReceiver() { */ private fun downloadChapters(chapterUrls: Array, mangaId: Long) { launchIO { - val manga = getMangaById.await(mangaId)?.toDbManga() + val manga = getManga.await(mangaId)?.toDbManga() val chapters = chapterUrls.mapNotNull { getChapter.await(it, mangaId)?.toDbChapter() } if (manga != null && chapters.isNotEmpty()) { downloadManager.downloadChapters(manga, chapters) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/job/DelayedTrackingUpdateJob.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/job/DelayedTrackingUpdateJob.kt index 6c5259ac7..508861e88 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/job/DelayedTrackingUpdateJob.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/job/DelayedTrackingUpdateJob.kt @@ -9,7 +9,7 @@ import androidx.work.NetworkType import androidx.work.OneTimeWorkRequestBuilder import androidx.work.WorkManager import androidx.work.WorkerParameters -import eu.kanade.domain.manga.interactor.GetMangaById +import eu.kanade.domain.manga.interactor.GetManga import eu.kanade.domain.track.interactor.GetTracks import eu.kanade.domain.track.interactor.InsertTrack import eu.kanade.domain.track.model.toDbTrack @@ -26,7 +26,7 @@ class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters) CoroutineWorker(context, workerParams) { override suspend fun doWork(): Result { - val getMangaById = Injekt.get() + val getManga = Injekt.get() val getTracks = Injekt.get() val insertTrack = Injekt.get() @@ -35,7 +35,7 @@ class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters) withContext(Dispatchers.IO) { val tracks = delayedTrackingStore.getItems().mapNotNull { - val manga = getMangaById.await(it.mangaId) ?: return@withContext + val manga = getManga.await(it.mangaId) ?: return@withContext getTracks.await(manga.id) .find { track -> track.id == it.trackId } ?.copy(lastChapterRead = it.lastChapterRead.toDouble()) 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 104347c09..bb5f5d383 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 @@ -6,8 +6,9 @@ import androidx.core.view.isVisible import com.bluelinelabs.conductor.Controller import com.bluelinelabs.conductor.RouterTransaction import com.google.android.material.dialog.MaterialAlertDialogBuilder +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.data.database.models.toDomainManga import eu.kanade.tachiyomi.data.preference.PreferencesHelper @@ -18,6 +19,7 @@ import eu.kanade.tachiyomi.ui.browse.migration.MigrationFlags import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchController import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchPresenter import eu.kanade.tachiyomi.ui.manga.MangaController +import kotlinx.coroutines.runBlocking import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy @@ -27,9 +29,11 @@ class SearchController( ) : GlobalSearchController(manga?.title) { constructor(mangaId: Long) : this( - Injekt.get() - .getManga(mangaId) - .executeAsBlocking(), + runBlocking { + Injekt.get() + .await(mangaId) + ?.toDbManga() + }, ) private var newManga: Manga? = null 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 2b9152ea1..18b86ae43 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 @@ -7,11 +7,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 @@ -67,13 +70,15 @@ open class BrowseSourcePresenter( private val sourceId: Long, searchQuery: String? = null, private val sourceManager: SourceManager = Injekt.get(), - private val db: DatabaseHelper = 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() { @@ -208,19 +213,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(title = sManga.title) } - return localManga + return localManga?.toDbManga()!! } /** @@ -255,7 +263,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) } @@ -282,7 +294,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/globalsearch/GlobalSearchPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchPresenter.kt index 0b1d04829..616f02663 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 @@ -38,8 +44,10 @@ open class GlobalSearchPresenter( private val initialQuery: String? = "", private val initialExtensionFilter: String? = 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() { /** @@ -248,7 +256,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 } @@ -260,18 +268,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(title = sManga.title) } - return localManga + return localManga!!.toDbManga() } } 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 eef42fa60..6e4cf976b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt @@ -11,13 +11,13 @@ import eu.kanade.domain.chapter.interactor.GetChapterByMangaId 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.UpdateManga import eu.kanade.domain.manga.model.Manga import eu.kanade.domain.manga.model.MangaUpdate import eu.kanade.domain.track.interactor.GetTracks import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.database.models.Chapter -import eu.kanade.tachiyomi.data.database.models.LibraryManga import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.track.TrackManager @@ -60,6 +60,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(), @@ -410,35 +411,7 @@ class LibraryPresenter( val defaultLibraryDisplayMode = preferences.libraryDisplayMode() val shouldSetFromCategory = preferences.categorizedDisplaySettings() - // TODO: Move this to domain/data layer - return handler - .subscribeToList { - 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, 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.unreadCount = unread_count.toInt() - this.readCount = read_count.toInt() - this.category = category.toInt() - } - } - } - .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/MangaPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt index 6cc03a653..def5afc5c 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 @@ -149,7 +149,7 @@ class MangaPresenter( presenterScope.launchIO { if (!getMangaAndChapters.awaitManga(mangaId).favorite) { - ChapterSettingsHelper.applySettingDefaults(mangaId, setMangaChapterFlags) + ChapterSettingsHelper.applySettingDefaults(mangaId) } getMangaAndChapters.subscribe(mangaId) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaFullCoverDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaFullCoverDialog.kt index 146a22994..f3eb13067 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaFullCoverDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaFullCoverDialog.kt @@ -20,7 +20,7 @@ import androidx.core.os.bundleOf import coil.imageLoader import coil.request.ImageRequest import coil.size.Size -import eu.kanade.domain.manga.interactor.GetMangaById +import eu.kanade.domain.manga.interactor.GetManga import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.domain.manga.model.Manga import eu.kanade.domain.manga.model.hasCustomCover @@ -161,7 +161,7 @@ class MangaFullCoverDialog : FullComposeController() { private var presenterScope: CoroutineScope = MainScope() @@ -176,7 +176,7 @@ class MangaFullCoverDialog : FullComposeController() { /** @@ -242,7 +242,7 @@ class ReaderPresenter( launchIO { try { - val manga = getMangaById.await(mangaId) + val manga = getManga.await(mangaId) withUIContext { manga?.let { init(it.toDbManga(), initialChapterId) } } @@ -570,7 +570,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, _ -> @@ -605,7 +607,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/sqldelight/data/mangas.sq b/app/src/main/sqldelight/data/mangas.sq index 753285299..96b8f87d5 100644 --- a/app/src/main/sqldelight/data/mangas.sq +++ b/app/src/main/sqldelight/data/mangas.sq @@ -145,6 +145,44 @@ deleteMangasNotInLibraryBySourceIds: DELETE FROM mangas WHERE favorite = 0 AND source IN :sourceIds; +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),