From dd24e14cf61f6f64fa4b139f2b7dad3519acb819 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 17 Jun 2026 17:20:58 +0200 Subject: [PATCH] Gate user status behind UserStatus feature flag --- .../impl/root/PreferencesRootPresenter.kt | 4 +- .../impl/root/PreferencesRootState.kt | 2 +- .../impl/root/PreferencesRootStateProvider.kt | 2 +- .../impl/root/PreferencesRootView.kt | 39 ++++++++++++++----- .../libraries/featureflag/api/FeatureFlags.kt | 7 ++++ 5 files changed, 40 insertions(+), 14 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt index fa69382cf8..3daeb5aec1 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt @@ -62,20 +62,20 @@ class PreferencesRootPresenter( ) : Presenter { @Composable override fun present(): PreferencesRootState { - val userStatusState = userStatusPresenter.present() val coroutineScope = rememberCoroutineScope() val matrixUser = matrixClient.userProfile.collectAsState() LaunchedEffect(Unit) { // Force a refresh of the profile matrixClient.getUserProfile() } - val isMultiAccountEnabled by remember { featureFlagService.isFeatureEnabledFlow(FeatureFlags.MultiAccount) }.collectAsState(initial = false) val showLinkNewDevice by remember { featureFlagService.isFeatureEnabledFlow(FeatureFlags.QrCodeLogin) }.collectAsState(initial = false) + val isUserStatusEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.UserStatus).collectAsState(initial = false) + val userStatusState = if (isUserStatusEnabled) userStatusPresenter.present() else null val otherSessions by remember { sessionStore.sessionsFlow().map { list -> diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt index 8163e4b7a0..c415547a80 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt @@ -17,7 +17,7 @@ import kotlinx.collections.immutable.ImmutableList data class PreferencesRootState( val myUser: MatrixUser, - val userStatusState: UserStatusState, + val userStatusState: UserStatusState?, val version: String, val deviceId: DeviceId?, val isMultiAccountEnabled: Boolean, diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt index 9e1557fd7b..1ac2e1f6f5 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt @@ -88,7 +88,7 @@ fun aPreferencesRootState( nbOfBlockedUsers: Int = 0, showLabsItem: Boolean = false, directLogoutState: DirectLogoutState = aDirectLogoutState(), - userStatusState: UserStatusState = aUserStatusState(), + userStatusState: UserStatusState? = aUserStatusState(), snackbarMessage: SnackbarMessage? = null, eventSink: (PreferencesRootEvent) -> Unit = {}, ) = PreferencesRootState( diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt index d92c1e4613..5221c82dda 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt @@ -25,6 +25,7 @@ import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.preferences.impl.R import io.element.android.features.preferences.impl.user.UserPreferences import io.element.android.features.preferences.impl.userstatus.UserStatusRow +import io.element.android.features.preferences.impl.userstatus.UserStatusState import io.element.android.libraries.architecture.coverage.ExcludeFromCoverage import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.list.ListItemContent @@ -82,15 +83,14 @@ fun PreferencesRootView( }, matrixUser = state.myUser, ) - HorizontalDivider() - UserStatusRow( - state = state.userStatusState, - modifier = Modifier.fillMaxWidth(), - ) - HorizontalDivider() + + if (state.userStatusState != null) { + UserStatusSection(state.userStatusState) + } if (state.isMultiAccountEnabled) { MultiAccountSection( state = state, + showTopDivider = state.userStatusState == null, onAddAccountClick = onAddAccountClick, ) } @@ -135,14 +135,33 @@ fun PreferencesRootView( } @Composable -private fun ColumnScope.MultiAccountSection( - state: PreferencesRootState, - onAddAccountClick: () -> Unit, -) { +private fun ColumnScope.UserStatusSection(userStatusState: UserStatusState) { HorizontalDivider( thickness = 8.dp, color = ElementTheme.colors.bgSubtleSecondary, ) + UserStatusRow( + state = userStatusState, + modifier = Modifier.fillMaxWidth(), + ) + HorizontalDivider( + thickness = 8.dp, + color = ElementTheme.colors.bgSubtleSecondary, + ) +} + +@Composable +private fun ColumnScope.MultiAccountSection( + state: PreferencesRootState, + showTopDivider: Boolean, + onAddAccountClick: () -> Unit, +) { + if(showTopDivider) { + HorizontalDivider( + thickness = 8.dp, + color = ElementTheme.colors.bgSubtleSecondary, + ) + } state.otherSessions.forEach { matrixUser -> MatrixUserRow( modifier = Modifier diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt index 0127e41c99..b298cd2f16 100644 --- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt +++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt @@ -137,4 +137,11 @@ enum class FeatureFlags( defaultValue = { false }, isFinished = false, ), + UserStatus( + key = "feature.user_status", + title = "User status", + description = "Allow users to set a status (e.g. In a meeting, Away) visible to their contacts.", + defaultValue = { false }, + isFinished = false, + ), }