diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt index a741da14e98..06d3ba36dc4 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt @@ -172,11 +172,13 @@ class RoomListPresenter( val showUnreadCount by produceState(false) { value = featureFlagService.isFeatureEnabled(FeatureFlags.UnreadIndicatorCount) } + val isSpaceSelected = spaceFiltersState.selectedFilter() != null val contentState = roomListContentState( securityBannerDismissed, showNewNotificationSoundBanner, showUnreadCount, + hasSelectedSpace = isSpaceSelected, ) return RoomListState( @@ -234,10 +236,19 @@ class RoomListPresenter( securityBannerDismissed: Boolean, showNewNotificationSoundBanner: Boolean, showUnreadCount: Boolean, + hasSelectedSpace: Boolean, ): RoomListContentState { val roomSummaries by produceState(initialValue = AsyncData.Loading()) { roomListDataSource.roomSummariesFlow.collect { value = AsyncData.Success(it) } } + val spaceMemberRoomIds by produceState>(initialValue = emptySet()) { + client.spaceService.spaceFiltersFlow.collect { filters -> + value = filters.flatMap { it.descendants }.toSet() + } + } + val hideSpaceRooms by remember { + sessionPreferencesStore.isHideSpaceRoomMembersEnabled() + }.collectAsState(initial = false) val loadingState by roomListDataSource.loadingState.collectAsState() val showEmpty by remember { derivedStateOf { @@ -259,13 +270,19 @@ class RoomListPresenter( else -> { coldStartWatcher.onRoomListVisible() + val filteredSummaries = if (hideSpaceRooms && !hasSelectedSpace) { + roomSummaries.dataOrNull().orEmpty().filter { it.roomId !in spaceMemberRoomIds } + } else { + roomSummaries.dataOrNull().orEmpty() + } + RoomListContentState.Rooms( securityBannerState = securityBannerState, showNewNotificationSoundBanner = showNewNotificationSoundBanner, showUnreadCount = showUnreadCount, fullScreenIntentPermissionsState = fullScreenIntentPermissionsPresenter.present(), batteryOptimizationState = batteryOptimizationPresenter.present(), - summaries = roomSummaries.dataOrNull().orEmpty().toImmutableList(), + summaries = filteredSummaries.toImmutableList(), seenRoomInvites = seenRoomInvites.toImmutableSet(), ) } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsEvents.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsEvents.kt index ef27c499afe..84715d0abda 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsEvents.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsEvents.kt @@ -21,4 +21,5 @@ sealed interface AdvancedSettingsEvents { data class SetTimelineMediaPreviewValue(val value: MediaPreviewValue) : AdvancedSettingsEvents data class SetHideInviteAvatars(val value: Boolean) : AdvancedSettingsEvents data class SetLiveLocationMinimumDistanceUpdate(val value: Int) : AdvancedSettingsEvents + data class SetHideSpaceRoomMembers(val enabled: Boolean) : AdvancedSettingsEvents } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenter.kt index 45c136ab626..efc2aa0cebc 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenter.kt @@ -57,6 +57,10 @@ class AdvancedSettingsPresenter( appPreferencesStore.getLiveLocationMinimumDistanceInMetersUpdateFlow().collect { value = it } } + val isHideSpaceRoomMembersEnabled by remember { + sessionPreferencesStore.isHideSpaceRoomMembersEnabled() + }.collectAsState(initial = false) + val mediaPreviewConfigState = mediaPreviewConfigStateStore.state() val themeOption by remember { @@ -130,6 +134,9 @@ class AdvancedSettingsPresenter( is AdvancedSettingsEvents.SetVideoUploadQuality -> sessionCoroutineScope.launch { sessionPreferencesStore.setVideoCompressionPreset(event.videoPreset) } + is AdvancedSettingsEvents.SetHideSpaceRoomMembers -> sessionCoroutineScope.launch { + sessionPreferencesStore.setHideSpaceRoomMembers(event.enabled) + } } } @@ -141,6 +148,7 @@ class AdvancedSettingsPresenter( availableThemeOptions = availableThemeOptions, mediaPreviewConfigState = mediaPreviewConfigState, liveLocationMinimumDistanceUpdate = liveLocationMinimumDistanceUpdate, + isHideSpaceRoomMembersEnabled = isHideSpaceRoomMembersEnabled, eventSink = ::handleEvent, ) } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsState.kt index 94019c1f01a..bb65b5f4937 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsState.kt @@ -24,6 +24,7 @@ data class AdvancedSettingsState( val availableThemeOptions: ImmutableList, val mediaPreviewConfigState: MediaPreviewConfigState, val liveLocationMinimumDistanceUpdate: Int?, + val isHideSpaceRoomMembersEnabled: Boolean, val eventSink: (AdvancedSettingsEvents) -> Unit ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsStateProvider.kt index 2df59e3cede..e5f9388e527 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsStateProvider.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsStateProvider.kt @@ -42,6 +42,7 @@ fun aAdvancedSettingsState( hideInviteAvatars: Boolean = false, timelineMediaPreviewValue: MediaPreviewValue = MediaPreviewValue.On, liveLocationMinimumDistanceUpdate: Int? = 50, + isHideSpaceRoomMembersEnabled: Boolean = false, setTimelineMediaPreviewAction: AsyncAction = AsyncAction.Uninitialized, setHideInviteAvatarsAction: AsyncAction = AsyncAction.Uninitialized, eventSink: (AdvancedSettingsEvents) -> Unit = {}, @@ -58,5 +59,6 @@ fun aAdvancedSettingsState( setHideInviteAvatarsAction = setHideInviteAvatarsAction ), liveLocationMinimumDistanceUpdate = liveLocationMinimumDistanceUpdate, + isHideSpaceRoomMembersEnabled = isHideSpaceRoomMembersEnabled, eventSink = eventSink ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsView.kt index c108c45d3b6..ce71385d997 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsView.kt @@ -116,6 +116,19 @@ fun AdvancedSettingsView( ), onClick = { state.eventSink(AdvancedSettingsEvents.SetSharePresenceEnabled(!state.isSharePresenceEnabled)) } ) + ListItem( + headlineContent = { + Text(text = stringResource(id = R.string.screen_advanced_settings_hide_space_rooms_toggle_title)) + }, + supportingContent = { + Text(text = stringResource(id = R.string.screen_advanced_settings_hide_space_rooms_toggle_description)) + }, + trailingContent = ListItemContent.Switch( + checked = state.isHideSpaceRoomMembersEnabled, + ), + onClick = { state.eventSink(AdvancedSettingsEvents.SetHideSpaceRoomMembers(!state.isHideSpaceRoomMembersEnabled)) } + ) + val compressImages = state.mediaOptimizationState?.shouldCompressImages when (state.mediaOptimizationState) { diff --git a/features/preferences/impl/src/main/res/values/temporary.xml b/features/preferences/impl/src/main/res/values/temporary.xml new file mode 100644 index 00000000000..7146e0f88b0 --- /dev/null +++ b/features/preferences/impl/src/main/res/values/temporary.xml @@ -0,0 +1,10 @@ + + + Hide rooms from spaces + When enabled, rooms that are part of a space will be hidden from the main room list. + diff --git a/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/SessionPreferencesStore.kt b/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/SessionPreferencesStore.kt index d3f3fb4e282..0a8b65140b8 100644 --- a/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/SessionPreferencesStore.kt +++ b/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/SessionPreferencesStore.kt @@ -35,5 +35,8 @@ interface SessionPreferencesStore { suspend fun setVideoCompressionPreset(preset: VideoCompressionPreset) fun getVideoCompressionPreset(): Flow + suspend fun setHideSpaceRoomMembers(enabled: Boolean) + fun isHideSpaceRoomMembersEnabled(): Flow + suspend fun clear() } diff --git a/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultSessionPreferencesStore.kt b/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultSessionPreferencesStore.kt index 907d454ada6..c00201732e5 100644 --- a/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultSessionPreferencesStore.kt +++ b/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultSessionPreferencesStore.kt @@ -47,6 +47,7 @@ class DefaultSessionPreferencesStore( private val skipSessionVerification = booleanPreferencesKey("skipSessionVerification") private val compressImages = booleanPreferencesKey("compressMedia") private val compressMediaPreset = stringPreferencesKey("compressMediaPreset") + private val hideSpaceRoomMembers = booleanPreferencesKey("hideSpaceRoomMembers") private val dataStoreFile = storeFile(context, sessionId) private val store = PreferenceDataStoreFactory.create( @@ -94,6 +95,9 @@ class DefaultSessionPreferencesStore( override fun getVideoCompressionPreset(): Flow = get(compressMediaPreset) { VideoCompressionPreset.STANDARD.name } .map { tryOrNull { VideoCompressionPreset.valueOf(it) } ?: VideoCompressionPreset.STANDARD } + override suspend fun setHideSpaceRoomMembers(enabled: Boolean) = update(hideSpaceRoomMembers, enabled) + override fun isHideSpaceRoomMembersEnabled(): Flow = get(hideSpaceRoomMembers) { false } + override suspend fun clear() { dataStoreFile.safeDelete() } diff --git a/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemorySessionPreferencesStore.kt b/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemorySessionPreferencesStore.kt index 7e2027d58fa..9c7bf495475 100644 --- a/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemorySessionPreferencesStore.kt +++ b/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemorySessionPreferencesStore.kt @@ -31,6 +31,7 @@ class InMemorySessionPreferencesStore( private val isSessionVerificationSkipped = MutableStateFlow(isSessionVerificationSkipped) private val doesCompressMedia = MutableStateFlow(doesCompressMedia) private val videoCompressionPreset = MutableStateFlow(videoCompressionPreset) + private val hideSpaceRoomMembers = MutableStateFlow(false) var clearCallCount = 0 private set @@ -84,6 +85,14 @@ class InMemorySessionPreferencesStore( return videoCompressionPreset } + override suspend fun setHideSpaceRoomMembers(enabled: Boolean) { + hideSpaceRoomMembers.value = enabled + } + + override fun isHideSpaceRoomMembersEnabled(): Flow { + return hideSpaceRoomMembers + } + override suspend fun clear() { clearCallCount++ isSendPublicReadReceiptsEnabled.tryEmit(true)