Wire UserStatusPresenter and UserStatusRow into PreferencesRoot

This commit is contained in:
ganfra
2026-06-12 15:48:54 +02:00
parent af5a237b4a
commit 6c34d647ca
7 changed files with 48 additions and 6 deletions
@@ -21,6 +21,7 @@ import androidx.compose.runtime.setValue
import dev.zacsweers.metro.Inject
import io.element.android.features.enterprise.api.SessionEnterpriseService
import io.element.android.features.logout.api.direct.DirectLogoutState
import io.element.android.features.preferences.impl.userstatus.UserStatusState
import io.element.android.features.preferences.impl.utils.ShowDeveloperSettingsProvider
import io.element.android.features.rageshake.api.RageshakeFeatureAvailability
import io.element.android.libraries.architecture.Presenter
@@ -57,9 +58,11 @@ class PreferencesRootPresenter(
private val featureFlagService: FeatureFlagService,
private val sessionStore: SessionStore,
private val sessionEnterpriseService: SessionEnterpriseService,
private val userStatusPresenter: Presenter<UserStatusState>,
) : Presenter<PreferencesRootState> {
@Composable
override fun present(): PreferencesRootState {
val userStatusState = userStatusPresenter.present()
val coroutineScope = rememberCoroutineScope()
val matrixUser = matrixClient.userProfile.collectAsState()
LaunchedEffect(Unit) {
@@ -137,6 +140,7 @@ class PreferencesRootPresenter(
return PreferencesRootState(
myUser = matrixUser.value,
userStatusState = userStatusState,
version = remember { versionFormatter.get() },
deviceId = matrixClient.deviceId,
isMultiAccountEnabled = isMultiAccountEnabled,
@@ -9,6 +9,7 @@
package io.element.android.features.preferences.impl.root
import io.element.android.features.logout.api.direct.DirectLogoutState
import io.element.android.features.preferences.impl.userstatus.UserStatusState
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
import io.element.android.libraries.matrix.api.core.DeviceId
import io.element.android.libraries.matrix.api.user.MatrixUser
@@ -16,6 +17,7 @@ import kotlinx.collections.immutable.ImmutableList
data class PreferencesRootState(
val myUser: MatrixUser,
val userStatusState: UserStatusState,
val version: String,
val deviceId: DeviceId?,
val isMultiAccountEnabled: Boolean,
@@ -11,6 +11,8 @@ package io.element.android.features.preferences.impl.root
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.logout.api.direct.DirectLogoutState
import io.element.android.features.logout.api.direct.aDirectLogoutState
import io.element.android.features.preferences.impl.userstatus.UserStatusState
import io.element.android.features.preferences.impl.userstatus.aUserStatusState
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
import io.element.android.libraries.matrix.api.core.DeviceId
import io.element.android.libraries.matrix.api.user.MatrixUser
@@ -86,6 +88,7 @@ fun aPreferencesRootState(
nbOfBlockedUsers: Int = 0,
showLabsItem: Boolean = false,
directLogoutState: DirectLogoutState = aDirectLogoutState(),
userStatusState: UserStatusState = aUserStatusState(),
snackbarMessage: SnackbarMessage? = null,
eventSink: (PreferencesRootEvent) -> Unit = {},
) = PreferencesRootState(
@@ -105,6 +108,7 @@ fun aPreferencesRootState(
nbOfBlockedUsers = nbOfBlockedUsers,
showLabsItem = showLabsItem,
directLogoutState = directLogoutState,
userStatusState = userStatusState,
snackbarMessage = snackbarMessage,
eventSink = eventSink,
)
@@ -10,6 +10,7 @@ package io.element.android.features.preferences.impl.root
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
@@ -23,6 +24,7 @@ import io.element.android.compound.theme.ElementTheme
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.libraries.architecture.coverage.ExcludeFromCoverage
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.components.list.ListItemContent
@@ -80,15 +82,18 @@ fun PreferencesRootView(
},
matrixUser = state.myUser,
)
HorizontalDivider()
UserStatusRow(
state = state.userStatusState,
modifier = Modifier.fillMaxWidth(),
)
HorizontalDivider()
if (state.isMultiAccountEnabled) {
MultiAccountSection(
state = state,
onAddAccountClick = onAddAccountClick,
)
} else {
HorizontalDivider()
}
// User status will be added here
// 'Account' section
ManageAccountSection(
state = state,
@@ -0,0 +1,20 @@
/*
* Copyright (c) 2026 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.preferences.impl.userstatus
import io.element.android.libraries.matrix.api.user.DisplayedStatus
fun aUserStatusState(
displayedStatus: DisplayedStatus? = null,
pickerState: UserStatusPickerState = UserStatusPickerState.Hidden,
eventSink: (UserStatusEvent) -> Unit = {},
) = UserStatusState(
displayedStatus = displayedStatus,
pickerState = pickerState,
eventSink = eventSink,
)
@@ -15,6 +15,7 @@ import com.google.common.truth.Truth.assertThat
import io.element.android.features.enterprise.api.SessionEnterpriseService
import io.element.android.features.enterprise.test.FakeSessionEnterpriseService
import io.element.android.features.logout.api.direct.aDirectLogoutState
import io.element.android.features.preferences.impl.userstatus.aUserStatusState
import io.element.android.features.preferences.impl.utils.ShowDeveloperSettingsProvider
import io.element.android.features.rageshake.api.RageshakeFeatureAvailability
import io.element.android.libraries.core.meta.BuildType
@@ -346,5 +347,6 @@ class PreferencesRootPresenterTest {
featureFlagService = featureFlagService,
sessionStore = sessionStore,
sessionEnterpriseService = sessionEnterpriseService,
userStatusPresenter = { aUserStatusState() },
)
}
@@ -12,8 +12,11 @@ package io.element.android.features.preferences.impl.root
import androidx.activity.ComponentActivity
import androidx.compose.ui.test.AndroidComposeUiTest
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.hasClickAction
import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performScrollTo
import androidx.compose.ui.test.v2.runAndroidComposeUiTest
import io.element.android.features.preferences.impl.R
import io.element.android.libraries.matrix.api.user.MatrixUser
@@ -281,7 +284,8 @@ class PreferencesRootViewTest : RobolectricTest() {
),
onOpenDeveloperSettings = callback,
)
clickOn(CommonStrings.common_developer_options)
val text = activity!!.getString(CommonStrings.common_developer_options)
onNode(hasText(text) and hasClickAction()).performScrollTo().performClick()
}
}
@@ -404,7 +408,8 @@ class PreferencesRootViewTest : RobolectricTest() {
),
onDeactivateClick = callback,
)
clickOn(CommonStrings.action_delete_account)
val text = activity!!.getString(CommonStrings.action_delete_account)
onNode(hasText(text) and hasClickAction()).performScrollTo().performClick()
}
}
@@ -430,7 +435,7 @@ class PreferencesRootViewTest : RobolectricTest() {
eventSink = eventsRecorder,
),
)
onNodeWithText(version).performClick()
onNodeWithText(version).performScrollTo().performClick()
eventsRecorder.assertSingle(PreferencesRootEvent.OnVersionInfoClick)
}
}