chore: Rewriting getLibrary func

This commit is contained in:
Ahmad Ansori Palembani 2024-06-18 21:12:01 +07:00
parent de48b52ec3
commit 893af9bd73
Signed by: null2264
GPG key ID: BA64F8B60AF3EFB6
9 changed files with 159 additions and 24 deletions

View file

@ -52,24 +52,16 @@ class CategoryPutResolver : DefaultPutResolver<Category>() {
class CategoryGetResolver : DefaultGetResolver<Category>() {
override fun mapFromCursor(cursor: Cursor): Category = CategoryImpl().apply {
id = cursor.getInt(cursor.getColumnIndex(COL_ID))
name = cursor.getString(cursor.getColumnIndex(COL_NAME))
order = cursor.getInt(cursor.getColumnIndex(COL_ORDER))
flags = cursor.getInt(cursor.getColumnIndex(COL_FLAGS))
override fun mapFromCursor(cursor: Cursor): Category = CategoryImpl().also {
it.id = cursor.getInt(cursor.getColumnIndex(COL_ID))
it.name = cursor.getString(cursor.getColumnIndex(COL_NAME))
it.order = cursor.getInt(cursor.getColumnIndex(COL_ORDER))
it.flags = cursor.getInt(cursor.getColumnIndex(COL_FLAGS))
val orderString = cursor.getString(cursor.getColumnIndex(COL_MANGA_ORDER))
when {
orderString.isNullOrBlank() -> {
mangaSort = 'a'
mangaOrder = emptyList()
}
orderString.firstOrNull()?.isLetter() == true -> {
mangaSort = orderString.first()
mangaOrder = emptyList()
}
else -> mangaOrder = orderString.split("/").mapNotNull { it.toLongOrNull() }
}
val (sort, order) = Category.mangaOrderFromString(orderString)
if (sort != null) it.mangaSort = sort
it.mangaOrder = order
}
}

View file

@ -30,6 +30,8 @@ interface Category : Serializable {
var langId: String?
var isSystem: Boolean
fun isAscending(): Boolean {
return ((mangaSort?.minus('a') ?: 0) % 2) != 1
}
@ -61,6 +63,7 @@ interface Category : Serializable {
fun createDefault(context: Context): Category =
create(context.getString(R.string.default_value)).apply {
id = 0
isSystem = true
}
fun createCustom(name: String, libSort: Int, ascending: Boolean): Category =
@ -78,6 +81,36 @@ interface Category : Serializable {
id = -1
order = -1
isAlone = true
isSystem = true
}
fun mangaOrderFromString(orderString: String?): Pair<Char?, List<Long>> {
return when {
orderString.isNullOrBlank() -> {
Pair('a', emptyList())
}
orderString.firstOrNull()?.isLetter() == true -> {
Pair(orderString.first(), emptyList())
}
else -> Pair(null, orderString.split("/").mapNotNull { it.toLongOrNull() })
}
}
fun mapper(
id: Long,
name: String,
sort: Long,
flags: Long,
orderString: String,
) = create(name).also {
it.id = id.toInt()
it.name = name
it.order = sort.toInt()
it.flags = flags.toInt()
val (mangaSort, order) = mangaOrderFromString(orderString)
if (mangaSort != null) it.mangaSort = mangaSort
it.mangaOrder = order
}
}
}

View file

@ -24,6 +24,8 @@ class CategoryImpl : Category {
override var langId: String? = null
override var isSystem: Boolean = false
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || javaClass != other.javaClass) return false

View file

@ -49,12 +49,15 @@ import eu.kanade.tachiyomi.util.system.launchUI
import eu.kanade.tachiyomi.util.system.withIOContext
import eu.kanade.tachiyomi.util.system.withUIContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
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.GetChapters
import yokai.domain.manga.interactor.GetLibraryManga
import yokai.util.isLewd
@ -63,6 +66,11 @@ import java.util.concurrent.*
import kotlin.math.roundToInt
import kotlin.random.Random
/**
* Typealias for the library manga, using the category as keys, and list of manga as values.
*/
typealias LibraryMap = Map<Category, List<LibraryItem>>
/**
* Presenter of [LibraryController].
*/
@ -75,6 +83,7 @@ class LibraryPresenter(
private val chapterFilter: ChapterFilter = Injekt.get(),
private val trackManager: TrackManager = Injekt.get(),
) : BaseCoroutinePresenter<LibraryController>(), DownloadQueue.DownloadListener {
private val getCategories: GetCategories by injectLazy()
private val getLibraryManga: GetLibraryManga by injectLazy()
private val getChapters: GetChapters by injectLazy()
@ -189,14 +198,15 @@ class LibraryPresenter(
/** Get favorited manga for library and sort and filter it */
fun getLibrary() {
if (categories.isEmpty()) {
val dbCategories = db.getCategories().executeAsBlocking()
if ((dbCategories + Category.createDefault(context)).distinctBy { it.order }.size != dbCategories.size + 1) {
reorderCategories(dbCategories)
}
categories = lastCategories ?: db.getCategories().executeAsBlocking().toMutableList()
}
presenterScope.launch {
if (categories.isEmpty()) {
val dbCategories = getCategories.await()
if ((dbCategories + Category.createDefault(context)).distinctBy { it.order }.size != dbCategories.size + 1) {
reorderCategories(dbCategories)
}
categories = lastCategories ?: getCategories.await().toMutableList()
}
val (library, hiddenItems) = withIOContext { getLibraryFromDB() }
setDownloadCount(library)
setUnreadBadge(library)
@ -700,6 +710,54 @@ class LibraryPresenter(
}
}
// TODO: Migrate getCategories to SQLDelight
/*
private fun getPreferencesFlow() = combine(
) {
ItemPreferences(
)
}
*/
private fun getLibraryFlow(): Flow<LibraryMap> {
return combine(
getCategories.subscribe(),
getLibraryManga.subscribe(),
) { categories, libraryMangaList ->
val categoryAll = Category.createAll(
context,
preferences.librarySortingMode().get(),
preferences.librarySortingAscending().get(),
)
val catItemAll = LibraryHeaderItem({ categoryAll }, -1)
val categorySet = mutableSetOf<Int>()
val headerItems = (
categories.mapNotNull { category ->
val id = category.id
if (id == null) {
null
} else {
id to LibraryHeaderItem({ getCategory(id) }, id)
}
} + (-1 to catItemAll) + (0 to LibraryHeaderItem({ getCategory(0) }, 0))
).toMap()
val libraryManga = libraryMangaList.mapNotNull {
val headerItem = (
if (!libraryIsGrouped) {
catItemAll
} else {
headerItems[it.category]
}
) ?: return@mapNotNull null
categorySet.add(it.category)
LibraryItem(it, headerItem, viewContext)
}.groupBy { it.manga.category }
categories.associateWith { libraryManga[it.id].orEmpty() }
}
}
/**
* Get the categories and all its manga from the database.
*
@ -707,7 +765,7 @@ class LibraryPresenter(
*/
private suspend fun getLibraryFromDB(): Pair<List<LibraryItem>, List<LibraryItem>> {
removeArticles = preferences.removeArticles().get()
val categories = db.getCategories().executeAsBlocking().toMutableList()
val categories = getCategories.await().toMutableList()
var libraryManga = getLibraryManga.await()
val showAll = showAllCategories
if (groupType > BY_DEFAULT) {
@ -1491,4 +1549,10 @@ class LibraryPresenter(
view?.updateDownloadStatus(!downloadManager.isPaused())
}
}
/*
@Immutable
data class ItemPreferences(
)
*/
}

View file

@ -5,10 +5,13 @@ import uy.kohesive.injekt.api.InjektRegistrar
import uy.kohesive.injekt.api.addFactory
import uy.kohesive.injekt.api.addSingletonFactory
import uy.kohesive.injekt.api.get
import yokai.data.category.CategoryRepositoryImpl
import yokai.data.chapter.ChapterRepositoryImpl
import yokai.data.extension.repo.ExtensionRepoRepositoryImpl
import yokai.data.library.custom.CustomMangaRepositoryImpl
import yokai.data.manga.MangaRepositoryImpl
import yokai.domain.category.CategoryRepository
import yokai.domain.category.interactor.GetCategories
import yokai.domain.chapter.ChapterRepository
import yokai.domain.chapter.interactor.GetAvailableScanlators
import yokai.domain.chapter.interactor.GetChapters
@ -52,5 +55,8 @@ class DomainModule : InjektModule {
addSingletonFactory<ChapterRepository> { ChapterRepositoryImpl(get()) }
addFactory { GetAvailableScanlators(get()) }
addFactory { GetChapters(get()) }
addSingletonFactory<CategoryRepository> { CategoryRepositoryImpl(get()) }
addFactory { GetCategories(get()) }
}
}

View file

@ -0,0 +1,14 @@
package yokai.data.category
import eu.kanade.tachiyomi.data.database.models.Category
import kotlinx.coroutines.flow.Flow
import yokai.data.DatabaseHandler
import yokai.domain.category.CategoryRepository
class CategoryRepositoryImpl(private val handler: DatabaseHandler) : CategoryRepository {
override suspend fun getAll(): List<Category> =
handler.awaitList { categoriesQueries.findAll(Category::mapper) }
override fun getAllAsFlow(): Flow<List<Category>> =
handler.subscribeToList { categoriesQueries.findAll(Category::mapper) }
}

View file

@ -0,0 +1,9 @@
package yokai.domain.category
import eu.kanade.tachiyomi.data.database.models.Category
import kotlinx.coroutines.flow.Flow
interface CategoryRepository {
suspend fun getAll(): List<Category>
fun getAllAsFlow(): Flow<List<Category>>
}

View file

@ -0,0 +1,10 @@
package yokai.domain.category.interactor
import yokai.domain.category.CategoryRepository
class GetCategories(
val categoryRepository: CategoryRepository,
) {
suspend fun await() = categoryRepository.getAll()
fun subscribe() = categoryRepository.getAllAsFlow()
}

View file

@ -5,3 +5,8 @@ CREATE TABLE categories(
flags INTEGER NOT NULL,
manga_order TEXT NOT NULL
);
findAll:
SELECT *
FROM categories
ORDER BY sort;