Use SQLDelight for all Manga related queries (#7447)

This commit is contained in:
Andreas
2022-07-03 16:17:41 +02:00
committed by GitHub
parent 6d6237e370
commit 17951cfd68
42 changed files with 343 additions and 753 deletions

View File

@@ -6,8 +6,9 @@ import androidx.core.view.isVisible
import com.bluelinelabs.conductor.Controller
import com.bluelinelabs.conductor.RouterTransaction
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import eu.kanade.domain.manga.interactor.GetManga
import eu.kanade.domain.manga.model.toDbManga
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.toDomainManga
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
@@ -18,6 +19,7 @@ import eu.kanade.tachiyomi.ui.browse.migration.MigrationFlags
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchController
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchPresenter
import eu.kanade.tachiyomi.ui.manga.MangaController
import kotlinx.coroutines.runBlocking
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
@@ -27,9 +29,11 @@ class SearchController(
) : GlobalSearchController(manga?.title) {
constructor(mangaId: Long) : this(
Injekt.get<DatabaseHelper>()
.getManga(mangaId)
.executeAsBlocking(),
runBlocking {
Injekt.get<GetManga>()
.await(mangaId)
?.toDbManga()
},
)
private var newManga: Manga? = null

View File

@@ -7,11 +7,14 @@ import eu.kanade.domain.category.interactor.SetMangaCategories
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
import eu.kanade.domain.manga.interactor.GetDuplicateLibraryManga
import eu.kanade.domain.manga.interactor.GetManga
import eu.kanade.domain.manga.interactor.InsertManga
import eu.kanade.domain.manga.interactor.UpdateManga
import eu.kanade.domain.manga.model.toDbManga
import eu.kanade.domain.manga.model.toMangaUpdate
import eu.kanade.domain.track.interactor.InsertTrack
import eu.kanade.domain.track.model.toDomainTrack
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.toDomainManga
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
@@ -67,13 +70,15 @@ open class BrowseSourcePresenter(
private val sourceId: Long,
searchQuery: String? = null,
private val sourceManager: SourceManager = Injekt.get(),
private val db: DatabaseHelper = Injekt.get(),
private val prefs: PreferencesHelper = Injekt.get(),
private val coverCache: CoverCache = Injekt.get(),
private val getManga: GetManga = Injekt.get(),
private val getDuplicateLibraryManga: GetDuplicateLibraryManga = Injekt.get(),
private val getCategories: GetCategories = Injekt.get(),
private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
private val setMangaCategories: SetMangaCategories = Injekt.get(),
private val insertManga: InsertManga = Injekt.get(),
private val updateManga: UpdateManga = Injekt.get(),
private val insertTrack: InsertTrack = Injekt.get(),
private val syncChaptersWithTrackServiceTwoWay: SyncChaptersWithTrackServiceTwoWay = Injekt.get(),
) : BasePresenter<BrowseSourceController>() {
@@ -208,19 +213,22 @@ open class BrowseSourcePresenter(
* @return a manga from the database.
*/
private fun networkToLocalManga(sManga: SManga, sourceId: Long): Manga {
var localManga = db.getManga(sManga.url, sourceId).executeAsBlocking()
var localManga = runBlocking { getManga.await(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()
localManga = newManga
newManga.id = -1
val result = runBlocking {
val id = insertManga.await(newManga.toDomainManga()!!)
getManga.await(id!!)
}
localManga = result
} 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
localManga.title = sManga.title
localManga = localManga.copy(title = sManga.title)
}
return localManga
return localManga?.toDbManga()!!
}
/**
@@ -255,7 +263,11 @@ open class BrowseSourcePresenter(
val networkManga = source.getMangaDetails(manga.toMangaInfo())
manga.copyFrom(networkManga.toSManga())
manga.initialized = true
db.insertManga(manga).executeAsBlocking()
updateManga.await(
manga
.toDomainManga()
?.toMangaUpdate()!!,
)
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
}
@@ -282,7 +294,13 @@ open class BrowseSourcePresenter(
autoAddTrack(manga)
}
db.insertManga(manga).executeAsBlocking()
runBlocking {
updateManga.await(
manga
.toDomainManga()
?.toMangaUpdate()!!,
)
}
}
private fun autoAddTrack(manga: Manga) {

View File

@@ -1,8 +1,13 @@
package eu.kanade.tachiyomi.ui.browse.source.globalsearch
import android.os.Bundle
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.domain.manga.interactor.GetManga
import eu.kanade.domain.manga.interactor.InsertManga
import eu.kanade.domain.manga.interactor.UpdateManga
import eu.kanade.domain.manga.model.toDbManga
import eu.kanade.domain.manga.model.toMangaUpdate
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.toDomainManga
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.extension.ExtensionManager
@@ -16,6 +21,7 @@ import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter
import eu.kanade.tachiyomi.util.lang.runAsObservable
import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.runBlocking
import logcat.LogPriority
import rx.Observable
import rx.Subscription
@@ -38,8 +44,10 @@ open class GlobalSearchPresenter(
private val initialQuery: String? = "",
private val initialExtensionFilter: String? = null,
val sourceManager: SourceManager = Injekt.get(),
val db: DatabaseHelper = Injekt.get(),
val preferences: PreferencesHelper = Injekt.get(),
private val getManga: GetManga = Injekt.get(),
private val insertManga: InsertManga = Injekt.get(),
private val updateManga: UpdateManga = Injekt.get(),
) : BasePresenter<GlobalSearchController>() {
/**
@@ -248,7 +256,7 @@ open class GlobalSearchPresenter(
val networkManga = source.getMangaDetails(manga.toMangaInfo())
manga.copyFrom(networkManga.toSManga())
manga.initialized = true
db.insertManga(manga).executeAsBlocking()
runBlocking { updateManga.await(manga.toDomainManga()!!.toMangaUpdate()) }
return manga
}
@@ -260,18 +268,21 @@ open class GlobalSearchPresenter(
* @return a manga from the database.
*/
protected open fun networkToLocalManga(sManga: SManga, sourceId: Long): Manga {
var localManga = db.getManga(sManga.url, sourceId).executeAsBlocking()
var localManga = runBlocking { getManga.await(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()
localManga = newManga
newManga.id = -1
val result = runBlocking {
val id = insertManga.await(newManga.toDomainManga()!!)
getManga.await(id!!)
}
localManga = result
} 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
localManga.title = sManga.title
localManga = localManga.copy(title = sManga.title)
}
return localManga
return localManga!!.toDbManga()
}
}

View File

@@ -11,13 +11,13 @@ import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
import eu.kanade.domain.chapter.interactor.UpdateChapter
import eu.kanade.domain.chapter.model.ChapterUpdate
import eu.kanade.domain.chapter.model.toDbChapter
import eu.kanade.domain.manga.interactor.GetLibraryManga
import eu.kanade.domain.manga.interactor.UpdateManga
import eu.kanade.domain.manga.model.Manga
import eu.kanade.domain.manga.model.MangaUpdate
import eu.kanade.domain.track.interactor.GetTracks
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.LibraryManga
import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.track.TrackManager
@@ -60,6 +60,7 @@ typealias LibraryMap = Map<Long, List<LibraryItem>>
*/
class LibraryPresenter(
private val handler: DatabaseHandler = Injekt.get(),
private val getLibraryManga: GetLibraryManga = Injekt.get(),
private val getTracks: GetTracks = Injekt.get(),
private val getCategories: GetCategories = Injekt.get(),
private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
@@ -410,35 +411,7 @@ class LibraryPresenter(
val defaultLibraryDisplayMode = preferences.libraryDisplayMode()
val shouldSetFromCategory = preferences.categorizedDisplaySettings()
// TODO: Move this to domain/data layer
return handler
.subscribeToList {
mangasQueries.getLibrary { _id: Long, source: Long, url: String, artist: String?, author: String?, description: String?, genre: List<String>?, title: String, status: Long, thumbnail_url: String?, favorite: Boolean, last_update: Long?, next_update: Long?, initialized: Boolean, viewer: Long, chapter_flags: Long, cover_last_modified: Long, date_added: Long, unread_count: Long, read_count: Long, category: Long ->
LibraryManga().apply {
this.id = _id
this.source = source
this.url = url
this.artist = artist
this.author = author
this.description = description
this.genre = genre?.joinToString()
this.title = title
this.status = status.toInt()
this.thumbnail_url = thumbnail_url
this.favorite = favorite
this.last_update = last_update ?: 0
this.initialized = initialized
this.viewer_flags = viewer.toInt()
this.chapter_flags = chapter_flags.toInt()
this.cover_last_modified = cover_last_modified
this.date_added = date_added
this.unreadCount = unread_count.toInt()
this.readCount = read_count.toInt()
this.category = category.toInt()
}
}
}
.asObservable()
return getLibraryManga.subscribe().asObservable()
.map { list ->
list.map { libraryManga ->
// Display mode based on user preference: take it from global library setting or category

View File

@@ -149,7 +149,7 @@ class MangaPresenter(
presenterScope.launchIO {
if (!getMangaAndChapters.awaitManga(mangaId).favorite) {
ChapterSettingsHelper.applySettingDefaults(mangaId, setMangaChapterFlags)
ChapterSettingsHelper.applySettingDefaults(mangaId)
}
getMangaAndChapters.subscribe(mangaId)

View File

@@ -20,7 +20,7 @@ import androidx.core.os.bundleOf
import coil.imageLoader
import coil.request.ImageRequest
import coil.size.Size
import eu.kanade.domain.manga.interactor.GetMangaById
import eu.kanade.domain.manga.interactor.GetManga
import eu.kanade.domain.manga.interactor.UpdateManga
import eu.kanade.domain.manga.model.Manga
import eu.kanade.domain.manga.model.hasCustomCover
@@ -161,7 +161,7 @@ class MangaFullCoverDialog : FullComposeController<MangaFullCoverDialog.MangaFul
inner class MangaFullCoverPresenter(
private val mangaId: Long,
private val getMangaById: GetMangaById = Injekt.get(),
private val getManga: GetManga = Injekt.get(),
) : Presenter<MangaFullCoverDialog>() {
private var presenterScope: CoroutineScope = MainScope()
@@ -176,7 +176,7 @@ class MangaFullCoverDialog : FullComposeController<MangaFullCoverDialog.MangaFul
override fun onCreate(savedState: Bundle?) {
super.onCreate(savedState)
presenterScope.launchIO {
getMangaById.subscribe(mangaId)
getManga.subscribe(mangaId)
.collect { _mangaFlow.value = it }
}
}

View File

@@ -11,13 +11,13 @@ import eu.kanade.domain.chapter.model.ChapterUpdate
import eu.kanade.domain.chapter.model.toDbChapter
import eu.kanade.domain.history.interactor.UpsertHistory
import eu.kanade.domain.history.model.HistoryUpdate
import eu.kanade.domain.manga.interactor.GetMangaById
import eu.kanade.domain.manga.interactor.GetManga
import eu.kanade.domain.manga.interactor.SetMangaViewerFlags
import eu.kanade.domain.manga.model.isLocal
import eu.kanade.domain.manga.model.toDbManga
import eu.kanade.domain.track.interactor.GetTracks
import eu.kanade.domain.track.interactor.InsertTrack
import eu.kanade.domain.track.model.toDbTrack
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.toDomainManga
import eu.kanade.tachiyomi.data.download.DownloadManager
@@ -68,17 +68,17 @@ import java.util.concurrent.TimeUnit
* Presenter used by the activity to perform background operations.
*/
class ReaderPresenter(
private val db: DatabaseHelper = Injekt.get(),
private val sourceManager: SourceManager = Injekt.get(),
private val downloadManager: DownloadManager = Injekt.get(),
private val preferences: PreferencesHelper = Injekt.get(),
private val delayedTrackingStore: DelayedTrackingStore = Injekt.get(),
private val getMangaById: GetMangaById = Injekt.get(),
private val getManga: GetManga = Injekt.get(),
private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
private val getTracks: GetTracks = Injekt.get(),
private val insertTrack: InsertTrack = Injekt.get(),
private val upsertHistory: UpsertHistory = Injekt.get(),
private val updateChapter: UpdateChapter = Injekt.get(),
private val setMangaViewerFlags: SetMangaViewerFlags = Injekt.get(),
) : BasePresenter<ReaderActivity>() {
/**
@@ -242,7 +242,7 @@ class ReaderPresenter(
launchIO {
try {
val manga = getMangaById.await(mangaId)
val manga = getManga.await(mangaId)
withUIContext {
manga?.let { init(it.toDbManga(), initialChapterId) }
}
@@ -570,7 +570,9 @@ class ReaderPresenter(
fun setMangaReadingMode(readingModeType: Int) {
val manga = manga ?: return
manga.readingModeType = readingModeType
db.updateViewerFlags(manga).executeAsBlocking()
runBlocking {
setMangaViewerFlags.awaitSetMangaReadingMode(manga.id!!.toLong(), readingModeType.toLong())
}
Observable.timer(250, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
.subscribeFirst({ view, _ ->
@@ -605,7 +607,9 @@ class ReaderPresenter(
fun setMangaOrientationType(rotationType: Int) {
val manga = manga ?: return
manga.orientationType = rotationType
db.updateViewerFlags(manga).executeAsBlocking()
runBlocking {
setMangaViewerFlags.awaitSetOrientationType(manga.id!!.toLong(), rotationType.toLong())
}
logcat(LogPriority.INFO) { "Manga orientation is ${manga.orientationType}" }