diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersEvent.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersEvent.kt index 2db514b68d..b57b274cd5 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersEvent.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/spacefilters/SpaceFiltersEvent.kt @@ -7,4 +7,22 @@ package io.element.android.features.home.impl.spacefilters -sealed interface SpaceFiltersEvent +import io.element.android.libraries.matrix.api.spaces.SpaceServiceFilter + +sealed interface SpaceFiltersEvent { + // Only valid in Unselected state + sealed interface Unselected : SpaceFiltersEvent { + data object ShowFilters : Unselected + } + + // Only valid in Selecting state + sealed interface Selecting : SpaceFiltersEvent { + data object Cancel : Selecting + data class SelectFilter(val spaceFilter: SpaceServiceFilter) : Selecting + } + + // Only valid in Selected state + sealed interface Selected : SpaceFiltersEvent { + data object ClearSelection : Selected + } +} 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 21ed0c1070..dbccfa0a1b 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 @@ -8,15 +8,87 @@ package io.element.android.features.home.impl.spacefilters import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import dev.zacsweers.metro.Inject import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags +import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.spaces.SpaceServiceFilter +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.flow.map @Inject -class SpaceFiltersPresenter : Presenter { +class SpaceFiltersPresenter( + private val featureFlagService: FeatureFlagService, + private val matrixClient: MatrixClient, +) : Presenter { @Composable override fun present(): SpaceFiltersState { - return SpaceFiltersState( - eventSink = {}, - ) + val isFeatureEnabled by featureFlagService + .isFeatureEnabledFlow(FeatureFlags.RoomListSpaceFilters) + .collectAsState(initial = false) + + if (!isFeatureEnabled) { + return SpaceFiltersState.Disabled + } + + val availableFilters by remember { + matrixClient.spaceService.spaceFiltersFlow.map { it.toImmutableList() } + }.collectAsState(initial = persistentListOf()) + + var selectionMode by remember { mutableStateOf(SelectionMode.Unselected) } + + fun handleUnselectedEvent(event: SpaceFiltersEvent.Unselected) { + when (event) { + SpaceFiltersEvent.Unselected.ShowFilters -> { + selectionMode = SelectionMode.Selecting + } + } + } + + fun handleSelectingEvent(event: SpaceFiltersEvent.Selecting) { + when (event) { + SpaceFiltersEvent.Selecting.Cancel -> { + selectionMode = SelectionMode.Unselected + } + is SpaceFiltersEvent.Selecting.SelectFilter -> { + selectionMode = SelectionMode.Selected(event.spaceFilter) + } + } + } + + fun handleSelectedEvent(event: SpaceFiltersEvent.Selected) { + when (event) { + SpaceFiltersEvent.Selected.ClearSelection -> { + selectionMode = SelectionMode.Unselected + } + } + } + + return when (val mode = selectionMode) { + SelectionMode.Unselected -> SpaceFiltersState.Unselected( + eventSink = ::handleUnselectedEvent, + ) + SelectionMode.Selecting -> SpaceFiltersState.Selecting( + availableFilters = availableFilters, + eventSink = ::handleSelectingEvent, + ) + is SelectionMode.Selected -> SpaceFiltersState.Selected( + selectedFilter = mode.filter, + eventSink = ::handleSelectedEvent, + ) + } } } + +private sealed interface SelectionMode { + data object Unselected : SelectionMode + data object Selecting : SelectionMode + data class Selected(val filter: SpaceServiceFilter) : SelectionMode +} 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 af56cfdba1..1e54a51bcb 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,6 +7,23 @@ package io.element.android.features.home.impl.spacefilters -data class SpaceFiltersState( - val eventSink: (SpaceFiltersEvent) -> Unit, -) +import io.element.android.libraries.matrix.api.spaces.SpaceServiceFilter +import kotlinx.collections.immutable.ImmutableList + +sealed interface SpaceFiltersState { + data object Disabled : SpaceFiltersState + + data class Unselected( + val eventSink: (SpaceFiltersEvent.Unselected) -> Unit, + ) : SpaceFiltersState + + data class Selecting( + val availableFilters: ImmutableList, + val eventSink: (SpaceFiltersEvent.Selecting) -> Unit, + ) : SpaceFiltersState + + data class Selected( + val selectedFilter: SpaceServiceFilter, + val eventSink: (SpaceFiltersEvent.Selected) -> Unit, + ) : SpaceFiltersState +} 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 b999228969..f6c5cccef4 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 @@ -8,14 +8,56 @@ package io.element.android.features.home.impl.spacefilters import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.spaces.SpaceServiceFilter +import io.element.android.libraries.previewutils.room.aSpaceRoom +import kotlinx.collections.immutable.persistentListOf class SpaceFiltersStateProvider : PreviewParameterProvider { override val values: Sequence - get() = sequenceOf(aSpaceFiltersState()) + get() = sequenceOf( + aDisabledSpaceFiltersState(), + anUnselectedSpaceFiltersState(), + aSelectingSpaceFiltersState(), + aSelectedSpaceFiltersState(), + ) } -fun aSpaceFiltersState( - eventSink: (SpaceFiltersEvent) -> Unit = {}, -) = SpaceFiltersState( +fun aDisabledSpaceFiltersState() = SpaceFiltersState.Disabled + +fun anUnselectedSpaceFiltersState( + eventSink: (SpaceFiltersEvent.Unselected) -> Unit = {}, +) = SpaceFiltersState.Unselected( eventSink = eventSink, ) + +fun aSelectingSpaceFiltersState( + availableFilters: List = listOf( + aSpaceServiceFilter(displayName = "Work"), + aSpaceServiceFilter(displayName = "Personal", roomId = RoomId("!personal:example.com")), + aSpaceServiceFilter(displayName = "Gaming", roomId = RoomId("!gaming:example.com")), + ), + eventSink: (SpaceFiltersEvent.Selecting) -> Unit = {}, +) = SpaceFiltersState.Selecting( + availableFilters = persistentListOf(*availableFilters.toTypedArray()), + eventSink = eventSink, +) + +fun aSelectedSpaceFiltersState( + selectedFilter: SpaceServiceFilter = aSpaceServiceFilter(displayName = "Work"), + eventSink: (SpaceFiltersEvent.Selected) -> Unit = {}, +) = SpaceFiltersState.Selected( + selectedFilter = selectedFilter, + eventSink = eventSink, +) + +fun aSpaceServiceFilter( + displayName: String = "Space", + roomId: RoomId = RoomId("!space:example.com"), + level: Int = 0, + descendants: List = emptyList(), +) = SpaceServiceFilter( + spaceRoom = aSpaceRoom(displayName = displayName, roomId = roomId), + level = level, + descendants = descendants, +)