Handle SpaceFilter interaction with other RoomListFilters
This commit is contained in:
@@ -228,6 +228,7 @@ private fun HomeScaffold(
|
||||
RoomListContentView(
|
||||
contentState = roomListState.contentState,
|
||||
filtersState = roomListState.filtersState,
|
||||
spaceFiltersState = roomListState.spaceFiltersState,
|
||||
lazyListState = roomsLazyListState,
|
||||
hideInvitesAvatars = roomListState.hideInvitesAvatars,
|
||||
eventSink = roomListState.eventSink,
|
||||
|
||||
@@ -45,6 +45,8 @@ import io.element.android.features.home.impl.roomlist.RoomListContentState
|
||||
import io.element.android.features.home.impl.roomlist.RoomListContentStateProvider
|
||||
import io.element.android.features.home.impl.roomlist.RoomListEvent
|
||||
import io.element.android.features.home.impl.roomlist.SecurityBannerState
|
||||
import io.element.android.features.home.impl.spacefilters.SpaceFiltersState
|
||||
import io.element.android.features.home.impl.spacefilters.anUnselectedSpaceFiltersState
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.theme.components.Button
|
||||
@@ -59,6 +61,7 @@ import kotlinx.collections.immutable.ImmutableList
|
||||
fun RoomListContentView(
|
||||
contentState: RoomListContentState,
|
||||
filtersState: RoomListFiltersState,
|
||||
spaceFiltersState: SpaceFiltersState,
|
||||
lazyListState: LazyListState,
|
||||
hideInvitesAvatars: Boolean,
|
||||
eventSink: (RoomListEvent) -> Unit,
|
||||
@@ -93,6 +96,7 @@ fun RoomListContentView(
|
||||
state = contentState,
|
||||
hideInvitesAvatars = hideInvitesAvatars,
|
||||
filtersState = filtersState,
|
||||
spaceFiltersState = spaceFiltersState,
|
||||
eventSink = eventSink,
|
||||
onSetUpRecoveryClick = onSetUpRecoveryClick,
|
||||
onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick,
|
||||
@@ -172,6 +176,7 @@ private fun RoomsView(
|
||||
state: RoomListContentState.Rooms,
|
||||
hideInvitesAvatars: Boolean,
|
||||
filtersState: RoomListFiltersState,
|
||||
spaceFiltersState: SpaceFiltersState,
|
||||
eventSink: (RoomListEvent) -> Unit,
|
||||
onSetUpRecoveryClick: () -> Unit,
|
||||
onConfirmRecoveryKeyClick: () -> Unit,
|
||||
@@ -180,9 +185,12 @@ private fun RoomsView(
|
||||
lazyListState: LazyListState,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
if (state.summaries.isEmpty() && filtersState.hasAnyFilterSelected) {
|
||||
val isSpaceFilterSelected = spaceFiltersState is SpaceFiltersState.Selected
|
||||
val hasAnyFilterSelected = filtersState.hasAnyFilterSelected || isSpaceFilterSelected
|
||||
if (state.summaries.isEmpty() && hasAnyFilterSelected) {
|
||||
EmptyViewForFilterStates(
|
||||
selectedFilters = filtersState.selectedFilters(),
|
||||
isSpaceFilterSelected = isSpaceFilterSelected,
|
||||
modifier = modifier.fillMaxSize()
|
||||
)
|
||||
} else {
|
||||
@@ -278,9 +286,10 @@ private fun RoomsViewList(
|
||||
@Composable
|
||||
private fun EmptyViewForFilterStates(
|
||||
selectedFilters: ImmutableList<RoomListFilter>,
|
||||
isSpaceFilterSelected: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val emptyStateResources = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters) ?: return
|
||||
val emptyStateResources = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters, isSpaceFilterSelected) ?: return
|
||||
EmptyScaffold(
|
||||
title = emptyStateResources.title,
|
||||
subtitle = emptyStateResources.subtitle,
|
||||
@@ -331,6 +340,7 @@ internal fun RoomListContentViewPreview(@PreviewParameter(RoomListContentStatePr
|
||||
)
|
||||
}
|
||||
),
|
||||
spaceFiltersState = anUnselectedSpaceFiltersState(),
|
||||
hideInvitesAvatars = false,
|
||||
eventSink = {},
|
||||
onSetUpRecoveryClick = {},
|
||||
|
||||
@@ -24,8 +24,12 @@ data class RoomListFiltersEmptyStateResources(
|
||||
/**
|
||||
* Create a [RoomListFiltersEmptyStateResources] from a list of selected filters.
|
||||
*/
|
||||
fun fromSelectedFilters(selectedFilters: List<RoomListFilter>): RoomListFiltersEmptyStateResources? {
|
||||
fun fromSelectedFilters(selectedFilters: List<RoomListFilter>, isSpaceFilterSelected: Boolean): RoomListFiltersEmptyStateResources? {
|
||||
return when {
|
||||
isSpaceFilterSelected -> RoomListFiltersEmptyStateResources(
|
||||
title = R.string.screen_roomlist_filter_mixed_empty_state_title,
|
||||
subtitle = R.string.screen_roomlist_filter_mixed_empty_state_subtitle
|
||||
)
|
||||
selectedFilters.isEmpty() -> null
|
||||
selectedFilters.size == 1 -> {
|
||||
when (selectedFilters.first()) {
|
||||
|
||||
@@ -11,4 +11,5 @@ package io.element.android.features.home.impl.filters
|
||||
sealed interface RoomListFiltersEvent {
|
||||
data class ToggleFilter(val filter: RoomListFilter) : RoomListFiltersEvent
|
||||
data object ClearSelectedFilters : RoomListFiltersEvent
|
||||
data class SetHiddenFilter(val filters: Set<RoomListFilter>): RoomListFiltersEvent
|
||||
}
|
||||
|
||||
@@ -30,6 +30,9 @@ class RoomListFiltersPresenter(
|
||||
is RoomListFiltersEvent.ToggleFilter -> {
|
||||
filterSelectionStrategy.toggle(event.filter)
|
||||
}
|
||||
is RoomListFiltersEvent.SetHiddenFilter -> {
|
||||
filterSelectionStrategy.setHiddenFilters(event.filters)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,17 +15,29 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
@ContributesBinding(SessionScope::class)
|
||||
class DefaultFilterSelectionStrategy : FilterSelectionStrategy {
|
||||
private val selectedFilters = LinkedHashSet<RoomListFilter>()
|
||||
private val _selectedFilters = LinkedHashSet<RoomListFilter>()
|
||||
private val hiddenFilters = LinkedHashSet<RoomListFilter>()
|
||||
private val selectedFilters
|
||||
get() = _selectedFilters - hiddenFilters
|
||||
|
||||
private val availableFilters
|
||||
get() = RoomListFilter.entries.toSet() - hiddenFilters
|
||||
|
||||
override val filterSelectionStates = MutableStateFlow(buildFilters())
|
||||
|
||||
override fun setHiddenFilters(filters: Set<RoomListFilter>) {
|
||||
hiddenFilters.clear()
|
||||
hiddenFilters.addAll(filters)
|
||||
filterSelectionStates.value = buildFilters()
|
||||
}
|
||||
|
||||
override fun select(filter: RoomListFilter) {
|
||||
selectedFilters.add(filter)
|
||||
_selectedFilters.add(filter)
|
||||
filterSelectionStates.value = buildFilters()
|
||||
}
|
||||
|
||||
override fun deselect(filter: RoomListFilter) {
|
||||
selectedFilters.remove(filter)
|
||||
_selectedFilters.remove(filter)
|
||||
filterSelectionStates.value = buildFilters()
|
||||
}
|
||||
|
||||
@@ -34,7 +46,7 @@ class DefaultFilterSelectionStrategy : FilterSelectionStrategy {
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
selectedFilters.clear()
|
||||
_selectedFilters.clear()
|
||||
filterSelectionStates.value = buildFilters()
|
||||
}
|
||||
|
||||
@@ -45,7 +57,7 @@ class DefaultFilterSelectionStrategy : FilterSelectionStrategy {
|
||||
isSelected = true
|
||||
)
|
||||
}
|
||||
val unselectedFilters = RoomListFilter.entries - selectedFilters - selectedFilters.flatMap { it.incompatibleFilters }.toSet()
|
||||
val unselectedFilters = availableFilters - selectedFilters - selectedFilters.flatMap { it.incompatibleFilters }.toSet()
|
||||
val unselectedFilterStates = unselectedFilters.map {
|
||||
FilterSelectionState(
|
||||
filter = it,
|
||||
|
||||
@@ -14,6 +14,7 @@ import kotlinx.coroutines.flow.StateFlow
|
||||
interface FilterSelectionStrategy {
|
||||
val filterSelectionStates: StateFlow<Set<FilterSelectionState>>
|
||||
|
||||
fun setHiddenFilters(filters: Set<RoomListFilter>)
|
||||
fun select(filter: RoomListFilter)
|
||||
fun deselect(filter: RoomListFilter)
|
||||
fun isSelected(filter: RoomListFilter): Boolean
|
||||
|
||||
@@ -28,6 +28,9 @@ import im.vector.app.features.analytics.plan.Interaction
|
||||
import io.element.android.features.announcement.api.Announcement
|
||||
import io.element.android.features.announcement.api.AnnouncementService
|
||||
import io.element.android.features.home.impl.datasource.RoomListDataSource
|
||||
import io.element.android.features.home.impl.filters.RoomListFilter.People
|
||||
import io.element.android.features.home.impl.filters.RoomListFilter.Rooms
|
||||
import io.element.android.features.home.impl.filters.RoomListFiltersEvent
|
||||
import io.element.android.features.home.impl.filters.RoomListFiltersState
|
||||
import io.element.android.features.home.impl.filters.into
|
||||
import io.element.android.features.home.impl.search.RoomListSearchEvent
|
||||
@@ -156,13 +159,16 @@ class RoomListPresenter(
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(filtersState.filterSelectionStates, spaceFiltersState.selectedFilter()) {
|
||||
val selectedFilters = filtersState.filterSelectionStates.mapNotNull { filterState ->
|
||||
if (!filterState.isSelected) {
|
||||
return@mapNotNull null
|
||||
}
|
||||
filterState.filter.into()
|
||||
LaunchedEffect(spaceFiltersState.selectedFilter()) {
|
||||
val hiddenFilters = if (spaceFiltersState is SpaceFiltersState.Selected) {
|
||||
setOf(People, Rooms)
|
||||
} else {
|
||||
emptySet()
|
||||
}
|
||||
filtersState.eventSink(RoomListFiltersEvent.SetHiddenFilter(hiddenFilters))
|
||||
}
|
||||
LaunchedEffect(filtersState.filterSelectionStates, spaceFiltersState.selectedFilter()) {
|
||||
val selectedFilters = filtersState.selectedFilters().map { filter -> filter.into() }
|
||||
val selectedSpaceFilter = when (spaceFiltersState) {
|
||||
is SpaceFiltersState.Selected -> RoomListFilter.Identifiers(spaceFiltersState.selectedFilter.descendants)
|
||||
else -> null
|
||||
|
||||
@@ -16,14 +16,14 @@ class RoomListFiltersEmptyStateResourcesTest {
|
||||
@Test
|
||||
fun `fromSelectedFilters should return null when selectedFilters is empty`() {
|
||||
val selectedFilters = emptyList<RoomListFilter>()
|
||||
val result = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters)
|
||||
val result = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters, isSpaceFilterSelected = false)
|
||||
assertThat(result).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `fromSelectedFilters should return exact RoomListFiltersEmptyStateResources when selectedFilters has only unread filter`() {
|
||||
val selectedFilters = listOf(RoomListFilter.Unread)
|
||||
val result = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters)
|
||||
val result = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters, isSpaceFilterSelected = false)
|
||||
assertThat(result).isNotNull()
|
||||
assertThat(result?.title).isEqualTo(R.string.screen_roomlist_filter_unreads_empty_state_title)
|
||||
assertThat(result?.subtitle).isEqualTo(R.string.screen_roomlist_filter_mixed_empty_state_subtitle)
|
||||
@@ -32,7 +32,7 @@ class RoomListFiltersEmptyStateResourcesTest {
|
||||
@Test
|
||||
fun `fromSelectedFilters should return exact RoomListFiltersEmptyStateResources when selectedFilters has only people filter`() {
|
||||
val selectedFilters = listOf(RoomListFilter.People)
|
||||
val result = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters)
|
||||
val result = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters, isSpaceFilterSelected = false)
|
||||
assertThat(result).isNotNull()
|
||||
assertThat(result?.title).isEqualTo(R.string.screen_roomlist_filter_people_empty_state_title)
|
||||
assertThat(result?.subtitle).isEqualTo(R.string.screen_roomlist_filter_mixed_empty_state_subtitle)
|
||||
@@ -41,7 +41,7 @@ class RoomListFiltersEmptyStateResourcesTest {
|
||||
@Test
|
||||
fun `fromSelectedFilters should return exact RoomListFiltersEmptyStateResources when selectedFilters has only rooms filter`() {
|
||||
val selectedFilters = listOf(RoomListFilter.Rooms)
|
||||
val result = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters)
|
||||
val result = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters, isSpaceFilterSelected = false)
|
||||
assertThat(result).isNotNull()
|
||||
assertThat(result?.title).isEqualTo(R.string.screen_roomlist_filter_rooms_empty_state_title)
|
||||
assertThat(result?.subtitle).isEqualTo(R.string.screen_roomlist_filter_mixed_empty_state_subtitle)
|
||||
@@ -50,7 +50,7 @@ class RoomListFiltersEmptyStateResourcesTest {
|
||||
@Test
|
||||
fun `fromSelectedFilters should return exact RoomListFiltersEmptyStateResources when selectedFilters has only favourites filter`() {
|
||||
val selectedFilters = listOf(RoomListFilter.Favourites)
|
||||
val result = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters)
|
||||
val result = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters, isSpaceFilterSelected = false)
|
||||
assertThat(result).isNotNull()
|
||||
assertThat(result?.title).isEqualTo(R.string.screen_roomlist_filter_favourites_empty_state_title)
|
||||
assertThat(result?.subtitle).isEqualTo(R.string.screen_roomlist_filter_favourites_empty_state_subtitle)
|
||||
@@ -59,7 +59,7 @@ class RoomListFiltersEmptyStateResourcesTest {
|
||||
@Test
|
||||
fun `fromSelectedFilters should return exact RoomListFiltersEmptyStateResources when selectedFilters has only invites filter`() {
|
||||
val selectedFilters = listOf(RoomListFilter.Invites)
|
||||
val result = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters)
|
||||
val result = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters, isSpaceFilterSelected = false)
|
||||
assertThat(result).isNotNull()
|
||||
assertThat(result?.title).isEqualTo(R.string.screen_roomlist_filter_invites_empty_state_title)
|
||||
assertThat(result?.subtitle).isEqualTo(R.string.screen_roomlist_filter_mixed_empty_state_subtitle)
|
||||
@@ -68,7 +68,15 @@ class RoomListFiltersEmptyStateResourcesTest {
|
||||
@Test
|
||||
fun `fromSelectedFilters should return exact RoomListFiltersEmptyStateResources when selectedFilters has multiple filters`() {
|
||||
val selectedFilters = listOf(RoomListFilter.Unread, RoomListFilter.People, RoomListFilter.Rooms, RoomListFilter.Favourites)
|
||||
val result = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters)
|
||||
val result = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters, isSpaceFilterSelected = false)
|
||||
assertThat(result).isNotNull()
|
||||
assertThat(result?.title).isEqualTo(R.string.screen_roomlist_filter_mixed_empty_state_title)
|
||||
assertThat(result?.subtitle).isEqualTo(R.string.screen_roomlist_filter_mixed_empty_state_subtitle)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `fromSelectedFilters should return exact RoomListFiltersEmptyStateResources when isSpaceFilterSelected is true`() {
|
||||
val result = RoomListFiltersEmptyStateResources.fromSelectedFilters(emptyList(), isSpaceFilterSelected = true)
|
||||
assertThat(result).isNotNull()
|
||||
assertThat(result?.title).isEqualTo(R.string.screen_roomlist_filter_mixed_empty_state_title)
|
||||
assertThat(result?.subtitle).isEqualTo(R.string.screen_roomlist_filter_mixed_empty_state_subtitle)
|
||||
|
||||
Reference in New Issue
Block a user