From 9f66c85281e02eb6a73034d79a3441c98803ffd6 Mon Sep 17 00:00:00 2001 From: arkon Date: Sun, 19 Jun 2022 10:15:17 -0400 Subject: [PATCH] Migrate duplicate manga check to SQLDelight Extracted from #7244 Co-authored-by: ivaniskandar --- .../kanade/data/manga/MangaRepositoryImpl.kt | 6 +++ .../java/eu/kanade/domain/DomainModule.kt | 2 + .../interactor/GetDuplicateLibraryManga.kt | 10 +++++ .../manga/repository/MangaRepository.kt | 2 + .../data/database/queries/MangaQueries.kt | 15 ------- .../source/browse/BrowseSourceController.kt | 45 ++++++++++++------- .../source/browse/BrowseSourcePresenter.kt | 7 ++- .../tachiyomi/ui/manga/MangaController.kt | 18 +++++--- .../tachiyomi/ui/manga/MangaPresenter.kt | 7 ++- app/src/main/sqldelight/data/mangas.sq | 7 +++ 10 files changed, 77 insertions(+), 42 deletions(-) create mode 100644 app/src/main/java/eu/kanade/domain/manga/interactor/GetDuplicateLibraryManga.kt 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 562584c6e..945b800b2 100644 --- a/app/src/main/java/eu/kanade/data/manga/MangaRepositoryImpl.kt +++ b/app/src/main/java/eu/kanade/data/manga/MangaRepositoryImpl.kt @@ -22,6 +22,12 @@ class MangaRepositoryImpl( return handler.subscribeToList { mangasQueries.getFavoriteBySourceId(sourceId, mangaMapper) } } + override suspend fun getDuplicateLibraryManga(title: String, sourceId: Long): Manga? { + return handler.awaitOneOrNull { + mangasQueries.getDuplicateLibraryManga(title, sourceId, mangaMapper) + } + } + override suspend fun resetViewerFlags(): Boolean { return try { handler.await { mangasQueries.resetViewerFlags() } diff --git a/app/src/main/java/eu/kanade/domain/DomainModule.kt b/app/src/main/java/eu/kanade/domain/DomainModule.kt index 931a1dc13..8c329b1f7 100644 --- a/app/src/main/java/eu/kanade/domain/DomainModule.kt +++ b/app/src/main/java/eu/kanade/domain/DomainModule.kt @@ -26,6 +26,7 @@ import eu.kanade.domain.history.interactor.RemoveHistoryById import eu.kanade.domain.history.interactor.RemoveHistoryByMangaId 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.GetFavoritesBySourceId import eu.kanade.domain.manga.interactor.GetMangaById import eu.kanade.domain.manga.interactor.ResetViewerFlags @@ -58,6 +59,7 @@ class DomainModule : InjektModule { addFactory { DeleteCategory(get()) } addSingletonFactory { MangaRepositoryImpl(get()) } + addFactory { GetDuplicateLibraryManga(get()) } addFactory { GetFavoritesBySourceId(get()) } addFactory { GetMangaById(get()) } addFactory { GetNextChapter(get()) } diff --git a/app/src/main/java/eu/kanade/domain/manga/interactor/GetDuplicateLibraryManga.kt b/app/src/main/java/eu/kanade/domain/manga/interactor/GetDuplicateLibraryManga.kt new file mode 100644 index 000000000..9a0b4a828 --- /dev/null +++ b/app/src/main/java/eu/kanade/domain/manga/interactor/GetDuplicateLibraryManga.kt @@ -0,0 +1,10 @@ +package eu.kanade.domain.manga.interactor + +import eu.kanade.domain.manga.model.Manga +import eu.kanade.domain.manga.repository.MangaRepository + +class GetDuplicateLibraryManga(private val mangaRepository: MangaRepository) { + suspend fun await(title: String, sourceId: Long): Manga? { + return mangaRepository.getDuplicateLibraryManga(title.lowercase(), sourceId) + } +} 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 875cc9cdc..98f897b32 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 @@ -10,6 +10,8 @@ interface MangaRepository { fun getFavoritesBySourceId(sourceId: Long): Flow> + suspend fun getDuplicateLibraryManga(title: String, sourceId: Long): Manga? + suspend fun resetViewerFlags(): Boolean suspend fun update(update: MangaUpdate): Boolean 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 953e05c05..25b504d72 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 @@ -28,21 +28,6 @@ interface MangaQueries : DbProvider { .withGetResolver(LibraryMangaGetResolver.INSTANCE) .prepare() - fun getDuplicateLibraryManga(manga: Manga) = db.get() - .`object`(Manga::class.java) - .withQuery( - Query.builder() - .table(MangaTable.TABLE) - .where("${MangaTable.COL_FAVORITE} = 1 AND LOWER(${MangaTable.COL_TITLE}) = ? AND ${MangaTable.COL_SOURCE} != ?") - .whereArgs( - manga.title.lowercase(), - manga.source, - ) - .limit(1) - .build(), - ) - .prepare() - fun getFavoriteMangas(sortByTitle: Boolean = true): PreparedGetListOfObjects { var queryBuilder = Query.builder() .table(MangaTable.TABLE) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt index 89a88d733..22f7049e8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt @@ -42,6 +42,8 @@ import eu.kanade.tachiyomi.ui.manga.AddDuplicateMangaDialog import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.ui.more.MoreController import eu.kanade.tachiyomi.ui.webview.WebViewActivity +import eu.kanade.tachiyomi.util.lang.launchIO +import eu.kanade.tachiyomi.util.lang.withUIContext import eu.kanade.tachiyomi.util.preference.asImmediateFlow import eu.kanade.tachiyomi.util.system.connectivityManager import eu.kanade.tachiyomi.util.system.logcat @@ -589,27 +591,36 @@ open class BrowseSourceController(bundle: Bundle) : override fun onItemLongClick(position: Int) { val activity = activity ?: return val manga = (adapter?.getItem(position) as? SourceItem?)?.manga ?: return - val duplicateManga = presenter.getDuplicateLibraryManga(manga) + launchIO { + val duplicateManga = presenter.getDuplicateLibraryManga(manga) - if (manga.favorite) { - MaterialAlertDialogBuilder(activity) - .setTitle(manga.title) - .setItems(arrayOf(activity.getString(R.string.remove_from_library))) { _, which -> - when (which) { - 0 -> { - presenter.changeMangaFavorite(manga) - adapter?.notifyItemChanged(position) - activity.toast(activity.getString(R.string.manga_removed_library)) + withUIContext { + if (manga.favorite) { + MaterialAlertDialogBuilder(activity) + .setTitle(manga.title) + .setItems(arrayOf(activity.getString(R.string.remove_from_library))) { _, which -> + when (which) { + 0 -> { + presenter.changeMangaFavorite(manga) + adapter?.notifyItemChanged(position) + activity.toast(activity.getString(R.string.manga_removed_library)) + } + } } + .show() + } else { + if (duplicateManga != null) { + AddDuplicateMangaDialog(this@BrowseSourceController, duplicateManga) { + addToLibrary( + manga, + position, + ) + } + .showDialog(router) + } else { + addToLibrary(manga, position) } } - .show() - } else { - if (duplicateManga != null) { - AddDuplicateMangaDialog(this, duplicateManga) { addToLibrary(manga, position) } - .showDialog(router) - } else { - addToLibrary(manga, position) } } } 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 6b0694c93..3e5d9d1e2 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 @@ -2,6 +2,8 @@ package eu.kanade.tachiyomi.ui.browse.source.browse import android.os.Bundle import eu.davidea.flexibleadapter.items.IFlexible +import eu.kanade.domain.manga.interactor.GetDuplicateLibraryManga +import eu.kanade.domain.manga.model.toDbManga import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Category @@ -60,6 +62,7 @@ open class BrowseSourcePresenter( private val db: DatabaseHelper = Injekt.get(), private val prefs: PreferencesHelper = Injekt.get(), private val coverCache: CoverCache = Injekt.get(), + private val getDuplicateLibraryManga: GetDuplicateLibraryManga = Injekt.get(), ) : BasePresenter() { /** @@ -348,8 +351,8 @@ open class BrowseSourcePresenter( return db.getCategories().executeAsBlocking() } - fun getDuplicateLibraryManga(manga: Manga): Manga? { - return db.getDuplicateLibraryManga(manga).executeAsBlocking() + suspend fun getDuplicateLibraryManga(manga: Manga): Manga? { + return getDuplicateLibraryManga.await(manga.title, manga.source)?.toDbManga() } /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt index 11d1fd339..d2198f8b7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt @@ -87,6 +87,7 @@ import eu.kanade.tachiyomi.ui.webview.WebViewActivity import eu.kanade.tachiyomi.util.hasCustomCover import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchUI +import eu.kanade.tachiyomi.util.lang.withUIContext import eu.kanade.tachiyomi.util.system.logcat import eu.kanade.tachiyomi.util.system.toShareIntent import eu.kanade.tachiyomi.util.system.toast @@ -516,12 +517,17 @@ class MangaController : activity?.toast(activity?.getString(R.string.manga_removed_library)) activity?.invalidateOptionsMenu() } else { - val duplicateManga = presenter.getDuplicateLibraryManga(manga) - if (duplicateManga != null) { - AddDuplicateMangaDialog(this, duplicateManga) { addToLibrary(manga) } - .showDialog(router) - } else { - addToLibrary(manga) + launchIO { + val duplicateManga = presenter.getDuplicateLibraryManga(manga) + + withUIContext { + if (duplicateManga != null) { + AddDuplicateMangaDialog(this@MangaController, duplicateManga) { addToLibrary(manga) } + .showDialog(router) + } else { + addToLibrary(manga) + } + } } } } 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 a2da0f41d..31127a093 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 @@ -6,6 +6,8 @@ import android.os.Bundle import com.jakewharton.rxrelay.PublishRelay import eu.kanade.domain.chapter.interactor.GetChapterByMangaId import eu.kanade.domain.chapter.model.toDbChapter +import eu.kanade.domain.manga.interactor.GetDuplicateLibraryManga +import eu.kanade.domain.manga.model.toDbManga import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Category @@ -69,6 +71,7 @@ class MangaPresenter( private val downloadManager: DownloadManager = Injekt.get(), private val coverCache: CoverCache = Injekt.get(), private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(), + private val getDuplicateLibraryManga: GetDuplicateLibraryManga = Injekt.get(), ) : BasePresenter() { /** @@ -167,8 +170,8 @@ class MangaPresenter( fetchTrackers() } - fun getDuplicateLibraryManga(manga: Manga): Manga? { - return db.getDuplicateLibraryManga(manga).executeAsBlocking() + suspend fun getDuplicateLibraryManga(manga: Manga): Manga? { + return getDuplicateLibraryManga.await(manga.title, manga.source)?.toDbManga() } // Manga info - start diff --git a/app/src/main/sqldelight/data/mangas.sq b/app/src/main/sqldelight/data/mangas.sq index a20f32a49..38349cf95 100644 --- a/app/src/main/sqldelight/data/mangas.sq +++ b/app/src/main/sqldelight/data/mangas.sq @@ -58,6 +58,13 @@ FROM mangas WHERE favorite = 1 AND source = :sourceId; +getDuplicateLibraryManga: +SELECT * +FROM mangas +WHERE favorite = 1 +AND LOWER(title) = :title +AND source != :source; + resetViewerFlags: UPDATE mangas SET viewer = 0;