mirror of
https://github.com/null2264/yokai.git
synced 2025-06-20 18:24:42 +00:00
refactor(db): Migrate getManga queries to SQLDelight
This commit is contained in:
parent
312f9e197b
commit
aae9a68c8b
14 changed files with 65 additions and 67 deletions
|
@ -4,12 +4,9 @@ import android.content.Context
|
|||
import android.text.format.Formatter
|
||||
import co.touchlab.kermit.Logger
|
||||
import coil3.imageLoader
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.updateCoverLastModified
|
||||
import eu.kanade.tachiyomi.domain.manga.models.Manga
|
||||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||
import eu.kanade.tachiyomi.util.system.e
|
||||
import eu.kanade.tachiyomi.util.system.executeOnIO
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import eu.kanade.tachiyomi.util.system.withIOContext
|
||||
import eu.kanade.tachiyomi.util.system.withUIContext
|
||||
|
@ -19,8 +16,8 @@ import java.io.InputStream
|
|||
import java.util.concurrent.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import yokai.domain.manga.interactor.GetManga
|
||||
import yokai.i18n.MR
|
||||
import yokai.util.lang.getString
|
||||
|
||||
|
@ -40,6 +37,8 @@ class CoverCache(val context: Context) {
|
|||
private const val ONLINE_COVERS_DIR = "online_covers"
|
||||
}
|
||||
|
||||
private val getManga: GetManga by injectLazy()
|
||||
|
||||
/** Cache directory used for cache management.*/
|
||||
private val cacheDir = getCacheDir(COVERS_DIR)
|
||||
|
||||
|
@ -68,9 +67,8 @@ class CoverCache(val context: Context) {
|
|||
}
|
||||
|
||||
suspend fun deleteOldCovers() {
|
||||
val db = Injekt.get<DatabaseHelper>()
|
||||
var deletedSize = 0L
|
||||
val urls = db.getFavoriteMangas().executeOnIO().mapNotNull {
|
||||
val urls = getManga.awaitFavorites().mapNotNull {
|
||||
it.thumbnail_url?.let { url ->
|
||||
it.updateCoverLastModified()
|
||||
return@mapNotNull DiskUtil.hashKeyForDisk(url)
|
||||
|
|
|
@ -10,29 +10,6 @@ import eu.kanade.tachiyomi.domain.manga.models.Manga
|
|||
|
||||
interface MangaQueries : DbProvider {
|
||||
|
||||
fun getFavoriteMangas() = db.get()
|
||||
.listOfObjects(Manga::class.java)
|
||||
.withQuery(
|
||||
Query.builder()
|
||||
.table(MangaTable.TABLE)
|
||||
.where("${MangaTable.COL_FAVORITE} = ?")
|
||||
.whereArgs(1)
|
||||
.orderBy(MangaTable.COL_TITLE)
|
||||
.build(),
|
||||
)
|
||||
.prepare()
|
||||
|
||||
fun getManga(url: String, sourceId: Long) = db.get()
|
||||
.`object`(Manga::class.java)
|
||||
.withQuery(
|
||||
Query.builder()
|
||||
.table(MangaTable.TABLE)
|
||||
.where("${MangaTable.COL_URL} = ? AND ${MangaTable.COL_SOURCE} = ?")
|
||||
.whereArgs(url, sourceId)
|
||||
.build(),
|
||||
)
|
||||
.prepare()
|
||||
|
||||
fun getManga(id: Long) = db.get()
|
||||
.`object`(Manga::class.java)
|
||||
.withQuery(
|
||||
|
|
|
@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.data.download
|
|||
|
||||
import android.content.Context
|
||||
import com.hippo.unifile.UniFile
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||
import eu.kanade.tachiyomi.domain.manga.models.Manga
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
|
@ -118,6 +117,7 @@ class DownloadProvider(private val context: Context) {
|
|||
* @param manga the manga of the chapter.
|
||||
* @param source the source of the chapter.
|
||||
*/
|
||||
/*
|
||||
fun renameChapters() {
|
||||
val db by injectLazy<DatabaseHelper>()
|
||||
val sourceManager by injectLazy<SourceManager>()
|
||||
|
@ -136,6 +136,7 @@ class DownloadProvider(private val context: Context) {
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
fun renameMangaFolder(from: String, to: String, sourceId: Long) {
|
||||
val sourceManager by injectLazy<SourceManager>()
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
package eu.kanade.tachiyomi.smartsearch
|
||||
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.create
|
||||
import eu.kanade.tachiyomi.domain.manga.models.Manga
|
||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.util.lang.toNormalized
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.supervisorScope
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import yokai.domain.manga.interactor.GetManga
|
||||
import yokai.domain.manga.interactor.InsertManga
|
||||
import yokai.util.normalizedLevenshteinSimilarity
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class SmartSearchEngine(
|
||||
parentContext: CoroutineContext,
|
||||
|
@ -20,7 +21,8 @@ class SmartSearchEngine(
|
|||
) : CoroutineScope {
|
||||
override val coroutineContext: CoroutineContext = parentContext + Job() + Dispatchers.Default
|
||||
|
||||
private val db: DatabaseHelper by injectLazy()
|
||||
private val getManga: GetManga by injectLazy()
|
||||
private val insertManga: InsertManga by injectLazy()
|
||||
|
||||
/*suspend fun smartSearch(source: CatalogueSource, title: String): SManga? {
|
||||
val cleanedTitle = cleanSmartSearchTitle(title)
|
||||
|
@ -129,12 +131,11 @@ class SmartSearchEngine(
|
|||
* @return a manga from the database.
|
||||
*/
|
||||
suspend fun networkToLocalManga(sManga: SManga, sourceId: Long): Manga {
|
||||
var localManga = db.getManga(sManga.url, sourceId).executeAsBlocking()
|
||||
var localManga = getManga.awaitByUrlAndSource(sManga.url, sourceId)
|
||||
if (localManga == null) {
|
||||
val newManga = Manga.create(sManga.url, sManga.title, sourceId)
|
||||
newManga.copyFrom(sManga)
|
||||
val result = db.insertManga(newManga).executeAsBlocking()
|
||||
newManga.id = result.insertedId()
|
||||
newManga.id = insertManga.await(newManga)
|
||||
localManga = newManga
|
||||
}
|
||||
return localManga
|
||||
|
|
|
@ -9,6 +9,8 @@ import eu.kanade.tachiyomi.domain.manga.models.Manga
|
|||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import yokai.domain.chapter.interactor.GetChapter
|
||||
import yokai.domain.manga.interactor.GetManga
|
||||
|
||||
abstract class DelegatedHttpSource {
|
||||
|
||||
|
@ -16,6 +18,8 @@ abstract class DelegatedHttpSource {
|
|||
abstract val domainName: String
|
||||
|
||||
protected val db: DatabaseHelper by injectLazy()
|
||||
protected val getChapter: GetChapter by injectLazy()
|
||||
protected val getManga: GetManga by injectLazy()
|
||||
|
||||
protected val network: NetworkHelper by injectLazy()
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
|||
import eu.kanade.tachiyomi.domain.manga.models.Manga
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.online.DelegatedHttpSource
|
||||
import eu.kanade.tachiyomi.util.system.executeOnIO
|
||||
import java.util.Locale
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.withContext
|
||||
|
@ -15,7 +15,6 @@ import uy.kohesive.injekt.Injekt
|
|||
import uy.kohesive.injekt.api.get
|
||||
import yokai.i18n.MR
|
||||
import yokai.util.lang.getString
|
||||
import java.util.*
|
||||
|
||||
class Cubari : DelegatedHttpSource() {
|
||||
override val domainName: String = "cubari"
|
||||
|
@ -32,11 +31,11 @@ class Cubari : DelegatedHttpSource() {
|
|||
val mangaUrl = "/read/$cubariType/$cubariPath"
|
||||
return withContext(Dispatchers.IO) {
|
||||
val deferredManga = async {
|
||||
db.getManga(mangaUrl, delegate?.id!!).executeAsBlocking() ?: getMangaInfo(mangaUrl)
|
||||
getManga.awaitByUrlAndSource(mangaUrl, delegate?.id!!) ?: getMangaInfo(mangaUrl)
|
||||
}
|
||||
val deferredChapters = async {
|
||||
db.getManga(mangaUrl, delegate?.id!!).executeAsBlocking()?.let { manga ->
|
||||
val chapters = db.getChapters(manga).executeOnIO()
|
||||
getManga.awaitByUrlAndSource(mangaUrl, delegate?.id!!)?.let { manga ->
|
||||
val chapters = getChapter.awaitAll(manga, false)
|
||||
val chapter = findChapter(chapters, cubariType, chapterNumber)
|
||||
if (chapter != null) {
|
||||
return@async chapters
|
||||
|
|
|
@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.network.await
|
|||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.online.DelegatedHttpSource
|
||||
import java.util.Locale
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.withContext
|
||||
|
@ -21,7 +22,6 @@ import uy.kohesive.injekt.api.get
|
|||
import uy.kohesive.injekt.injectLazy
|
||||
import yokai.i18n.MR
|
||||
import yokai.util.lang.getString
|
||||
import java.util.*
|
||||
|
||||
class MangaDex : DelegatedHttpSource() {
|
||||
|
||||
|
@ -64,7 +64,7 @@ class MangaDex : DelegatedHttpSource() {
|
|||
val mangaUrl = "/manga/$mangaId/"
|
||||
return withContext(Dispatchers.IO) {
|
||||
val deferredManga = async {
|
||||
db.getManga(mangaUrl, delegate?.id!!).executeAsBlocking() ?: getMangaInfo(mangaUrl)
|
||||
getManga.awaitByUrlAndSource(mangaUrl, delegate?.id!!) ?: getMangaInfo(mangaUrl)
|
||||
}
|
||||
val deferredChapters = async { getChapters(mangaUrl) }
|
||||
val manga = deferredManga.await()
|
||||
|
|
|
@ -63,9 +63,8 @@ open class FoolSlide(override val domainName: String, private val urlModifier: S
|
|||
return withContext(Dispatchers.IO) {
|
||||
val mangaUrl = "$urlModifier/series/$mangaName/"
|
||||
val sourceId = delegate?.id ?: return@withContext null
|
||||
val dbManga = db.getManga(mangaUrl, sourceId).executeAsBlocking()
|
||||
val deferredManga = async {
|
||||
dbManga ?: getManga(mangaUrl)
|
||||
getManga.awaitByUrlAndSource(mangaUrl, sourceId) ?: getManga(mangaUrl)
|
||||
}
|
||||
val chapterUrl = chapterUrl(uri)
|
||||
val deferredChapters = async { getChapters(mangaUrl) }
|
||||
|
|
|
@ -53,7 +53,7 @@ class MangaPlus : DelegatedHttpSource() {
|
|||
val trimmedTitle = title.substring(0, title.length - 1)
|
||||
val mangaUrl = "#/titles/$titleId"
|
||||
val deferredManga = async {
|
||||
db.getManga(mangaUrl, delegate?.id!!).executeAsBlocking() ?: getMangaInfo(mangaUrl)
|
||||
getManga.awaitByUrlAndSource(mangaUrl, delegate?.id!!) ?: getMangaInfo(mangaUrl)
|
||||
}
|
||||
val deferredChapters = async { getChapters(mangaUrl) }
|
||||
val manga = deferredManga.await()
|
||||
|
|
|
@ -9,7 +9,6 @@ import eu.kanade.tachiyomi.source.LocalSource
|
|||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.ui.base.presenter.BaseCoroutinePresenter
|
||||
import eu.kanade.tachiyomi.util.system.executeOnIO
|
||||
import eu.kanade.tachiyomi.util.system.withUIContext
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -17,6 +16,7 @@ import kotlinx.coroutines.withContext
|
|||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import yokai.domain.manga.interactor.GetManga
|
||||
import yokai.domain.ui.UiPreferences
|
||||
|
||||
abstract class BaseMigrationPresenter<T : BaseMigrationInterface>(
|
||||
|
@ -25,6 +25,8 @@ abstract class BaseMigrationPresenter<T : BaseMigrationInterface>(
|
|||
val uiPreferences: UiPreferences = Injekt.get(),
|
||||
val preferences: PreferencesHelper = Injekt.get(),
|
||||
) : BaseCoroutinePresenter<T>() {
|
||||
private val getManga: GetManga by injectLazy()
|
||||
|
||||
private var selectedSource: Pair<String, Long>? = null
|
||||
var sourceItems = emptyList<SourceItem>()
|
||||
protected set
|
||||
|
@ -35,7 +37,7 @@ abstract class BaseMigrationPresenter<T : BaseMigrationInterface>(
|
|||
|
||||
fun refreshMigrations() {
|
||||
presenterScope.launch {
|
||||
val favs = db.getFavoriteMangas().executeOnIO()
|
||||
val favs = getManga.awaitFavorites()
|
||||
sourceItems = findSourcesWithManga(favs)
|
||||
mangaItems = HashMap(
|
||||
sourceItems.associate {
|
||||
|
@ -92,7 +94,7 @@ abstract class BaseMigrationPresenter<T : BaseMigrationInterface>(
|
|||
}
|
||||
|
||||
protected suspend fun firstTimeMigration() {
|
||||
val favs = db.getFavoriteMangas().executeOnIO()
|
||||
val favs = getManga.awaitFavorites()
|
||||
sourceItems = findSourcesWithManga(favs)
|
||||
mangaItems = HashMap(
|
||||
sourceItems.associate {
|
||||
|
|
|
@ -9,10 +9,6 @@ import androidx.core.view.doOnNextLayout
|
|||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.kanade.tachiyomi.R
|
||||
import yokai.i18n.MR
|
||||
import yokai.util.lang.getString
|
||||
import dev.icerock.moko.resources.compose.stringResource
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.databinding.MigrationControllerBinding
|
||||
|
@ -28,6 +24,9 @@ import kotlinx.coroutines.Dispatchers
|
|||
import kotlinx.coroutines.withContext
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import yokai.domain.manga.interactor.GetManga
|
||||
import yokai.i18n.MR
|
||||
import yokai.util.lang.getString
|
||||
|
||||
class MigrationController :
|
||||
BaseCoroutineController<MigrationControllerBinding, MigrationPresenter>(),
|
||||
|
@ -95,7 +94,7 @@ class MigrationController :
|
|||
val item = adapter?.getItem(position) as? SourceItem ?: return
|
||||
|
||||
launchUI {
|
||||
val manga = Injekt.get<DatabaseHelper>().getFavoriteMangas().executeAsBlocking()
|
||||
val manga = Injekt.get<GetManga>().awaitFavorites()
|
||||
val sourceMangas =
|
||||
manga.asSequence().filter { it.source == item.source.id }.map { it.id!! }.toList()
|
||||
withContext(Dispatchers.Main) {
|
||||
|
|
|
@ -39,6 +39,11 @@ import kotlinx.coroutines.flow.map
|
|||
import kotlinx.coroutines.flow.onEach
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import yokai.domain.manga.interactor.GetManga
|
||||
import yokai.domain.manga.interactor.InsertManga
|
||||
import yokai.domain.manga.interactor.UpdateManga
|
||||
import yokai.domain.manga.models.MangaUpdate
|
||||
import yokai.domain.ui.UiPreferences
|
||||
|
||||
/**
|
||||
|
@ -54,6 +59,9 @@ open class BrowseSourcePresenter(
|
|||
val preferences: PreferencesHelper = Injekt.get(),
|
||||
private val coverCache: CoverCache = Injekt.get(),
|
||||
) : BaseCoroutinePresenter<BrowseSourceController>() {
|
||||
private val getManga: GetManga by injectLazy()
|
||||
private val insertManga: InsertManga by injectLazy()
|
||||
private val updateManga: UpdateManga by injectLazy()
|
||||
|
||||
/**
|
||||
* Selected source.
|
||||
|
@ -225,17 +233,21 @@ open class BrowseSourcePresenter(
|
|||
* @param sManga the manga from the source.
|
||||
* @return a manga from the database.
|
||||
*/
|
||||
private fun networkToLocalManga(sManga: SManga, sourceId: Long): Manga {
|
||||
var localManga = db.getManga(sManga.url, sourceId).executeAsBlocking()
|
||||
private suspend fun networkToLocalManga(sManga: SManga, sourceId: Long): Manga {
|
||||
var localManga = getManga.awaitByUrlAndSource(sManga.url, sourceId)
|
||||
if (localManga == null) {
|
||||
val newManga = Manga.create(sManga.url, sManga.title, sourceId)
|
||||
newManga.copyFrom(sManga)
|
||||
val result = db.insertManga(newManga).executeAsBlocking()
|
||||
newManga.id = result.insertedId()
|
||||
newManga.id = insertManga.await(newManga)
|
||||
localManga = newManga
|
||||
} else if (localManga.title.isBlank()) {
|
||||
localManga.title = sManga.title
|
||||
db.insertManga(localManga).executeAsBlocking()
|
||||
updateManga.await(
|
||||
MangaUpdate(
|
||||
id = localManga.id!!,
|
||||
title = sManga.title,
|
||||
)
|
||||
)
|
||||
} else if (!localManga.favorite) {
|
||||
// if the manga isn't a favorite, set its display title from source
|
||||
// if it later becomes a favorite, updated title will go to db
|
||||
|
@ -273,7 +285,7 @@ open class BrowseSourcePresenter(
|
|||
val networkManga = source.getMangaDetails(manga.copy())
|
||||
manga.copyFrom(networkManga)
|
||||
manga.initialized = true
|
||||
db.insertManga(manga).executeAsBlocking()
|
||||
updateManga.await(manga.toMangaUpdate())
|
||||
} catch (e: Exception) {
|
||||
Logger.e(e) { "Something went wrong while trying to initialize manga" }
|
||||
}
|
||||
|
|
|
@ -29,6 +29,9 @@ import kotlinx.coroutines.sync.withPermit
|
|||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import yokai.domain.manga.interactor.GetManga
|
||||
import yokai.domain.manga.interactor.InsertManga
|
||||
import yokai.domain.manga.interactor.UpdateManga
|
||||
|
||||
/**
|
||||
* Presenter of [GlobalSearchController]
|
||||
|
@ -47,6 +50,9 @@ open class GlobalSearchPresenter(
|
|||
private val preferences: PreferencesHelper = Injekt.get(),
|
||||
private val coverCache: CoverCache = Injekt.get(),
|
||||
) : BaseCoroutinePresenter<GlobalSearchController>() {
|
||||
private val getManga: GetManga by injectLazy()
|
||||
private val insertManga: InsertManga by injectLazy()
|
||||
private val updateManga: UpdateManga by injectLazy()
|
||||
|
||||
/**
|
||||
* Enabled sources.
|
||||
|
@ -256,7 +262,7 @@ open class GlobalSearchPresenter(
|
|||
val networkManga = source.getMangaDetails(manga.copy())
|
||||
manga.copyFrom(networkManga)
|
||||
manga.initialized = true
|
||||
db.insertManga(manga).executeAsBlocking()
|
||||
updateManga.await(manga.toMangaUpdate())
|
||||
return manga
|
||||
}
|
||||
|
||||
|
@ -267,13 +273,12 @@ open class GlobalSearchPresenter(
|
|||
* @param sManga the manga from the source.
|
||||
* @return a manga from the database.
|
||||
*/
|
||||
protected open fun networkToLocalManga(sManga: SManga, sourceId: Long): Manga {
|
||||
var localManga = db.getManga(sManga.url, sourceId).executeAsBlocking()
|
||||
protected open suspend fun networkToLocalManga(sManga: SManga, sourceId: Long): Manga {
|
||||
var localManga = getManga.awaitByUrlAndSource(sManga.url, sourceId)
|
||||
if (localManga == null) {
|
||||
val newManga = Manga.create(sManga.url, sManga.title, sourceId)
|
||||
newManga.copyFrom(sManga)
|
||||
val result = db.insertManga(newManga).executeAsBlocking()
|
||||
newManga.id = result.insertedId()
|
||||
newManga.id = insertManga.await(newManga)
|
||||
localManga = newManga
|
||||
} else if (!localManga.favorite) {
|
||||
// if the manga isn't a favorite, set its display title from source
|
||||
|
|
|
@ -48,7 +48,8 @@ WHERE favorite = 1 AND lower(title) = :title AND source != :source;
|
|||
findFavorites:
|
||||
SELECT *
|
||||
FROM mangas
|
||||
WHERE favorite = 1;
|
||||
WHERE favorite = 1
|
||||
ORDER BY title;
|
||||
|
||||
findReadNotFavorites:
|
||||
SELECT *
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue