From 1639d1f67f91a08e5588c0427e717f78bf830c53 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 2 Feb 2026 19:51:22 +0100 Subject: [PATCH] Add SearchField to SpaceFiltersView --- .../spacefilters/SpaceFiltersPresenter.kt | 14 +++++++++---- .../impl/spacefilters/SpaceFiltersState.kt | 15 ++++++++++++- .../spacefilters/SpaceFiltersStateProvider.kt | 3 +++ .../impl/spacefilters/SpaceFiltersView.kt | 21 ++++++++++++++----- 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersPresenter.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersPresenter.kt index dbccfa0a1b..bcc6071723 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersPresenter.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersPresenter.kt @@ -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.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, diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersState.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersState.kt index 1e54a51bcb..cecda8b381 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersState.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersState.kt @@ -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, + val searchQuery: TextFieldState, val eventSink: (SpaceFiltersEvent.Selecting) -> Unit, - ) : SpaceFiltersState + ) : SpaceFiltersState { + val visibleFilters: ImmutableList + 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, diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersStateProvider.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersStateProvider.kt index 3c64b93e40..03159a9db4 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersStateProvider.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersStateProvider.kt @@ -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, ) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersView.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersView.kt index a8a6e0a23f..29313cb924 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersView.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersView.kt @@ -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, + 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(