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 a3e283b341..92a2f33e7c 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 @@ -9,8 +9,8 @@ package io.element.android.features.home.impl.spacefilters import androidx.compose.foundation.text.input.rememberTextFieldState import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -86,12 +86,15 @@ class SpaceFiltersPresenter( ) } is SelectionMode.Selected -> { - // Keep in sync with the available filters if rooms are added/removed - val selectedFilter by remember { - derivedStateOf { - availableFilters - .firstOrNull { it.spaceRoom.roomId == mode.filter.spaceRoom.roomId } - ?: mode.filter + var selectedFilter by remember { mutableStateOf(mode.filter) } + // Makes sure the selectedFilter stays in sync with the available filters + LaunchedEffect(availableFilters) { + val upToDateFilter = availableFilters + .firstOrNull { it.spaceRoom.roomId == mode.filter.spaceRoom.roomId } + if (upToDateFilter == null) { + selectionMode = SelectionMode.Unselected + } else { + selectedFilter = upToDateFilter } } SpaceFiltersState.Selected( diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersPresenterTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersPresenterTest.kt index 8621721e2a..4d4b908624 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersPresenterTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersPresenterTest.kt @@ -164,6 +164,43 @@ class SpaceFiltersPresenterTest { } } + @Test + fun `present - selected filter is cleared when space is removed from available filters`() = runTest { + val spaceFilter = aSpaceServiceFilter(displayName = "Work", roomId = RoomId("!work:example.com")) + val otherSpaceFilter = aSpaceServiceFilter(displayName = "Personal", roomId = RoomId("!personal:example.com")) + + val spaceService = FakeSpaceService() + val matrixClient = FakeMatrixClient(spaceService = spaceService) + + val presenter = createSpaceFiltersPresenter( + featureFlagService = FakeFeatureFlagService( + initialState = mapOf(FeatureFlags.RoomListSpaceFilters.key to true) + ), + matrixClient = matrixClient, + ) + presenter.test { + // Go to Selecting and emit filters + val unselectedState = awaitLastSequentialItem() as SpaceFiltersState.Unselected + unselectedState.eventSink(SpaceFiltersEvent.Unselected.ShowFilters) + spaceService.emitSpaceFilters(listOf(spaceFilter, otherSpaceFilter)) + + // Select the filter + val selectingState = awaitLastSequentialItem() as SpaceFiltersState.Selecting + selectingState.eventSink(SpaceFiltersEvent.Selecting.SelectFilter(spaceFilter)) + + // Verify in Selected state + val selectedState = awaitLastSequentialItem() as SpaceFiltersState.Selected + assertThat(selectedState.selectedFilter).isEqualTo(spaceFilter) + + // Remove the selected space from available filters (but keep other spaces) + spaceService.emitSpaceFilters(listOf(otherSpaceFilter)) + + // Should auto-transition to Unselected + val finalState = awaitLastSequentialItem() + assertThat(finalState).isInstanceOf(SpaceFiltersState.Unselected::class.java) + } + } + @Test fun `present - selected filter stays in sync when available filters update`() = runTest { val originalFilter = aSpaceServiceFilter(