From e15a867106bea490ed92d78b046535d3985ba1d0 Mon Sep 17 00:00:00 2001 From: arkon Date: Fri, 10 Jun 2022 21:33:56 -0400 Subject: [PATCH] Convert clear database queries to SQLDelight --- .../data/chapter/ChapterRepositoryImpl.kt | 4 +- .../kanade/data/manga/MangaRepositoryImpl.kt | 6 +-- .../data/source/SourceRepositoryImpl.kt | 13 +++++- .../java/eu/kanade/domain/DomainModule.kt | 8 ++-- .../GetSourcesWithNonLibraryManga.kt | 14 ++++++ .../source/repository/SourceRepository.kt | 3 ++ .../database/models/SourceIdMangaCount.kt | 3 -- .../data/database/queries/MangaQueries.kt | 25 ---------- .../data/database/queries/RawQueries.kt | 12 ----- .../SourceIdMangaCountGetResolver.kt | 23 ---------- .../database/ClearDatabasePresenter.kt | 46 ++++++++----------- .../database/ClearDatabaseSourceItem.kt | 4 +- app/src/main/sqldelight/data/mangas.sq | 12 ++++- 13 files changed, 72 insertions(+), 101 deletions(-) create mode 100644 app/src/main/java/eu/kanade/domain/source/interactor/GetSourcesWithNonLibraryManga.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/database/models/SourceIdMangaCount.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/SourceIdMangaCountGetResolver.kt diff --git a/app/src/main/java/eu/kanade/data/chapter/ChapterRepositoryImpl.kt b/app/src/main/java/eu/kanade/data/chapter/ChapterRepositoryImpl.kt index 0d7ae610a4..1fa5d9fd23 100644 --- a/app/src/main/java/eu/kanade/data/chapter/ChapterRepositoryImpl.kt +++ b/app/src/main/java/eu/kanade/data/chapter/ChapterRepositoryImpl.kt @@ -8,12 +8,12 @@ import eu.kanade.tachiyomi.util.system.logcat import logcat.LogPriority class ChapterRepositoryImpl( - private val databaseHandler: DatabaseHandler, + private val handler: DatabaseHandler, ) : ChapterRepository { override suspend fun update(chapterUpdate: ChapterUpdate) { try { - databaseHandler.await { + handler.await { chaptersQueries.update( chapterUpdate.mangaId, chapterUpdate.url, 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 70ff72e294..f5d0788f65 100644 --- a/app/src/main/java/eu/kanade/data/manga/MangaRepositoryImpl.kt +++ b/app/src/main/java/eu/kanade/data/manga/MangaRepositoryImpl.kt @@ -8,16 +8,16 @@ import kotlinx.coroutines.flow.Flow import logcat.LogPriority class MangaRepositoryImpl( - private val databaseHandler: DatabaseHandler, + private val handler: DatabaseHandler, ) : MangaRepository { override fun getFavoritesBySourceId(sourceId: Long): Flow> { - return databaseHandler.subscribeToList { mangasQueries.getFavoriteBySourceId(sourceId, mangaMapper) } + return handler.subscribeToList { mangasQueries.getFavoriteBySourceId(sourceId, mangaMapper) } } override suspend fun resetViewerFlags(): Boolean { return try { - databaseHandler.await { mangasQueries.resetViewerFlags() } + handler.await { mangasQueries.resetViewerFlags() } true } catch (e: Exception) { logcat(LogPriority.ERROR, e) diff --git a/app/src/main/java/eu/kanade/data/source/SourceRepositoryImpl.kt b/app/src/main/java/eu/kanade/data/source/SourceRepositoryImpl.kt index 4db18e633e..87db873257 100644 --- a/app/src/main/java/eu/kanade/data/source/SourceRepositoryImpl.kt +++ b/app/src/main/java/eu/kanade/data/source/SourceRepositoryImpl.kt @@ -7,6 +7,7 @@ import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.SourceManager import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map +import eu.kanade.tachiyomi.source.Source as LoadedSource class SourceRepositoryImpl( private val sourceManager: SourceManager, @@ -29,13 +30,23 @@ class SourceRepositoryImpl( val sourceIdWithFavoriteCount = handler.subscribeToList { mangasQueries.getSourceIdWithFavoriteCount() } return sourceIdWithFavoriteCount.map { sourceIdsWithCount -> sourceIdsWithCount + .filterNot { it.source == LocalSource.ID } .map { (sourceId, count) -> val source = sourceManager.getOrStub(sourceId).run { sourceMapper(this) } source to count } - .filterNot { it.first.id == LocalSource.ID } + } + } + + override fun getSourcesWithNonLibraryManga(): Flow>> { + val sourceIdWithNonLibraryManga = handler.subscribeToList { mangasQueries.getSourceIdsWithNonLibraryManga() } + return sourceIdWithNonLibraryManga.map { sourceId -> + sourceId.map { (sourceId, count) -> + val source = sourceManager.getOrStub(sourceId) + source to count + } } } } diff --git a/app/src/main/java/eu/kanade/domain/DomainModule.kt b/app/src/main/java/eu/kanade/domain/DomainModule.kt index ccd9560a6d..3e5d483a3c 100644 --- a/app/src/main/java/eu/kanade/domain/DomainModule.kt +++ b/app/src/main/java/eu/kanade/domain/DomainModule.kt @@ -23,6 +23,7 @@ import eu.kanade.domain.manga.repository.MangaRepository import eu.kanade.domain.source.interactor.GetEnabledSources import eu.kanade.domain.source.interactor.GetLanguagesWithSources import eu.kanade.domain.source.interactor.GetSourcesWithFavoriteCount +import eu.kanade.domain.source.interactor.GetSourcesWithNonLibraryManga import eu.kanade.domain.source.interactor.SetMigrateSorting import eu.kanade.domain.source.interactor.ToggleLanguage import eu.kanade.domain.source.interactor.ToggleSource @@ -58,12 +59,13 @@ class DomainModule : InjektModule { addFactory { GetExtensionLanguages(get(), get()) } addSingletonFactory { SourceRepositoryImpl(get(), get()) } - addFactory { GetLanguagesWithSources(get(), get()) } addFactory { GetEnabledSources(get(), get()) } - addFactory { ToggleSource(get()) } - addFactory { ToggleSourcePin(get()) } + addFactory { GetLanguagesWithSources(get(), get()) } addFactory { GetSourcesWithFavoriteCount(get(), get()) } + addFactory { GetSourcesWithNonLibraryManga(get()) } addFactory { SetMigrateSorting(get()) } addFactory { ToggleLanguage(get()) } + addFactory { ToggleSource(get()) } + addFactory { ToggleSourcePin(get()) } } } diff --git a/app/src/main/java/eu/kanade/domain/source/interactor/GetSourcesWithNonLibraryManga.kt b/app/src/main/java/eu/kanade/domain/source/interactor/GetSourcesWithNonLibraryManga.kt new file mode 100644 index 0000000000..5bcf634432 --- /dev/null +++ b/app/src/main/java/eu/kanade/domain/source/interactor/GetSourcesWithNonLibraryManga.kt @@ -0,0 +1,14 @@ +package eu.kanade.domain.source.interactor + +import eu.kanade.domain.source.repository.SourceRepository +import eu.kanade.tachiyomi.source.Source +import kotlinx.coroutines.flow.Flow + +class GetSourcesWithNonLibraryManga( + private val repository: SourceRepository, +) { + + fun subscribe(): Flow>> { + return repository.getSourcesWithNonLibraryManga() + } +} diff --git a/app/src/main/java/eu/kanade/domain/source/repository/SourceRepository.kt b/app/src/main/java/eu/kanade/domain/source/repository/SourceRepository.kt index 5f07a30f5b..00590ca9b2 100644 --- a/app/src/main/java/eu/kanade/domain/source/repository/SourceRepository.kt +++ b/app/src/main/java/eu/kanade/domain/source/repository/SourceRepository.kt @@ -2,6 +2,7 @@ package eu.kanade.domain.source.repository import eu.kanade.domain.source.model.Source import kotlinx.coroutines.flow.Flow +import eu.kanade.tachiyomi.source.Source as LoadedSource interface SourceRepository { @@ -10,4 +11,6 @@ interface SourceRepository { fun getOnlineSources(): Flow> fun getSourcesWithFavoriteCount(): Flow>> + + fun getSourcesWithNonLibraryManga(): Flow>> } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/SourceIdMangaCount.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/SourceIdMangaCount.kt deleted file mode 100644 index bb91e1337c..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/SourceIdMangaCount.kt +++ /dev/null @@ -1,3 +0,0 @@ -package eu.kanade.tachiyomi.data.database.models - -data class SourceIdMangaCount(val source: Long, val count: Int) 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 index d410a090ed..0bfc93d0af 100644 --- 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 @@ -1,20 +1,16 @@ package eu.kanade.tachiyomi.data.database.queries -import com.pushtorefresh.storio.Queries import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetListOfObjects -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.LibraryManga import eu.kanade.tachiyomi.data.database.models.Manga -import eu.kanade.tachiyomi.data.database.models.SourceIdMangaCount import eu.kanade.tachiyomi.data.database.resolvers.LibraryMangaGetResolver import eu.kanade.tachiyomi.data.database.resolvers.MangaCoverLastModifiedPutResolver import eu.kanade.tachiyomi.data.database.resolvers.MangaFavoritePutResolver import eu.kanade.tachiyomi.data.database.resolvers.MangaFlagsPutResolver import eu.kanade.tachiyomi.data.database.resolvers.MangaLastUpdatedPutResolver -import eu.kanade.tachiyomi.data.database.resolvers.SourceIdMangaCountGetResolver import eu.kanade.tachiyomi.data.database.tables.CategoryTable import eu.kanade.tachiyomi.data.database.tables.ChapterTable import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable @@ -86,17 +82,6 @@ interface MangaQueries : DbProvider { ) .prepare() - fun getSourceIdsWithNonLibraryManga() = db.get() - .listOfObjects(SourceIdMangaCount::class.java) - .withQuery( - RawQuery.builder() - .query(getSourceIdsWithNonLibraryMangaQuery()) - .observesTables(MangaTable.TABLE) - .build(), - ) - .withGetResolver(SourceIdMangaCountGetResolver.INSTANCE) - .prepare() - fun insertManga(manga: Manga) = db.put().`object`(manga).prepare() fun insertMangas(mangas: List) = db.put().objects(mangas).prepare() @@ -131,16 +116,6 @@ interface MangaQueries : DbProvider { .withPutResolver(MangaCoverLastModifiedPutResolver()) .prepare() - fun deleteMangasNotInLibraryBySourceIds(sourceIds: List) = db.delete() - .byQuery( - DeleteQuery.builder() - .table(MangaTable.TABLE) - .where("${MangaTable.COL_FAVORITE} = ? AND ${MangaTable.COL_SOURCE} IN (${Queries.placeholders(sourceIds.size)})") - .whereArgs(0, *sourceIds.toTypedArray()) - .build(), - ) - .prepare() - fun getLastReadManga() = db.get() .listOfObjects(Manga::class.java) .withQuery( 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 index c1209d4c1e..6ae95e670c 100644 --- 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 @@ -1,6 +1,5 @@ package eu.kanade.tachiyomi.data.database.queries -import eu.kanade.tachiyomi.data.database.resolvers.SourceIdMangaCountGetResolver import eu.kanade.tachiyomi.data.database.tables.CategoryTable as Category import eu.kanade.tachiyomi.data.database.tables.ChapterTable as Chapter import eu.kanade.tachiyomi.data.database.tables.HistoryTable as History @@ -113,14 +112,3 @@ fun getCategoriesForMangaQuery() = ${MangaCategory.TABLE}.${MangaCategory.COL_CATEGORY_ID} WHERE ${MangaCategory.COL_MANGA_ID} = ? """ - -/** Query to get the list of sources in the database that have - * non-library manga, and how many - */ -fun getSourceIdsWithNonLibraryMangaQuery() = - """ - SELECT ${Manga.COL_SOURCE}, COUNT(*) as ${SourceIdMangaCountGetResolver.COL_COUNT} - FROM ${Manga.TABLE} - WHERE ${Manga.COL_FAVORITE} = 0 - GROUP BY ${Manga.COL_SOURCE} - """ diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/SourceIdMangaCountGetResolver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/SourceIdMangaCountGetResolver.kt deleted file mode 100644 index 3e023dd438..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/SourceIdMangaCountGetResolver.kt +++ /dev/null @@ -1,23 +0,0 @@ -package eu.kanade.tachiyomi.data.database.resolvers - -import android.annotation.SuppressLint -import android.database.Cursor -import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver -import eu.kanade.tachiyomi.data.database.models.SourceIdMangaCount -import eu.kanade.tachiyomi.data.database.tables.MangaTable - -class SourceIdMangaCountGetResolver : DefaultGetResolver() { - - companion object { - val INSTANCE = SourceIdMangaCountGetResolver() - const val COL_COUNT = "manga_count" - } - - @SuppressLint("Range") - override fun mapFromCursor(cursor: Cursor): SourceIdMangaCount { - val sourceID = cursor.getLong(cursor.getColumnIndexOrThrow(MangaTable.COL_SOURCE)) - val count = cursor.getInt(cursor.getColumnIndexOrThrow(COL_COUNT)) - - return SourceIdMangaCount(sourceID, count) - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/database/ClearDatabasePresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/database/ClearDatabasePresenter.kt index 192bd81a92..0c9081ae49 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/database/ClearDatabasePresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/database/ClearDatabasePresenter.kt @@ -1,43 +1,37 @@ package eu.kanade.tachiyomi.ui.setting.database import android.os.Bundle +import eu.kanade.domain.source.interactor.GetSourcesWithNonLibraryManga import eu.kanade.tachiyomi.Database -import eu.kanade.tachiyomi.data.database.DatabaseHelper -import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter -import rx.Observable -import rx.android.schedulers.AndroidSchedulers -import rx.schedulers.Schedulers +import eu.kanade.tachiyomi.util.lang.launchIO +import eu.kanade.tachiyomi.util.lang.withUIContext +import kotlinx.coroutines.flow.collectLatest import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get -class ClearDatabasePresenter : BasePresenter() { - - private val db = Injekt.get() - private val database = Injekt.get() - - private val sourceManager = Injekt.get() +class ClearDatabasePresenter( + private val database: Database = Injekt.get(), + private val getSourcesWithNonLibraryManga: GetSourcesWithNonLibraryManga = Injekt.get(), +) : BasePresenter() { override fun onCreate(savedState: Bundle?) { super.onCreate(savedState) - getDatabaseSourcesObservable() - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribeLatestCache(ClearDatabaseController::setItems) + + presenterScope.launchIO { + getSourcesWithNonLibraryManga.subscribe() + .collectLatest { list -> + val items = list + .map { (source, count) -> ClearDatabaseSourceItem(source, count) } + .sortedBy { it.source.name } + + withUIContext { view?.setItems(items) } + } + } } fun clearDatabaseForSourceIds(sources: List) { - db.deleteMangasNotInLibraryBySourceIds(sources).executeAsBlocking() + database.mangasQueries.deleteMangasNotInLibraryBySourceIds(sources) database.historyQueries.removeResettedHistory() } - - private fun getDatabaseSourcesObservable(): Observable> { - return db.getSourceIdsWithNonLibraryManga().asRxObservable() - .map { sourceCounts -> - sourceCounts.map { - val sourceObj = sourceManager.getOrStub(it.source) - ClearDatabaseSourceItem(sourceObj, it.count) - }.sortedBy { it.source.name } - } - } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/database/ClearDatabaseSourceItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/database/ClearDatabaseSourceItem.kt index 9862b9ba0e..9a7933d776 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/database/ClearDatabaseSourceItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/database/ClearDatabaseSourceItem.kt @@ -13,7 +13,7 @@ import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.icon -data class ClearDatabaseSourceItem(val source: Source, private val mangaCount: Int) : AbstractFlexibleItem() { +data class ClearDatabaseSourceItem(val source: Source, private val mangaCount: Long) : AbstractFlexibleItem() { override fun getLayoutRes(): Int { return R.layout.clear_database_source_item @@ -31,7 +31,7 @@ data class ClearDatabaseSourceItem(val source: Source, private val mangaCount: I private val binding = ClearDatabaseSourceItemBinding.bind(view) - fun bind(source: Source, count: Int) { + fun bind(source: Source, count: Long) { binding.title.text = source.toString() binding.description.text = itemView.context.getString(R.string.clear_database_source_item_count, count) diff --git a/app/src/main/sqldelight/data/mangas.sq b/app/src/main/sqldelight/data/mangas.sq index a1b61f4228..ccb351da2e 100644 --- a/app/src/main/sqldelight/data/mangas.sq +++ b/app/src/main/sqldelight/data/mangas.sq @@ -46,4 +46,14 @@ AND source = :sourceId; resetViewerFlags: UPDATE mangas -SET viewer = 0; \ No newline at end of file +SET viewer = 0; + +getSourceIdsWithNonLibraryManga: +SELECT source, COUNT(*) AS manga_count +FROM mangas +WHERE favorite = 0 +GROUP BY source; + +deleteMangasNotInLibraryBySourceIds: +DELETE FROM mangas +WHERE favorite = 0 AND source IN :sourceIds; \ No newline at end of file