Migrate duplicate manga check to SQLDelight

Extracted from #7244

Co-authored-by: ivaniskandar <ivaniskandar@users.noreply.github.com>
This commit is contained in:
arkon 2022-06-19 10:15:17 -04:00
parent 0f5731360b
commit 9f66c85281
10 changed files with 77 additions and 42 deletions

View File

@ -22,6 +22,12 @@ class MangaRepositoryImpl(
return handler.subscribeToList { mangasQueries.getFavoriteBySourceId(sourceId, mangaMapper) } 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 { override suspend fun resetViewerFlags(): Boolean {
return try { return try {
handler.await { mangasQueries.resetViewerFlags() } handler.await { mangasQueries.resetViewerFlags() }

View File

@ -26,6 +26,7 @@ import eu.kanade.domain.history.interactor.RemoveHistoryById
import eu.kanade.domain.history.interactor.RemoveHistoryByMangaId import eu.kanade.domain.history.interactor.RemoveHistoryByMangaId
import eu.kanade.domain.history.interactor.UpsertHistory import eu.kanade.domain.history.interactor.UpsertHistory
import eu.kanade.domain.history.repository.HistoryRepository 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.GetFavoritesBySourceId
import eu.kanade.domain.manga.interactor.GetMangaById import eu.kanade.domain.manga.interactor.GetMangaById
import eu.kanade.domain.manga.interactor.ResetViewerFlags import eu.kanade.domain.manga.interactor.ResetViewerFlags
@ -58,6 +59,7 @@ class DomainModule : InjektModule {
addFactory { DeleteCategory(get()) } addFactory { DeleteCategory(get()) }
addSingletonFactory<MangaRepository> { MangaRepositoryImpl(get()) } addSingletonFactory<MangaRepository> { MangaRepositoryImpl(get()) }
addFactory { GetDuplicateLibraryManga(get()) }
addFactory { GetFavoritesBySourceId(get()) } addFactory { GetFavoritesBySourceId(get()) }
addFactory { GetMangaById(get()) } addFactory { GetMangaById(get()) }
addFactory { GetNextChapter(get()) } addFactory { GetNextChapter(get()) }

View File

@ -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)
}
}

View File

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

View File

@ -28,21 +28,6 @@ interface MangaQueries : DbProvider {
.withGetResolver(LibraryMangaGetResolver.INSTANCE) .withGetResolver(LibraryMangaGetResolver.INSTANCE)
.prepare() .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> { fun getFavoriteMangas(sortByTitle: Boolean = true): PreparedGetListOfObjects<Manga> {
var queryBuilder = Query.builder() var queryBuilder = Query.builder()
.table(MangaTable.TABLE) .table(MangaTable.TABLE)

View File

@ -42,6 +42,8 @@ import eu.kanade.tachiyomi.ui.manga.AddDuplicateMangaDialog
import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.ui.manga.MangaController
import eu.kanade.tachiyomi.ui.more.MoreController import eu.kanade.tachiyomi.ui.more.MoreController
import eu.kanade.tachiyomi.ui.webview.WebViewActivity 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.preference.asImmediateFlow
import eu.kanade.tachiyomi.util.system.connectivityManager import eu.kanade.tachiyomi.util.system.connectivityManager
import eu.kanade.tachiyomi.util.system.logcat import eu.kanade.tachiyomi.util.system.logcat
@ -589,8 +591,10 @@ open class BrowseSourceController(bundle: Bundle) :
override fun onItemLongClick(position: Int) { override fun onItemLongClick(position: Int) {
val activity = activity ?: return val activity = activity ?: return
val manga = (adapter?.getItem(position) as? SourceItem?)?.manga ?: return val manga = (adapter?.getItem(position) as? SourceItem?)?.manga ?: return
launchIO {
val duplicateManga = presenter.getDuplicateLibraryManga(manga) val duplicateManga = presenter.getDuplicateLibraryManga(manga)
withUIContext {
if (manga.favorite) { if (manga.favorite) {
MaterialAlertDialogBuilder(activity) MaterialAlertDialogBuilder(activity)
.setTitle(manga.title) .setTitle(manga.title)
@ -606,13 +610,20 @@ open class BrowseSourceController(bundle: Bundle) :
.show() .show()
} else { } else {
if (duplicateManga != null) { if (duplicateManga != null) {
AddDuplicateMangaDialog(this, duplicateManga) { addToLibrary(manga, position) } AddDuplicateMangaDialog(this@BrowseSourceController, duplicateManga) {
addToLibrary(
manga,
position,
)
}
.showDialog(router) .showDialog(router)
} else { } else {
addToLibrary(manga, position) addToLibrary(manga, position)
} }
} }
} }
}
}
private fun addToLibrary(newManga: Manga, position: Int) { private fun addToLibrary(newManga: Manga, position: Int) {
val activity = activity ?: return val activity = activity ?: return

View File

@ -2,6 +2,8 @@ package eu.kanade.tachiyomi.ui.browse.source.browse
import android.os.Bundle import android.os.Bundle
import eu.davidea.flexibleadapter.items.IFlexible 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.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.database.models.Category
@ -60,6 +62,7 @@ open class BrowseSourcePresenter(
private val db: DatabaseHelper = Injekt.get(), private val db: DatabaseHelper = Injekt.get(),
private val prefs: PreferencesHelper = Injekt.get(), private val prefs: PreferencesHelper = Injekt.get(),
private val coverCache: CoverCache = Injekt.get(), private val coverCache: CoverCache = Injekt.get(),
private val getDuplicateLibraryManga: GetDuplicateLibraryManga = Injekt.get(),
) : BasePresenter<BrowseSourceController>() { ) : BasePresenter<BrowseSourceController>() {
/** /**
@ -348,8 +351,8 @@ open class BrowseSourcePresenter(
return db.getCategories().executeAsBlocking() return db.getCategories().executeAsBlocking()
} }
fun getDuplicateLibraryManga(manga: Manga): Manga? { suspend fun getDuplicateLibraryManga(manga: Manga): Manga? {
return db.getDuplicateLibraryManga(manga).executeAsBlocking() return getDuplicateLibraryManga.await(manga.title, manga.source)?.toDbManga()
} }
/** /**

View File

@ -87,6 +87,7 @@ import eu.kanade.tachiyomi.ui.webview.WebViewActivity
import eu.kanade.tachiyomi.util.hasCustomCover import eu.kanade.tachiyomi.util.hasCustomCover
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchUI 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.logcat
import eu.kanade.tachiyomi.util.system.toShareIntent import eu.kanade.tachiyomi.util.system.toShareIntent
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
@ -516,15 +517,20 @@ class MangaController :
activity?.toast(activity?.getString(R.string.manga_removed_library)) activity?.toast(activity?.getString(R.string.manga_removed_library))
activity?.invalidateOptionsMenu() activity?.invalidateOptionsMenu()
} else { } else {
launchIO {
val duplicateManga = presenter.getDuplicateLibraryManga(manga) val duplicateManga = presenter.getDuplicateLibraryManga(manga)
withUIContext {
if (duplicateManga != null) { if (duplicateManga != null) {
AddDuplicateMangaDialog(this, duplicateManga) { addToLibrary(manga) } AddDuplicateMangaDialog(this@MangaController, duplicateManga) { addToLibrary(manga) }
.showDialog(router) .showDialog(router)
} else { } else {
addToLibrary(manga) addToLibrary(manga)
} }
} }
} }
}
}
fun onTrackingClick() { fun onTrackingClick() {
trackSheet?.show() trackSheet?.show()

View File

@ -6,6 +6,8 @@ import android.os.Bundle
import com.jakewharton.rxrelay.PublishRelay import com.jakewharton.rxrelay.PublishRelay
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
import eu.kanade.domain.chapter.model.toDbChapter 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.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.database.models.Category
@ -69,6 +71,7 @@ class MangaPresenter(
private val downloadManager: DownloadManager = Injekt.get(), private val downloadManager: DownloadManager = Injekt.get(),
private val coverCache: CoverCache = Injekt.get(), private val coverCache: CoverCache = Injekt.get(),
private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(), private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
private val getDuplicateLibraryManga: GetDuplicateLibraryManga = Injekt.get(),
) : BasePresenter<MangaController>() { ) : BasePresenter<MangaController>() {
/** /**
@ -167,8 +170,8 @@ class MangaPresenter(
fetchTrackers() fetchTrackers()
} }
fun getDuplicateLibraryManga(manga: Manga): Manga? { suspend fun getDuplicateLibraryManga(manga: Manga): Manga? {
return db.getDuplicateLibraryManga(manga).executeAsBlocking() return getDuplicateLibraryManga.await(manga.title, manga.source)?.toDbManga()
} }
// Manga info - start // Manga info - start

View File

@ -58,6 +58,13 @@ FROM mangas
WHERE favorite = 1 WHERE favorite = 1
AND source = :sourceId; AND source = :sourceId;
getDuplicateLibraryManga:
SELECT *
FROM mangas
WHERE favorite = 1
AND LOWER(title) = :title
AND source != :source;
resetViewerFlags: resetViewerFlags:
UPDATE mangas UPDATE mangas
SET viewer = 0; SET viewer = 0;