mirror of
https://github.com/null2264/yokai.git
synced 2025-06-20 18:24:42 +00:00
refactor(db): Migrate track queries (that can be migrated) to SQLDelight
This commit is contained in:
parent
93ec13f324
commit
726613e6d7
14 changed files with 98 additions and 40 deletions
|
@ -20,8 +20,7 @@ interface TrackQueries : DbProvider {
|
|||
)
|
||||
.prepare()
|
||||
|
||||
fun insertTrack(track: Track) = db.put().`object`(track).prepare()
|
||||
|
||||
// FIXME: Migrate to SQLDelight, on halt: in StorIO transaction
|
||||
fun insertTracks(tracks: List<Track>) = db.put().objects(tracks).prepare()
|
||||
|
||||
}
|
||||
|
|
|
@ -81,12 +81,14 @@ import kotlinx.coroutines.sync.Semaphore
|
|||
import kotlinx.coroutines.sync.withPermit
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import yokai.domain.category.interactor.GetCategories
|
||||
import yokai.domain.chapter.interactor.GetChapter
|
||||
import yokai.domain.manga.interactor.GetLibraryManga
|
||||
import yokai.domain.manga.interactor.UpdateManga
|
||||
import yokai.domain.manga.models.cover
|
||||
import yokai.domain.track.interactor.GetTrack
|
||||
import yokai.domain.track.interactor.InsertTrack
|
||||
import yokai.i18n.MR
|
||||
import yokai.util.lang.getString
|
||||
|
||||
|
@ -107,6 +109,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
|||
private val getLibraryManga: GetLibraryManga = Injekt.get()
|
||||
private val updateManga: UpdateManga = Injekt.get()
|
||||
private val getTrack: GetTrack = Injekt.get()
|
||||
private val insertTrack: InsertTrack by injectLazy()
|
||||
|
||||
private var extraDeferredJobs = mutableListOf<Deferred<Any>>()
|
||||
|
||||
|
@ -322,9 +325,9 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
|||
if (service != null && service in loggedServices) {
|
||||
try {
|
||||
val newTrack = service.refresh(track)
|
||||
db.insertTrack(newTrack).executeAsBlocking()
|
||||
insertTrack.await(newTrack)
|
||||
|
||||
syncChaptersWithTrackServiceTwoWay(db, getChapter.awaitAll(manga.id!!, false), track, service)
|
||||
syncChaptersWithTrackServiceTwoWay(getChapter.awaitAll(manga.id!!, false), track, service)
|
||||
} catch (e: Exception) {
|
||||
Logger.e(e)
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ import androidx.work.WorkerParameters
|
|||
import co.touchlab.kermit.Logger
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.util.system.e
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
@ -21,12 +20,14 @@ import uy.kohesive.injekt.api.get
|
|||
import uy.kohesive.injekt.injectLazy
|
||||
import yokai.domain.manga.interactor.GetManga
|
||||
import yokai.domain.track.interactor.GetTrack
|
||||
import yokai.domain.track.interactor.InsertTrack
|
||||
|
||||
class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters) :
|
||||
CoroutineWorker(context, workerParams) {
|
||||
|
||||
private val getManga: GetManga by injectLazy()
|
||||
private val getTrack: GetTrack by injectLazy()
|
||||
private val insertTrack: InsertTrack by injectLazy()
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
val preferences = Injekt.get<PreferencesHelper>()
|
||||
|
@ -56,7 +57,7 @@ class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters)
|
|||
try {
|
||||
track.last_chapter_read = trackChapter.second
|
||||
service.update(track, true)
|
||||
db.insertTrack(track).executeAsBlocking()
|
||||
insertTrack.await(track)
|
||||
} catch (e: Exception) {
|
||||
Logger.e(e) { "Unable to update tracker [tracker id ${track.sync_id}]" }
|
||||
}
|
||||
|
|
|
@ -2191,7 +2191,7 @@ open class LibraryController(
|
|||
*/
|
||||
private fun showChangeMangaCategoriesSheet() {
|
||||
val activity = activity ?: return
|
||||
selectedMangas.toList().moveCategories(presenter.db, activity) {
|
||||
selectedMangas.toList().moveCategories(activity) {
|
||||
presenter.getLibrary()
|
||||
destroyActionModeIfNeeded()
|
||||
}
|
||||
|
|
|
@ -1634,7 +1634,7 @@ class MangaDetailsController :
|
|||
|
||||
private fun showCategoriesSheet() {
|
||||
val adding = !presenter.manga.favorite
|
||||
presenter.manga.moveCategories(presenter.db, activity!!, adding) {
|
||||
presenter.manga.moveCategories(activity!!, adding) {
|
||||
updateHeader()
|
||||
if (adding) {
|
||||
showAddedSnack()
|
||||
|
|
|
@ -97,6 +97,7 @@ import yokai.domain.manga.models.cover
|
|||
import yokai.domain.storage.StorageManager
|
||||
import yokai.domain.track.interactor.DeleteTrack
|
||||
import yokai.domain.track.interactor.GetTrack
|
||||
import yokai.domain.track.interactor.InsertTrack
|
||||
import yokai.i18n.MR
|
||||
import yokai.util.lang.getString
|
||||
|
||||
|
@ -118,6 +119,7 @@ class MangaDetailsPresenter(
|
|||
private val updateManga: UpdateManga by injectLazy()
|
||||
private val deleteTrack: DeleteTrack by injectLazy()
|
||||
private val getTrack: GetTrack by injectLazy()
|
||||
private val insertTrack: InsertTrack by injectLazy()
|
||||
private val getHistory: GetHistory by injectLazy()
|
||||
|
||||
private val networkPreferences: NetworkPreferences by injectLazy()
|
||||
|
@ -1020,8 +1022,8 @@ class MangaDetailsPresenter(
|
|||
null
|
||||
}
|
||||
if (trackItem != null) {
|
||||
db.insertTrack(trackItem).executeAsBlocking()
|
||||
syncChaptersWithTrackServiceTwoWay(db, chapters, trackItem, item.service)
|
||||
insertTrack.await(trackItem)
|
||||
syncChaptersWithTrackServiceTwoWay(chapters, trackItem, item.service)
|
||||
trackItem
|
||||
} else {
|
||||
item.track
|
||||
|
@ -1061,10 +1063,10 @@ class MangaDetailsPresenter(
|
|||
}
|
||||
withContext(Dispatchers.IO) {
|
||||
if (binding != null) {
|
||||
db.insertTrack(binding).executeAsBlocking()
|
||||
insertTrack.await(binding)
|
||||
}
|
||||
|
||||
syncChaptersWithTrackServiceTwoWay(db, chapters, item, service)
|
||||
syncChaptersWithTrackServiceTwoWay(chapters, item, service)
|
||||
}
|
||||
fetchTracks()
|
||||
}
|
||||
|
@ -1092,7 +1094,7 @@ class MangaDetailsPresenter(
|
|||
null
|
||||
}
|
||||
if (binding != null) {
|
||||
withContext(Dispatchers.IO) { db.insertTrack(binding).executeAsBlocking() }
|
||||
withContext(Dispatchers.IO) { insertTrack.await(binding) }
|
||||
fetchTracks()
|
||||
} else {
|
||||
trackRefreshDone()
|
||||
|
|
|
@ -998,7 +998,7 @@ class ReaderViewModel(
|
|||
|
||||
launchIO {
|
||||
val newChapterRead = readerChapter.chapter.chapter_number
|
||||
val errors = updateTrackChapterRead(db, preferences, manga?.id, newChapterRead, true)
|
||||
val errors = updateTrackChapterRead(preferences, manga?.id, newChapterRead, true)
|
||||
if (errors.isNotEmpty()) {
|
||||
eventChannel.send(Event.ShareTrackingError(errors))
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ import yokai.domain.chapter.interactor.GetChapter
|
|||
import yokai.domain.manga.interactor.GetManga
|
||||
import yokai.domain.manga.interactor.UpdateManga
|
||||
import yokai.domain.manga.models.MangaUpdate
|
||||
import yokai.domain.track.interactor.InsertTrack
|
||||
import yokai.i18n.MR
|
||||
import yokai.util.lang.getString
|
||||
import android.R as AR
|
||||
|
@ -83,12 +84,11 @@ suspend fun Manga.shouldDownloadNewChapters(prefs: PreferencesHelper, getCategor
|
|||
return categoriesForManga.any { it in includedCategories }
|
||||
}
|
||||
|
||||
fun Manga.moveCategories(db: DatabaseHelper, activity: Activity, onMangaMoved: () -> Unit) {
|
||||
moveCategories(db, activity, false, onMangaMoved)
|
||||
fun Manga.moveCategories(activity: Activity, onMangaMoved: () -> Unit) {
|
||||
moveCategories(activity, false, onMangaMoved)
|
||||
}
|
||||
|
||||
fun Manga.moveCategories(
|
||||
db: DatabaseHelper,
|
||||
activity: Activity,
|
||||
addingToLibrary: Boolean,
|
||||
onMangaMoved: () -> Unit,
|
||||
|
@ -110,13 +110,12 @@ fun Manga.moveCategories(
|
|||
) {
|
||||
onMangaMoved()
|
||||
if (addingToLibrary) {
|
||||
autoAddTrack(db, onMangaMoved)
|
||||
autoAddTrack(onMangaMoved)
|
||||
}
|
||||
}.show()
|
||||
}
|
||||
|
||||
fun List<Manga>.moveCategories(
|
||||
db: DatabaseHelper,
|
||||
activity: Activity,
|
||||
onMangaMoved: () -> Unit,
|
||||
) {
|
||||
|
@ -211,7 +210,7 @@ fun Manga.addOrRemoveToFavorites(
|
|||
defaultCategory != null -> {
|
||||
favorite = true
|
||||
date_added = Date().time
|
||||
autoAddTrack(db, onMangaMoved)
|
||||
autoAddTrack(onMangaMoved)
|
||||
// FIXME: Don't do blocking
|
||||
runBlocking {
|
||||
updateManga.await(
|
||||
|
@ -228,7 +227,7 @@ fun Manga.addOrRemoveToFavorites(
|
|||
onMangaMoved()
|
||||
return view.snack(activity.getString(MR.strings.added_to_, defaultCategory.name)) {
|
||||
setAction(MR.strings.change) {
|
||||
moveCategories(db, activity, onMangaMoved)
|
||||
moveCategories(activity, onMangaMoved)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -238,7 +237,7 @@ fun Manga.addOrRemoveToFavorites(
|
|||
) -> { // last used category(s)
|
||||
favorite = true
|
||||
date_added = Date().time
|
||||
autoAddTrack(db, onMangaMoved)
|
||||
autoAddTrack(onMangaMoved)
|
||||
// FIXME: Don't do blocking
|
||||
runBlocking {
|
||||
updateManga.await(
|
||||
|
@ -270,14 +269,14 @@ fun Manga.addOrRemoveToFavorites(
|
|||
),
|
||||
) {
|
||||
setAction(MR.strings.change) {
|
||||
moveCategories(db, activity, onMangaMoved)
|
||||
moveCategories(activity, onMangaMoved)
|
||||
}
|
||||
}
|
||||
}
|
||||
defaultCategoryId == 0 || categories.isEmpty() -> { // 'Default' or no category
|
||||
favorite = true
|
||||
date_added = Date().time
|
||||
autoAddTrack(db, onMangaMoved)
|
||||
autoAddTrack(onMangaMoved)
|
||||
// FIXME: Don't do blocking
|
||||
runBlocking {
|
||||
updateManga.await(
|
||||
|
@ -294,7 +293,7 @@ fun Manga.addOrRemoveToFavorites(
|
|||
return if (categories.isNotEmpty()) {
|
||||
view.snack(activity.getString(MR.strings.added_to_, activity.getString(MR.strings.default_value))) {
|
||||
setAction(MR.strings.change) {
|
||||
moveCategories(db, activity, onMangaMoved)
|
||||
moveCategories(activity, onMangaMoved)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -302,7 +301,7 @@ fun Manga.addOrRemoveToFavorites(
|
|||
}
|
||||
}
|
||||
else -> { // Always ask
|
||||
showSetCategoriesSheet(db, activity, categories, onMangaAdded, onMangaMoved)
|
||||
showSetCategoriesSheet(activity, categories, onMangaAdded, onMangaMoved)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -352,7 +351,6 @@ fun Manga.addOrRemoveToFavorites(
|
|||
}
|
||||
|
||||
private fun Manga.showSetCategoriesSheet(
|
||||
db: DatabaseHelper,
|
||||
activity: Activity,
|
||||
categories: List<Category>,
|
||||
onMangaAdded: (Pair<Long, Boolean>?) -> Unit,
|
||||
|
@ -372,7 +370,7 @@ private fun Manga.showSetCategoriesSheet(
|
|||
) {
|
||||
(activity as? MainActivity)?.showNotificationPermissionPrompt()
|
||||
onMangaAdded(null)
|
||||
autoAddTrack(db, onMangaMoved)
|
||||
autoAddTrack(onMangaMoved)
|
||||
}.show()
|
||||
}
|
||||
|
||||
|
@ -470,10 +468,11 @@ private fun showAddDuplicateDialog(
|
|||
}.show()
|
||||
}
|
||||
|
||||
fun Manga.autoAddTrack(db: DatabaseHelper, onMangaMoved: () -> Unit) {
|
||||
fun Manga.autoAddTrack(onMangaMoved: () -> Unit) {
|
||||
val loggedServices = Injekt.get<TrackManager>().services.filter { it.isLogged }
|
||||
val source = Injekt.get<SourceManager>().getOrStub(this.source)
|
||||
val getChapter = Injekt.get<GetChapter>()
|
||||
val insertTrack = Injekt.get<InsertTrack>()
|
||||
loggedServices
|
||||
.filterIsInstance<EnhancedTrackService>()
|
||||
.filter { it.accept(source) }
|
||||
|
@ -484,9 +483,13 @@ fun Manga.autoAddTrack(db: DatabaseHelper, onMangaMoved: () -> Unit) {
|
|||
val mangaId = this@autoAddTrack.id!!
|
||||
track.manga_id = mangaId
|
||||
(service as TrackService).bind(track)
|
||||
db.insertTrack(track).executeAsBlocking()
|
||||
insertTrack.await(track)
|
||||
|
||||
syncChaptersWithTrackServiceTwoWay(db, getChapter.awaitAll(mangaId, false), track, service as TrackService)
|
||||
syncChaptersWithTrackServiceTwoWay(
|
||||
getChapter.awaitAll(mangaId, false),
|
||||
track,
|
||||
service as TrackService
|
||||
)
|
||||
withUIContext {
|
||||
onMangaMoved()
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import eu.kanade.tachiyomi.data.track.DelayedTrackingUpdateJob
|
|||
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.util.system.e
|
||||
import eu.kanade.tachiyomi.util.system.isOnline
|
||||
import eu.kanade.tachiyomi.util.system.launchIO
|
||||
import eu.kanade.tachiyomi.util.system.w
|
||||
|
@ -20,6 +19,7 @@ import uy.kohesive.injekt.Injekt
|
|||
import uy.kohesive.injekt.api.get
|
||||
import yokai.domain.chapter.interactor.UpdateChapter
|
||||
import yokai.domain.track.interactor.GetTrack
|
||||
import yokai.domain.track.interactor.InsertTrack
|
||||
|
||||
/**
|
||||
* Helper method for syncing a remote track with the local chapters, and back
|
||||
|
@ -30,11 +30,11 @@ import yokai.domain.track.interactor.GetTrack
|
|||
* @param service the tracker service.
|
||||
*/
|
||||
suspend fun syncChaptersWithTrackServiceTwoWay(
|
||||
db: DatabaseHelper,
|
||||
chapters: List<Chapter>,
|
||||
remoteTrack: Track,
|
||||
service: TrackService,
|
||||
updateChapter: UpdateChapter = Injekt.get(),
|
||||
insertTrack: InsertTrack = Injekt.get()
|
||||
) = withIOContext {
|
||||
if (service !is EnhancedTrackService) {
|
||||
return@withIOContext
|
||||
|
@ -54,7 +54,7 @@ suspend fun syncChaptersWithTrackServiceTwoWay(
|
|||
|
||||
try {
|
||||
service.update(remoteTrack)
|
||||
db.insertTrack(remoteTrack).executeAsBlocking()
|
||||
insertTrack.await(remoteTrack)
|
||||
} catch (e: Throwable) {
|
||||
Logger.w(e)
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ fun updateTrackChapterMarkedAsRead(
|
|||
// We want these to execute even if the presenter is destroyed
|
||||
trackingJobs[mangaId] = launchIO {
|
||||
delay(delay)
|
||||
updateTrackChapterRead(db, preferences, mangaId, newChapterRead)
|
||||
updateTrackChapterRead(preferences, mangaId, newChapterRead)
|
||||
fetchTracks?.invoke()
|
||||
trackingJobs.remove(mangaId)
|
||||
} to newChapterRead
|
||||
|
@ -94,12 +94,12 @@ fun updateTrackChapterMarkedAsRead(
|
|||
}
|
||||
|
||||
suspend fun updateTrackChapterRead(
|
||||
db: DatabaseHelper,
|
||||
preferences: PreferencesHelper,
|
||||
mangaId: Long?,
|
||||
newChapterRead: Float,
|
||||
retryWhenOnline: Boolean = false,
|
||||
getTrack: GetTrack = Injekt.get()
|
||||
getTrack: GetTrack = Injekt.get(),
|
||||
insertTrack: InsertTrack = Injekt.get(),
|
||||
): List<Pair<TrackService, String?>> {
|
||||
val trackManager = Injekt.get<TrackManager>()
|
||||
val trackList = getTrack.awaitAllByMangaId(mangaId)
|
||||
|
@ -113,7 +113,7 @@ suspend fun updateTrackChapterRead(
|
|||
try {
|
||||
track.last_chapter_read = newChapterRead
|
||||
service.update(track, true)
|
||||
db.insertTrack(track).executeAsBlocking()
|
||||
insertTrack.await(track)
|
||||
} catch (e: Exception) {
|
||||
Logger.e(e) { "Unable to update tracker [tracker id ${track.sync_id}]" }
|
||||
failures.add(service to e.localizedMessage)
|
||||
|
|
|
@ -44,6 +44,7 @@ import yokai.domain.recents.interactor.GetRecents
|
|||
import yokai.domain.track.TrackRepository
|
||||
import yokai.domain.track.interactor.DeleteTrack
|
||||
import yokai.domain.track.interactor.GetTrack
|
||||
import yokai.domain.track.interactor.InsertTrack
|
||||
|
||||
fun domainModule() = module {
|
||||
factory { TrustExtension(get(), get()) }
|
||||
|
@ -90,4 +91,5 @@ fun domainModule() = module {
|
|||
single<TrackRepository> { TrackRepositoryImpl(get()) }
|
||||
factory { DeleteTrack(get()) }
|
||||
factory { GetTrack(get()) }
|
||||
factory { InsertTrack(get()) }
|
||||
}
|
||||
|
|
|
@ -10,4 +10,22 @@ class TrackRepositoryImpl(private val handler: DatabaseHandler) : TrackRepositor
|
|||
|
||||
override suspend fun deleteForManga(mangaId: Long, syncId: Long) =
|
||||
handler.await { manga_syncQueries.deleteForManga(mangaId, syncId) }
|
||||
|
||||
override suspend fun insert(track: Track) =
|
||||
handler.await {
|
||||
manga_syncQueries.insert(
|
||||
mangaId = track.manga_id,
|
||||
syncId = track.sync_id,
|
||||
remoteId = track.media_id,
|
||||
libraryId = track.library_id,
|
||||
title = track.title,
|
||||
lastChapterRead = track.last_chapter_read.toDouble(),
|
||||
totalChapters = track.total_chapters,
|
||||
status = track.status.toLong(),
|
||||
score = track.score.toDouble(),
|
||||
remoteUrl = track.tracking_url,
|
||||
startDate = track.started_reading_date,
|
||||
finishDate = track.finished_reading_date,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,4 +5,5 @@ import eu.kanade.tachiyomi.data.database.models.Track
|
|||
interface TrackRepository {
|
||||
suspend fun getAllByMangaId(mangaId: Long): List<Track>
|
||||
suspend fun deleteForManga(mangaId: Long, syncId: Long)
|
||||
suspend fun insert(track: Track)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package yokai.domain.track.interactor
|
||||
|
||||
import eu.kanade.tachiyomi.data.database.models.Track
|
||||
import yokai.domain.track.TrackRepository
|
||||
|
||||
class InsertTrack(
|
||||
private val trackRepository: TrackRepository,
|
||||
) {
|
||||
suspend fun await(track: Track) = trackRepository.insert(track)
|
||||
}
|
|
@ -1,5 +1,3 @@
|
|||
import kotlin.Float;
|
||||
|
||||
CREATE TABLE manga_sync(
|
||||
_id INTEGER NOT NULL PRIMARY KEY,
|
||||
manga_id INTEGER NOT NULL,
|
||||
|
@ -27,3 +25,24 @@ WHERE manga_id = :mangaId;
|
|||
deleteForManga:
|
||||
DELETE FROM manga_sync
|
||||
WHERE manga_id = :mangaId AND sync_id = :syncId;
|
||||
|
||||
insert:
|
||||
INSERT INTO manga_sync(manga_id, sync_id, remote_id, library_id, title, last_chapter_read, total_chapters, status, score, remote_url, start_date, finish_date)
|
||||
VALUES(:mangaId, :syncId, :remoteId, :libraryId, :title, :lastChapterRead, :totalChapters, :status, :score, :remoteUrl, :startDate, :finishDate);
|
||||
|
||||
update:
|
||||
UPDATE manga_sync
|
||||
SET
|
||||
manga_id = coalesce(:mangaId, manga_id),
|
||||
sync_id = coalesce(:syncId, sync_id),
|
||||
remote_id = coalesce(:remoteId, remote_id),
|
||||
library_id = coalesce(:libraryId, library_id),
|
||||
title = coalesce(:title, title),
|
||||
last_chapter_read = coalesce(:lastChapterRead, last_chapter_read),
|
||||
total_chapters = coalesce(:totalChapters, total_chapters),
|
||||
status = coalesce(:status, status),
|
||||
score = coalesce(:score, score),
|
||||
remote_url = coalesce(:remoteUrl, remote_url),
|
||||
start_date = coalesce(:startDate, start_date),
|
||||
finish_date = coalesce(:finishDate, finish_date)
|
||||
WHERE _id = :id;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue