From 63da463e0213f272bebfdf5a62e81d341f8dfc40 Mon Sep 17 00:00:00 2001 From: stevenyomi <95685115+stevenyomi@users.noreply.github.com> Date: Sun, 18 Dec 2022 03:51:03 +0800 Subject: [PATCH] Clean up usages of listing UI models (#8762) --- .../presentation/browse/SourcesScreen.kt | 10 +-- .../kanade/presentation/components/AppBar.kt | 3 +- .../migration/search/MigrateSearchScreen.kt | 3 +- .../migration/search/SourceSearchScreen.kt | 4 +- .../tachiyomi/ui/browse/source/SourcesTab.kt | 4 +- .../source/browse/BrowseSourceScreen.kt | 20 +++--- .../source/browse/BrowseSourceScreenModel.kt | 67 +++++++------------ .../source/globalsearch/GlobalSearchScreen.kt | 3 +- 8 files changed, 51 insertions(+), 63 deletions(-) diff --git a/app/src/main/java/eu/kanade/presentation/browse/SourcesScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/SourcesScreen.kt index d125038057..c37719c2a7 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/SourcesScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/SourcesScreen.kt @@ -21,7 +21,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import eu.kanade.domain.source.interactor.GetRemoteManga import eu.kanade.domain.source.model.Pin import eu.kanade.domain.source.model.Source import eu.kanade.presentation.browse.components.BaseSourceItem @@ -35,13 +34,14 @@ import eu.kanade.presentation.util.topSmallPaddingValues import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.ui.browse.source.SourcesState +import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreenModel.Listing import eu.kanade.tachiyomi.util.system.LocaleHelper @Composable fun SourcesScreen( state: SourcesState, contentPadding: PaddingValues, - onClickItem: (Source, String) -> Unit, + onClickItem: (Source, Listing) -> Unit, onClickPin: (Source) -> Unit, onLongClickItem: (Source) -> Unit, ) { @@ -109,18 +109,18 @@ private fun SourceHeader( private fun SourceItem( modifier: Modifier = Modifier, source: Source, - onClickItem: (Source, String) -> Unit, + onClickItem: (Source, Listing) -> Unit, onLongClickItem: (Source) -> Unit, onClickPin: (Source) -> Unit, ) { BaseSourceItem( modifier = modifier, source = source, - onClickItem = { onClickItem(source, GetRemoteManga.QUERY_POPULAR) }, + onClickItem = { onClickItem(source, Listing.Popular) }, onLongClickItem = { onLongClickItem(source) }, action = { if (source.supportsLatest) { - TextButton(onClick = { onClickItem(source, GetRemoteManga.QUERY_LATEST) }) { + TextButton(onClick = { onClickItem(source, Listing.Latest) }) { Text( text = stringResource(R.string.latest), style = LocalTextStyle.current.copy( diff --git a/app/src/main/java/eu/kanade/presentation/components/AppBar.kt b/app/src/main/java/eu/kanade/presentation/components/AppBar.kt index f94513bb7a..db26ca0a49 100644 --- a/app/src/main/java/eu/kanade/presentation/components/AppBar.kt +++ b/app/src/main/java/eu/kanade/presentation/components/AppBar.kt @@ -240,7 +240,8 @@ fun SearchToolbar( val keyboardController = LocalSoftwareKeyboardController.current val focusManager = LocalFocusManager.current - val searchAndClearFocus: () -> Unit = { + val searchAndClearFocus: () -> Unit = f@{ + if (searchQuery.isBlank()) return@f onSearch(searchQuery) focusManager.clearFocus() keyboardController?.hide() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateSearchScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateSearchScreen.kt index ba4148a36c..f8478882de 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateSearchScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateSearchScreen.kt @@ -50,6 +50,7 @@ import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.ui.browse.migration.MigrationFlags +import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreenModel.Listing import eu.kanade.tachiyomi.ui.manga.MangaScreen import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchUI @@ -77,7 +78,7 @@ class MigrateSearchScreen(private val mangaId: Long) : Screen { if (!screenModel.incognitoMode.get()) { screenModel.lastUsedSourceId.set(it.id) } - navigator.push(SourceSearchScreen(state.manga!!, it.id, state.searchQuery)) + navigator.push(SourceSearchScreen(state.manga!!, it.id, Listing.Search(state.searchQuery, it.getFilterList()))) }, onClickItem = { screenModel.setDialog(MigrateSearchDialog.Migrate(it)) }, onLongClickItem = { navigator.push(MangaScreen(it.id, true)) }, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SourceSearchScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SourceSearchScreen.kt index 84bfe77cfc..2c8188d05d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SourceSearchScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SourceSearchScreen.kt @@ -40,7 +40,7 @@ import kotlinx.coroutines.launch data class SourceSearchScreen( private val oldManga: Manga, private val sourceId: Long, - private val query: String? = null, + private val listing: BrowseSourceScreenModel.Listing, ) : Screen { @Composable @@ -50,7 +50,7 @@ data class SourceSearchScreen( val navigator = LocalNavigator.currentOrThrow val scope = rememberCoroutineScope() - val screenModel = rememberScreenModel { BrowseSourceScreenModel(sourceId = sourceId, searchQuery = query) } + val screenModel = rememberScreenModel { BrowseSourceScreenModel(sourceId, listing) } val state by screenModel.state.collectAsState() val snackbarHostState = remember { SnackbarHostState() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesTab.kt index 92ea22e589..ce88e582d6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesTab.kt @@ -46,9 +46,9 @@ fun Screen.sourcesTab(): TabContent { SourcesScreen( state = state, contentPadding = contentPadding, - onClickItem = { source, query -> + onClickItem = { source, listing -> screenModel.onOpenSource(source) - navigator.push(BrowseSourceScreen(source.id, query)) + navigator.push(BrowseSourceScreen(source.id, listing)) }, onClickPin = screenModel::togglePin, onLongClickItem = screenModel::showSourceDialog, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt index b322e2ee77..0c2dd8355d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt @@ -39,7 +39,6 @@ import cafe.adriel.voyager.core.screen.Screen import cafe.adriel.voyager.core.screen.uniqueScreenKey import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow -import eu.kanade.domain.source.interactor.GetRemoteManga import eu.kanade.presentation.browse.BrowseSourceContent import eu.kanade.presentation.browse.components.BrowseSourceToolbar import eu.kanade.presentation.browse.components.RemoveMangaDialog @@ -51,6 +50,7 @@ import eu.kanade.presentation.util.AssistContentScreen import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.online.HttpSource +import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreenModel.Listing import eu.kanade.tachiyomi.ui.category.CategoryScreen import eu.kanade.tachiyomi.ui.manga.MangaScreen import eu.kanade.tachiyomi.ui.webview.WebViewActivity @@ -62,7 +62,7 @@ import kotlinx.coroutines.flow.receiveAsFlow data class BrowseSourceScreen( private val sourceId: Long, - private val query: String? = null, + private val listing: Listing, ) : Screen, AssistContentScreen { private var assistUrl: String? = null @@ -79,7 +79,7 @@ data class BrowseSourceScreen( val haptic = LocalHapticFeedback.current val uriHandler = LocalUriHandler.current - val screenModel = rememberScreenModel { BrowseSourceScreenModel(sourceId, query) } + val screenModel = rememberScreenModel { BrowseSourceScreenModel(sourceId, listing) } val state by screenModel.state.collectAsState() val snackbarHostState = remember { SnackbarHostState() } @@ -125,10 +125,10 @@ data class BrowseSourceScreen( horizontalArrangement = Arrangement.spacedBy(8.dp), ) { FilterChip( - selected = state.currentFilter == BrowseSourceScreenModel.Filter.Popular, + selected = state.listing == Listing.Popular, onClick = { - screenModel.reset() - screenModel.search(GetRemoteManga.QUERY_POPULAR) + screenModel.resetFilters() + screenModel.setListing(Listing.Popular) }, leadingIcon = { Icon( @@ -144,10 +144,10 @@ data class BrowseSourceScreen( ) if (screenModel.source.supportsLatest) { FilterChip( - selected = state.currentFilter == BrowseSourceScreenModel.Filter.Latest, + selected = state.listing == Listing.Latest, onClick = { - screenModel.reset() - screenModel.search(GetRemoteManga.QUERY_LATEST) + screenModel.resetFilters() + screenModel.setListing(Listing.Latest) }, leadingIcon = { Icon( @@ -164,7 +164,7 @@ data class BrowseSourceScreen( } if (state.filters.isNotEmpty()) { FilterChip( - selected = state.currentFilter is BrowseSourceScreenModel.Filter.UserInput, + selected = state.listing is Listing.Search, onClick = screenModel::openFilterSheet, leadingIcon = { Icon( diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt index d56f7ec0ab..a89284706d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt @@ -79,7 +79,7 @@ import eu.kanade.tachiyomi.source.model.Filter as SourceModelFilter class BrowseSourceScreenModel( private val sourceId: Long, - searchQuery: String?, + listing: Listing, private val sourceManager: SourceManager = Injekt.get(), sourcePreferences: SourcePreferences = Injekt.get(), private val libraryPreferences: LibraryPreferences = Injekt.get(), @@ -95,7 +95,7 @@ class BrowseSourceScreenModel( private val updateManga: UpdateManga = Injekt.get(), private val insertTrack: InsertTrack = Injekt.get(), private val syncChaptersWithTrackServiceTwoWay: SyncChaptersWithTrackServiceTwoWay = Injekt.get(), -) : StateScreenModel(State(Filter.valueOf(searchQuery))) { +) : StateScreenModel(State(listing)) { private val loggedServices by lazy { Injekt.get().services.filter { it.isLogged } } @@ -109,15 +109,15 @@ class BrowseSourceScreenModel( private var filterSheet: SourceFilterSheet? = null /** - * Flow of Pager flow tied to [State.currentFilter] + * Flow of Pager flow tied to [State.listing] */ - val mangaPagerFlowFlow = state.map { it.currentFilter } + val mangaPagerFlowFlow = state.map { it.listing } .distinctUntilChanged() - .map { currentFilter -> + .map { listing -> Pager( PagingConfig(pageSize = 25), ) { - getRemoteManga.subscribe(sourceId, currentFilter.query ?: "", currentFilter.filters) + getRemoteManga.subscribe(sourceId, listing.query ?: "", listing.filters) }.flow .map { pagingData -> pagingData.map { sManga -> @@ -146,26 +146,21 @@ class BrowseSourceScreenModel( return if (columns == 0) GridCells.Adaptive(128.dp) else GridCells.Fixed(columns) } - fun reset() { + fun resetFilters() { mutableState.update { it.copy(filters = source.getFilterList()) } } - fun search(query: String? = null, filters: FilterList? = null) { - Filter.valueOf(query).let { - if (it !is Filter.UserInput) { - mutableState.update { state -> state.copy(currentFilter = it) } - return - } - } + fun setListing(listing: Listing) { + mutableState.update { it.copy(listing = listing) } + } + + fun search(query: String? = null, filters: FilterList? = null) { + val input = state.value.listing as? Listing.Search + ?: Listing.Search(query = null, filters = source.getFilterList()) - val input = if (state.value.currentFilter is Filter.UserInput) { - state.value.currentFilter as Filter.UserInput - } else { - Filter.UserInput() - } mutableState.update { it.copy( - currentFilter = input.copy( + listing = input.copy( query = query ?: input.query, filters = filters ?: input.filters, ), @@ -204,14 +199,14 @@ class BrowseSourceScreenModel( } mutableState.update { - val filter = if (genreExists) { - Filter.UserInput(filters = defaultFilters) + val listing = if (genreExists) { + Listing.Search(query = null, filters = defaultFilters) } else { - Filter.UserInput(query = genreName) + Listing.Search(query = genreName, filters = defaultFilters) } it.copy( filters = defaultFilters, - currentFilter = filter, + listing = listing, ) } } @@ -367,7 +362,7 @@ class BrowseSourceScreenModel( context = context, onFilterClicked = { search(filters = state.value.filters) }, onResetClicked = { - reset() + resetFilters() filterSheet?.setFilters(state.value.filterItems) }, ) @@ -375,20 +370,10 @@ class BrowseSourceScreenModel( filterSheet?.setFilters(state.value.filterItems) } - sealed class Filter(open val query: String?, open val filters: FilterList) { - object Popular : Filter(query = GetRemoteManga.QUERY_POPULAR, filters = FilterList()) - object Latest : Filter(query = GetRemoteManga.QUERY_LATEST, filters = FilterList()) - data class UserInput(override val query: String? = null, override val filters: FilterList = FilterList()) : Filter(query = query, filters = filters) - - companion object { - fun valueOf(query: String?): Filter { - return when (query) { - GetRemoteManga.QUERY_POPULAR -> Popular - GetRemoteManga.QUERY_LATEST -> Latest - else -> UserInput(query = query) - } - } - } + sealed class Listing(open val query: String?, open val filters: FilterList) { + object Popular : Listing(query = GetRemoteManga.QUERY_POPULAR, filters = FilterList()) + object Latest : Listing(query = GetRemoteManga.QUERY_LATEST, filters = FilterList()) + data class Search(override val query: String?, override val filters: FilterList) : Listing(query = query, filters = filters) } sealed class Dialog { @@ -403,13 +388,13 @@ class BrowseSourceScreenModel( @Immutable data class State( - val currentFilter: Filter, + val listing: Listing, val filters: FilterList = FilterList(), val toolbarQuery: String? = null, val dialog: Dialog? = null, ) { val filterItems get() = filters.toItems() - val isUserQuery get() = currentFilter is Filter.UserInput && !currentFilter.query.isNullOrEmpty() + val isUserQuery get() = listing is Listing.Search && !listing.query.isNullOrEmpty() } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchScreen.kt index 368806bb21..71dfa6d1f5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchScreen.kt @@ -10,6 +10,7 @@ import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow import eu.kanade.presentation.browse.GlobalSearchScreen import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreen +import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreenModel.Listing import eu.kanade.tachiyomi.ui.manga.MangaScreen class GlobalSearchScreen( @@ -46,7 +47,7 @@ class GlobalSearchScreen( if (!screenModel.incognitoMode.get()) { screenModel.lastUsedSourceId.set(it.id) } - navigator.push(BrowseSourceScreen(it.id, state.searchQuery)) + navigator.push(BrowseSourceScreen(it.id, Listing.Search(state.searchQuery, it.getFilterList()))) }, onClickItem = { navigator.push(MangaScreen(it.id, true)) }, onLongClickItem = { navigator.push(MangaScreen(it.id, true)) },