Add SearchField to SpaceFiltersView

This commit is contained in:
ganfra 2026-02-02 19:51:22 +01:00
parent 4a94e36b3e
commit 1639d1f67f
4 changed files with 43 additions and 10 deletions

View file

@ -7,6 +7,7 @@
package io.element.android.features.home.impl.spacefilters
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
@ -42,6 +43,7 @@ class SpaceFiltersPresenter(
matrixClient.spaceService.spaceFiltersFlow.map { it.toImmutableList() }
}.collectAsState(initial = persistentListOf())
var selectionMode by remember { mutableStateOf<SelectionMode>(SelectionMode.Unselected) }
fun handleUnselectedEvent(event: SpaceFiltersEvent.Unselected) {
@ -75,10 +77,14 @@ class SpaceFiltersPresenter(
SelectionMode.Unselected -> SpaceFiltersState.Unselected(
eventSink = ::handleUnselectedEvent,
)
SelectionMode.Selecting -> SpaceFiltersState.Selecting(
availableFilters = availableFilters,
eventSink = ::handleSelectingEvent,
)
SelectionMode.Selecting -> {
val searchQuery = rememberTextFieldState()
SpaceFiltersState.Selecting(
availableFilters = availableFilters,
searchQuery = searchQuery,
eventSink = ::handleSelectingEvent,
)
}
is SelectionMode.Selected -> SpaceFiltersState.Selected(
selectedFilter = mode.filter,
eventSink = ::handleSelectedEvent,

View file

@ -7,8 +7,10 @@
package io.element.android.features.home.impl.spacefilters
import androidx.compose.foundation.text.input.TextFieldState
import io.element.android.libraries.matrix.api.spaces.SpaceServiceFilter
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
sealed interface SpaceFiltersState {
data object Disabled : SpaceFiltersState
@ -19,8 +21,19 @@ sealed interface SpaceFiltersState {
data class Selecting(
val availableFilters: ImmutableList<SpaceServiceFilter>,
val searchQuery: TextFieldState,
val eventSink: (SpaceFiltersEvent.Selecting) -> Unit,
) : SpaceFiltersState
) : SpaceFiltersState {
val visibleFilters: ImmutableList<SpaceServiceFilter>
get() {
val query = searchQuery.text.toString()
if (query.isBlank()) return availableFilters
return availableFilters.filter { filter ->
filter.spaceRoom.displayName.contains(query, ignoreCase = true) ||
(filter.spaceRoom.canonicalAlias?.value ?: "").contains(query, ignoreCase = true)
}.toImmutableList()
}
}
data class Selected(
val selectedFilter: SpaceServiceFilter,

View file

@ -7,6 +7,7 @@
package io.element.android.features.home.impl.spacefilters
import androidx.compose.foundation.text.input.TextFieldState
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
@ -53,9 +54,11 @@ fun aSelectingSpaceFiltersState(
roomId = RoomId("!gaming:example.com"),
),
),
searchQuery: TextFieldState = TextFieldState(),
eventSink: (SpaceFiltersEvent.Selecting) -> Unit = {},
) = SpaceFiltersState.Selecting(
availableFilters = persistentListOf(*availableFilters.toTypedArray()),
searchQuery = searchQuery,
eventSink = eventSink,
)

View file

@ -20,6 +20,7 @@ import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.text.input.TextFieldState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
@ -30,6 +31,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
@ -39,9 +41,11 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarType
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet
import io.element.android.libraries.designsystem.theme.components.SearchField
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.matrix.api.spaces.SpaceServiceFilter
import io.element.android.libraries.matrix.ui.model.getAvatarData
import io.element.android.libraries.ui.strings.CommonStrings
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@ -72,7 +76,8 @@ fun SpaceFiltersView(
onDismissRequest = { state.eventSink(SpaceFiltersEvent.Selecting.Cancel) },
) {
SpaceFiltersBottomSheetContent(
filters = state.availableFilters,
filters = state.visibleFilters,
searchQuery = state.searchQuery,
onFilterSelected = { filter ->
state.eventSink(SpaceFiltersEvent.Selecting.SelectFilter(filter))
}
@ -85,20 +90,26 @@ fun SpaceFiltersView(
@Composable
private fun SpaceFiltersBottomSheetContent(
filters: List<SpaceServiceFilter>,
searchQuery: TextFieldState,
onFilterSelected: (SpaceServiceFilter) -> Unit,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier
.fillMaxWidth()
.padding(bottom = 16.dp)
.padding(vertical = 16.dp, horizontal = 16.dp)
) {
Text(
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
text = "Your spaces",
style = ElementTheme.typography.fontBodyLgMedium,
style = ElementTheme.typography.fontHeadingSmMedium,
)
Spacer(modifier = Modifier.height(8.dp))
Spacer(modifier = Modifier.height(12.dp))
SearchField(
state = searchQuery,
modifier = Modifier.fillMaxWidth(),
placeholder = stringResource(CommonStrings.action_search),
)
Spacer(modifier = Modifier.height(16.dp))
LazyColumn {
items(filters) { filter ->
SpaceFilterItem(