mirror of
https://github.com/null2264/yokai.git
synced 2025-06-21 10:44:42 +00:00
refactor: Migrate GetLibraryManga to use SQLDelight
This commit is contained in:
parent
d2f493ab57
commit
b17578365d
14 changed files with 177 additions and 79 deletions
|
@ -3,6 +3,7 @@ package dev.yokai.core.di
|
||||||
import dev.yokai.domain.extension.repo.ExtensionRepoRepository
|
import dev.yokai.domain.extension.repo.ExtensionRepoRepository
|
||||||
import dev.yokai.data.extension.repo.ExtensionRepoRepositoryImpl
|
import dev.yokai.data.extension.repo.ExtensionRepoRepositoryImpl
|
||||||
import dev.yokai.data.library.custom.CustomMangaRepositoryImpl
|
import dev.yokai.data.library.custom.CustomMangaRepositoryImpl
|
||||||
|
import dev.yokai.data.manga.MangaRepositoryImpl
|
||||||
import dev.yokai.domain.extension.interactor.TrustExtension
|
import dev.yokai.domain.extension.interactor.TrustExtension
|
||||||
import dev.yokai.domain.extension.repo.interactor.CreateExtensionRepo
|
import dev.yokai.domain.extension.repo.interactor.CreateExtensionRepo
|
||||||
import dev.yokai.domain.extension.repo.interactor.DeleteExtensionRepo
|
import dev.yokai.domain.extension.repo.interactor.DeleteExtensionRepo
|
||||||
|
@ -14,6 +15,8 @@ import dev.yokai.domain.library.custom.CustomMangaRepository
|
||||||
import dev.yokai.domain.library.custom.interactor.CreateCustomManga
|
import dev.yokai.domain.library.custom.interactor.CreateCustomManga
|
||||||
import dev.yokai.domain.library.custom.interactor.DeleteCustomManga
|
import dev.yokai.domain.library.custom.interactor.DeleteCustomManga
|
||||||
import dev.yokai.domain.library.custom.interactor.GetCustomManga
|
import dev.yokai.domain.library.custom.interactor.GetCustomManga
|
||||||
|
import dev.yokai.domain.manga.MangaRepository
|
||||||
|
import dev.yokai.domain.manga.interactor.GetLibraryManga
|
||||||
import uy.kohesive.injekt.api.InjektModule
|
import uy.kohesive.injekt.api.InjektModule
|
||||||
import uy.kohesive.injekt.api.InjektRegistrar
|
import uy.kohesive.injekt.api.InjektRegistrar
|
||||||
import uy.kohesive.injekt.api.addFactory
|
import uy.kohesive.injekt.api.addFactory
|
||||||
|
@ -36,5 +39,8 @@ class DomainModule : InjektModule {
|
||||||
addFactory { CreateCustomManga(get()) }
|
addFactory { CreateCustomManga(get()) }
|
||||||
addFactory { DeleteCustomManga(get()) }
|
addFactory { DeleteCustomManga(get()) }
|
||||||
addFactory { GetCustomManga(get()) }
|
addFactory { GetCustomManga(get()) }
|
||||||
|
|
||||||
|
addSingletonFactory<MangaRepository> { MangaRepositoryImpl(get()) }
|
||||||
|
addFactory { GetLibraryManga(get()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package dev.yokai.data.manga
|
||||||
|
|
||||||
|
import dev.yokai.data.DatabaseHandler
|
||||||
|
import dev.yokai.domain.manga.MangaRepository
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.LibraryManga
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
class MangaRepositoryImpl(private val handler: DatabaseHandler) : MangaRepository {
|
||||||
|
override suspend fun getLibraryManga(): List<LibraryManga> =
|
||||||
|
handler.awaitList { library_viewQueries.findAll(LibraryManga::mapper) }
|
||||||
|
|
||||||
|
override fun getLibraryMangaAsFlow(): Flow<List<LibraryManga>> =
|
||||||
|
handler.subscribeToList { library_viewQueries.findAll(LibraryManga::mapper) }
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package dev.yokai.domain.manga
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.LibraryManga
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
interface MangaRepository {
|
||||||
|
suspend fun getLibraryManga(): List<LibraryManga>
|
||||||
|
fun getLibraryMangaAsFlow(): Flow<List<LibraryManga>>
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package dev.yokai.domain.manga.interactor
|
||||||
|
|
||||||
|
import dev.yokai.domain.manga.MangaRepository
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.LibraryManga
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
class GetLibraryManga(
|
||||||
|
private val mangaRepository: MangaRepository,
|
||||||
|
) {
|
||||||
|
suspend fun await(): List<LibraryManga> = mangaRepository.getLibraryManga()
|
||||||
|
fun subscribe(): Flow<List<LibraryManga>> = mangaRepository.getLibraryMangaAsFlow()
|
||||||
|
}
|
|
@ -1,5 +1,9 @@
|
||||||
package eu.kanade.tachiyomi.data.database.models
|
package eu.kanade.tachiyomi.data.database.models
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.data.database.updateStrategyAdapter
|
||||||
|
import eu.kanade.tachiyomi.source.model.UpdateStrategy
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
class LibraryManga : MangaImpl() {
|
class LibraryManga : MangaImpl() {
|
||||||
|
|
||||||
var unread: Int = 0
|
var unread: Int = 0
|
||||||
|
@ -28,5 +32,55 @@ class LibraryManga : MangaImpl() {
|
||||||
status = -1
|
status = -1
|
||||||
read = hideCount
|
read = hideCount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun mapper(
|
||||||
|
id: Long,
|
||||||
|
source: Long,
|
||||||
|
url: String,
|
||||||
|
artist: String?,
|
||||||
|
author: String?,
|
||||||
|
description: String?,
|
||||||
|
genre: String?,
|
||||||
|
title: String,
|
||||||
|
status: Long,
|
||||||
|
thumbnailUrl: String?,
|
||||||
|
favorite: Long,
|
||||||
|
lastUpdate: Long?,
|
||||||
|
initialized: Boolean,
|
||||||
|
viewerFlags: Long,
|
||||||
|
hideTitle: Long,
|
||||||
|
chapterFlags: Long,
|
||||||
|
dateAdded: Long?,
|
||||||
|
filteredScanlators: String?,
|
||||||
|
updateStrategy: Long,
|
||||||
|
total: Long,
|
||||||
|
readCount: Double,
|
||||||
|
bookmarkCount: Double,
|
||||||
|
categoryId: Long
|
||||||
|
): LibraryManga = createBlank(categoryId.toInt()).apply {
|
||||||
|
this.id = id
|
||||||
|
this.source = source
|
||||||
|
this.url = url
|
||||||
|
this.artist = artist
|
||||||
|
this.author = author
|
||||||
|
this.description = description
|
||||||
|
this.genre = genre
|
||||||
|
this.title = title
|
||||||
|
this.status = status.toInt()
|
||||||
|
this.thumbnail_url = thumbnailUrl
|
||||||
|
this.favorite = favorite > 0
|
||||||
|
this.last_update = lastUpdate ?: 0L
|
||||||
|
this.initialized = initialized
|
||||||
|
this.viewer_flags = viewerFlags.toInt()
|
||||||
|
this.hide_title = hideTitle > 0
|
||||||
|
this.chapter_flags = chapterFlags.toInt()
|
||||||
|
this.date_added = dateAdded ?: 0L
|
||||||
|
this.filtered_scanlators = filteredScanlators
|
||||||
|
this.update_strategy = updateStrategy.toInt().let(updateStrategyAdapter::decode)
|
||||||
|
this.read = readCount.roundToInt()
|
||||||
|
this.unread = (total - this.read).toInt()
|
||||||
|
this.bookmarkCount = bookmarkCount.roundToInt()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,8 @@ import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
|
||||||
import com.pushtorefresh.storio.sqlite.queries.Query
|
import com.pushtorefresh.storio.sqlite.queries.Query
|
||||||
import com.pushtorefresh.storio.sqlite.queries.RawQuery
|
import com.pushtorefresh.storio.sqlite.queries.RawQuery
|
||||||
import eu.kanade.tachiyomi.data.database.DbProvider
|
import eu.kanade.tachiyomi.data.database.DbProvider
|
||||||
import eu.kanade.tachiyomi.data.database.models.LibraryManga
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.database.models.SourceIdMangaCount
|
import eu.kanade.tachiyomi.data.database.models.SourceIdMangaCount
|
||||||
import eu.kanade.tachiyomi.data.database.resolvers.LibraryMangaGetResolver
|
|
||||||
import eu.kanade.tachiyomi.data.database.resolvers.MangaDateAddedPutResolver
|
import eu.kanade.tachiyomi.data.database.resolvers.MangaDateAddedPutResolver
|
||||||
import eu.kanade.tachiyomi.data.database.resolvers.MangaFavoritePutResolver
|
import eu.kanade.tachiyomi.data.database.resolvers.MangaFavoritePutResolver
|
||||||
import eu.kanade.tachiyomi.data.database.resolvers.MangaFilteredScanlatorsPutResolver
|
import eu.kanade.tachiyomi.data.database.resolvers.MangaFilteredScanlatorsPutResolver
|
||||||
|
@ -17,9 +15,7 @@ import eu.kanade.tachiyomi.data.database.resolvers.MangaInfoPutResolver
|
||||||
import eu.kanade.tachiyomi.data.database.resolvers.MangaLastUpdatedPutResolver
|
import eu.kanade.tachiyomi.data.database.resolvers.MangaLastUpdatedPutResolver
|
||||||
import eu.kanade.tachiyomi.data.database.resolvers.MangaTitlePutResolver
|
import eu.kanade.tachiyomi.data.database.resolvers.MangaTitlePutResolver
|
||||||
import eu.kanade.tachiyomi.data.database.resolvers.SourceIdMangaCountGetResolver
|
import eu.kanade.tachiyomi.data.database.resolvers.SourceIdMangaCountGetResolver
|
||||||
import eu.kanade.tachiyomi.data.database.tables.CategoryTable
|
|
||||||
import eu.kanade.tachiyomi.data.database.tables.ChapterTable
|
import eu.kanade.tachiyomi.data.database.tables.ChapterTable
|
||||||
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable
|
|
||||||
import eu.kanade.tachiyomi.data.database.tables.MangaTable
|
import eu.kanade.tachiyomi.data.database.tables.MangaTable
|
||||||
|
|
||||||
interface MangaQueries : DbProvider {
|
interface MangaQueries : DbProvider {
|
||||||
|
@ -33,17 +29,6 @@ interface MangaQueries : DbProvider {
|
||||||
)
|
)
|
||||||
.prepare()
|
.prepare()
|
||||||
|
|
||||||
fun getLibraryMangas() = db.get()
|
|
||||||
.listOfObjects(LibraryManga::class.java)
|
|
||||||
.withQuery(
|
|
||||||
RawQuery.builder()
|
|
||||||
.query(libraryQuery)
|
|
||||||
.observesTables(MangaTable.TABLE, ChapterTable.TABLE, MangaCategoryTable.TABLE, CategoryTable.TABLE)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.withGetResolver(LibraryMangaGetResolver.INSTANCE)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun getDuplicateLibraryManga(manga: Manga) = db.get()
|
fun getDuplicateLibraryManga(manga: Manga) = db.get()
|
||||||
.`object`(Manga::class.java)
|
.`object`(Manga::class.java)
|
||||||
.withQuery(
|
.withQuery(
|
||||||
|
|
|
@ -8,45 +8,6 @@ import eu.kanade.tachiyomi.data.database.tables.HistoryTable as History
|
||||||
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable as MangaCategory
|
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable as MangaCategory
|
||||||
import eu.kanade.tachiyomi.data.database.tables.MangaTable as Manga
|
import eu.kanade.tachiyomi.data.database.tables.MangaTable as Manga
|
||||||
|
|
||||||
/**
|
|
||||||
* Query to get the manga from the library, with their categories and unread count.
|
|
||||||
*/
|
|
||||||
val libraryQuery =
|
|
||||||
"""
|
|
||||||
SELECT M.*, COALESCE(MC.${MangaCategory.COL_CATEGORY_ID}, 0) AS ${Manga.COL_CATEGORY}
|
|
||||||
FROM (
|
|
||||||
SELECT ${Manga.TABLE}.*, COALESCE(C.unread, '') AS ${Manga.COL_UNREAD}, COALESCE(R.hasread, '') AS ${Manga.COL_HAS_READ}, COALESCE(B.bookmarkCount, 0) AS ${Manga.COL_BOOKMARK_COUNT}
|
|
||||||
FROM ${Manga.TABLE}
|
|
||||||
LEFT JOIN (
|
|
||||||
SELECT ${Chapter.COL_MANGA_ID}, GROUP_CONCAT(IFNULL(${Chapter.TABLE}.${Chapter.COL_SCANLATOR}, "N/A"), " [.] ") AS unread
|
|
||||||
FROM ${Chapter.TABLE}
|
|
||||||
WHERE ${Chapter.COL_READ} = 0
|
|
||||||
GROUP BY ${Chapter.COL_MANGA_ID}
|
|
||||||
) AS C
|
|
||||||
ON ${Manga.COL_ID} = C.${Chapter.COL_MANGA_ID}
|
|
||||||
LEFT JOIN (
|
|
||||||
SELECT ${Chapter.COL_MANGA_ID}, GROUP_CONCAT(IFNULL(${Chapter.TABLE}.${Chapter.COL_SCANLATOR}, "N/A"), " [.] ") AS hasread
|
|
||||||
FROM ${Chapter.TABLE}
|
|
||||||
WHERE ${Chapter.COL_READ} = 1
|
|
||||||
GROUP BY ${Chapter.COL_MANGA_ID}
|
|
||||||
) AS R
|
|
||||||
ON ${Manga.COL_ID} = R.${Chapter.COL_MANGA_ID}
|
|
||||||
LEFT JOIN (
|
|
||||||
SELECT ${Chapter.COL_MANGA_ID}, COUNT(*) AS bookmarkCount
|
|
||||||
FROM ${Chapter.TABLE}
|
|
||||||
WHERE ${Chapter.COL_BOOKMARK} = 1
|
|
||||||
GROUP BY ${Chapter.COL_MANGA_ID}
|
|
||||||
) AS B
|
|
||||||
ON ${Manga.COL_ID} = B.${Chapter.COL_MANGA_ID}
|
|
||||||
WHERE ${Manga.COL_FAVORITE} = 1
|
|
||||||
GROUP BY ${Manga.COL_ID}
|
|
||||||
ORDER BY ${Manga.COL_TITLE}
|
|
||||||
) AS M
|
|
||||||
LEFT JOIN (
|
|
||||||
SELECT * FROM ${MangaCategory.TABLE}) AS MC
|
|
||||||
ON MC.${MangaCategory.COL_MANGA_ID} = M.${Manga.COL_ID}
|
|
||||||
"""
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query to get the recent chapters of manga from the library up to a date.
|
* Query to get the recent chapters of manga from the library up to a date.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -19,6 +19,7 @@ import androidx.work.WorkerParameters
|
||||||
import coil3.imageLoader
|
import coil3.imageLoader
|
||||||
import coil3.request.CachePolicy
|
import coil3.request.CachePolicy
|
||||||
import coil3.request.ImageRequest
|
import coil3.request.ImageRequest
|
||||||
|
import dev.yokai.domain.manga.interactor.GetLibraryManga
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
|
@ -67,6 +68,7 @@ import kotlinx.coroutines.ensureActive
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.asSharedFlow
|
import kotlinx.coroutines.flow.asSharedFlow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlinx.coroutines.sync.Semaphore
|
import kotlinx.coroutines.sync.Semaphore
|
||||||
import kotlinx.coroutines.sync.withPermit
|
import kotlinx.coroutines.sync.withPermit
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
@ -89,6 +91,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||||
private val downloadManager: DownloadManager = Injekt.get()
|
private val downloadManager: DownloadManager = Injekt.get()
|
||||||
private val trackManager: TrackManager = Injekt.get()
|
private val trackManager: TrackManager = Injekt.get()
|
||||||
private val mangaShortcutManager: MangaShortcutManager = Injekt.get()
|
private val mangaShortcutManager: MangaShortcutManager = Injekt.get()
|
||||||
|
private val getLibraryManga: GetLibraryManga = Injekt.get()
|
||||||
|
|
||||||
private var extraDeferredJobs = mutableListOf<Deferred<Any>>()
|
private var extraDeferredJobs = mutableListOf<Deferred<Any>>()
|
||||||
|
|
||||||
|
@ -155,7 +158,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||||
|
|
||||||
val mangaList = (
|
val mangaList = (
|
||||||
if (savedMangasList != null) {
|
if (savedMangasList != null) {
|
||||||
val mangas = db.getLibraryMangas().executeAsBlocking().filter {
|
val mangas = getLibraryManga.await().filter {
|
||||||
it.id in savedMangasList
|
it.id in savedMangasList
|
||||||
}.distinctBy { it.id }
|
}.distinctBy { it.id }
|
||||||
val categoryId = inputData.getInt(KEY_CATEGORY, -1)
|
val categoryId = inputData.getInt(KEY_CATEGORY, -1)
|
||||||
|
@ -466,7 +469,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getMangaToUpdate(): List<LibraryManga> {
|
private suspend fun getMangaToUpdate(): List<LibraryManga> {
|
||||||
val categoryId = inputData.getInt(KEY_CATEGORY, -1)
|
val categoryId = inputData.getInt(KEY_CATEGORY, -1)
|
||||||
return getMangaToUpdate(categoryId)
|
return getMangaToUpdate(categoryId)
|
||||||
}
|
}
|
||||||
|
@ -477,8 +480,8 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||||
* @param categoryId the category to update
|
* @param categoryId the category to update
|
||||||
* @return a list of manga to update
|
* @return a list of manga to update
|
||||||
*/
|
*/
|
||||||
private fun getMangaToUpdate(categoryId: Int): List<LibraryManga> {
|
private suspend fun getMangaToUpdate(categoryId: Int): List<LibraryManga> {
|
||||||
val libraryManga = db.getLibraryMangas().executeAsBlocking()
|
val libraryManga = getLibraryManga.await()
|
||||||
|
|
||||||
val listToUpdate = if (categoryId != -1) {
|
val listToUpdate = if (categoryId != -1) {
|
||||||
categoryIds.add(categoryId)
|
categoryIds.add(categoryId)
|
||||||
|
@ -555,7 +558,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addCategory(categoryId: Int) {
|
private fun addCategory(categoryId: Int) {
|
||||||
val mangas = filterMangaToUpdate(getMangaToUpdate(categoryId)).sortedBy { it.title }
|
val mangas = filterMangaToUpdate(runBlocking { getMangaToUpdate(categoryId) }).sortedBy { it.title }
|
||||||
categoryIds.add(categoryId)
|
categoryIds.add(categoryId)
|
||||||
addManga(mangas)
|
addManga(mangas)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
package eu.kanade.tachiyomi.ui.library
|
package eu.kanade.tachiyomi.ui.library
|
||||||
|
|
||||||
|
import dev.yokai.domain.manga.interactor.GetLibraryManga
|
||||||
import dev.yokai.util.isLewd
|
import dev.yokai.util.isLewd
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.core.preference.minusAssign
|
||||||
|
import eu.kanade.tachiyomi.core.preference.plusAssign
|
||||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.Category
|
import eu.kanade.tachiyomi.data.database.models.Category
|
||||||
|
@ -14,8 +17,6 @@ import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||||
import eu.kanade.tachiyomi.data.preference.DelayedLibrarySuggestionsJob
|
import eu.kanade.tachiyomi.data.preference.DelayedLibrarySuggestionsJob
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.core.preference.minusAssign
|
|
||||||
import eu.kanade.tachiyomi.core.preference.plusAssign
|
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
import eu.kanade.tachiyomi.source.LocalSource
|
import eu.kanade.tachiyomi.source.LocalSource
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
|
@ -51,9 +52,8 @@ import kotlinx.coroutines.runBlocking
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import java.util.Calendar
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.util.Date
|
import java.util.*
|
||||||
import java.util.Locale
|
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
@ -70,6 +70,7 @@ class LibraryPresenter(
|
||||||
private val chapterFilter: ChapterFilter = Injekt.get(),
|
private val chapterFilter: ChapterFilter = Injekt.get(),
|
||||||
private val trackManager: TrackManager = Injekt.get(),
|
private val trackManager: TrackManager = Injekt.get(),
|
||||||
) : BaseCoroutinePresenter<LibraryController>() {
|
) : BaseCoroutinePresenter<LibraryController>() {
|
||||||
|
private val getLibraryManga: GetLibraryManga by injectLazy()
|
||||||
|
|
||||||
private val context = preferences.context
|
private val context = preferences.context
|
||||||
private val viewContext
|
private val viewContext
|
||||||
|
@ -162,7 +163,7 @@ class LibraryPresenter(
|
||||||
) {
|
) {
|
||||||
// Doing this instead of a job in case the app isn't used often
|
// Doing this instead of a job in case the app isn't used often
|
||||||
presenterScope.launchIO {
|
presenterScope.launchIO {
|
||||||
setSearchSuggestion(preferences, db, sourceManager)
|
setSearchSuggestion(preferences, getLibraryManga, sourceManager)
|
||||||
withUIContext { view?.setTitle() }
|
withUIContext { view?.setTitle() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -713,10 +714,10 @@ class LibraryPresenter(
|
||||||
*
|
*
|
||||||
* @return an list of all the manga in a itemized form.
|
* @return an list of all the manga in a itemized form.
|
||||||
*/
|
*/
|
||||||
private fun getLibraryFromDB(): Pair<List<LibraryItem>, List<LibraryItem>> {
|
private suspend fun getLibraryFromDB(): Pair<List<LibraryItem>, List<LibraryItem>> {
|
||||||
removeArticles = preferences.removeArticles().get()
|
removeArticles = preferences.removeArticles().get()
|
||||||
val categories = db.getCategories().executeAsBlocking().toMutableList()
|
val categories = db.getCategories().executeAsBlocking().toMutableList()
|
||||||
var libraryManga = db.getLibraryMangas().executeAsBlocking()
|
var libraryManga = getLibraryManga.await()
|
||||||
val showAll = showAllCategories
|
val showAll = showAllCategories
|
||||||
if (groupType > BY_DEFAULT) {
|
if (groupType > BY_DEFAULT) {
|
||||||
libraryManga = libraryManga.distinctBy { it.id }
|
libraryManga = libraryManga.distinctBy { it.id }
|
||||||
|
@ -1381,7 +1382,7 @@ class LibraryPresenter(
|
||||||
|
|
||||||
suspend fun setSearchSuggestion(
|
suspend fun setSearchSuggestion(
|
||||||
preferences: PreferencesHelper,
|
preferences: PreferencesHelper,
|
||||||
db: DatabaseHelper,
|
getLibraryManga: GetLibraryManga,
|
||||||
sourceManager: SourceManager,
|
sourceManager: SourceManager,
|
||||||
) {
|
) {
|
||||||
val random: Random = run {
|
val random: Random = run {
|
||||||
|
@ -1398,7 +1399,7 @@ class LibraryPresenter(
|
||||||
RecentsPresenter.getRecentManga(true).map { it.first }
|
RecentsPresenter.getRecentManga(true).map { it.first }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val libraryManga by lazy { db.getLibraryMangas().executeAsBlocking() }
|
val libraryManga by lazy { runBlocking { getLibraryManga.await() } }
|
||||||
preferences.librarySearchSuggestion().set(
|
preferences.librarySearchSuggestion().set(
|
||||||
when (val value = random.nextInt(0, 5)) {
|
when (val value = random.nextInt(0, 5)) {
|
||||||
randomSource -> {
|
randomSource -> {
|
||||||
|
@ -1450,8 +1451,9 @@ class LibraryPresenter(
|
||||||
/** Give library manga to a date added based on min chapter fetch */
|
/** Give library manga to a date added based on min chapter fetch */
|
||||||
fun updateDB() {
|
fun updateDB() {
|
||||||
val db: DatabaseHelper = Injekt.get()
|
val db: DatabaseHelper = Injekt.get()
|
||||||
|
val getLibraryManga: GetLibraryManga by injectLazy()
|
||||||
db.inTransaction {
|
db.inTransaction {
|
||||||
val libraryManga = db.getLibraryMangas().executeAsBlocking()
|
val libraryManga = runBlocking { getLibraryManga.await() }
|
||||||
libraryManga.forEach { manga ->
|
libraryManga.forEach { manga ->
|
||||||
if (manga.date_added == 0L) {
|
if (manga.date_added == 0L) {
|
||||||
val chapters = db.getChapters(manga).executeAsBlocking()
|
val chapters = db.getChapters(manga).executeAsBlocking()
|
||||||
|
@ -1474,8 +1476,9 @@ class LibraryPresenter(
|
||||||
fun updateCustoms() {
|
fun updateCustoms() {
|
||||||
val db: DatabaseHelper = Injekt.get()
|
val db: DatabaseHelper = Injekt.get()
|
||||||
val cc: CoverCache = Injekt.get()
|
val cc: CoverCache = Injekt.get()
|
||||||
|
val getLibraryManga: GetLibraryManga by injectLazy()
|
||||||
db.inTransaction {
|
db.inTransaction {
|
||||||
val libraryManga = db.getLibraryMangas().executeAsBlocking()
|
val libraryManga = runBlocking { getLibraryManga.await() }
|
||||||
libraryManga.forEach { manga ->
|
libraryManga.forEach { manga ->
|
||||||
if (manga.thumbnail_url?.startsWith("custom", ignoreCase = true) == true) {
|
if (manga.thumbnail_url?.startsWith("custom", ignoreCase = true) == true) {
|
||||||
val file = cc.getCoverFile(manga)
|
val file = cc.getCoverFile(manga)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package eu.kanade.tachiyomi.ui.more.stats
|
package eu.kanade.tachiyomi.ui.more.stats
|
||||||
|
|
||||||
|
import dev.yokai.domain.manga.interactor.GetLibraryManga
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.LibraryManga
|
import eu.kanade.tachiyomi.data.database.models.LibraryManga
|
||||||
|
@ -16,8 +17,10 @@ import eu.kanade.tachiyomi.source.CatalogueSource
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.ui.more.stats.StatsHelper.getReadDuration
|
import eu.kanade.tachiyomi.ui.more.stats.StatsHelper.getReadDuration
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Presenter of [StatsController].
|
* Presenter of [StatsController].
|
||||||
|
@ -29,12 +32,13 @@ class StatsPresenter(
|
||||||
private val downloadManager: DownloadManager = Injekt.get(),
|
private val downloadManager: DownloadManager = Injekt.get(),
|
||||||
private val sourceManager: SourceManager = Injekt.get(),
|
private val sourceManager: SourceManager = Injekt.get(),
|
||||||
) {
|
) {
|
||||||
|
private val getLibraryManga: GetLibraryManga by injectLazy()
|
||||||
|
|
||||||
private val libraryMangas = getLibrary()
|
private val libraryMangas = getLibrary()
|
||||||
val mangaDistinct = libraryMangas.distinct()
|
val mangaDistinct = libraryMangas.distinct()
|
||||||
|
|
||||||
private fun getLibrary(): MutableList<LibraryManga> {
|
private fun getLibrary(): MutableList<LibraryManga> {
|
||||||
return db.getLibraryMangas().executeAsBlocking()
|
return runBlocking { getLibraryManga.await() }.toMutableList()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTracks(manga: Manga): MutableList<Track> {
|
fun getTracks(manga: Manga): MutableList<Track> {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.more.stats.details
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.text.format.DateUtils
|
import android.text.format.DateUtils
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
|
import dev.yokai.domain.manga.interactor.GetLibraryManga
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.Category
|
import eu.kanade.tachiyomi.data.database.models.Category
|
||||||
|
@ -27,6 +28,7 @@ import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||||
import eu.kanade.tachiyomi.util.system.launchIO
|
import eu.kanade.tachiyomi.util.system.launchIO
|
||||||
import eu.kanade.tachiyomi.util.system.roundToTwoDecimal
|
import eu.kanade.tachiyomi.util.system.roundToTwoDecimal
|
||||||
import eu.kanade.tachiyomi.util.system.withUIContext
|
import eu.kanade.tachiyomi.util.system.withUIContext
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
@ -41,6 +43,7 @@ class StatsDetailsPresenter(
|
||||||
val trackManager: TrackManager = Injekt.get(),
|
val trackManager: TrackManager = Injekt.get(),
|
||||||
private val sourceManager: SourceManager = Injekt.get(),
|
private val sourceManager: SourceManager = Injekt.get(),
|
||||||
) : BaseCoroutinePresenter<StatsDetailsController>() {
|
) : BaseCoroutinePresenter<StatsDetailsController>() {
|
||||||
|
private val getLibraryManga: GetLibraryManga by injectLazy()
|
||||||
|
|
||||||
private val context
|
private val context
|
||||||
get() = view?.view?.context ?: prefs.context
|
get() = view?.view?.context ?: prefs.context
|
||||||
|
@ -555,7 +558,7 @@ class StatsDetailsPresenter(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLibrary(): MutableList<LibraryManga> {
|
fun getLibrary(): MutableList<LibraryManga> {
|
||||||
return db.getLibraryMangas().executeAsBlocking()
|
return runBlocking { getLibraryManga.await() }.toMutableList()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCategories(): MutableList<Category> {
|
private fun getCategories(): MutableList<Category> {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package eu.kanade.tachiyomi.ui.setting.controllers
|
package eu.kanade.tachiyomi.ui.setting.controllers
|
||||||
|
|
||||||
import androidx.preference.PreferenceScreen
|
import androidx.preference.PreferenceScreen
|
||||||
|
import dev.yokai.domain.manga.interactor.GetLibraryManga
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.Category
|
import eu.kanade.tachiyomi.data.database.models.Category
|
||||||
|
@ -28,11 +29,13 @@ import eu.kanade.tachiyomi.util.system.launchUI
|
||||||
import eu.kanade.tachiyomi.util.view.withFadeTransaction
|
import eu.kanade.tachiyomi.util.view.withFadeTransaction
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
import uy.kohesive.injekt.injectLazy
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
|
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
|
||||||
|
|
||||||
class SettingsLibraryController : SettingsLegacyController() {
|
class SettingsLibraryController : SettingsLegacyController() {
|
||||||
|
|
||||||
private val db: DatabaseHelper = Injekt.get()
|
private val db: DatabaseHelper by injectLazy()
|
||||||
|
private val getLibraryManga: GetLibraryManga by injectLazy()
|
||||||
|
|
||||||
override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply {
|
override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply {
|
||||||
titleRes = R.string.library
|
titleRes = R.string.library
|
||||||
|
@ -54,7 +57,7 @@ class SettingsLibraryController : SettingsLegacyController() {
|
||||||
it as Boolean
|
it as Boolean
|
||||||
if (it) {
|
if (it) {
|
||||||
launchIO {
|
launchIO {
|
||||||
LibraryPresenter.setSearchSuggestion(preferences, db, Injekt.get())
|
LibraryPresenter.setSearchSuggestion(preferences, getLibraryManga, Injekt.get())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DelayedLibrarySuggestionsJob.setupTask(context, false)
|
DelayedLibrarySuggestionsJob.setupTask(context, false)
|
||||||
|
|
37
app/src/main/sqldelight/tachiyomi/migrations/20.sqm
Normal file
37
app/src/main/sqldelight/tachiyomi/migrations/20.sqm
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
CREATE VIEW library_view AS
|
||||||
|
SELECT
|
||||||
|
M.*,
|
||||||
|
coalesce(C.total, 0) AS total,
|
||||||
|
coalesce(C.read_count, 0) AS has_read,
|
||||||
|
coalesce(C.bookmark_count, 0) AS bookmark_count,
|
||||||
|
coalesce(MC.category_id, 0) AS category
|
||||||
|
FROM mangas AS M
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT
|
||||||
|
chapters.manga_id,
|
||||||
|
count(*) AS total,
|
||||||
|
sum(read) AS read_count,
|
||||||
|
sum(bookmark) AS bookmark_count
|
||||||
|
FROM chapters
|
||||||
|
LEFT JOIN (
|
||||||
|
WITH RECURSIVE split(seq, _id, name, str) AS (
|
||||||
|
SELECT 0, mangas._id, NULL, replace(ifnull(mangas.filtered_scanlators, ''), ' & ', '[.]')||'[.]' FROM mangas
|
||||||
|
UNION ALL SELECT
|
||||||
|
seq+1,
|
||||||
|
_id,
|
||||||
|
substr(str, 0, instr(str, '[.]')),
|
||||||
|
substr(str, instr(str, '[.]')+3)
|
||||||
|
FROM split WHERE str != ''
|
||||||
|
) SELECT _id, name FROM split WHERE split.seq != 0 ORDER BY split.seq ASC
|
||||||
|
) AS filtered_scanlators
|
||||||
|
ON chapters.manga_id = filtered_scanlators._id
|
||||||
|
AND ifnull(chapters.scanlator, 'N/A') = ifnull(filtered_scanlators.name, '/<INVALID>/')
|
||||||
|
WHERE filtered_scanlators.name IS NULL
|
||||||
|
GROUP BY chapters.manga_id
|
||||||
|
) AS C
|
||||||
|
ON M._id = C.manga_id
|
||||||
|
LEFT JOIN mangas_categories AS MC
|
||||||
|
ON MC.manga_id = M._id
|
||||||
|
WHERE M.favorite = 1
|
||||||
|
GROUP BY M._id
|
||||||
|
ORDER BY M.title;
|
|
@ -14,13 +14,13 @@ LEFT JOIN (
|
||||||
sum(bookmark) AS bookmark_count
|
sum(bookmark) AS bookmark_count
|
||||||
FROM chapters
|
FROM chapters
|
||||||
LEFT JOIN (
|
LEFT JOIN (
|
||||||
WITH RECURSIVE split(seq, _id, name, str) AS (
|
WITH RECURSIVE split(seq, _id, name, str) AS ( -- Probably should migrate this to its own table someday
|
||||||
SELECT 0, mangas._id, NULL, replace(ifnull(mangas.filtered_scanlators, ''), ' & ', ',')||',' FROM mangas
|
SELECT 0, mangas._id, NULL, replace(ifnull(mangas.filtered_scanlators, ''), ' & ', '[.]')||'[.]' FROM mangas
|
||||||
UNION ALL SELECT
|
UNION ALL SELECT
|
||||||
seq+1,
|
seq+1,
|
||||||
_id,
|
_id,
|
||||||
substr(str, 0, instr(str, ',')),
|
substr(str, 0, instr(str, '[.]')),
|
||||||
substr(str, instr(str, ',')+1)
|
substr(str, instr(str, '[.]')+3)
|
||||||
FROM split WHERE str != ''
|
FROM split WHERE str != ''
|
||||||
) SELECT _id, name FROM split WHERE split.seq != 0 ORDER BY split.seq ASC
|
) SELECT _id, name FROM split WHERE split.seq != 0 ORDER BY split.seq ASC
|
||||||
) AS filtered_scanlators
|
) AS filtered_scanlators
|
||||||
|
@ -35,3 +35,7 @@ ON MC.manga_id = M._id
|
||||||
WHERE M.favorite = 1
|
WHERE M.favorite = 1
|
||||||
GROUP BY M._id
|
GROUP BY M._id
|
||||||
ORDER BY M.title;
|
ORDER BY M.title;
|
||||||
|
|
||||||
|
findAll:
|
||||||
|
SELECT *
|
||||||
|
FROM library_view;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue