From ec36c9faf7c8b1845516d86c636981408c166662 Mon Sep 17 00:00:00 2001 From: Ahmad Ansori Palembani <46041660+null2264@users.noreply.github.com> Date: Sat, 30 Nov 2024 17:30:19 +0700 Subject: [PATCH] refactor(library): Use flow to retrieve library (#159) * refactor(library): Use flow to retrieve library * fix(library): Use fetchLibrary in getLibraryFlow --- .../tachiyomi/ui/library/LibraryPresenter.kt | 98 ++++++++----------- 1 file changed, 40 insertions(+), 58 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt index b56e45291c..42ab46dc2b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt @@ -52,10 +52,15 @@ import java.util.concurrent.* import kotlin.math.roundToInt 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.shareIn import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext @@ -100,6 +105,11 @@ class LibraryPresenter( private val getTrack: GetTrack by injectLazy() private val getHistory: GetHistory by injectLazy() + private val _fetchLibrary: Channel = Channel(Channel.UNLIMITED) + val fetchLibrary = _fetchLibrary.receiveAsFlow() + .onStart { emit(Unit) } + .shareIn(presenterScope, SharingStarted.Lazily, 1) + private val context = preferences.context private val viewContext get() = view?.view?.context @@ -197,7 +207,7 @@ class LibraryPresenter( } */ - getLibrary() + subscribeLibrary() if (!preferences.showLibrarySearchSuggestions().isSet()) { DelayedLibrarySuggestionsJob.setupTask(context, true) @@ -232,57 +242,41 @@ class LibraryPresenter( categories = lastCategories ?: getCategories.await().toMutableList() } - getLibraryFlow().collectLatest { data -> + combine( + getLibraryFlow(), + fetchLibrary, + ) { data, _ -> categories = data.categories allCategories = data.allCategories - 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) + data.items } + .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 */ fun getLibrary() { 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, _) = 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) + _fetchLibrary.send(Unit) } } @@ -820,14 +814,6 @@ class LibraryPresenter( 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. * @@ -839,9 +825,9 @@ class LibraryPresenter( getLibraryManga.subscribe(), getPreferencesFlow(), preferences.removeArticles().changes(), - ) { allCategories, libraryMangaList, prefs, removeArticles -> - val groupType = prefs.groupType - val libraryIsGrouped = groupType != UNGROUPED + fetchLibrary, + ) { allCategories, libraryMangaList, prefs, removeArticles, _ -> + groupType = prefs.groupType val data = if (groupType <= BY_DEFAULT || !libraryIsGrouped) { getLibraryItems( @@ -1297,11 +1283,7 @@ class LibraryPresenter( } /** Called when Library Service updates a manga, update the item as well */ - fun updateManga() { - presenterScope.launch { - getLibrary() - } - } + fun updateManga() = getLibrary() /** Undo the removal of the manga once in library */ fun reAddMangas(mangas: List) {