Improve SpaceFilters: hide when empty and fix tests

This commit is contained in:
ganfra 2026-02-05 11:33:24 +01:00
parent 5e0e1f8f4f
commit 0466663d64
4 changed files with 72 additions and 20 deletions

View file

@ -36,14 +36,14 @@ class SpaceFiltersPresenter(
.isFeatureEnabledFlow(FeatureFlags.RoomListSpaceFilters) .isFeatureEnabledFlow(FeatureFlags.RoomListSpaceFilters)
.collectAsState(initial = false) .collectAsState(initial = false)
if (!isFeatureEnabled) {
return SpaceFiltersState.Disabled
}
val availableFilters by remember { val availableFilters by remember {
matrixClient.spaceService.spaceFiltersFlow.map { it.toImmutableList() } matrixClient.spaceService.spaceFiltersFlow.map { it.toImmutableList() }
}.collectAsState(initial = persistentListOf()) }.collectAsState(initial = persistentListOf())
if (!isFeatureEnabled || availableFilters.isEmpty()) {
return SpaceFiltersState.Disabled
}
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) {

View file

@ -13,7 +13,7 @@ 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
import io.element.android.libraries.matrix.api.spaces.SpaceServiceFilter import io.element.android.libraries.matrix.api.spaces.SpaceServiceFilter
import io.element.android.libraries.previewutils.room.aSpaceRoom import io.element.android.libraries.previewutils.room.aSpaceRoom
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList
class SpaceFiltersStateProvider : PreviewParameterProvider<SpaceFiltersState> { class SpaceFiltersStateProvider : PreviewParameterProvider<SpaceFiltersState> {
override val values: Sequence<SpaceFiltersState> override val values: Sequence<SpaceFiltersState>
@ -55,7 +55,7 @@ fun aSelectingSpaceFiltersState(
searchQuery: String = "", searchQuery: String = "",
eventSink: (SpaceFiltersEvent.Selecting) -> Unit = {}, eventSink: (SpaceFiltersEvent.Selecting) -> Unit = {},
) = SpaceFiltersState.Selecting( ) = SpaceFiltersState.Selecting(
availableFilters = persistentListOf(*availableFilters.toTypedArray()), availableFilters = availableFilters.toImmutableList(),
searchQuery = TextFieldState(searchQuery), searchQuery = TextFieldState(searchQuery),
eventSink = eventSink, eventSink = eventSink,
) )

View file

@ -49,7 +49,6 @@ 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 import io.element.android.libraries.ui.strings.CommonStrings
import timber.log.Timber
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable

View file

@ -35,13 +35,34 @@ class SpaceFiltersPresenterTest {
} }
@Test @Test
fun `present - when feature flag is enabled returns Unselected state initially`() = runTest { fun `present - when available filters is empty returns Disabled state`() = runTest {
val presenter = createSpaceFiltersPresenter( val presenter = createSpaceFiltersPresenter(
featureFlagService = FakeFeatureFlagService( featureFlagService = FakeFeatureFlagService(
initialState = mapOf(FeatureFlags.RoomListSpaceFilters.key to true) initialState = mapOf(FeatureFlags.RoomListSpaceFilters.key to true)
) )
) )
presenter.test { presenter.test {
val state = awaitLastSequentialItem()
assertThat(state).isEqualTo(SpaceFiltersState.Disabled)
}
}
@Test
fun `present - when feature flag is enabled and filters exist returns Unselected state`() = runTest {
val spaceFilter = aSpaceServiceFilter(displayName = "Test Space")
val spaceService = FakeSpaceService()
val matrixClient = FakeMatrixClient(spaceService = spaceService)
val presenter = createSpaceFiltersPresenter(
featureFlagService = FakeFeatureFlagService(
initialState = mapOf(FeatureFlags.RoomListSpaceFilters.key to true)
),
matrixClient = matrixClient,
)
presenter.test {
// Emit filters
spaceService.emitSpaceFilters(listOf(spaceFilter))
val state = awaitLastSequentialItem() val state = awaitLastSequentialItem()
assertThat(state).isInstanceOf(SpaceFiltersState.Unselected::class.java) assertThat(state).isInstanceOf(SpaceFiltersState.Unselected::class.java)
} }
@ -49,12 +70,20 @@ class SpaceFiltersPresenterTest {
@Test @Test
fun `present - ShowFilters event transitions from Unselected to Selecting`() = runTest { fun `present - ShowFilters event transitions from Unselected to Selecting`() = runTest {
val spaceFilter = aSpaceServiceFilter(displayName = "Test Space")
val spaceService = FakeSpaceService()
val matrixClient = FakeMatrixClient(spaceService = spaceService)
val presenter = createSpaceFiltersPresenter( val presenter = createSpaceFiltersPresenter(
featureFlagService = FakeFeatureFlagService( featureFlagService = FakeFeatureFlagService(
initialState = mapOf(FeatureFlags.RoomListSpaceFilters.key to true) initialState = mapOf(FeatureFlags.RoomListSpaceFilters.key to true)
) ),
matrixClient = matrixClient,
) )
presenter.test { presenter.test {
// Emit filters first
spaceService.emitSpaceFilters(listOf(spaceFilter))
val unselectedState = awaitLastSequentialItem() as SpaceFiltersState.Unselected val unselectedState = awaitLastSequentialItem() as SpaceFiltersState.Unselected
unselectedState.eventSink(SpaceFiltersEvent.Unselected.ShowFilters) unselectedState.eventSink(SpaceFiltersEvent.Unselected.ShowFilters)
@ -65,12 +94,20 @@ class SpaceFiltersPresenterTest {
@Test @Test
fun `present - Cancel event in Selecting state transitions back to Unselected`() = runTest { fun `present - Cancel event in Selecting state transitions back to Unselected`() = runTest {
val spaceFilter = aSpaceServiceFilter(displayName = "Test Space")
val spaceService = FakeSpaceService()
val matrixClient = FakeMatrixClient(spaceService = spaceService)
val presenter = createSpaceFiltersPresenter( val presenter = createSpaceFiltersPresenter(
featureFlagService = FakeFeatureFlagService( featureFlagService = FakeFeatureFlagService(
initialState = mapOf(FeatureFlags.RoomListSpaceFilters.key to true) initialState = mapOf(FeatureFlags.RoomListSpaceFilters.key to true)
) ),
matrixClient = matrixClient,
) )
presenter.test { presenter.test {
// Emit filters first
spaceService.emitSpaceFilters(listOf(spaceFilter))
// Start in Unselected // Start in Unselected
val unselectedState = awaitLastSequentialItem() as SpaceFiltersState.Unselected val unselectedState = awaitLastSequentialItem() as SpaceFiltersState.Unselected
unselectedState.eventSink(SpaceFiltersEvent.Unselected.ShowFilters) unselectedState.eventSink(SpaceFiltersEvent.Unselected.ShowFilters)
@ -88,12 +125,19 @@ class SpaceFiltersPresenterTest {
@Test @Test
fun `present - SelectFilter event in Selecting state transitions to Selected`() = runTest { fun `present - SelectFilter event in Selecting state transitions to Selected`() = runTest {
val spaceFilter = aSpaceServiceFilter(displayName = "Test Space") val spaceFilter = aSpaceServiceFilter(displayName = "Test Space")
val spaceService = FakeSpaceService()
val matrixClient = FakeMatrixClient(spaceService = spaceService)
val presenter = createSpaceFiltersPresenter( val presenter = createSpaceFiltersPresenter(
featureFlagService = FakeFeatureFlagService( featureFlagService = FakeFeatureFlagService(
initialState = mapOf(FeatureFlags.RoomListSpaceFilters.key to true) initialState = mapOf(FeatureFlags.RoomListSpaceFilters.key to true)
) ),
matrixClient = matrixClient,
) )
presenter.test { presenter.test {
// Emit filters first
spaceService.emitSpaceFilters(listOf(spaceFilter))
// Start in Unselected // Start in Unselected
val unselectedState = awaitLastSequentialItem() as SpaceFiltersState.Unselected val unselectedState = awaitLastSequentialItem() as SpaceFiltersState.Unselected
unselectedState.eventSink(SpaceFiltersEvent.Unselected.ShowFilters) unselectedState.eventSink(SpaceFiltersEvent.Unselected.ShowFilters)
@ -111,12 +155,19 @@ class SpaceFiltersPresenterTest {
@Test @Test
fun `present - ClearSelection event in Selected state transitions back to Unselected`() = runTest { fun `present - ClearSelection event in Selected state transitions back to Unselected`() = runTest {
val spaceFilter = aSpaceServiceFilter(displayName = "Test Space") val spaceFilter = aSpaceServiceFilter(displayName = "Test Space")
val spaceService = FakeSpaceService()
val matrixClient = FakeMatrixClient(spaceService = spaceService)
val presenter = createSpaceFiltersPresenter( val presenter = createSpaceFiltersPresenter(
featureFlagService = FakeFeatureFlagService( featureFlagService = FakeFeatureFlagService(
initialState = mapOf(FeatureFlags.RoomListSpaceFilters.key to true) initialState = mapOf(FeatureFlags.RoomListSpaceFilters.key to true)
) ),
matrixClient = matrixClient,
) )
presenter.test { presenter.test {
// Emit filters first
spaceService.emitSpaceFilters(listOf(spaceFilter))
// Start in Unselected // Start in Unselected
val unselectedState = awaitLastSequentialItem() as SpaceFiltersState.Unselected val unselectedState = awaitLastSequentialItem() as SpaceFiltersState.Unselected
unselectedState.eventSink(SpaceFiltersEvent.Unselected.ShowFilters) unselectedState.eventSink(SpaceFiltersEvent.Unselected.ShowFilters)
@ -151,13 +202,13 @@ class SpaceFiltersPresenterTest {
matrixClient = matrixClient, matrixClient = matrixClient,
) )
presenter.test { presenter.test {
// Emit space filters
spaceService.emitSpaceFilters(spaceFilters)
// Start in Unselected // Start in Unselected
val unselectedState = awaitLastSequentialItem() as SpaceFiltersState.Unselected val unselectedState = awaitLastSequentialItem() as SpaceFiltersState.Unselected
unselectedState.eventSink(SpaceFiltersEvent.Unselected.ShowFilters) unselectedState.eventSink(SpaceFiltersEvent.Unselected.ShowFilters)
// Emit space filters
spaceService.emitSpaceFilters(spaceFilters)
// Now in Selecting with available filters // Now in Selecting with available filters
val selectingState = awaitLastSequentialItem() as SpaceFiltersState.Selecting val selectingState = awaitLastSequentialItem() as SpaceFiltersState.Selecting
assertThat(selectingState.availableFilters).containsExactly(spaceFilter1, spaceFilter2).inOrder() assertThat(selectingState.availableFilters).containsExactly(spaceFilter1, spaceFilter2).inOrder()
@ -179,10 +230,12 @@ class SpaceFiltersPresenterTest {
matrixClient = matrixClient, matrixClient = matrixClient,
) )
presenter.test { presenter.test {
// Go to Selecting and emit filters // Emit filters first
spaceService.emitSpaceFilters(listOf(spaceFilter, otherSpaceFilter))
// Go to Selecting
val unselectedState = awaitLastSequentialItem() as SpaceFiltersState.Unselected val unselectedState = awaitLastSequentialItem() as SpaceFiltersState.Unselected
unselectedState.eventSink(SpaceFiltersEvent.Unselected.ShowFilters) unselectedState.eventSink(SpaceFiltersEvent.Unselected.ShowFilters)
spaceService.emitSpaceFilters(listOf(spaceFilter, otherSpaceFilter))
// Select the filter // Select the filter
val selectingState = awaitLastSequentialItem() as SpaceFiltersState.Selecting val selectingState = awaitLastSequentialItem() as SpaceFiltersState.Selecting
@ -224,13 +277,13 @@ class SpaceFiltersPresenterTest {
matrixClient = matrixClient, matrixClient = matrixClient,
) )
presenter.test { presenter.test {
// Emit initial space filters
spaceService.emitSpaceFilters(listOf(originalFilter))
// Start in Unselected // Start in Unselected
val unselectedState = awaitLastSequentialItem() as SpaceFiltersState.Unselected val unselectedState = awaitLastSequentialItem() as SpaceFiltersState.Unselected
unselectedState.eventSink(SpaceFiltersEvent.Unselected.ShowFilters) unselectedState.eventSink(SpaceFiltersEvent.Unselected.ShowFilters)
// Emit initial space filters
spaceService.emitSpaceFilters(listOf(originalFilter))
// Now in Selecting // Now in Selecting
val selectingState = awaitLastSequentialItem() as SpaceFiltersState.Selecting val selectingState = awaitLastSequentialItem() as SpaceFiltersState.Selecting
selectingState.eventSink(SpaceFiltersEvent.Selecting.SelectFilter(originalFilter)) selectingState.eventSink(SpaceFiltersEvent.Selecting.SelectFilter(originalFilter))