Add SearchField to SpaceFiltersView

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

View file

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

View file

@ -7,8 +7,10 @@
package io.element.android.features.home.impl.spacefilters 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 io.element.android.libraries.matrix.api.spaces.SpaceServiceFilter
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
sealed interface SpaceFiltersState { sealed interface SpaceFiltersState {
data object Disabled : SpaceFiltersState data object Disabled : SpaceFiltersState
@ -19,8 +21,19 @@ sealed interface SpaceFiltersState {
data class Selecting( data class Selecting(
val availableFilters: ImmutableList<SpaceServiceFilter>, val availableFilters: ImmutableList<SpaceServiceFilter>,
val searchQuery: TextFieldState,
val eventSink: (SpaceFiltersEvent.Selecting) -> Unit, 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( data class Selected(
val selectedFilter: SpaceServiceFilter, val selectedFilter: SpaceServiceFilter,

View file

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

View file

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