mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01:00 
			
		
		
		
	Clean up usages of listing UI models (#8762)
This commit is contained in:
		@@ -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(
 | 
			
		||||
 
 | 
			
		||||
@@ -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()
 | 
			
		||||
 
 | 
			
		||||
@@ -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)) },
 | 
			
		||||
 
 | 
			
		||||
@@ -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() }
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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(
 | 
			
		||||
 
 | 
			
		||||
@@ -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<BrowseSourceScreenModel.State>(State(Filter.valueOf(searchQuery))) {
 | 
			
		||||
) : StateScreenModel<BrowseSourceScreenModel.State>(State(listing)) {
 | 
			
		||||
 | 
			
		||||
    private val loggedServices by lazy { Injekt.get<TrackManager>().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()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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)) },
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user