Browse Source

Migrate duplicate manga check to SQLDelight

Extracted from #7244

Co-authored-by: ivaniskandar <[email protected]>
arkon 2 years ago
parent
commit
9f66c85281

+ 6 - 0
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() }

+ 2 - 0
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<MangaRepository> { MangaRepositoryImpl(get()) }
+        addFactory { GetDuplicateLibraryManga(get()) }
         addFactory { GetFavoritesBySourceId(get()) }
         addFactory { GetMangaById(get()) }
         addFactory { GetNextChapter(get()) }

+ 10 - 0
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)
+    }
+}

+ 2 - 0
app/src/main/java/eu/kanade/domain/manga/repository/MangaRepository.kt

@@ -10,6 +10,8 @@ interface MangaRepository {
 
     fun getFavoritesBySourceId(sourceId: Long): Flow<List<Manga>>
 
+    suspend fun getDuplicateLibraryManga(title: String, sourceId: Long): Manga?
+
     suspend fun resetViewerFlags(): Boolean
 
     suspend fun update(update: MangaUpdate): Boolean

+ 0 - 15
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<Manga> {
         var queryBuilder = Query.builder()
             .table(MangaTable.TABLE)

+ 29 - 18
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)
-
-        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))
+        launchIO {
+            val duplicateManga = presenter.getDuplicateLibraryManga(manga)
+
+            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)
             }
         }
     }

+ 5 - 2
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<BrowseSourceController>() {
 
     /**
@@ -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()
     }
 
     /**

+ 12 - 6
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)
+                    }
+                }
             }
         }
     }

+ 5 - 2
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<MangaController>() {
 
     /**
@@ -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

+ 7 - 0
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;