refactor(library): Use flow to retrieve library (#159)

* refactor(library): Use flow to retrieve library

* fix(library): Use fetchLibrary in getLibraryFlow
This commit is contained in:
Ahmad Ansori Palembani 2024-11-30 17:30:19 +07:00 committed by GitHub
parent a940722f2b
commit ec36c9faf7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -52,10 +52,15 @@ import java.util.concurrent.*
import kotlin.math.roundToInt import kotlin.math.roundToInt
import kotlin.random.Random import kotlin.random.Random
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -100,6 +105,11 @@ class LibraryPresenter(
private val getTrack: GetTrack by injectLazy() private val getTrack: GetTrack by injectLazy()
private val getHistory: GetHistory 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 context = preferences.context private val context = preferences.context
private val viewContext private val viewContext
get() = view?.view?.context get() = view?.view?.context
@ -197,7 +207,7 @@ class LibraryPresenter(
} }
*/ */
getLibrary() subscribeLibrary()
if (!preferences.showLibrarySearchSuggestions().isSet()) { if (!preferences.showLibrarySearchSuggestions().isSet()) {
DelayedLibrarySuggestionsJob.setupTask(context, true) DelayedLibrarySuggestionsJob.setupTask(context, true)
@ -232,57 +242,41 @@ class LibraryPresenter(
categories = lastCategories ?: getCategories.await().toMutableList() categories = lastCategories ?: getCategories.await().toMutableList()
} }
getLibraryFlow().collectLatest { data -> combine(
getLibraryFlow(),
fetchLibrary,
) { data, _ ->
categories = data.categories categories = data.categories
allCategories = data.allCategories allCategories = data.allCategories
val library = data.items 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)
}
} }
} }
// FIXME: Remove this, it's useless
/** Get favorited manga for library and sort and filter it */ /** Get favorited manga for library and sort and filter it */
fun getLibrary() { fun getLibrary() {
presenterScope.launch { presenterScope.launch {
if (categories.isEmpty()) { _fetchLibrary.send(Unit)
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, _) = withIOContext { getLibraryFromDB() }
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)
} }
} }
@ -820,14 +814,6 @@ class LibraryPresenter(
return this return this
} }
// FIXME: Seems like it's impossible to redirect current implementation to getLibraryFlow(), simply because of how
// J2K implements the library UI, both "Show all categories" (not to be confused with "Ungrouped") and
// "Show one category at a time" share the same data, which explains why J2K use blankItem instead of checking if
// list is empty to show the user if the category is empty or not. Understandable tbh, since it's pretty painful to
// maintain these two option on pre-Compose.
// ;
// Seems like I'll need to completely convert the UI to Compose first.
/** /**
* Library's flow. * Library's flow.
* *
@ -839,9 +825,9 @@ class LibraryPresenter(
getLibraryManga.subscribe(), getLibraryManga.subscribe(),
getPreferencesFlow(), getPreferencesFlow(),
preferences.removeArticles().changes(), preferences.removeArticles().changes(),
) { allCategories, libraryMangaList, prefs, removeArticles -> fetchLibrary,
val groupType = prefs.groupType ) { allCategories, libraryMangaList, prefs, removeArticles, _ ->
val libraryIsGrouped = groupType != UNGROUPED groupType = prefs.groupType
val data = if (groupType <= BY_DEFAULT || !libraryIsGrouped) { val data = if (groupType <= BY_DEFAULT || !libraryIsGrouped) {
getLibraryItems( getLibraryItems(
@ -1297,11 +1283,7 @@ class LibraryPresenter(
} }
/** Called when Library Service updates a manga, update the item as well */ /** Called when Library Service updates a manga, update the item as well */
fun updateManga() { fun updateManga() = getLibrary()
presenterScope.launch {
getLibrary()
}
}
/** Undo the removal of the manga once in library */ /** Undo the removal of the manga once in library */
fun reAddMangas(mangas: List<Manga>) { fun reAddMangas(mangas: List<Manga>) {