mirror of
https://github.com/null2264/yokai.git
synced 2025-06-20 18:24:42 +00:00
refactor(library): Utilise flow even more (#272)
* revert: "revert: "refactor(library): Some adjustments""
This reverts commit 2b639d0630
.
* fix: Don't use emptyFlow
* fix: Fix build
* fix: Don't overwrite allCategories inside `combine {}`
* fix: Fix build
This commit is contained in:
parent
09bd1a9f78
commit
365d259e94
4 changed files with 87 additions and 77 deletions
|
@ -557,7 +557,7 @@ open class LibraryController(
|
|||
}
|
||||
presenter.groupType = item
|
||||
shouldScrollToTop = true
|
||||
presenter.getLibrary()
|
||||
presenter.updateLibrary()
|
||||
true
|
||||
}.show()
|
||||
}
|
||||
|
@ -1056,7 +1056,7 @@ open class LibraryController(
|
|||
if (type.isEnter) {
|
||||
binding.filterBottomSheet.filterBottomSheet.isVisible = true
|
||||
if (type == ControllerChangeType.POP_ENTER) {
|
||||
presenter.getLibrary()
|
||||
presenter.updateLibrary()
|
||||
isPoppingIn = true
|
||||
}
|
||||
binding.recyclerCover.isClickable = false
|
||||
|
@ -1095,7 +1095,7 @@ open class LibraryController(
|
|||
if (!isBindingInitialized) return
|
||||
updateFilterSheetY()
|
||||
if (observeLater) {
|
||||
presenter.getLibrary()
|
||||
presenter.updateLibrary()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1408,7 +1408,7 @@ open class LibraryController(
|
|||
|
||||
private fun onRefresh() {
|
||||
showCategories(false)
|
||||
presenter.getLibrary()
|
||||
presenter.updateLibrary()
|
||||
destroyActionModeIfNeeded()
|
||||
}
|
||||
|
||||
|
@ -1432,14 +1432,14 @@ open class LibraryController(
|
|||
val isShowAllCategoriesSet = preferences.showAllCategories().get()
|
||||
if (!query.isNullOrBlank() && this.query.isBlank() && !isShowAllCategoriesSet) {
|
||||
presenter.forceShowAllCategories = preferences.showAllCategoriesWhenSearchingSingleCategory().get()
|
||||
presenter.getLibrary()
|
||||
presenter.updateLibrary()
|
||||
} else if (query.isNullOrBlank() && this.query.isNotBlank() && !isShowAllCategoriesSet) {
|
||||
if (!isSubClass) {
|
||||
preferences.showAllCategoriesWhenSearchingSingleCategory()
|
||||
.set(presenter.forceShowAllCategories)
|
||||
}
|
||||
presenter.forceShowAllCategories = false
|
||||
presenter.getLibrary()
|
||||
presenter.updateLibrary()
|
||||
}
|
||||
|
||||
if (query != this.query && !query.isNullOrBlank()) {
|
||||
|
@ -1641,7 +1641,7 @@ open class LibraryController(
|
|||
if (mangaId == null) {
|
||||
adapter.getHeaderPositions().forEach { adapter.notifyItemChanged(it) }
|
||||
} else {
|
||||
presenter.updateManga()
|
||||
presenter.updateLibrary()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1820,7 +1820,7 @@ open class LibraryController(
|
|||
val category = (adapter.getItem(position) as? LibraryHeaderItem)?.category ?: return
|
||||
if (!category.isDynamic) {
|
||||
ManageCategoryDialog(category) {
|
||||
presenter.getLibrary()
|
||||
presenter.updateLibrary()
|
||||
}.showDialog(router)
|
||||
}
|
||||
}
|
||||
|
@ -1913,7 +1913,7 @@ open class LibraryController(
|
|||
isGone = true
|
||||
setOnClickListener {
|
||||
presenter.forceShowAllCategories = !presenter.forceShowAllCategories
|
||||
presenter.getLibrary()
|
||||
presenter.updateLibrary()
|
||||
isSelected = presenter.forceShowAllCategories
|
||||
}
|
||||
val pad = 12.dpToPx
|
||||
|
@ -2193,7 +2193,7 @@ open class LibraryController(
|
|||
val activity = activity ?: return
|
||||
viewScope.launchIO {
|
||||
selectedMangas.toList().moveCategories(activity) {
|
||||
presenter.getLibrary()
|
||||
presenter.updateLibrary()
|
||||
destroyActionModeIfNeeded()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.data.database.models.LibraryManga
|
|||
import eu.kanade.tachiyomi.data.database.models.Track
|
||||
import eu.kanade.tachiyomi.data.database.models.removeCover
|
||||
import eu.kanade.tachiyomi.data.database.models.seriesType
|
||||
import eu.kanade.tachiyomi.data.download.DownloadCache
|
||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||
import eu.kanade.tachiyomi.data.preference.DelayedLibrarySuggestionsJob
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
|
@ -51,11 +52,9 @@ import kotlin.random.Random
|
|||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.flow.retry
|
||||
import kotlinx.coroutines.flow.shareIn
|
||||
|
@ -89,6 +88,7 @@ class LibraryPresenter(
|
|||
private val preferences: PreferencesHelper = Injekt.get(),
|
||||
private val coverCache: CoverCache = Injekt.get(),
|
||||
val sourceManager: SourceManager = Injekt.get(),
|
||||
private val downloadCache: DownloadCache = Injekt.get(),
|
||||
private val downloadManager: DownloadManager = Injekt.get(),
|
||||
private val chapterFilter: ChapterFilter = Injekt.get(),
|
||||
private val trackManager: TrackManager = Injekt.get(),
|
||||
|
@ -103,10 +103,7 @@ class LibraryPresenter(
|
|||
private val getTrack: GetTrack by injectLazy()
|
||||
private val getHistory: GetHistory by injectLazy()
|
||||
|
||||
private val _fetchLibrary: Channel<Unit> = Channel(Channel.UNLIMITED)
|
||||
val fetchLibrary = _fetchLibrary.receiveAsFlow()
|
||||
.onStart { emit(Unit) }
|
||||
.shareIn(presenterScope, SharingStarted.Lazily, 1)
|
||||
private val forceUpdateEvent: Channel<Unit> = Channel(Channel.UNLIMITED)
|
||||
|
||||
private val context = preferences.context
|
||||
private val viewContext
|
||||
|
@ -129,6 +126,8 @@ class LibraryPresenter(
|
|||
private var allCategories: List<Category> = emptyList()
|
||||
|
||||
/** List of all manga to update the */
|
||||
// TODO: Store sectioned before flattening it out for "show all categories"
|
||||
private var currentLibrary: Map<Category, List<LibraryItem>> = mapOf()
|
||||
var libraryItems: List<LibraryItem> = emptyList()
|
||||
private var sectionedLibraryItems: MutableMap<Int, List<LibraryItem>> = mutableMapOf()
|
||||
var currentCategory = -1
|
||||
|
@ -197,6 +196,7 @@ class LibraryPresenter(
|
|||
}
|
||||
|
||||
subscribeLibrary()
|
||||
updateLibrary()
|
||||
|
||||
if (!preferences.showLibrarySearchSuggestions().isSet()) {
|
||||
DelayedLibrarySuggestionsJob.setupTask(context, true)
|
||||
|
@ -233,38 +233,29 @@ class LibraryPresenter(
|
|||
|
||||
combine(
|
||||
getLibraryFlow(),
|
||||
fetchLibrary,
|
||||
) { data, _ ->
|
||||
downloadCache.changes,
|
||||
) { data, _ -> data }.collectLatest { data ->
|
||||
categories = data.categories
|
||||
allCategories = data.allCategories
|
||||
|
||||
data.items
|
||||
val library = data.items
|
||||
val hiddenItems = library.filter { it.manga.isHidden() }.mapNotNull { it.manga.items }.flatten()
|
||||
|
||||
setDownloadCount(library)
|
||||
setUnreadBadge(library)
|
||||
setSourceLanguage(library)
|
||||
setDownloadCount(hiddenItems)
|
||||
setUnreadBadge(hiddenItems)
|
||||
setSourceLanguage(hiddenItems)
|
||||
|
||||
allLibraryItems = library
|
||||
hiddenLibraryItems = hiddenItems
|
||||
val mangaMap = library
|
||||
.applyFilters()
|
||||
.applySort()
|
||||
val freshStart = libraryItems.isEmpty()
|
||||
sectionLibrary(mangaMap, freshStart)
|
||||
}
|
||||
.collectLatest { library ->
|
||||
val hiddenItems = library.filter { it.manga.isHidden() }.mapNotNull { it.manga.items }.flatten()
|
||||
|
||||
setDownloadCount(library)
|
||||
setUnreadBadge(library)
|
||||
setSourceLanguage(library)
|
||||
setDownloadCount(hiddenItems)
|
||||
setUnreadBadge(hiddenItems)
|
||||
setSourceLanguage(hiddenItems)
|
||||
|
||||
allLibraryItems = library
|
||||
hiddenLibraryItems = hiddenItems
|
||||
val mangaMap = library
|
||||
.applyFilters()
|
||||
.applySort()
|
||||
val freshStart = libraryItems.isEmpty()
|
||||
sectionLibrary(mangaMap, freshStart)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Get favorited manga for library and sort and filter it */
|
||||
fun getLibrary() {
|
||||
presenterScope.launch {
|
||||
_fetchLibrary.send(Unit)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -321,8 +312,7 @@ class LibraryPresenter(
|
|||
|
||||
private suspend fun sectionLibrary(items: List<LibraryItem>, freshStart: Boolean = false) {
|
||||
libraryItems = items
|
||||
val showAll = showAllCategories || !libraryIsGrouped ||
|
||||
categories.size <= 1
|
||||
val showAll = showAllCategories || !libraryIsGrouped || categories.size <= 1
|
||||
sectionedLibraryItems = items.groupBy { it.header.category.id ?: 0 }.toMutableMap()
|
||||
if (!showAll && currentCategory == -1) {
|
||||
currentCategory = categories.find {
|
||||
|
@ -758,6 +748,9 @@ class LibraryPresenter(
|
|||
|
||||
preferences.librarySortingMode().changes(),
|
||||
preferences.librarySortingAscending().changes(),
|
||||
|
||||
preferences.collapsedCategories().changes(),
|
||||
preferences.collapsedDynamicCategories().changes(),
|
||||
) {
|
||||
ItemPreferences(
|
||||
filterDownloaded = it[0] as Int,
|
||||
|
@ -771,6 +764,8 @@ class LibraryPresenter(
|
|||
showAllCategories = it[8] as Boolean,
|
||||
sortingMode = it[9] as Int,
|
||||
sortAscending = it[10] as Boolean,
|
||||
collapsedCategories = it[11] as Set<String>,
|
||||
collapsedDynamicCategories = it[12] as Set<String>,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -808,26 +803,27 @@ class LibraryPresenter(
|
|||
* If category id '-1' is not empty, it means the library not grouped by categories
|
||||
*/
|
||||
private fun getLibraryFlow(): Flow<LibraryData> {
|
||||
return combine(
|
||||
val libraryFlow = combine(
|
||||
getCategories.subscribe(),
|
||||
// FIXME: Remove retry once a real solution is found
|
||||
getLibraryManga.subscribe().retry(1) { e -> e is NullPointerException },
|
||||
getPreferencesFlow(),
|
||||
preferences.removeArticles().changes(),
|
||||
fetchLibrary
|
||||
) { dbCategories, libraryMangaList, prefs, removeArticles, _ ->
|
||||
forceUpdateEvent.receiveAsFlow(),
|
||||
) { dbCategories, libraryMangaList, prefs, _ ->
|
||||
groupType = prefs.groupType
|
||||
|
||||
val defaultCategory = createDefaultCategory()
|
||||
val allCategories = listOf(defaultCategory) + dbCategories
|
||||
|
||||
val (items, categories, hiddenItems) = if (groupType <= BY_DEFAULT || !libraryIsGrouped) {
|
||||
// FIXME: Should return Map<Int, LibraryItem> where Int is category id
|
||||
if (groupType <= BY_DEFAULT || !libraryIsGrouped) {
|
||||
getLibraryItems(
|
||||
dbCategories,
|
||||
allCategories, // FIXME: Don't depends on allCategories
|
||||
libraryMangaList,
|
||||
prefs.sortingMode,
|
||||
prefs.sortAscending,
|
||||
prefs.showAllCategories,
|
||||
prefs.collapsedCategories,
|
||||
defaultCategory,
|
||||
)
|
||||
} else {
|
||||
|
@ -836,8 +832,17 @@ class LibraryPresenter(
|
|||
prefs.sortingMode,
|
||||
prefs.sortAscending,
|
||||
groupType,
|
||||
prefs.collapsedDynamicCategories,
|
||||
)
|
||||
}
|
||||
} to allCategories
|
||||
}
|
||||
|
||||
return combine(
|
||||
libraryFlow,
|
||||
preferences.removeArticles().changes(),
|
||||
) { library, removeArticles ->
|
||||
val (libraryItems, allCategories) = library
|
||||
val (items, categories, hiddenItems) = libraryItems
|
||||
|
||||
LibraryData(
|
||||
categories = categories,
|
||||
|
@ -855,6 +860,7 @@ class LibraryPresenter(
|
|||
sortingMode: Int,
|
||||
isAscending: Boolean,
|
||||
showAll: Boolean,
|
||||
collapsedCategories: Set<String>,
|
||||
defaultCategory: Category,
|
||||
): Triple<List<LibraryItem>, List<Category>, List<LibraryItem>> {
|
||||
val categories = allCategories.toMutableList()
|
||||
|
@ -878,6 +884,11 @@ class LibraryPresenter(
|
|||
} + (-1 to catItemAll) + (0 to LibraryHeaderItem({ categories.getOrDefault(0) }, 0))
|
||||
).toMap()
|
||||
|
||||
// TODO
|
||||
val map = libraryManga.groupBy {
|
||||
categories.getOrDefault(it.category)
|
||||
}
|
||||
|
||||
val items = if (libraryIsGrouped) {
|
||||
libraryManga
|
||||
} else {
|
||||
|
@ -897,16 +908,14 @@ class LibraryPresenter(
|
|||
val categoriesHidden = if (forceShowAllCategories || controllerIsSubClass) {
|
||||
emptySet()
|
||||
} else {
|
||||
preferences.collapsedCategories().get().mapNotNull { it.toIntOrNull() }.toSet()
|
||||
collapsedCategories.mapNotNull { it.toIntOrNull() }.toSet()
|
||||
}
|
||||
|
||||
if (categorySet.contains(0)) categories.add(0, defaultCategory)
|
||||
if (libraryIsGrouped) {
|
||||
categories.forEach { category ->
|
||||
val catId = category.id ?: return@forEach
|
||||
if (catId > 0 && !categorySet.contains(catId) &&
|
||||
(catId !in categoriesHidden || !showAll)
|
||||
) {
|
||||
if (catId > 0 && !categorySet.contains(catId) && (catId !in categoriesHidden || !showAll)) {
|
||||
val headerItem = headerItems[catId]
|
||||
if (headerItem != null) {
|
||||
items.add(
|
||||
|
@ -959,6 +968,7 @@ class LibraryPresenter(
|
|||
sortingMode: Int,
|
||||
isAscending: Boolean,
|
||||
groupType: Int,
|
||||
collapsedDynamicCategories: Set<String>,
|
||||
): Triple<List<LibraryItem>, List<Category>, List<LibraryItem>> {
|
||||
val tagItems: MutableMap<String, LibraryHeaderItem> = mutableMapOf()
|
||||
|
||||
|
@ -1061,7 +1071,7 @@ class LibraryPresenter(
|
|||
val hiddenDynamics = if (controllerIsSubClass) {
|
||||
emptySet()
|
||||
} else {
|
||||
preferences.collapsedDynamicCategories().get()
|
||||
collapsedDynamicCategories
|
||||
}
|
||||
val headers = tagItems.map { item ->
|
||||
Category.createCustom(
|
||||
|
@ -1217,7 +1227,6 @@ class LibraryPresenter(
|
|||
.mapNotNull { if (it.id != null) MangaUpdate(it.id!!, favorite = false) else null }
|
||||
|
||||
withIOContext { updateManga.awaitAll(mangaToDelete) }
|
||||
getLibrary()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1240,8 +1249,11 @@ class LibraryPresenter(
|
|||
}
|
||||
}
|
||||
|
||||
/** Called when Library Service updates a manga, update the item as well */
|
||||
fun updateManga() = getLibrary()
|
||||
/** Force update the library */
|
||||
fun updateLibrary() = presenterScope.launch {
|
||||
forceUpdateEvent.send(Unit)
|
||||
}
|
||||
|
||||
|
||||
/** Undo the removal of the manga once in library */
|
||||
fun reAddMangas(mangas: List<Manga>) {
|
||||
|
@ -1251,12 +1263,12 @@ class LibraryPresenter(
|
|||
|
||||
withIOContext { updateManga.awaitAll(mangaToAdd) }
|
||||
(view as? FilteredLibraryController)?.updateStatsPage()
|
||||
getLibrary()
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns first unread chapter of a manga */
|
||||
fun getFirstUnread(manga: Manga): Chapter? {
|
||||
// FIXME: Don't do blocking
|
||||
val chapters = runBlocking { getChapter.awaitAll(manga) }
|
||||
return ChapterSort(manga, chapterFilter, preferences).getNextUnreadChapter(chapters, false)
|
||||
}
|
||||
|
@ -1308,7 +1320,6 @@ class LibraryPresenter(
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Use SQLDelight
|
||||
/** Shift a manga's category via drag & drop */
|
||||
fun moveMangaToCategory(
|
||||
manga: LibraryManga,
|
||||
|
@ -1354,7 +1365,7 @@ class LibraryPresenter(
|
|||
)
|
||||
}
|
||||
}
|
||||
getLibrary()
|
||||
updateLibrary()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1389,7 +1400,6 @@ class LibraryPresenter(
|
|||
}
|
||||
preferences.collapsedDynamicCategories().set(categoriesHidden)
|
||||
}
|
||||
getLibrary()
|
||||
}
|
||||
|
||||
private fun getDynamicCategoryName(category: Category): String =
|
||||
|
@ -1420,7 +1430,6 @@ class LibraryPresenter(
|
|||
}
|
||||
}
|
||||
}
|
||||
getLibrary()
|
||||
}
|
||||
|
||||
fun allCategoriesExpanded(): Boolean {
|
||||
|
@ -1462,7 +1471,7 @@ class LibraryPresenter(
|
|||
|
||||
mapMangaChapters[manga] = chapters
|
||||
}
|
||||
getLibrary()
|
||||
updateLibrary()
|
||||
}
|
||||
return mapMangaChapters
|
||||
}
|
||||
|
@ -1478,7 +1487,7 @@ class LibraryPresenter(
|
|||
}
|
||||
}.flatten()
|
||||
updateChapter.awaitAll(updates)
|
||||
getLibrary()
|
||||
updateLibrary()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1651,6 +1660,9 @@ class LibraryPresenter(
|
|||
|
||||
val sortingMode: Int,
|
||||
val sortAscending: Boolean,
|
||||
|
||||
val collapsedCategories: Set<String>,
|
||||
val collapsedDynamicCategories: Set<String>,
|
||||
)
|
||||
|
||||
data class LibraryData(
|
||||
|
|
|
@ -2,16 +2,14 @@ package eu.kanade.tachiyomi.ui.library.display
|
|||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import eu.kanade.tachiyomi.R
|
||||
import yokai.i18n.MR
|
||||
import yokai.util.lang.getString
|
||||
import dev.icerock.moko.resources.compose.stringResource
|
||||
import eu.kanade.tachiyomi.databinding.LibraryCategoryLayoutBinding
|
||||
import eu.kanade.tachiyomi.util.bindToPreference
|
||||
import eu.kanade.tachiyomi.util.lang.withSubtitle
|
||||
import eu.kanade.tachiyomi.util.system.toInt
|
||||
import eu.kanade.tachiyomi.widget.BaseLibraryDisplayView
|
||||
import kotlin.math.min
|
||||
import yokai.i18n.MR
|
||||
import yokai.util.lang.getString
|
||||
|
||||
class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||
BaseLibraryDisplayView<LibraryCategoryLayoutBinding>(context, attrs) {
|
||||
|
@ -20,7 +18,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
|
|||
override fun initGeneralPreferences() {
|
||||
with(binding) {
|
||||
showAll.bindToPreference(preferences.showAllCategories()) {
|
||||
controller?.presenter?.getLibrary()
|
||||
controller?.presenter?.updateLibrary()
|
||||
binding.categoryShow.isEnabled = it
|
||||
}
|
||||
categoryShow.isEnabled = showAll.isChecked
|
||||
|
@ -30,7 +28,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
|
|||
dynamicToBottom.text = context.getString(MR.strings.move_dynamic_to_bottom)
|
||||
.withSubtitle(context, MR.strings.when_grouping_by_sources_tags)
|
||||
dynamicToBottom.bindToPreference(preferences.collapsedDynamicAtBottom()) {
|
||||
controller?.presenter?.getLibrary()
|
||||
controller?.presenter?.updateLibrary()
|
||||
}
|
||||
showEmptyCatsFiltering.bindToPreference(preferences.showEmptyCategoriesWhileFiltering()) {
|
||||
controller?.presenter?.requestFilterUpdate()
|
||||
|
|
|
@ -36,6 +36,8 @@ import eu.kanade.tachiyomi.util.view.isCollapsed
|
|||
import eu.kanade.tachiyomi.util.view.isExpanded
|
||||
import eu.kanade.tachiyomi.util.view.isHidden
|
||||
import eu.kanade.tachiyomi.util.view.setText
|
||||
import kotlin.math.max
|
||||
import kotlin.math.roundToInt
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.drop
|
||||
|
@ -48,8 +50,6 @@ import uy.kohesive.injekt.api.get
|
|||
import uy.kohesive.injekt.injectLazy
|
||||
import yokai.i18n.MR
|
||||
import yokai.util.lang.getString
|
||||
import kotlin.math.max
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||
LinearLayout(context, attrs),
|
||||
|
@ -637,7 +637,7 @@ class FilterBottomSheet @JvmOverloads constructor(context: Context, attrs: Attri
|
|||
SeriesType('m', MR.strings.series_type),
|
||||
Bookmarked('b', MR.strings.bookmarked),
|
||||
Tracked('t', MR.strings.tracking),
|
||||
ContentType('s', MR.strings.content_type);
|
||||
ContentType('s', MR.strings.content_type)
|
||||
;
|
||||
|
||||
companion object {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue