Add room list filter combining based on space selection

This commit is contained in:
ganfra 2026-02-02 21:46:33 +01:00
parent 2f0da202df
commit 212a8e3aa3
7 changed files with 48 additions and 49 deletions

View file

@ -9,6 +9,7 @@
package io.element.android.features.home.impl.filters
import io.element.android.features.home.impl.R
import io.element.android.libraries.matrix.api.roomlist.RoomListFilter as MatrixRoomListFilter
/**
* Enum class representing the different filters that can be applied to the room list.
@ -30,3 +31,13 @@ enum class RoomListFilter(val stringResource: Int) {
Invites -> setOf(Rooms, People, Unread, Favourites)
}
}
fun RoomListFilter.into(): MatrixRoomListFilter {
return when (this) {
RoomListFilter.Rooms -> MatrixRoomListFilter.Category.Group
RoomListFilter.People -> MatrixRoomListFilter.Category.People
RoomListFilter.Unread -> MatrixRoomListFilter.Unread
RoomListFilter.Favourites -> MatrixRoomListFilter.Favorite
RoomListFilter.Invites -> MatrixRoomListFilter.Invite
}
}

View file

@ -9,24 +9,17 @@
package io.element.android.features.home.impl.filters
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.produceState
import dev.zacsweers.metro.Inject
import io.element.android.features.home.impl.datasource.RoomListDataSource
import io.element.android.features.home.impl.filters.selection.FilterSelectionStrategy
import io.element.android.libraries.architecture.Presenter
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.map
import io.element.android.libraries.matrix.api.roomlist.RoomListFilter as MatrixRoomListFilter
@Inject
class RoomListFiltersPresenter(
private val roomListDataSource: RoomListDataSource,
private val filterSelectionStrategy: FilterSelectionStrategy,
) : Presenter<RoomListFiltersState> {
private val initialFilters = filterSelectionStrategy.filterSelectionStates.value.toImmutableList()
@Composable
override fun present(): RoomListFiltersState {
fun handleEvent(event: RoomListFiltersEvent) {
@ -40,31 +33,9 @@ class RoomListFiltersPresenter(
}
}
val filters by produceState(initialValue = initialFilters) {
filterSelectionStrategy.filterSelectionStates
.map { filters ->
value = filters.toImmutableList()
filters.mapNotNull { filterState ->
if (!filterState.isSelected) {
return@mapNotNull null
}
when (filterState.filter) {
RoomListFilter.Rooms -> MatrixRoomListFilter.Category.Group
RoomListFilter.People -> MatrixRoomListFilter.Category.People
RoomListFilter.Unread -> MatrixRoomListFilter.Unread
RoomListFilter.Favourites -> MatrixRoomListFilter.Favorite
RoomListFilter.Invites -> MatrixRoomListFilter.Invite
}
}
}
.collectLatest { filters ->
val result = MatrixRoomListFilter.All(filters)
roomListDataSource.updateFilter(result)
}
}
val filters by filterSelectionStrategy.filterSelectionStates.collectAsState()
return RoomListFiltersState(
filterSelectionStates = filters,
filterSelectionStates = filters.toImmutableList(),
eventSink = ::handleEvent,
)
}

View file

@ -29,9 +29,11 @@ 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.RoomListFiltersState
import io.element.android.features.home.impl.filters.into
import io.element.android.features.home.impl.search.RoomListSearchEvent
import io.element.android.features.home.impl.search.RoomListSearchState
import io.element.android.features.home.impl.spacefilters.SpaceFiltersState
import io.element.android.features.home.impl.spacefilters.selectedFilter
import io.element.android.features.invite.api.SeenInvitesStore
import io.element.android.features.invite.api.acceptdecline.AcceptDeclineInviteEvents.AcceptInvite
import io.element.android.features.invite.api.acceptdecline.AcceptDeclineInviteEvents.DeclineInvite
@ -45,6 +47,7 @@ import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.encryption.RecoveryState
import io.element.android.libraries.matrix.api.roomlist.RoomList
import io.element.android.libraries.matrix.api.roomlist.RoomListFilter
import io.element.android.libraries.matrix.api.timeline.ReceiptType
import io.element.android.libraries.matrix.ui.safety.rememberHideInvitesAvatar
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
@ -153,6 +156,21 @@ class RoomListPresenter(
}
}
LaunchedEffect(filtersState.filterSelectionStates, spaceFiltersState.selectedFilter()) {
val selectedFilters = filtersState.filterSelectionStates.mapNotNull { filterState ->
if (!filterState.isSelected) {
return@mapNotNull null
}
filterState.filter.into()
}
val selectedSpaceFilter = when (spaceFiltersState) {
is SpaceFiltersState.Selected -> RoomListFilter.Identifiers(spaceFiltersState.selectedFilter.descendants)
else -> null
}
val allFilters = RoomListFilter.All(selectedFilters + listOfNotNull(selectedSpaceFilter))
roomListDataSource.updateFilter(allFilters)
}
val contentState = roomListContentState(
securityBannerDismissed,
showNewNotificationSoundBanner,

View file

@ -8,6 +8,7 @@
package io.element.android.features.home.impl.spacefilters
import androidx.compose.foundation.text.input.TextFieldState
import io.element.android.features.home.impl.filters.RoomListFilter
import io.element.android.libraries.matrix.api.spaces.SpaceServiceFilter
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
@ -40,3 +41,10 @@ sealed interface SpaceFiltersState {
val eventSink: (SpaceFiltersEvent.Selected) -> Unit,
) : SpaceFiltersState
}
fun SpaceFiltersState.selectedFilter(): SpaceServiceFilter? {
return when (this) {
is SpaceFiltersState.Selected -> this.selectedFilter
else -> null
}
}

View file

@ -9,9 +9,6 @@
package io.element.android.features.home.impl.filters
import com.google.common.truth.Truth.assertThat
import io.element.android.features.home.impl.FakeDateTimeObserver
import io.element.android.features.home.impl.datasource.RoomListDataSource
import io.element.android.features.home.impl.datasource.aRoomListRoomSummaryFactory
import io.element.android.features.home.impl.filters.selection.DefaultFilterSelectionStrategy
import io.element.android.features.home.impl.filters.selection.FilterSelectionState
import io.element.android.libraries.dateformatter.api.DateFormatter
@ -22,10 +19,8 @@ import io.element.android.libraries.matrix.api.notificationsettings.Notification
import io.element.android.libraries.matrix.api.roomlist.RoomListService
import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.tests.testutils.awaitLastSequentialItem
import io.element.android.tests.testutils.test
import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.advanceUntilIdle
@ -117,18 +112,6 @@ private fun TestScope.createRoomListFiltersPresenter(
roomLatestEventFormatter: RoomLatestEventFormatter = FakeRoomLatestEventFormatter(),
): RoomListFiltersPresenter {
return RoomListFiltersPresenter(
roomListDataSource = RoomListDataSource(
roomListService = roomListService,
roomListRoomSummaryFactory = aRoomListRoomSummaryFactory(
dateFormatter = dateFormatter,
roomLatestEventFormatter = roomLatestEventFormatter,
),
coroutineDispatchers = testCoroutineDispatchers(),
notificationSettingsService = notificationSettingsService,
sessionCoroutineScope = backgroundScope,
dateTimeObserver = FakeDateTimeObserver(),
analyticsService = FakeAnalyticsService(),
),
filterSelectionStrategy = DefaultFilterSelectionStrategy(),
)
}

View file

@ -8,6 +8,8 @@
package io.element.android.libraries.matrix.api.roomlist
import io.element.android.libraries.matrix.api.core.RoomId
sealed interface RoomListFilter {
companion object {
/**
@ -41,6 +43,10 @@ sealed interface RoomListFilter {
val filters: List<RoomListFilter>
) : RoomListFilter
data class Identifiers(
val values : List<RoomId>,
): RoomListFilter
/**
* A filter that matches rooms that are unread.
*/

