Pass listing query to BrowseSourceScreen (#8763)
# Conflicts: # app/src/main/java/eu/kanade/presentation/browse/SourcesScreen.kt # app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesTab.kt # app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt # app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt
This commit is contained in:
parent
a6d0031462
commit
f02d41051e
@ -28,7 +28,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
|
||||
@ -42,13 +41,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,
|
||||
) {
|
||||
@ -136,18 +136,18 @@ private fun SourceItem(
|
||||
showLatest: Boolean,
|
||||
showPin: Boolean,
|
||||
// SY <--
|
||||
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 /* SY --> */ && showLatest /* SY <-- */) {
|
||||
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()
|
||||
|
@ -15,7 +15,6 @@ import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.OpenInNew
|
||||
import androidx.compose.material.icons.outlined.NewReleases
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.NavigationBarDefaults
|
||||
@ -68,7 +67,7 @@ fun NewUpdateScreen(
|
||||
vertical = MaterialTheme.padding.small,
|
||||
),
|
||||
) {
|
||||
Button(
|
||||
TextButton(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
onClick = onAcceptUpdate,
|
||||
) {
|
||||
|
@ -50,6 +50,7 @@ fun Screen.feedTab(): TabContent {
|
||||
navigator.push(
|
||||
BrowseSourceScreen(
|
||||
source.id,
|
||||
listingQuery = null,
|
||||
savedSearch = savedSearch.id,
|
||||
),
|
||||
)
|
||||
|
@ -30,7 +30,7 @@ import eu.kanade.tachiyomi.util.Constants
|
||||
data class SourceSearchScreen(
|
||||
private val oldManga: Manga,
|
||||
private val sourceId: Long,
|
||||
private val query: String? = null,
|
||||
private val query: String?,
|
||||
) : Screen {
|
||||
|
||||
@Composable
|
||||
@ -39,7 +39,7 @@ data class SourceSearchScreen(
|
||||
val uriHandler = LocalUriHandler.current
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
|
||||
val screenModel = rememberScreenModel { BrowseSourceScreenModel(sourceId = sourceId, searchQuery = query) }
|
||||
val screenModel = rememberScreenModel { BrowseSourceScreenModel(sourceId, query) }
|
||||
val state by screenModel.state.collectAsState()
|
||||
|
||||
val snackbarHostState = remember { SnackbarHostState() }
|
||||
|
@ -12,7 +12,6 @@ import cafe.adriel.voyager.core.model.rememberScreenModel
|
||||
import cafe.adriel.voyager.core.screen.Screen
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import eu.kanade.domain.source.interactor.GetRemoteManga.Companion.QUERY_POPULAR
|
||||
import eu.kanade.presentation.browse.SourceCategoriesDialog
|
||||
import eu.kanade.presentation.browse.SourceOptionsDialog
|
||||
import eu.kanade.presentation.browse.SourcesScreen
|
||||
@ -21,6 +20,7 @@ import eu.kanade.presentation.components.TabContent
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.browse.source.SourcesScreen.SmartSearchConfig
|
||||
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreen
|
||||
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreenModel.Listing
|
||||
import eu.kanade.tachiyomi.ui.browse.source.feed.SourceFeedScreen
|
||||
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchScreen
|
||||
import exh.ui.smartsearch.SmartSearchScreen
|
||||
@ -62,12 +62,12 @@ fun Screen.sourcesTab(
|
||||
SourcesScreen(
|
||||
state = state,
|
||||
contentPadding = contentPadding,
|
||||
onClickItem = { source, query ->
|
||||
onClickItem = { source, listing ->
|
||||
// SY -->
|
||||
val screen = when {
|
||||
smartSearchConfig != null -> SmartSearchScreen(source.id, smartSearchConfig)
|
||||
(query.isBlank() || query == QUERY_POPULAR) && screenModel.useNewSourceNavigation -> SourceFeedScreen(source.id)
|
||||
else -> BrowseSourceScreen(source.id, query)
|
||||
listing == Listing.Popular && screenModel.useNewSourceNavigation -> SourceFeedScreen(source.id)
|
||||
else -> BrowseSourceScreen(source.id, listing.query)
|
||||
}
|
||||
screenModel.onOpenSource(source)
|
||||
navigator.push(screen)
|
||||
|
@ -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.FailedToLoadSavedSearchDialog
|
||||
@ -56,6 +55,7 @@ import eu.kanade.tachiyomi.source.LocalSource
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.ui.browse.extension.details.SourcePreferencesScreen
|
||||
import eu.kanade.tachiyomi.ui.browse.source.SourcesScreen
|
||||
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
|
||||
@ -67,7 +67,7 @@ import kotlinx.coroutines.flow.receiveAsFlow
|
||||
|
||||
data class BrowseSourceScreen(
|
||||
private val sourceId: Long,
|
||||
private val query: String? = null,
|
||||
private val listingQuery: String?,
|
||||
// SY -->
|
||||
private val filtersJson: String? = null,
|
||||
private val savedSearch: Long? = null,
|
||||
@ -92,7 +92,7 @@ data class BrowseSourceScreen(
|
||||
val screenModel = rememberScreenModel {
|
||||
BrowseSourceScreenModel(
|
||||
sourceId = sourceId,
|
||||
searchQuery = query,
|
||||
listingQuery = listingQuery,
|
||||
// SY -->
|
||||
filtersJson = filtersJson,
|
||||
savedSearch = savedSearch,
|
||||
@ -147,10 +147,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(
|
||||
@ -166,10 +166,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(
|
||||
@ -186,7 +186,7 @@ data class BrowseSourceScreen(
|
||||
}
|
||||
/* SY --> if (state.filters.isNotEmpty())*/ run /* SY <-- */ {
|
||||
FilterChip(
|
||||
selected = state.currentFilter is BrowseSourceScreenModel.Filter.UserInput,
|
||||
selected = state.listing is Listing.Search,
|
||||
onClick = screenModel::openFilterSheet,
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
|
@ -107,7 +107,7 @@ import eu.kanade.tachiyomi.source.model.Filter as SourceModelFilter
|
||||
|
||||
open class BrowseSourceScreenModel(
|
||||
private val sourceId: Long,
|
||||
searchQuery: String?,
|
||||
listingQuery: String?,
|
||||
// SY -->
|
||||
private val filtersJson: String? = null,
|
||||
private val savedSearch: Long? = null,
|
||||
@ -135,7 +135,7 @@ open class BrowseSourceScreenModel(
|
||||
private val insertSavedSearch: InsertSavedSearch = Injekt.get(),
|
||||
private val getExhSavedSearch: GetExhSavedSearch = Injekt.get(),
|
||||
// SY <--
|
||||
) : StateScreenModel<BrowseSourceScreenModel.State>(State(Filter.valueOf(searchQuery))) {
|
||||
) : StateScreenModel<BrowseSourceScreenModel.State>(State(Listing.valueOf(listingQuery))) {
|
||||
|
||||
private val loggedServices by lazy { Injekt.get<TrackManager>().services.filter { it.isLogged } }
|
||||
|
||||
@ -149,16 +149,16 @@ open 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),
|
||||
) {
|
||||
// SY -->
|
||||
createSourcePagingSource(currentFilter.query ?: "", currentFilter.filters)
|
||||
createSourcePagingSource(listing.query ?: "", listing.filters)
|
||||
// SY <--
|
||||
}.flow
|
||||
.map { pagingData ->
|
||||
@ -184,7 +184,19 @@ open class BrowseSourceScreenModel(
|
||||
// SY <--
|
||||
|
||||
init {
|
||||
mutableState.update { it.copy(filters = source.getFilterList()) }
|
||||
mutableState.update {
|
||||
val initialListing = it.listing
|
||||
val listing = if (initialListing is Listing.Search) {
|
||||
initialListing.copy(filters = source.getFilterList())
|
||||
} else {
|
||||
initialListing
|
||||
}
|
||||
|
||||
it.copy(
|
||||
listing = listing,
|
||||
filters = source.getFilterList(),
|
||||
)
|
||||
}
|
||||
|
||||
// SY -->
|
||||
val savedSearchFilters = savedSearch
|
||||
@ -234,31 +246,26 @@ open class BrowseSourceScreenModel(
|
||||
}
|
||||
// SY <--
|
||||
|
||||
fun reset() {
|
||||
fun resetFilters() {
|
||||
mutableState.update { it.copy(filters = source.getFilterList()) }
|
||||
}
|
||||
|
||||
fun setListing(listing: Listing) {
|
||||
mutableState.update { it.copy(listing = listing) }
|
||||
}
|
||||
|
||||
fun search(query: String? = null, filters: FilterList? = null) {
|
||||
// SY -->
|
||||
if (filters != null && filters !== state.value.filters) {
|
||||
mutableState.update { state -> state.copy(filters = filters) }
|
||||
}
|
||||
// SY <--
|
||||
Filter.valueOf(query).let {
|
||||
if (it !is Filter.UserInput) {
|
||||
mutableState.update { state -> state.copy(currentFilter = it) }
|
||||
return
|
||||
}
|
||||
}
|
||||
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,
|
||||
),
|
||||
@ -297,14 +304,14 @@ open 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,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -472,8 +479,8 @@ open class BrowseSourceScreenModel(
|
||||
// SY <--
|
||||
onFilterClicked = { search(filters = state.filters) },
|
||||
onResetClicked = {
|
||||
reset()
|
||||
filterSheet?.setFilters(state.value.filterItems)
|
||||
resetFilters()
|
||||
filterSheet?.setFilters(state.filterItems)
|
||||
},
|
||||
// EXH -->
|
||||
onSaveClicked = {
|
||||
@ -511,20 +518,20 @@ open class BrowseSourceScreenModel(
|
||||
// EXH <--
|
||||
)
|
||||
|
||||
filterSheet?.setFilters(state.value.filterItems)
|
||||
filterSheet?.setFilters(state.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)
|
||||
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)
|
||||
|
||||
companion object {
|
||||
fun valueOf(query: String?): Filter {
|
||||
fun valueOf(query: String?): Listing {
|
||||
return when (query) {
|
||||
GetRemoteManga.QUERY_POPULAR -> Popular
|
||||
GetRemoteManga.QUERY_LATEST -> Latest
|
||||
else -> UserInput(query = query)
|
||||
else -> Search(query = query, filters = FilterList()) // filters are filled in later
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -548,7 +555,7 @@ open class BrowseSourceScreenModel(
|
||||
|
||||
@Immutable
|
||||
data class State(
|
||||
val currentFilter: Filter,
|
||||
val listing: Listing,
|
||||
val filters: FilterList = FilterList(),
|
||||
val toolbarQuery: String? = null,
|
||||
val dialog: Dialog? = null,
|
||||
@ -557,7 +564,7 @@ open class BrowseSourceScreenModel(
|
||||
// SY <--
|
||||
) {
|
||||
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()
|
||||
}
|
||||
|
||||
// EXH -->
|
||||
@ -565,8 +572,8 @@ open class BrowseSourceScreenModel(
|
||||
name: String,
|
||||
) {
|
||||
coroutineScope.launchNonCancellable {
|
||||
val query = state.value.currentFilter.query
|
||||
val filterList = state.value.currentFilter.filters.ifEmpty { source.getFilterList() }
|
||||
val query = state.value.listing.query
|
||||
val filterList = state.value.listing.filters.ifEmpty { source.getFilterList() }
|
||||
insertSavedSearch.await(
|
||||
SavedSearch(
|
||||
id = -1,
|
||||
|
@ -199,7 +199,7 @@ class SourceFeedScreen(val sourceId: Long) : Screen {
|
||||
}
|
||||
|
||||
private fun onSavedSearchClick(navigator: Navigator, source: CatalogueSource, savedSearch: SavedSearch) {
|
||||
navigator.replace(BrowseSourceScreen(source.id, savedSearch = savedSearch.id))
|
||||
navigator.replace(BrowseSourceScreen(source.id, listingQuery = null, savedSearch = savedSearch.id))
|
||||
}
|
||||
|
||||
private fun onSearchClick(navigator: Navigator, source: CatalogueSource, query: String) {
|
||||
|
@ -52,7 +52,7 @@ class SmartSearchScreen(private val sourceId: Long, private val smartSearchConfi
|
||||
navigator.push(
|
||||
BrowseSourceScreen(
|
||||
sourceId = screenModel.source.id,
|
||||
query = smartSearchConfig.origTitle,
|
||||
listingQuery = smartSearchConfig.origTitle,
|
||||
smartSearchConfig = smartSearchConfig,
|
||||
),
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user