Reimplement extensions search
Not sure if I should abstract this out to per-tab though. Maybe when we need it...
This commit is contained in:
parent
38950f7bc8
commit
21804bfc45
4 changed files with 41 additions and 16 deletions
|
@ -21,6 +21,8 @@ fun TabbedScreen(
|
||||||
@StringRes titleRes: Int,
|
@StringRes titleRes: Int,
|
||||||
tabs: List<TabContent>,
|
tabs: List<TabContent>,
|
||||||
startIndex: Int? = null,
|
startIndex: Int? = null,
|
||||||
|
searchQuery: String? = null,
|
||||||
|
onChangeSearchQuery: (String?) -> Unit = {},
|
||||||
incognitoMode: Boolean,
|
incognitoMode: Boolean,
|
||||||
downloadedOnlyMode: Boolean,
|
downloadedOnlyMode: Boolean,
|
||||||
) {
|
) {
|
||||||
|
@ -35,12 +37,27 @@ fun TabbedScreen(
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
|
if (searchQuery == null) {
|
||||||
AppBar(
|
AppBar(
|
||||||
title = stringResource(titleRes),
|
title = stringResource(titleRes),
|
||||||
actions = {
|
actions = {
|
||||||
AppBarActions(tabs[state.currentPage].actions)
|
AppBarActions(tabs[state.currentPage].actions)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
SearchToolbar(
|
||||||
|
searchQuery = searchQuery,
|
||||||
|
onChangeSearchQuery = {
|
||||||
|
onChangeSearchQuery(it)
|
||||||
|
},
|
||||||
|
onClickCloseSearch = {
|
||||||
|
onChangeSearchQuery(null)
|
||||||
|
},
|
||||||
|
onClickResetSearch = {
|
||||||
|
onChangeSearchQuery("")
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
Column(modifier = Modifier.padding(paddingValues)) {
|
Column(modifier = Modifier.padding(paddingValues)) {
|
||||||
|
|
|
@ -5,6 +5,8 @@ import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import eu.kanade.presentation.components.TabbedScreen
|
import eu.kanade.presentation.components.TabbedScreen
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
|
@ -31,6 +33,8 @@ class BrowseController : FullComposeController<BrowsePresenter>, RootController
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun ComposeContent() {
|
override fun ComposeContent() {
|
||||||
|
val query by presenter.extensionsPresenter.query.collectAsState()
|
||||||
|
|
||||||
TabbedScreen(
|
TabbedScreen(
|
||||||
titleRes = R.string.browse,
|
titleRes = R.string.browse,
|
||||||
tabs = listOf(
|
tabs = listOf(
|
||||||
|
@ -39,6 +43,8 @@ class BrowseController : FullComposeController<BrowsePresenter>, RootController
|
||||||
migrateSourcesTab(router, presenter.migrationSourcesPresenter),
|
migrateSourcesTab(router, presenter.migrationSourcesPresenter),
|
||||||
),
|
),
|
||||||
startIndex = 1.takeIf { toExtensions },
|
startIndex = 1.takeIf { toExtensions },
|
||||||
|
searchQuery = query,
|
||||||
|
onChangeSearchQuery = { presenter.extensionsPresenter.search(it) },
|
||||||
incognitoMode = presenter.isIncognitoMode,
|
incognitoMode = presenter.isIncognitoMode,
|
||||||
downloadedOnlyMode = presenter.isDownloadOnly,
|
downloadedOnlyMode = presenter.isDownloadOnly,
|
||||||
)
|
)
|
||||||
|
|
|
@ -16,6 +16,8 @@ import eu.kanade.tachiyomi.util.lang.launchIO
|
||||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
@ -33,7 +35,8 @@ class ExtensionsPresenter(
|
||||||
private val getExtensions: GetExtensionsByType = Injekt.get(),
|
private val getExtensions: GetExtensionsByType = Injekt.get(),
|
||||||
) : ExtensionsState by state {
|
) : ExtensionsState by state {
|
||||||
|
|
||||||
private val _query: MutableStateFlow<String> = MutableStateFlow("")
|
private val _query: MutableStateFlow<String?> = MutableStateFlow(null)
|
||||||
|
val query: StateFlow<String?> = _query.asStateFlow()
|
||||||
|
|
||||||
private var _currentDownloads = MutableStateFlow<Map<String, InstallStep>>(hashMapOf())
|
private var _currentDownloads = MutableStateFlow<Map<String, InstallStep>>(hashMapOf())
|
||||||
|
|
||||||
|
@ -77,8 +80,10 @@ class ExtensionsPresenter(
|
||||||
getExtensions.subscribe(),
|
getExtensions.subscribe(),
|
||||||
_currentDownloads,
|
_currentDownloads,
|
||||||
) { query, (_updates, _installed, _available, _untrusted), downloads ->
|
) { query, (_updates, _installed, _available, _untrusted), downloads ->
|
||||||
|
val searchQuery = query ?: ""
|
||||||
|
|
||||||
val languagesWithExtensions = _available
|
val languagesWithExtensions = _available
|
||||||
.filter(queryFilter(query))
|
.filter(queryFilter(searchQuery))
|
||||||
.groupBy { LocaleHelper.getSourceDisplayName(it.lang, context) }
|
.groupBy { LocaleHelper.getSourceDisplayName(it.lang, context) }
|
||||||
.toSortedMap()
|
.toSortedMap()
|
||||||
.flatMap { (key, value) ->
|
.flatMap { (key, value) ->
|
||||||
|
@ -90,14 +95,14 @@ class ExtensionsPresenter(
|
||||||
|
|
||||||
val items = mutableListOf<ExtensionUiModel>()
|
val items = mutableListOf<ExtensionUiModel>()
|
||||||
|
|
||||||
val updates = _updates.filter(queryFilter(query)).map(extensionMapper(downloads))
|
val updates = _updates.filter(queryFilter(searchQuery)).map(extensionMapper(downloads))
|
||||||
if (updates.isNotEmpty()) {
|
if (updates.isNotEmpty()) {
|
||||||
items.add(ExtensionUiModel.Header.Resource(R.string.ext_updates_pending))
|
items.add(ExtensionUiModel.Header.Resource(R.string.ext_updates_pending))
|
||||||
items.addAll(updates)
|
items.addAll(updates)
|
||||||
}
|
}
|
||||||
|
|
||||||
val installed = _installed.filter(queryFilter(query)).map(extensionMapper(downloads))
|
val installed = _installed.filter(queryFilter(searchQuery)).map(extensionMapper(downloads))
|
||||||
val untrusted = _untrusted.filter(queryFilter(query)).map(extensionMapper(downloads))
|
val untrusted = _untrusted.filter(queryFilter(searchQuery)).map(extensionMapper(downloads))
|
||||||
if (installed.isNotEmpty() || untrusted.isNotEmpty()) {
|
if (installed.isNotEmpty() || untrusted.isNotEmpty()) {
|
||||||
items.add(ExtensionUiModel.Header.Resource(R.string.ext_installed))
|
items.add(ExtensionUiModel.Header.Resource(R.string.ext_installed))
|
||||||
items.addAll(installed)
|
items.addAll(installed)
|
||||||
|
@ -122,7 +127,7 @@ class ExtensionsPresenter(
|
||||||
.launchIn(presenterScope)
|
.launchIn(presenterScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun search(query: String) {
|
fun search(query: String?) {
|
||||||
presenterScope.launchIO {
|
presenterScope.launchIO {
|
||||||
_query.emit(query)
|
_query.emit(query)
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,10 +25,7 @@ fun extensionsTab(
|
||||||
AppBar.Action(
|
AppBar.Action(
|
||||||
title = stringResource(R.string.action_search),
|
title = stringResource(R.string.action_search),
|
||||||
icon = Icons.Outlined.Search,
|
icon = Icons.Outlined.Search,
|
||||||
onClick = {
|
onClick = { presenter.search("") },
|
||||||
// TODO: extensions search
|
|
||||||
// presenter.search(query)
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
|
|
||||||
AppBar.Action(
|
AppBar.Action(
|
||||||
|
|
Reference in a new issue