refactor(db): Migrate GetTrack to SQLDelight

This commit is contained in:
Ahmad Ansori Palembani 2024-11-28 20:53:26 +07:00
parent e9a68f661f
commit c183802096
Signed by: null2264
GPG key ID: BA64F8B60AF3EFB6
26 changed files with 154 additions and 48 deletions

View file

@ -5,19 +5,23 @@ import eu.kanade.tachiyomi.data.backup.models.BackupChapter
import eu.kanade.tachiyomi.data.backup.models.BackupHistory
import eu.kanade.tachiyomi.data.backup.models.BackupManga
import eu.kanade.tachiyomi.data.backup.models.BackupTracking
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.library.CustomMangaManager
import eu.kanade.tachiyomi.domain.manga.models.Manga
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import yokai.data.DatabaseHandler
import yokai.domain.category.interactor.GetCategories
import yokai.domain.chapter.interactor.GetChapter
import yokai.domain.history.interactor.GetHistory
import yokai.domain.track.interactor.GetTrack
class MangaBackupCreator(
private val db: DatabaseHelper = Injekt.get(),
private val customMangaManager: CustomMangaManager = Injekt.get(),
private val handler: DatabaseHandler = Injekt.get(),
private val getCategories: GetCategories = Injekt.get(),
private val getChapter: GetChapter = Injekt.get(),
private val getHistory: GetHistory = Injekt.get(),
private val getTrack: GetTrack = Injekt.get(),
) {
suspend operator fun invoke(mangas: List<Manga>, options: BackupOptions): List<BackupManga> {
return mangas.map {
@ -55,7 +59,7 @@ class MangaBackupCreator(
// Check if user wants category information in backup
if (options.categories) {
// Backup categories for this manga
val categoriesForManga = db.getCategoriesForManga(manga).executeAsBlocking()
val categoriesForManga = getCategories.awaitByMangaId(manga.id!!)
if (categoriesForManga.isNotEmpty()) {
mangaObject.categories = categoriesForManga.mapNotNull { it.order }
}
@ -63,7 +67,7 @@ class MangaBackupCreator(
// Check if user wants track information in backup
if (options.tracking) {
val tracks = db.getTracks(manga).executeAsBlocking()
val tracks = getTrack.awaitAllByMangaId(manga.id!!)
if (tracks.isNotEmpty()) {
mangaObject.tracking = tracks.map { BackupTracking.copyFrom(it) }
}
@ -71,7 +75,7 @@ class MangaBackupCreator(
// Check if user wants history information in backup
if (options.history) {
val historyForManga = db.getHistoryByMangaId(manga.id!!).executeAsBlocking()
val historyForManga = getHistory.awaitAllByMangaId(manga.id!!)
if (historyForManga.isNotEmpty()) {
val history = historyForManga.mapNotNull { history ->
val url = getChapter.awaitById(history.chapter_id)?.url

View file

@ -28,6 +28,7 @@ import yokai.domain.library.custom.model.CustomMangaInfo
import yokai.domain.manga.interactor.GetManga
import yokai.domain.manga.interactor.InsertManga
import yokai.domain.manga.interactor.UpdateManga
import yokai.domain.track.interactor.GetTrack
class MangaBackupRestorer(
private val db: DatabaseHelper = Injekt.get(),
@ -41,6 +42,7 @@ class MangaBackupRestorer(
private val updateManga: UpdateManga = Injekt.get(),
private val getHistory: GetHistory = Injekt.get(),
private val upsertHistory: UpsertHistory = Injekt.get(),
private val getTrack: GetTrack = Injekt.get(),
) {
suspend fun restoreManga(
backupManga: BackupManga,
@ -239,7 +241,7 @@ class MangaBackupRestorer(
tracks.map { it.manga_id = manga.id!! }
// Get tracks from database
val dbTracks = db.getTracks(manga).executeAsBlocking()
val dbTracks = getTrack.awaitAllByMangaId(manga.id!!)
val trackToUpdate = mutableListOf<Track>()
tracks.forEach { track ->

View file

@ -42,5 +42,35 @@ interface Track : Serializable {
fun create(serviceId: Long): Track = TrackImpl().apply {
sync_id = serviceId
}
fun mapper(
id: Long,
mangaId: Long,
syncId: Long,
remoteId: Long,
libraryId: Long?,
title: String,
lastChapterRead: Double,
totalChapters: Long,
status: Long,
score: Double,
remoteUrl: String,
startDate: Long,
finishDate: Long,
) = TrackImpl().apply {
this.id = id
this.manga_id = mangaId
this.sync_id = syncId
this.media_id = remoteId
this.library_id = libraryId
this.title = title
this.last_chapter_read = lastChapterRead.toFloat()
this.total_chapters = totalChapters
this.score = score.toFloat()
this.status = status.toInt()
this.started_reading_date = startDate
this.finished_reading_date = finishDate
this.tracking_url = remoteUrl
}
}
}

View file

@ -10,15 +10,14 @@ import eu.kanade.tachiyomi.domain.manga.models.Manga
interface TrackQueries : DbProvider {
fun getTracks(manga: Manga) = getTracks(manga.id)
fun getTracks(mangaId: Long?) = db.get()
// FIXME: Migrate to SQLDelight, on halt: in StorIO transaction
fun getTracks(manga: Manga) = db.get()
.listOfObjects(Track::class.java)
.withQuery(
Query.builder()
.table(TrackTable.TABLE)
.where("${TrackTable.COL_MANGA_ID} = ?")
.whereArgs(mangaId)
.whereArgs(manga.id)
.build(),
)
.prepare()

View file

@ -85,6 +85,7 @@ 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.i18n.MR
import yokai.util.lang.getString
@ -103,6 +104,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
private val mangaShortcutManager: MangaShortcutManager = Injekt.get()
private val getLibraryManga: GetLibraryManga = Injekt.get()
private val updateManga: UpdateManga = Injekt.get()
private val getTrack: GetTrack = Injekt.get()
private var extraDeferredJobs = mutableListOf<Deferred<Any>>()
@ -302,7 +304,6 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
* Method that updates the metadata of the connected tracking services. It's called in a
* background thread, so it's safe to do heavy operations or network calls here.
*/
private suspend fun updateTrackings(mangaToUpdate: List<LibraryManga>) {
// Initialize the variables holding the progress of the updates.
var count = 0
@ -312,7 +313,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
mangaToUpdate.forEach { manga ->
notifier.showProgressNotification(manga, count++, mangaToUpdate.size)
val tracks = db.getTracks(manga).executeAsBlocking()
val tracks = getTrack.awaitAllByMangaId(manga.id!!)
tracks.forEach { track ->
val service = trackManager.getService(track.sync_id)

View file

@ -18,10 +18,16 @@ 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.domain.track.interactor.GetTrack
class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters) :
CoroutineWorker(context, workerParams) {
private val getManga: GetManga by injectLazy()
private val getTrack: GetTrack by injectLazy()
override suspend fun doWork(): Result {
val preferences = Injekt.get<PreferencesHelper>()
val db = Injekt.get<DatabaseHelper>()
@ -40,8 +46,8 @@ class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters)
withContext(Dispatchers.IO) {
trackings.forEach {
val mangaId = it.key
val manga = db.getManga(mangaId).executeAsBlocking() ?: return@withContext
val trackList = db.getTracks(manga).executeAsBlocking()
val manga = getManga.awaitById(mangaId) ?: return@withContext
val trackList = getTrack.awaitAllByMangaId(manga.id)
it.value.map { tC ->
val trackChapter = tC.second
val service = trackManager.getService(trackChapter.first)

View file

@ -73,6 +73,7 @@ import yokai.domain.manga.interactor.GetLibraryManga
import yokai.domain.manga.interactor.GetManga
import yokai.domain.manga.interactor.UpdateManga
import yokai.domain.manga.models.MangaUpdate
import yokai.domain.track.interactor.GetTrack
import yokai.i18n.MR
import yokai.util.isLewd
import yokai.util.lang.getString
@ -94,6 +95,7 @@ class LibraryPresenter(
private val getChapter: GetChapter by injectLazy()
private val updateChapter: UpdateChapter by injectLazy()
private val updateManga: UpdateManga by injectLazy()
private val getTrack: GetTrack by injectLazy()
private val context = preferences.context
private val viewContext
@ -423,7 +425,7 @@ class LibraryPresenter(
return filteredItems
}
private fun matchesFilters(
private suspend fun matchesFilters(
item: LibraryItem,
filterPrefs: ItemPreferences,
filterTrackers: String,
@ -475,7 +477,7 @@ class LibraryPresenter(
return true
}
private fun matchesCustomFilters(
private suspend fun matchesCustomFilters(
item: LibraryItem,
customFilters: FilteredLibraryController,
filterTrackers: String,
@ -498,7 +500,7 @@ class LibraryPresenter(
}
val trackingScore = customFilters.filterTrackingScore
if (trackingScore > 0 || trackingScore == -1) {
val tracks = db.getTracks(item.manga).executeAsBlocking()
val tracks = getTrack.awaitAllByMangaId(item.manga.id!!)
val hasTrack = loggedServices.any { service ->
tracks.any { it.sync_id == service.id }
@ -556,14 +558,14 @@ class LibraryPresenter(
return service?.get10PointScore(this.score)
}
private fun matchesFilterTracking(
private suspend fun matchesFilterTracking(
item: LibraryItem,
filterTracked: Int,
filterTrackers: String,
): Boolean {
// Filter for tracked (or per tracked service)
if (filterTracked != STATE_IGNORE) {
val tracks = db.getTracks(item.manga).executeAsBlocking()
val tracks = getTrack.awaitAllByMangaId(item.manga.id!!)
val hasTrack = loggedServices.any { service ->
tracks.any { it.sync_id == service.id }
@ -992,7 +994,7 @@ class LibraryPresenter(
)
}
private fun getDynamicLibraryItems(
private suspend fun getDynamicLibraryItems(
libraryManga: List<LibraryManga>,
sortingMode: Int,
isAscending: Boolean,
@ -1031,7 +1033,7 @@ class LibraryPresenter(
}
}
BY_TRACK_STATUS -> {
val tracks = db.getTracks(manga).executeAsBlocking()
val tracks = getTrack.awaitAllByMangaId(manga.id!!)
val track = tracks.find { track ->
loggedServices.any { it.id == track?.sync_id }
}

View file

@ -94,6 +94,7 @@ import yokai.domain.manga.interactor.UpdateManga
import yokai.domain.manga.models.MangaUpdate
import yokai.domain.manga.models.cover
import yokai.domain.storage.StorageManager
import yokai.domain.track.interactor.GetTrack
import yokai.i18n.MR
import yokai.util.lang.getString
@ -112,6 +113,7 @@ class MangaDetailsPresenter(
private val getManga: GetManga by injectLazy()
private val updateChapter: UpdateChapter by injectLazy()
private val updateManga: UpdateManga by injectLazy()
private val getTrack: GetTrack by injectLazy()
private val networkPreferences: NetworkPreferences by injectLazy()
@ -176,7 +178,9 @@ class MangaDetailsPresenter(
downloadManager.addListener(this)
tracks = db.getTracks(manga).executeAsBlocking()
runBlocking {
tracks = getTrack.awaitAllByMangaId(manga.id!!)
}
}
/**
@ -1008,7 +1012,7 @@ class MangaDetailsPresenter(
}
suspend fun fetchTracks() {
tracks = withContext(Dispatchers.IO) { db.getTracks(manga).executeAsBlocking() }
tracks = withContext(Dispatchers.IO) { getTrack.awaitAllByMangaId(manga.id!!) }
setTrackItems()
withContext(Dispatchers.Main) { view?.refreshTracking(trackList) }
}

View file

@ -7,7 +7,9 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.library.CustomMangaManager
import eu.kanade.tachiyomi.domain.manga.models.Manga
import eu.kanade.tachiyomi.util.system.toInt
import kotlinx.coroutines.runBlocking
import uy.kohesive.injekt.injectLazy
import yokai.domain.track.interactor.GetTrack
import yokai.i18n.MR
import yokai.util.lang.getString
@ -21,6 +23,7 @@ object MigrationFlags {
private val coverCache: CoverCache by injectLazy()
private val db: DatabaseHelper by injectLazy()
private val customMangaManager: CustomMangaManager by injectLazy()
private val getTrack: GetTrack by injectLazy()
val titles get() = arrayOf(MR.strings.chapters, MR.strings.categories, MR.strings.tracking, MR.strings.custom_manga_info)
val flags get() = arrayOf(CHAPTERS, CATEGORIES, TRACK, CUSTOM_MANGA_INFO)
@ -61,7 +64,7 @@ object MigrationFlags {
fun flags(manga: Manga?): Array<Int> {
val flags = arrayOf(CHAPTERS, CATEGORIES).toMutableList()
if (manga != null) {
if (db.getTracks(manga).executeAsBlocking().isNotEmpty()) {
if (runBlocking { getTrack.awaitAllByMangaId(manga.id) }.isNotEmpty()) {
flags.add(TRACK)
}

View file

@ -14,12 +14,14 @@ import eu.kanade.tachiyomi.domain.manga.models.Manga
import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.ui.base.presenter.BaseCoroutinePresenter
import eu.kanade.tachiyomi.ui.more.stats.StatsHelper.getReadDuration
import kotlinx.coroutines.runBlocking
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import yokai.domain.manga.interactor.GetLibraryManga
import yokai.domain.track.interactor.GetTrack
import yokai.i18n.MR
import yokai.util.lang.getString
@ -32,8 +34,9 @@ class StatsPresenter(
private val trackManager: TrackManager = Injekt.get(),
private val downloadManager: DownloadManager = Injekt.get(),
private val sourceManager: SourceManager = Injekt.get(),
) {
): BaseCoroutinePresenter<StatsController>() {
private val getLibraryManga: GetLibraryManga by injectLazy()
private val getTrack: GetTrack by injectLazy()
private val libraryMangas = getLibrary()
val mangaDistinct = libraryMangas.distinct()
@ -43,7 +46,7 @@ class StatsPresenter(
}
fun getTracks(manga: Manga): MutableList<Track> {
return db.getTracks(manga).executeAsBlocking()
return runBlocking { getTrack.awaitAllByMangaId(manga.id) }.toMutableList()
}
fun getLoggedTrackers(): List<TrackService> {

View file

@ -39,6 +39,7 @@ import yokai.util.lang.getString
import java.util.*
import java.util.concurrent.*
import kotlin.math.roundToInt
import yokai.domain.track.interactor.GetTrack
class StatsDetailsPresenter(
private val db: DatabaseHelper = Injekt.get(),
@ -47,6 +48,7 @@ class StatsDetailsPresenter(
private val sourceManager: SourceManager = Injekt.get(),
) : BaseCoroutinePresenter<StatsDetailsController>() {
private val getLibraryManga: GetLibraryManga by injectLazy()
private val getTrack: GetTrack by injectLazy()
private val context
get() = view?.view?.context ?: prefs.context
@ -557,7 +559,7 @@ class StatsDetailsPresenter(
}
fun getTracks(manga: Manga): MutableList<Track> {
return db.getTracks(manga).executeAsBlocking()
return runBlocking { getTrack.awaitAllByMangaId(manga.id) }.toMutableList()
}
fun getLibrary(): MutableList<LibraryManga> {

View file

@ -88,6 +88,7 @@ import yokai.domain.manga.interactor.InsertManga
import yokai.domain.manga.interactor.UpdateManga
import yokai.domain.manga.models.MangaUpdate
import yokai.domain.storage.StorageManager
import yokai.domain.track.interactor.GetTrack
import yokai.i18n.MR
import yokai.util.lang.getString
@ -113,6 +114,7 @@ class ReaderViewModel(
private val updateManga: UpdateManga by injectLazy()
private val getHistory: GetHistory by injectLazy()
private val upsertHistory: UpsertHistory by injectLazy()
private val getTrack: GetTrack by injectLazy()
private val mutableState = MutableStateFlow(State())
val state = mutableState.asStateFlow()
@ -178,11 +180,7 @@ class ReaderViewModel(
private var scope = CoroutineScope(Job() + Dispatchers.Default)
private var hasTrackers: Boolean = false
private val checkTrackers: (Manga) -> Unit = { manga ->
val tracks = db.getTracks(manga).executeAsBlocking()
hasTrackers = tracks.size > 0
}
private suspend fun checkTrackers(manga: Manga) = getTrack.awaitAllByMangaId(manga.id).isNotEmpty()
init {
var secondRun = false
@ -251,7 +249,7 @@ class ReaderViewModel(
chapterId = initialChapterId
}
checkTrackers(manga)
hasTrackers = checkTrackers(manga)
NotificationReceiver.dismissNotification(
preferences.context,

View file

@ -42,9 +42,12 @@ import eu.kanade.tachiyomi.util.view.withFadeTransaction
import eu.kanade.tachiyomi.widget.TriStateCheckBox
import java.util.Date
import java.util.Locale
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import yokai.domain.chapter.interactor.GetChapter
import yokai.domain.manga.interactor.GetManga
import yokai.i18n.MR
import yokai.util.lang.getString
import android.R as AR
@ -144,20 +147,16 @@ fun Manga.addOrRemoveToFavorites(
onMangaAdded: (Pair<Long, Boolean>?) -> Unit,
onMangaMoved: () -> Unit,
onMangaDeleted: () -> Unit,
getManga: GetManga = Injekt.get()
): Snackbar? {
if (!favorite) {
if (checkForDupes) {
// TODO
/*
val duplicateManga = runBlocking(Dispatchers.IO) { handler.awaitOne {
mangasQueries.findDuplicateFavorite(
val duplicateManga = runBlocking(Dispatchers.IO) {
getManga.awaitDuplicateFavorite(
this@addOrRemoveToFavorites.title,
this@addOrRemoveToFavorites.source,
Manga::mapper,
)
} }
*/
val duplicateManga = db.getDuplicateLibraryManga(this).executeAsBlocking()
}
if (duplicateManga != null) {
showAddDuplicateDialog(
this,

View file

@ -19,6 +19,7 @@ import kotlinx.coroutines.delay
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import yokai.domain.chapter.interactor.UpdateChapter
import yokai.domain.track.interactor.GetTrack
/**
* Helper method for syncing a remote track with the local chapters, and back
@ -98,9 +99,10 @@ suspend fun updateTrackChapterRead(
mangaId: Long?,
newChapterRead: Float,
retryWhenOnline: Boolean = false,
getTrack: GetTrack = Injekt.get()
): List<Pair<TrackService, String?>> {
val trackManager = Injekt.get<TrackManager>()
val trackList = db.getTracks(mangaId).executeAsBlocking()
val trackList = getTrack.awaitAllByMangaId(mangaId)
val failures = mutableListOf<Pair<TrackService, String?>>()
trackList.map { track ->
val service = trackManager.getService(track.sync_id)

View file

@ -7,6 +7,7 @@ import yokai.data.extension.repo.ExtensionRepoRepositoryImpl
import yokai.data.history.HistoryRepositoryImpl
import yokai.data.library.custom.CustomMangaRepositoryImpl
import yokai.data.manga.MangaRepositoryImpl
import yokai.data.track.TrackRepositoryImpl
import yokai.domain.category.CategoryRepository
import yokai.domain.category.interactor.GetCategories
import yokai.domain.chapter.ChapterRepository
@ -37,10 +38,15 @@ import yokai.domain.manga.interactor.GetManga
import yokai.domain.manga.interactor.InsertManga
import yokai.domain.manga.interactor.UpdateManga
import yokai.domain.recents.interactor.GetRecents
import yokai.domain.track.TrackRepository
import yokai.domain.track.interactor.GetTrack
fun domainModule() = module {
factory { TrustExtension(get(), get()) }
single<CategoryRepository> { CategoryRepositoryImpl(get()) }
factory { GetCategories(get()) }
single<ExtensionRepoRepository> { ExtensionRepoRepositoryImpl(get()) }
factory { CreateExtensionRepo(get()) }
factory { DeleteExtensionRepo(get()) }
@ -74,6 +80,6 @@ fun domainModule() = module {
factory { GetRecents(get(), get()) }
single<CategoryRepository> { CategoryRepositoryImpl(get()) }
factory { GetCategories(get()) }
single<TrackRepository> { TrackRepositoryImpl(get()) }
factory { GetTrack(get()) }
}

View file

@ -9,6 +9,9 @@ class CategoryRepositoryImpl(private val handler: DatabaseHandler) : CategoryRep
override suspend fun getAll(): List<Category> =
handler.awaitList { categoriesQueries.findAll(Category::mapper) }
override suspend fun getAllByMangaId(mangaId: Long): List<Category> =
handler.awaitList { categoriesQueries.findAllByMangaId(mangaId, Category::mapper) }
override fun getAllAsFlow(): Flow<List<Category>> =
handler.subscribeToList { categoriesQueries.findAll(Category::mapper) }
}

View file

@ -35,6 +35,9 @@ class MangaRepositoryImpl(private val handler: DatabaseHandler) : MangaRepositor
override fun getLibraryMangaAsFlow(): Flow<List<LibraryManga>> =
handler.subscribeToList { library_viewQueries.findAll(LibraryManga::mapper) }
override suspend fun getDuplicateFavorite(title: String, source: Long): Manga? =
handler.awaitOneOrNull { mangasQueries.findDuplicateFavorite(title, source, Manga::mapper) }
override suspend fun update(update: MangaUpdate): Boolean {
return try {
partialUpdate(update)

View file

@ -0,0 +1,10 @@
package yokai.data.track
import eu.kanade.tachiyomi.data.database.models.Track
import yokai.data.DatabaseHandler
import yokai.domain.track.TrackRepository
class TrackRepositoryImpl(private val handler: DatabaseHandler) : TrackRepository {
override suspend fun getAllByMangaId(mangaId: Long): List<Track> =
handler.awaitList { manga_syncQueries.getAllByMangaId(mangaId, Track::mapper) }
}

View file

@ -5,5 +5,6 @@ import kotlinx.coroutines.flow.Flow
interface CategoryRepository {
suspend fun getAll(): List<Category>
suspend fun getAllByMangaId(mangaId: Long): List<Category>
fun getAllAsFlow(): Flow<List<Category>>
}

View file

@ -6,5 +6,6 @@ class GetCategories(
private val categoryRepository: CategoryRepository,
) {
suspend fun await() = categoryRepository.getAll()
suspend fun awaitByMangaId(mangaId: Long) = categoryRepository.getAllByMangaId(mangaId)
fun subscribe() = categoryRepository.getAllAsFlow()
}

View file

@ -11,6 +11,7 @@ interface MangaRepository {
suspend fun getMangaById(id: Long): Manga?
suspend fun getFavorites(): List<Manga>
suspend fun getReadNotFavorites(): List<Manga>
suspend fun getDuplicateFavorite(title: String, source: Long): Manga?
fun getMangaListAsFlow(): Flow<List<Manga>>
suspend fun getLibraryManga(): List<LibraryManga>
fun getLibraryMangaAsFlow(): Flow<List<LibraryManga>>

View file

@ -12,4 +12,5 @@ class GetManga (
suspend fun awaitById(id: Long) = mangaRepository.getMangaById(id)
suspend fun awaitFavorites() = mangaRepository.getFavorites()
suspend fun awaitReadNotFavorites() = mangaRepository.getReadNotFavorites()
suspend fun awaitDuplicateFavorite(title: String, source: Long) = mangaRepository.getDuplicateFavorite(title, source)
}

View file

@ -0,0 +1,7 @@
package yokai.domain.track
import eu.kanade.tachiyomi.data.database.models.Track
interface TrackRepository {
suspend fun getAllByMangaId(mangaId: Long): List<Track>
}

View file

@ -0,0 +1,9 @@
package yokai.domain.track.interactor
import yokai.domain.track.TrackRepository
class GetTrack(
private val trackRepository: TrackRepository,
) {
suspend fun awaitAllByMangaId(mangaId: Long?) = mangaId?.let { trackRepository.getAllByMangaId(it) } ?: listOf()
}

View file

@ -10,3 +10,8 @@ findAll:
SELECT *
FROM categories
ORDER BY sort;
findAllByMangaId:
SELECT categories.* FROM categories
JOIN mangas_categories ON categories._id = mangas_categories.category_id
WHERE mangas_categories.manga_id = :mangaId;

View file

@ -1,5 +1,4 @@
import kotlin.Float;
import kotlin.Long;
CREATE TABLE manga_sync(
_id INTEGER NOT NULL PRIMARY KEY,
@ -11,11 +10,16 @@ CREATE TABLE manga_sync(
last_chapter_read REAL NOT NULL,
total_chapters INTEGER NOT NULL,
status INTEGER NOT NULL,
score REAL AS Float NOT NULL,
score REAL NOT NULL,
remote_url TEXT NOT NULL,
start_date INTEGER AS Long NOT NULL,
finish_date INTEGER AS Long NOT NULL,
start_date INTEGER NOT NULL,
finish_date INTEGER NOT NULL,
UNIQUE (manga_id, sync_id) ON CONFLICT REPLACE,
FOREIGN KEY(manga_id) REFERENCES mangas (_id)
ON DELETE CASCADE
);
getAllByMangaId:
SELECT *
FROM manga_sync
WHERE manga_id = :mangaId;