View file

@ -14,6 +14,7 @@ import org.matrix.rustcomponents.sdk.RoomListEntriesDynamicFilterKind.Any
import org.matrix.rustcomponents.sdk.RoomListEntriesDynamicFilterKind.Category
import org.matrix.rustcomponents.sdk.RoomListEntriesDynamicFilterKind.DeduplicateVersions
import org.matrix.rustcomponents.sdk.RoomListEntriesDynamicFilterKind.Favourite
import org.matrix.rustcomponents.sdk.RoomListEntriesDynamicFilterKind.Identifiers
import org.matrix.rustcomponents.sdk.RoomListEntriesDynamicFilterKind.Invite
import org.matrix.rustcomponents.sdk.RoomListEntriesDynamicFilterKind.NonLeft
import org.matrix.rustcomponents.sdk.RoomListEntriesDynamicFilterKind.NonSpace
@ -60,6 +61,7 @@ internal object RoomListFilterMapper {
return when (filter) {
is RoomListFilter.All -> All(filters = filter.filters.map { mapFilter(it) })
is RoomListFilter.Any -> Any(filters = filter.filters.map { mapFilter(it) })
is RoomListFilter.Identifiers -> Identifiers(identifiers = filter.values.map { it.value })
RoomListFilter.None -> None
RoomListFilter.Category.Group -> Category(RoomListFilterCategory.GROUP)
RoomListFilter.Category.People -> Category(RoomListFilterCategory.PEOPLE)