Migrate some categories SQL calls to SQLDelight

(cherry picked from commit a7decdb62d6226184827378bb851420f7628f856)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt
This commit is contained in:
arkon 2022-06-19 16:38:42 -04:00 committed by Jobobby04
parent 29f992fe33
commit 0e90c7fa16
8 changed files with 144 additions and 99 deletions

View File

@ -1,6 +1,7 @@
package eu.kanade.domain.category.model
import java.io.Serializable
import eu.kanade.tachiyomi.data.database.models.Category as DbCategory
data class Category(
val id: Long,
@ -11,3 +12,9 @@ data class Category(
val mangaOrder: List<Long>,
// SY <--
) : Serializable
fun Category.toDbCategory(): DbCategory = DbCategory.create(name).also {
it.id = id.toInt()
it.order = order.toInt()
it.flags = flags.toInt()
}

View File

@ -3,7 +3,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) {
class GetDuplicateLibraryManga(
private val mangaRepository: MangaRepository,
) {
suspend fun await(title: String, sourceId: Long): Manga? {
return mangaRepository.getDuplicateLibraryManga(title.lowercase(), sourceId)
}

View File

@ -5,6 +5,7 @@ import eu.kanade.domain.manga.repository.MangaRepository
class ResetViewerFlags(
private val mangaRepository: MangaRepository,
) {
suspend fun await(): Boolean {
return mangaRepository.resetViewerFlags()
}

View File

@ -20,6 +20,7 @@ import com.google.android.material.snackbar.Snackbar
import dev.chrisbanes.insetter.applyInsetter
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.domain.category.model.toDbCategory
import eu.kanade.domain.source.model.Source
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Category
@ -815,14 +816,16 @@ open class BrowseSourceController(bundle: Bundle) :
private fun addToLibrary(newManga: Manga, position: Int) {
val activity = activity ?: return
launchIO {
val categories = presenter.getCategories()
val defaultCategoryId = preferences.defaultCategory()
val defaultCategory = categories.find { it.id == defaultCategoryId }
val defaultCategory = categories.find { it.id == defaultCategoryId.toLong() }
withUIContext {
when {
// Default category set
defaultCategory != null -> {
presenter.moveMangaToCategory(newManga, defaultCategory)
presenter.moveMangaToCategory(newManga, defaultCategory.toDbCategory())
presenter.changeMangaFavorite(newManga)
adapter?.notifyItemChanged(position)
@ -849,11 +852,13 @@ open class BrowseSourceController(bundle: Bundle) :
}
}.toTypedArray()
ChangeMangaCategoriesDialog(this, listOf(newManga), categories, preselected)
ChangeMangaCategoriesDialog(this@BrowseSourceController, listOf(newManga), categories.map { it.toDbCategory() }, preselected)
.showDialog(router)
}
}
}
}
}
/**
* Update manga to use selected categories.

View File

@ -4,6 +4,7 @@ import android.os.Bundle
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.data.DatabaseHandler
import eu.kanade.data.exh.savedSearchMapper
import eu.kanade.domain.category.interactor.GetCategories
import eu.kanade.domain.manga.interactor.GetDuplicateLibraryManga
import eu.kanade.domain.manga.model.toDbManga
import eu.kanade.tachiyomi.data.cache.CoverCache
@ -55,6 +56,7 @@ import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
@ -70,8 +72,8 @@ import rx.schedulers.Schedulers
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import xyz.nulldev.ts.api.http.serializer.FilterSerializer
import java.lang.RuntimeException
import java.util.Date
import eu.kanade.domain.category.model.Category as DomainCategory
open class BrowseSourcePresenter(
private val sourceId: Long,
@ -86,6 +88,7 @@ open class BrowseSourcePresenter(
private val prefs: PreferencesHelper = Injekt.get(),
private val coverCache: CoverCache = Injekt.get(),
private val getDuplicateLibraryManga: GetDuplicateLibraryManga = Injekt.get(),
private val getCategories: GetCategories = Injekt.get(),
) : BasePresenter<BrowseSourceController>() {
/**
@ -437,8 +440,8 @@ open class BrowseSourcePresenter(
*
* @return List of categories, not including the default category
*/
fun getCategories(): List<Category> {
return db.getCategories().executeAsBlocking()
suspend fun getCategories(): List<DomainCategory> {
return getCategories.subscribe().firstOrNull() ?: emptyList()
}
suspend fun getDuplicateLibraryManga(manga: Manga): Manga? {
@ -451,9 +454,9 @@ open class BrowseSourcePresenter(
* @param manga the manga to get categories from.
* @return Array of category ids the manga is in, if none returns default id
*/
fun getMangaCategoryIds(manga: Manga): Array<Int?> {
fun getMangaCategoryIds(manga: Manga): Array<Long?> {
val categories = db.getCategoriesForManga(manga).executeAsBlocking()
return categories.mapNotNull { it.id }.toTypedArray()
return categories.mapNotNull { it?.id?.toLong() }.toTypedArray()
}
/**

View File

@ -35,6 +35,7 @@ import dev.chrisbanes.insetter.applyInsetter
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.SelectableAdapter
import eu.kanade.data.chapter.NoChaptersException
import eu.kanade.domain.category.model.toDbCategory
import eu.kanade.domain.history.model.HistoryWithRelations
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.cache.CoverCache
@ -116,6 +117,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import logcat.LogPriority
import reactivecircus.flowbinding.recyclerview.scrollStateChanges
@ -478,13 +480,15 @@ class MangaController :
}
override fun onPrepareOptionsMenu(menu: Menu) {
runBlocking {
// Hide options for local manga
menu.findItem(R.id.action_share).isVisible = !isLocalSource
menu.findItem(R.id.download_group).isVisible = !isLocalSource
// Hide options for non-library manga
menu.findItem(R.id.action_edit_categories).isVisible = presenter.manga.favorite && presenter.getCategories().isNotEmpty()
menu.findItem(R.id.action_migrate).isVisible = presenter.manga.favorite /* SY --> */ && presenter.manga.source != MERGED_SOURCE_ID // SY <--
menu.findItem(R.id.action_edit_categories).isVisible =
presenter.manga.favorite && presenter.getCategories().isNotEmpty()
menu.findItem(R.id.action_migrate).isVisible = presenter.manga.favorite
// SY -->
menu.findItem(R.id.action_edit).isVisible = presenter.manga.favorite || isLocalSource
@ -493,6 +497,7 @@ class MangaController :
menu.findItem(R.id.action_toggle_dedupe).isVisible = false // presenter.manga.source == MERGED_SOURCE_ID
// SY <--
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
@ -666,15 +671,17 @@ class MangaController :
}
private fun addToLibrary(newManga: Manga) {
launchIO {
val categories = presenter.getCategories()
val defaultCategoryId = preferences.defaultCategory()
val defaultCategory = categories.find { it.id == defaultCategoryId }
val defaultCategory = categories.find { it.id == defaultCategoryId.toLong() }
withUIContext {
when {
// Default category set
defaultCategory != null -> {
toggleFavorite()
presenter.moveMangaToCategory(newManga, defaultCategory)
presenter.moveMangaToCategory(newManga, defaultCategory.toDbCategory())
activity?.toast(activity?.getString(R.string.manga_added_library))
activity?.invalidateOptionsMenu()
}
@ -698,7 +705,13 @@ class MangaController :
}
}.toTypedArray()
showChangeCategoryDialog(newManga, categories, preselected)
showChangeCategoryDialog(
newManga,
categories.map { it.toDbCategory() },
preselected,
)
}
}
}
}
@ -813,9 +826,14 @@ class MangaController :
}
fun onCategoriesClick() {
launchIO {
val manga = presenter.manga
val categories = presenter.getCategories()
if (categories.isEmpty()) {
return@launchIO
}
val ids = presenter.getMangaCategoryIds(manga)
val preselected = categories.map {
if (it.id in ids) {
@ -824,7 +842,11 @@ class MangaController :
QuadStateTextView.State.UNCHECKED.ordinal
}
}.toTypedArray()
showChangeCategoryDialog(manga, categories, preselected)
withUIContext {
showChangeCategoryDialog(manga, categories.map { it.toDbCategory() }, preselected)
}
}
}
private fun showChangeCategoryDialog(manga: Manga, categories: List<Category>, preselected: Array<Int>) {

View File

@ -4,6 +4,7 @@ import android.content.Context
import android.net.Uri
import android.os.Bundle
import com.jakewharton.rxrelay.PublishRelay
import eu.kanade.domain.category.interactor.GetCategories
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
import eu.kanade.domain.chapter.interactor.GetMergedChapterByMangaId
import eu.kanade.domain.chapter.model.toDbChapter
@ -76,6 +77,7 @@ import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
@ -91,6 +93,7 @@ import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.util.Date
import eu.kanade.domain.category.model.Category as DomainCategory
class MangaPresenter(
val manga: Manga,
@ -103,6 +106,7 @@ class MangaPresenter(
private val sourceManager: SourceManager = Injekt.get(),
private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
private val getDuplicateLibraryManga: GetDuplicateLibraryManga = Injekt.get(),
private val getCategories: GetCategories = Injekt.get(),
private val getMergedChapterByMangaId: GetMergedChapterByMangaId = Injekt.get(),
) : BasePresenter<MangaController>() {
@ -585,8 +589,8 @@ class MangaPresenter(
*
* @return List of categories, not including the default category
*/
fun getCategories(): List<Category> {
return db.getCategories().executeAsBlocking()
suspend fun getCategories(): List<DomainCategory> {
return getCategories.subscribe().firstOrNull() ?: emptyList()
}
/**
@ -595,9 +599,9 @@ class MangaPresenter(
* @param manga the manga to get categories from.
* @return Array of category ids the manga is in, if none returns default id
*/
fun getMangaCategoryIds(manga: Manga): Array<Int> {
fun getMangaCategoryIds(manga: Manga): Array<Long> {
val categories = db.getCategoriesForManga(manga).executeAsBlocking()
return categories.mapNotNull { it.id }.toTypedArray()
return categories.mapNotNull { it?.id?.toLong() }.toTypedArray()
}
/**
@ -1041,14 +1045,14 @@ class MangaPresenter(
/**
* Whether downloaded only mode is enabled.
*/
fun forceDownloaded(): Boolean {
private fun forceDownloaded(): Boolean {
return manga.favorite && preferences.downloadedOnly().get()
}
/**
* Whether the display only downloaded filter is enabled.
*/
fun onlyDownloaded(): State {
private fun onlyDownloaded(): State {
if (forceDownloaded()) {
return State.INCLUDE
}
@ -1062,7 +1066,7 @@ class MangaPresenter(
/**
* Whether the display only downloaded filter is enabled.
*/
fun onlyBookmarked(): State {
private fun onlyBookmarked(): State {
return when (manga.bookmarkedFilter) {
Manga.CHAPTER_SHOW_BOOKMARKED -> State.INCLUDE
Manga.CHAPTER_SHOW_NOT_BOOKMARKED -> State.EXCLUDE
@ -1073,7 +1077,7 @@ class MangaPresenter(
/**
* Whether the display only unread filter is enabled.
*/
fun onlyUnread(): State {
private fun onlyUnread(): State {
return when (manga.readFilter) {
Manga.CHAPTER_SHOW_UNREAD -> State.INCLUDE
Manga.CHAPTER_SHOW_READ -> State.EXCLUDE

View File

@ -136,7 +136,7 @@ class MangaInfoHeaderAdapter(
.onEach { controller.onFavoriteClick() }
.launchIn(controller.viewScope)
if (controller.presenter.manga.favorite && controller.presenter.getCategories().isNotEmpty()) {
if (controller.presenter.manga.favorite) {
binding.btnFavorite.longClicks()
.onEach { controller.onCategoriesClick() }
.launchIn(controller.viewScope)