diff --git a/.maestro/tests/account/logout.yaml b/.maestro/tests/account/logout.yaml index 83f834da04..270020c82c 100644 --- a/.maestro/tests/account/logout.yaml +++ b/.maestro/tests/account/logout.yaml @@ -2,17 +2,25 @@ appId: ${MAESTRO_APP_ID} --- - tapOn: id: "home_screen-settings" -- tapOn: - id: "settings-user_profile" -- assertVisible: "Your account" - tapOn: "Remove this device" - takeScreenshot: build/maestro/900-SignOutScreen - back - tapOn: "Remove this device" +# Ensure pressing back cancels +- back +- tapOn: "Remove this device" # Ensure cancel cancels +- tapOn: "Cancel" +- tapOn: "Remove this device" +- tapOn: + text: "Remove this device" + index: 1 +# Cancel the dialog cancels the logout - tapOn: id: "dialog-negative" -- tapOn: "Remove this device" +- tapOn: + text: "Remove this device" + index: 1 - tapOn: id: "dialog-positive" - runFlow: ../assertions/assertInitDisplayed.yaml diff --git a/features/home/impl/build.gradle.kts b/features/home/impl/build.gradle.kts index c66a4fd0e6..5a9bb700f2 100644 --- a/features/home/impl/build.gradle.kts +++ b/features/home/impl/build.gradle.kts @@ -53,7 +53,6 @@ dependencies { implementation(projects.features.announcement.api) implementation(projects.features.invite.api) implementation(projects.features.networkmonitor.api) - implementation(projects.features.logout.api) implementation(projects.features.leaveroom.api) implementation(projects.features.rageshake.api) implementation(projects.services.analytics.api) @@ -67,7 +66,6 @@ dependencies { testCommonDependencies(libs, true) testImplementation(projects.features.announcement.test) testImplementation(projects.features.invite.test) - testImplementation(projects.features.logout.test) testImplementation(projects.features.networkmonitor.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.featureflag.test) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeFlowNode.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeFlowNode.kt index 20f27f67bd..74dd6e441d 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeFlowNode.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeFlowNode.kt @@ -40,7 +40,6 @@ import io.element.android.features.invite.api.InviteData import io.element.android.features.invite.api.acceptdecline.AcceptDeclineInviteView import io.element.android.features.invite.api.declineandblock.DeclineInviteAndBlockEntryPoint import io.element.android.features.leaveroom.api.LeaveRoomRenderer -import io.element.android.features.logout.api.direct.DirectLogoutView import io.element.android.features.reportroom.api.ReportRoomEntryPoint import io.element.android.features.rolesandpermissions.api.ChangeRoomMemberRolesEntryPoint import io.element.android.features.rolesandpermissions.api.ChangeRoomMemberRolesListType @@ -83,7 +82,6 @@ class HomeFlowNode( private val inviteFriendsUseCase: InviteFriendsUseCase, private val analyticsService: AnalyticsService, private val acceptDeclineInviteView: AcceptDeclineInviteView, - private val directLogoutView: DirectLogoutView, private val reportRoomEntryPoint: ReportRoomEntryPoint, private val declineInviteAndBlockUserEntryPoint: DeclineInviteAndBlockEntryPoint, private val changeRoomMemberRolesEntryPoint: ChangeRoomMemberRolesEntryPoint, @@ -248,7 +246,6 @@ class HomeFlowNode( ) } ) - directLogoutView.Render(state.directLogoutState) } } diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomePresenter.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomePresenter.kt index 1e49b1aa70..f0bcedbb43 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomePresenter.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomePresenter.kt @@ -21,7 +21,6 @@ import androidx.compose.runtime.setValue import dev.zacsweers.metro.Inject import io.element.android.features.home.impl.roomlist.RoomListState import io.element.android.features.home.impl.spaces.HomeSpacesState -import io.element.android.features.logout.api.direct.DirectLogoutState import io.element.android.features.rageshake.api.RageshakeFeatureAvailability import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher @@ -42,7 +41,6 @@ class HomePresenter( private val indicatorService: IndicatorService, private val roomListPresenter: Presenter, private val homeSpacesPresenter: Presenter, - private val logoutPresenter: Presenter, private val rageshakeFeatureAvailability: RageshakeFeatureAvailability, private val sessionStore: SessionStore, ) : Presenter { @@ -75,7 +73,6 @@ class HomePresenter( } // Avatar indicator val showAvatarIndicator by indicatorService.showRoomListTopBarIndicator() - val directLogoutState = logoutPresenter.present() fun handleEvent(event: HomeEvent) { when (event) { @@ -98,7 +95,6 @@ class HomePresenter( homeSpacesState = homeSpacesState, snackbarMessage = snackbarMessage, canReportBug = canReportBug, - directLogoutState = directLogoutState, eventSink = ::handleEvent, ) } diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeState.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeState.kt index ae59ef8eb9..462084aefb 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeState.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeState.kt @@ -11,7 +11,6 @@ package io.element.android.features.home.impl import io.element.android.features.home.impl.roomlist.RoomListState import io.element.android.features.home.impl.spacefilters.SpaceFiltersState import io.element.android.features.home.impl.spaces.HomeSpacesState -import io.element.android.features.logout.api.direct.DirectLogoutState import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.matrix.api.user.MatrixUser import kotlinx.collections.immutable.ImmutableList @@ -29,7 +28,6 @@ data class HomeState( val homeSpacesState: HomeSpacesState, val snackbarMessage: SnackbarMessage?, val canReportBug: Boolean, - val directLogoutState: DirectLogoutState, val eventSink: (HomeEvent) -> Unit, ) { val isBackHandlerEnabled = currentHomeNavigationBarItem != HomeNavigationBarItem.Chats || roomListState.spaceFiltersState is SpaceFiltersState.Selected diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeStatePreviewParam.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeStatePreviewParam.kt index 14ab6dc7f6..f39942275a 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeStatePreviewParam.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeStatePreviewParam.kt @@ -16,8 +16,6 @@ import io.element.android.features.home.impl.roomlist.aRoomsContentState import io.element.android.features.home.impl.roomlist.generateRoomListRoomSummaryList import io.element.android.features.home.impl.spaces.HomeSpacesState import io.element.android.features.home.impl.spaces.aHomeSpacesState -import io.element.android.features.logout.api.direct.DirectLogoutState -import io.element.android.features.logout.api.direct.aDirectLogoutState import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.user.MatrixUser @@ -63,7 +61,6 @@ internal fun aHomeState( roomListState: RoomListState = aRoomListState(), homeSpacesState: HomeSpacesState = aHomeSpacesState(), canReportBug: Boolean = true, - directLogoutState: DirectLogoutState = aDirectLogoutState(), eventSink: (HomeEvent) -> Unit = {} ) = HomeState( currentUserAndNeighbors = currentUserAndNeighbors.toImmutableList(), @@ -71,7 +68,6 @@ internal fun aHomeState( hasNetworkConnection = hasNetworkConnection, snackbarMessage = snackbarMessage, canReportBug = canReportBug, - directLogoutState = directLogoutState, currentHomeNavigationBarItem = currentHomeNavigationBarItem, roomListState = roomListState, homeSpacesState = homeSpacesState, diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/DefaultHomeEntryPointTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/DefaultHomeEntryPointTest.kt index c0cb5f7c01..cf9336b6ea 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/DefaultHomeEntryPointTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/DefaultHomeEntryPointTest.kt @@ -36,7 +36,6 @@ class DefaultHomeEntryPointTest : RobolectricTest() { inviteFriendsUseCase = { lambdaError() }, analyticsService = FakeAnalyticsService(), acceptDeclineInviteView = { _, _, _, _ -> lambdaError() }, - directLogoutView = { _ -> lambdaError() }, reportRoomEntryPoint = { _, _, _ -> lambdaError() }, declineInviteAndBlockUserEntryPoint = FakeDeclineInviteAndBlockEntryPoint(), changeRoomMemberRolesEntryPoint = { _, _, _, _ -> lambdaError() }, diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/HomePresenterTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/HomePresenterTest.kt index 58ad4eb100..a5553352db 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/HomePresenterTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/HomePresenterTest.kt @@ -12,7 +12,6 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.home.impl.roomlist.aRoomListState import io.element.android.features.home.impl.spaces.HomeSpacesState import io.element.android.features.home.impl.spaces.aHomeSpacesState -import io.element.android.features.logout.api.direct.aDirectLogoutState import io.element.android.features.rageshake.api.RageshakeFeatureAvailability import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher @@ -162,7 +161,6 @@ internal fun createHomePresenter( indicatorService = indicatorService, roomListPresenter = { aRoomListState() }, homeSpacesPresenter = homeSpacesPresenter, - logoutPresenter = { aDirectLogoutState() }, rageshakeFeatureAvailability = rageshakeFeatureAvailability, sessionStore = sessionStore, ) diff --git a/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/direct/DirectLogoutState.kt b/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/direct/DirectLogoutState.kt index 75c3392ac1..62b4d36bd1 100644 --- a/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/direct/DirectLogoutState.kt +++ b/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/direct/DirectLogoutState.kt @@ -11,7 +11,6 @@ package io.element.android.features.logout.api.direct import io.element.android.libraries.architecture.AsyncAction data class DirectLogoutState( - val canDoDirectSignOut: Boolean, val logoutAction: AsyncAction, val eventSink: (DirectLogoutEvent) -> Unit, ) diff --git a/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/direct/DirectLogoutStatePreviewParam.kt b/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/direct/DirectLogoutStatePreviewParam.kt index 936f7d2a58..ca1d9fbd0b 100644 --- a/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/direct/DirectLogoutStatePreviewParam.kt +++ b/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/direct/DirectLogoutStatePreviewParam.kt @@ -23,11 +23,9 @@ open class DirectLogoutStatePreviewParam : PreviewParameterProvider = AsyncAction.Uninitialized, eventSink: (DirectLogoutEvent) -> Unit = {}, ) = DirectLogoutState( - canDoDirectSignOut = canDoDirectSignOut, logoutAction = logoutAction, eventSink = eventSink, ) diff --git a/features/logout/impl/build.gradle.kts b/features/logout/impl/build.gradle.kts index d5356ced63..bc6646a68f 100644 --- a/features/logout/impl/build.gradle.kts +++ b/features/logout/impl/build.gradle.kts @@ -31,6 +31,7 @@ dependencies { implementation(projects.libraries.architecture) implementation(projects.libraries.featureflag.api) implementation(projects.libraries.matrix.api) + implementation(projects.libraries.matrixui) implementation(projects.libraries.designsystem) implementation(projects.libraries.testtags) implementation(projects.libraries.uiStrings) diff --git a/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/LogoutPresenter.kt b/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/LogoutPresenter.kt index 4ad8a6c78e..a3cd2f6429 100644 --- a/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/LogoutPresenter.kt +++ b/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/LogoutPresenter.kt @@ -41,6 +41,7 @@ class LogoutPresenter( @Composable override fun present(): LogoutState { val localCoroutineScope = rememberCoroutineScope() + val currentUser by matrixClient.userProfile.collectAsState() val logoutAction: MutableState> = remember { mutableStateOf(AsyncAction.Uninitialized) } @@ -90,6 +91,7 @@ class LogoutPresenter( } return LogoutState( + currentUser = currentUser, isLastDevice = isLastDevice, backupState = backupState, doesBackupExistOnServer = doesBackupExistOnServerAction.value.dataOrNull().orTrue(), diff --git a/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/LogoutState.kt b/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/LogoutState.kt index 6233c1cb23..dfab1906fb 100644 --- a/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/LogoutState.kt +++ b/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/LogoutState.kt @@ -12,8 +12,10 @@ import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.encryption.BackupState import io.element.android.libraries.matrix.api.encryption.BackupUploadState import io.element.android.libraries.matrix.api.encryption.RecoveryState +import io.element.android.libraries.matrix.api.user.MatrixUser data class LogoutState( + val currentUser: MatrixUser, val isLastDevice: Boolean, val backupState: BackupState, val doesBackupExistOnServer: Boolean, diff --git a/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/LogoutStatePreviewParam.kt b/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/LogoutStatePreviewParam.kt index e2d948a7f3..9db884330b 100644 --- a/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/LogoutStatePreviewParam.kt +++ b/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/LogoutStatePreviewParam.kt @@ -14,6 +14,8 @@ import io.element.android.libraries.matrix.api.encryption.BackupState import io.element.android.libraries.matrix.api.encryption.BackupUploadState import io.element.android.libraries.matrix.api.encryption.RecoveryState import io.element.android.libraries.matrix.api.encryption.SteadyStateException +import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.ui.components.aMatrixUser open class LogoutStatePreviewParam : PreviewParameterProvider { override val values: Sequence @@ -39,10 +41,12 @@ open class LogoutStatePreviewParam : PreviewParameterProvider { backupUploadState = BackupUploadState.Waiting, waitingForALongTime = true, ), + aLogoutState(currentUser = aMatrixUser(id = "@alice:server.org", displayName = null)), ) } fun aLogoutState( + currentUser: MatrixUser = aMatrixUser(), isLastDevice: Boolean = false, backupState: BackupState = BackupState.ENABLED, doesBackupExistOnServer: Boolean = true, @@ -52,6 +56,7 @@ fun aLogoutState( logoutAction: AsyncAction = AsyncAction.Uninitialized, eventSink: (LogoutEvent) -> Unit = {}, ) = LogoutState( + currentUser = currentUser, isLastDevice = isLastDevice, backupState = backupState, doesBackupExistOnServer = doesBackupExistOnServer, diff --git a/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/LogoutView.kt b/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/LogoutView.kt index 90a502fc16..4093be223d 100644 --- a/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/LogoutView.kt +++ b/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/LogoutView.kt @@ -11,7 +11,9 @@ package io.element.android.features.logout.impl import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -32,15 +34,22 @@ import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.LinearProgressIndicator import io.element.android.libraries.designsystem.theme.components.OutlinedButton import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.progressIndicatorTrackColor import io.element.android.libraries.matrix.api.encryption.BackupState import io.element.android.libraries.matrix.api.encryption.BackupUploadState import io.element.android.libraries.matrix.api.encryption.RecoveryState import io.element.android.libraries.matrix.api.encryption.SteadyStateException +import io.element.android.libraries.matrix.ui.components.accountinfo.AccountInfoCard +import io.element.android.libraries.matrix.ui.components.accountinfo.AccountInfoCardMode +import io.element.android.libraries.matrix.ui.components.accountinfo.AccountInfoCardState import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag import io.element.android.libraries.ui.strings.CommonStrings +/** + * Ref: https://www.figma.com/design/kEAcfun9iSpszeUDvdKZ6b/ER-351--Multi-account-in-EX?node-id=442-34581 + */ @Composable fun LogoutView( state: LogoutState, @@ -54,15 +63,17 @@ fun LogoutView( onBackClick = onBackClick, title = title(state), subTitle = subtitle(state), - iconStyle = BigIcon.Style.Default(CompoundIcons.KeySolid()), + iconStyle = BigIcon.Style.Default(CompoundIcons.Mobile()), modifier = modifier, + isScrollable = true, buttons = { Buttons( state = state, onChangeRecoveryKeyClick = onChangeRecoveryKeyClick, onLogoutClick = { eventSink(LogoutEvent.Logout(ignoreSdkError = false)) - } + }, + onCancelClick = onBackClick, ) }, ) { @@ -71,6 +82,8 @@ fun LogoutView( LogoutActionDialog( state.logoutAction, + // Do not show the progress dialog, the progress is rendered in the button. + showProgressDialog = false, onConfirmClick = { eventSink(LogoutEvent.Logout(ignoreSdkError = false)) }, @@ -116,6 +129,7 @@ private fun ColumnScope.Buttons( state: LogoutState, onLogoutClick: () -> Unit, onChangeRecoveryKeyClick: () -> Unit, + onCancelClick: () -> Unit, ) { val logoutAction = state.logoutAction if (state.isLastDevice) { @@ -139,6 +153,12 @@ private fun ColumnScope.Buttons( .testTag(TestTags.signOut), onClick = onLogoutClick, ) + TextButton( + text = stringResource(id = CommonStrings.action_cancel), + enabled = logoutAction !is AsyncAction.Loading, + modifier = Modifier.fillMaxWidth(), + onClick = onCancelClick, + ) } @Composable @@ -149,9 +169,16 @@ private fun Content( Column( modifier = modifier .fillMaxWidth() - .padding(top = 60.dp, start = 20.dp, end = 20.dp), + .padding(top = 8.dp, start = 16.dp, end = 16.dp), verticalArrangement = Arrangement.spacedBy(8.dp) ) { + AccountInfoCard( + AccountInfoCardState( + matrixUser = state.currentUser, + mode = AccountInfoCardMode.Simple, + ) + ) + Spacer(modifier = Modifier.height(16.dp)) when (state.backupUploadState) { is BackupUploadState.Uploading -> { LinearProgressIndicator( diff --git a/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/direct/DefaultDirectLogoutView.kt b/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/direct/DefaultDirectLogoutView.kt index 901e4e9654..454a7a25fb 100644 --- a/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/direct/DefaultDirectLogoutView.kt +++ b/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/direct/DefaultDirectLogoutView.kt @@ -27,6 +27,7 @@ class DefaultDirectLogoutView : DirectLogoutView { val eventSink = state.eventSink LogoutActionDialog( state.logoutAction, + showProgressDialog = true, onConfirmClick = { eventSink(DirectLogoutEvent.Logout(ignoreSdkError = false)) }, diff --git a/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/direct/DirectLogoutPresenter.kt b/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/direct/DirectLogoutPresenter.kt index 79798dd2ab..0b18856ff4 100644 --- a/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/direct/DirectLogoutPresenter.kt +++ b/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/direct/DirectLogoutPresenter.kt @@ -10,28 +10,22 @@ package io.element.android.features.logout.impl.direct import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import dev.zacsweers.metro.Inject import io.element.android.features.logout.api.direct.DirectLogoutEvent import io.element.android.features.logout.api.direct.DirectLogoutState -import io.element.android.features.logout.impl.tools.isBackingUp import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.runCatchingUpdatingState import io.element.android.libraries.matrix.api.MatrixClient -import io.element.android.libraries.matrix.api.encryption.BackupUploadState -import io.element.android.libraries.matrix.api.encryption.EncryptionService import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @Inject class DirectLogoutPresenter( private val matrixClient: MatrixClient, - private val encryptionService: EncryptionService, ) : Presenter { @Composable override fun present(): DirectLogoutState { @@ -41,13 +35,6 @@ class DirectLogoutPresenter( mutableStateOf(AsyncAction.Uninitialized) } - val backupUploadState: BackupUploadState by remember { - encryptionService.waitForBackupUploadSteadyState() - } - .collectAsState(initial = BackupUploadState.Unknown) - - val isLastDevice by encryptionService.isLastDevice.collectAsState() - fun handleEvent(event: DirectLogoutEvent) { when (event) { is DirectLogoutEvent.Logout -> { @@ -64,8 +51,6 @@ class DirectLogoutPresenter( } return DirectLogoutState( - canDoDirectSignOut = !isLastDevice && - !backupUploadState.isBackingUp(), logoutAction = logoutAction.value, eventSink = ::handleEvent, ) diff --git a/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/ui/LogoutActionDialog.kt b/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/ui/LogoutActionDialog.kt index 0222a991db..ca9e6d9a16 100644 --- a/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/ui/LogoutActionDialog.kt +++ b/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/ui/LogoutActionDialog.kt @@ -19,6 +19,7 @@ import io.element.android.libraries.ui.strings.CommonStrings @Composable fun LogoutActionDialog( state: AsyncAction, + showProgressDialog: Boolean, onConfirmClick: () -> Unit, onForceLogoutClick: () -> Unit, onDismissDialog: () -> Unit, @@ -31,8 +32,11 @@ fun LogoutActionDialog( onSubmitClick = onConfirmClick, onDismiss = onDismissDialog ) - is AsyncAction.Loading -> - ProgressDialog(text = stringResource(id = R.string.screen_signout_in_progress_dialog_content)) + is AsyncAction.Loading -> { + if (showProgressDialog) { + ProgressDialog(text = stringResource(id = R.string.screen_signout_in_progress_dialog_content)) + } + } is AsyncAction.Failure -> RetryDialog( title = stringResource(id = CommonStrings.dialog_title_error), diff --git a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPresenterTest.kt b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPresenterTest.kt index 5b14bc5cc3..f22eef1bc3 100644 --- a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPresenterTest.kt +++ b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPresenterTest.kt @@ -20,7 +20,9 @@ import io.element.android.libraries.matrix.api.encryption.BackupState import io.element.android.libraries.matrix.api.encryption.BackupUploadState import io.element.android.libraries.matrix.api.encryption.EncryptionService import io.element.android.libraries.matrix.api.encryption.RecoveryState +import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.test.AN_EXCEPTION +import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService import io.element.android.libraries.workmanager.api.WorkManagerRequestType @@ -39,11 +41,18 @@ class LogoutPresenterTest { @Test fun `present - initial state`() = runTest { - val presenter = createLogoutPresenter() + val presenter = createLogoutPresenter( + matrixClient = FakeMatrixClient( + sessionId = A_SESSION_ID, + userDisplayName = "Alice", + userAvatarUrl = "mxc://avatar", + ), + ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitFirstItem() + assertThat(initialState.currentUser).isEqualTo(MatrixUser(A_SESSION_ID, "Alice", "mxc://avatar")) assertThat(initialState.isLastDevice).isFalse() assertThat(initialState.backupState).isEqualTo(BackupState.UNKNOWN) assertThat(initialState.doesBackupExistOnServer).isTrue() diff --git a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutViewTest.kt b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutViewTest.kt index f69ec8f0ca..4ec9bb4811 100644 --- a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutViewTest.kt +++ b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutViewTest.kt @@ -13,8 +13,11 @@ package io.element.android.features.logout.impl import androidx.activity.ComponentActivity import androidx.compose.ui.test.AndroidComposeUiTest import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.v2.runAndroidComposeUiTest import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.matrix.ui.components.aMatrixUser import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EnsureNeverCalled @@ -25,8 +28,22 @@ import io.element.android.tests.testutils.pressBack import io.element.android.tests.testutils.pressTag import io.element.android.tests.testutils.robolectric.RobolectricTest import org.junit.Test +import org.robolectric.annotation.Config class LogoutViewTest : RobolectricTest() { + @Test + @Config(qualifiers = "h1024dp") + fun `the current user is displayed`() = runAndroidComposeUiTest { + setLogoutView( + aLogoutState( + currentUser = aMatrixUser(id = "@alice:server.org", displayName = "Alice"), + eventSink = EventsRecorder(expectEvents = false), + ), + ) + onNodeWithText("Alice").assertIsDisplayed() + onNodeWithText("@alice:server.org").assertIsDisplayed() + } + @Test fun `clicking on logout sends a LogoutEvent`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() @@ -88,10 +105,24 @@ class LogoutViewTest : RobolectricTest() { eventSink = eventsRecorder ), ) - clickOn(CommonStrings.action_cancel) + clickOn(CommonStrings.action_cancel, inDialog = true) eventsRecorder.assertSingle(LogoutEvent.CloseDialogs) } + @Test + fun `clicking on cancel invoke back callback`() = runAndroidComposeUiTest { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + setLogoutView( + aLogoutState( + eventSink = eventsRecorder + ), + onBackClick = callback, + ) + clickOn(CommonStrings.action_cancel) + } + } + @Test fun `last session setting button invoke onChangeRecoveryKeyClicked`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) diff --git a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/direct/DirectLogoutPresenterTest.kt b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/direct/DirectLogoutPresenterTest.kt index d11c31cf1b..ff0420e04d 100644 --- a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/direct/DirectLogoutPresenterTest.kt +++ b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/direct/DirectLogoutPresenterTest.kt @@ -16,13 +16,9 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.logout.api.direct.DirectLogoutEvent import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.MatrixClient -import io.element.android.libraries.matrix.api.encryption.BackupUploadState -import io.element.android.libraries.matrix.api.encryption.EncryptionService import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.FakeMatrixClient -import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService import io.element.android.tests.testutils.WarmUpRule -import kotlinx.coroutines.flow.flow import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test @@ -38,44 +34,6 @@ class DirectLogoutPresenterTest { presenter.present() }.test { val initialState = awaitFirstItem() - assertThat(initialState.canDoDirectSignOut).isTrue() - assertThat(initialState.logoutAction).isEqualTo(AsyncAction.Uninitialized) - } - } - - @Test - fun `present - initial state - last session`() = runTest { - val presenter = createDirectLogoutPresenter( - encryptionService = FakeEncryptionService().apply { - emitIsLastDevice(true) - } - ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - val initialState = awaitFirstItem() - assertThat(initialState.canDoDirectSignOut).isFalse() - assertThat(initialState.logoutAction).isEqualTo(AsyncAction.Uninitialized) - } - } - - @Test - fun `present - initial state - backing up`() = runTest { - val encryptionService = FakeEncryptionService() - encryptionService.givenWaitForBackupUploadSteadyStateFlow( - flow { - emit(BackupUploadState.Waiting) - } - ) - val presenter = createDirectLogoutPresenter( - encryptionService = encryptionService - ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { - skipItems(1) - val initialState = awaitFirstItem() - assertThat(initialState.canDoDirectSignOut).isFalse() assertThat(initialState.logoutAction).isEqualTo(AsyncAction.Uninitialized) } } @@ -180,9 +138,7 @@ class DirectLogoutPresenterTest { private fun createDirectLogoutPresenter( matrixClient: MatrixClient = FakeMatrixClient(), - encryptionService: EncryptionService = FakeEncryptionService(), ): DirectLogoutPresenter = DirectLogoutPresenter( matrixClient = matrixClient, - encryptionService = encryptionService, ) } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/account/PreferencesAccountPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/account/PreferencesAccountPresenter.kt index ad9686be9c..4e04cd0ab6 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/account/PreferencesAccountPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/account/PreferencesAccountPresenter.kt @@ -17,7 +17,6 @@ import androidx.compose.runtime.remember 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.rageshake.api.RageshakeFeatureAvailability import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher @@ -34,7 +33,6 @@ class PreferencesAccountPresenter( private val sessionVerificationService: SessionVerificationService, private val snackbarDispatcher: SnackbarDispatcher, private val indicatorService: IndicatorService, - private val directLogoutPresenter: Presenter, private val rageshakeFeatureAvailability: RageshakeFeatureAvailability, private val featureFlagService: FeatureFlagService, private val sessionEnterpriseService: SessionEnterpriseService, @@ -65,8 +63,6 @@ class PreferencesAccountPresenter( canDeactivateAccount = matrixClient.canDeactivateAccount() } - val directLogoutState = directLogoutPresenter.present() - val accountManagementUrl by produceState(initialValue = null) { value = matrixClient.getAccountManagementUrl(null) .getOrNull() @@ -83,7 +79,6 @@ class PreferencesAccountPresenter( canReportBug = canReportBug, showLinkNewDevice = showLinkNewDevice, canDeactivateAccount = canDeactivateAccount, - directLogoutState = directLogoutState, snackbarMessage = snackbarMessage, ) } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/account/PreferencesAccountState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/account/PreferencesAccountState.kt index 00abbf2ad4..eaf65328f0 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/account/PreferencesAccountState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/account/PreferencesAccountState.kt @@ -7,7 +7,6 @@ package io.element.android.features.preferences.impl.account -import io.element.android.features.logout.api.direct.DirectLogoutState import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.matrix.api.user.MatrixUser @@ -19,6 +18,5 @@ data class PreferencesAccountState( val canReportBug: Boolean, val showLinkNewDevice: Boolean, val canDeactivateAccount: Boolean, - val directLogoutState: DirectLogoutState, val snackbarMessage: SnackbarMessage?, ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/account/PreferencesAccountStatePreviewParam.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/account/PreferencesAccountStatePreviewParam.kt index 0cf42104ef..2308b75d43 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/account/PreferencesAccountStatePreviewParam.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/account/PreferencesAccountStatePreviewParam.kt @@ -8,8 +8,6 @@ package io.element.android.features.preferences.impl.account 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.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.ui.components.aMatrixUser @@ -56,7 +54,6 @@ fun aPreferencesAccountState( canReportBug: Boolean = false, showLinkNewDevice: Boolean = false, canDeactivateAccount: Boolean = false, - directLogoutState: DirectLogoutState = aDirectLogoutState(), snackbarMessage: SnackbarMessage? = null, ) = PreferencesAccountState( myUser = myUser, @@ -66,6 +63,5 @@ fun aPreferencesAccountState( canReportBug = canReportBug, showLinkNewDevice = showLinkNewDevice, canDeactivateAccount = canDeactivateAccount, - directLogoutState = directLogoutState, snackbarMessage = snackbarMessage, ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt index 57ed6294fa..c4416ad61e 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt @@ -19,8 +19,6 @@ import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedInject import io.element.android.annotations.ContributesNode import io.element.android.compound.theme.ElementTheme -import io.element.android.features.logout.api.direct.DirectLogoutEvent -import io.element.android.features.logout.api.direct.DirectLogoutView import io.element.android.features.preferences.impl.account.PreferencesAccountCallback import io.element.android.libraries.androidutils.browser.openUrlInChromeCustomTab import io.element.android.libraries.architecture.callback @@ -34,7 +32,6 @@ class PreferencesRootNode( @Assisted plugins: List, private val presenter: PreferencesRootPresenter, private val emojiPickerRenderer: EmojiPickerRenderer, - private val directLogoutView: DirectLogoutView, ) : Node(buildContext, plugins = plugins) { interface Callback : PreferencesAccountCallback, Plugin { fun navigateToAddAccount() @@ -89,16 +86,8 @@ class PreferencesRootNode( onManageAccountClick = { onManageAccountClick(activity, it, isDark) }, onOpenNotificationSettings = callback::navigateToNotificationSettings, onEditProfileClick = callback::navigateToUserProfile, - onSignOutClick = { - if (state.preferencesAccountState.directLogoutState.canDoDirectSignOut) { - state.preferencesAccountState.directLogoutState.eventSink(DirectLogoutEvent.Logout(ignoreSdkError = false)) - } else { - callback.startSignOutFlow() - } - }, + onSignOutClick = callback::startSignOutFlow, onDeactivateClick = callback::startAccountDeactivationFlow ) - - directLogoutView.Render(state = state.preferencesAccountState.directLogoutState) } } diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/account/PreferencesAccountPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/account/PreferencesAccountPresenterTest.kt index cd1bd186f4..dce2d78a0d 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/account/PreferencesAccountPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/account/PreferencesAccountPresenterTest.kt @@ -10,7 +10,6 @@ package io.element.android.features.preferences.impl.account 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.rageshake.api.RageshakeFeatureAvailability import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher import io.element.android.libraries.featureflag.api.FeatureFlagService @@ -65,7 +64,6 @@ class PreferencesAccountPresenterTest { assertThat(initialState.showSecureBackupBadge).isFalse() assertThat(initialState.accountManagementUrl).isNull() assertThat(initialState.showLinkNewDevice).isFalse() - assertThat(initialState.directLogoutState).isEqualTo(aDirectLogoutState()) assertThat(initialState.snackbarMessage).isNull() val loadedState = consumeItemsUntilPredicate { it.accountManagementUrl != null }.last() assertThat(loadedState.showSecureBackup).isFalse() @@ -169,7 +167,6 @@ class PreferencesAccountPresenterTest { sessionVerificationService = sessionVerificationService, snackbarDispatcher = SnackbarDispatcher(), indicatorService = indicatorService, - directLogoutPresenter = { aDirectLogoutState() }, rageshakeFeatureAvailability = rageshakeFeatureAvailability, featureFlagService = featureFlagService, sessionEnterpriseService = sessionEnterpriseService, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt index e4c8ebc641..bbf6d94d9b 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt @@ -31,6 +31,7 @@ enum class AvatarSize(val dp: Dp) { UserHeader(96.dp), UserListItem(36.dp), + AccountInfoUser(36.dp), SelectedUser(52.dp), SelectedRoom(56.dp), diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/accountinfo/AccountInfoCard.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/accountinfo/AccountInfoCard.kt new file mode 100644 index 0000000000..ab0b172cc5 --- /dev/null +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/accountinfo/AccountInfoCard.kt @@ -0,0 +1,192 @@ +/* + * 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.libraries.matrix.ui.components.accountinfo + +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clipToBounds +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.dp +import io.element.android.compound.theme.ElementTheme +import io.element.android.libraries.designsystem.atomic.atoms.RoundedIconAtom +import io.element.android.libraries.designsystem.atomic.atoms.RoundedIconAtomSize +import io.element.android.libraries.designsystem.atomic.molecules.TextWithLabelMolecule +import io.element.android.libraries.designsystem.components.avatar.Avatar +import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.components.avatar.AvatarType +import io.element.android.libraries.designsystem.icons.CompoundDrawables +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.theme.components.HorizontalDivider +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.ui.model.getAvatarData +import io.element.android.libraries.matrix.ui.model.getBestName +import io.element.android.libraries.ui.strings.CommonStrings + +/** + * Ref: https://www.figma.com/design/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?node-id=5873-996 + */ +@Composable +fun AccountInfoCard( + state: AccountInfoCardState, + modifier: Modifier = Modifier, +) { + Column( + modifier = modifier + .fillMaxWidth() + .border(1.dp, ElementTheme.colors.borderDisabled, RoundedCornerShape(8.dp)) + .padding(20.dp), + ) { + when (state.mode) { + AccountInfoCardMode.Simple -> Unit + is AccountInfoCardMode.DeviceVerification -> Unit + is AccountInfoCardMode.UserVerification -> { + Text( + // TODO + text = "User requesting verification:", + style = ElementTheme.typography.fontBodySmRegular, + color = ElementTheme.colors.textSecondary, + ) + Spacer(modifier = Modifier.height(8.dp)) + } + } + AccountInfoCardUser( + matrixUser = state.matrixUser, + ) + when (state.mode) { + AccountInfoCardMode.Simple -> Unit + is AccountInfoCardMode.DeviceVerification -> { + AccountInfoSeparator() + DeviceInfoRow(state.mode) + } + is AccountInfoCardMode.UserVerification -> { + AccountInfoSeparator() + AccountInfoCardUser( + matrixUser = state.mode.otherUser, + ) + } + } + } +} + +@Composable +private fun AccountInfoSeparator() { + HorizontalDivider( + modifier = Modifier.padding(vertical = 20.dp), + color = ElementTheme.colors.separatorPrimary, + ) +} + +@Composable +private fun DeviceInfoRow( + mode: AccountInfoCardMode.DeviceVerification, +) { + Column( + modifier = Modifier + .fillMaxWidth() + .semantics(mergeDescendants = true) {}, + verticalArrangement = Arrangement.spacedBy(12.dp), + ) { + Row( + horizontalArrangement = Arrangement.spacedBy(16.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + RoundedIconAtom( + modifier = Modifier, + size = RoundedIconAtomSize.Big, + resourceId = CompoundDrawables.ic_compound_devices + ) + Text( + text = mode.deviceName ?: mode.deviceId.value, + style = ElementTheme.typography.fontBodyMdMedium, + color = ElementTheme.colors.textPrimary, + ) + } + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + ) { + TextWithLabelMolecule( + // TODO i18n + label = "Signed in", + text = mode.signInFormattedTimestamp, + modifier = Modifier.weight(1f), + ) + TextWithLabelMolecule( + label = stringResource(CommonStrings.common_device_id), + text = mode.deviceId.value, + modifier = Modifier.weight(1f), + spellText = true, + ) + } + } +} + +@Composable +private fun AccountInfoCardUser(matrixUser: MatrixUser) { + val subtext = if (matrixUser.displayName.isNullOrEmpty()) null else matrixUser.userId.value + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + ) { + Avatar( + avatarData = matrixUser.getAvatarData(AvatarSize.AccountInfoUser), + avatarType = AvatarType.User, + ) + Spacer(modifier = Modifier.width(12.dp)) + Column( + modifier = Modifier.weight(1f), + ) { + // Name + Text( + modifier = Modifier.clipToBounds(), + text = matrixUser.getBestName(), + maxLines = 1, + overflow = TextOverflow.Ellipsis, + color = ElementTheme.colors.textPrimary, + style = ElementTheme.typography.fontBodyLgMedium, + ) + // Id + subtext?.let { + Text( + text = subtext, + color = ElementTheme.colors.textSecondary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + style = ElementTheme.typography.fontBodyMdRegular, + ) + } + } + } +} + +@PreviewsDayNight +@Composable +internal fun AccountInfoCardPreview( + @PreviewParameter(AccountInfoCardStatePreviewParam::class) state: AccountInfoCardState +) = ElementPreview { + // Add some padding to view the border + Box(modifier = Modifier.padding(16.dp)) { + AccountInfoCard(state) + } +} diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/accountinfo/AccountInfoCardState.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/accountinfo/AccountInfoCardState.kt new file mode 100644 index 0000000000..68b66d72ee --- /dev/null +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/accountinfo/AccountInfoCardState.kt @@ -0,0 +1,33 @@ +/* + * 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.libraries.matrix.ui.components.accountinfo + +import androidx.compose.runtime.Immutable +import io.element.android.libraries.matrix.api.core.DeviceId +import io.element.android.libraries.matrix.api.user.MatrixUser + +data class AccountInfoCardState( + val matrixUser: MatrixUser, + val mode: AccountInfoCardMode, +) + +@Immutable +sealed interface AccountInfoCardMode { + data object Simple : AccountInfoCardMode + + data class UserVerification( + val otherUser: MatrixUser, + ) : AccountInfoCardMode + + // TODO Replace SessionDetailsView with this component + data class DeviceVerification( + val deviceName: String?, + val deviceId: DeviceId, + val signInFormattedTimestamp: String, + ) : AccountInfoCardMode +} diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/accountinfo/AccountInfoCardStatePreviewParam.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/accountinfo/AccountInfoCardStatePreviewParam.kt new file mode 100644 index 0000000000..d383648154 --- /dev/null +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/accountinfo/AccountInfoCardStatePreviewParam.kt @@ -0,0 +1,41 @@ +/* + * 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.libraries.matrix.ui.components.accountinfo + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.matrix.api.core.DeviceId +import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.ui.components.aMatrixUser + +open class AccountInfoCardStatePreviewParam : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + anAccountInfoCardState(), + anAccountInfoCardState(aMatrixUser(displayName = null)), + anAccountInfoCardState( + mode = AccountInfoCardMode.UserVerification( + otherUser = aMatrixUser(displayName = "Other User"), + ) + ), + anAccountInfoCardState( + mode = AccountInfoCardMode.DeviceVerification( + deviceName = "My Device", + deviceId = DeviceId("DEVICEID"), + signInFormattedTimestamp = "2024-06-01 12:00:00", + ) + ), + ) +} + +private fun anAccountInfoCardState( + matrixUser: MatrixUser = aMatrixUser(), + mode: AccountInfoCardMode = AccountInfoCardMode.Simple, +) = AccountInfoCardState( + matrixUser = matrixUser, + mode = mode, +) diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_0_en.png index 69c57875c1..8f4e2b4c1c 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:44eae581d98f2dbb2a6d84b4f921b170ade4185be87bf3bc893a0bb29fcf5f09 -size 15528 +oid sha256:1e17f781dae39f5f5b013943b9b487fb3be5b21d490c5fb96028e6fb5d682141 +size 23288 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_10_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_10_en.png index da7923cf50..88d6dd4b37 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b1c09cbb0217a1fb844828590e7827c27a2e9a99ecf5aed225f4d1bd0e413c8d -size 29343 +oid sha256:325477f895a8c99bd020abb1169c7236c72f716f6a0cfa017c17ee04bd6af95f +size 36633 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_11_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_11_en.png index 68b16e509f..b36442ffdc 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6ee66772b20b9c1cacf1f9387c173f8170d0c132d6caddfbd389d254b2ae7aa5 -size 33977 +oid sha256:b99a0ee27a3f6f7a954625943b124451ad817425093e9f7e842082298ad19a1a +size 41351 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_12_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_12_en.png new file mode 100644 index 0000000000..ac8112489d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_12_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bb9457326b991e445f5abeb6ce23f4620a9ac62d6bf919a838b6f2864b27a96b +size 22796 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_1_en.png index 56510ac1e2..a8e3378c65 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3eed90dbcc789f3db882d61a31924668a42cf78e00cd634192a5bfb831f67190 -size 53659 +oid sha256:d15e0d6f7bc3dbf133b89587d61221deaee93065dab1f04eb825a50ea76f7afc +size 58418 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_2_en.png index 3bc29fbe6e..5525fbc5ad 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:228a9ed83c86a160fe494254ec654fc0bf1d6923e78f5de2b4057d386e25b333 -size 30750 +oid sha256:ef2738c74013f4c0aa3835f9372410de51e5646deb478edb518733e34eb45419 +size 38204 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_3_en.png index 56510ac1e2..a8e3378c65 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3eed90dbcc789f3db882d61a31924668a42cf78e00cd634192a5bfb831f67190 -size 53659 +oid sha256:d15e0d6f7bc3dbf133b89587d61221deaee93065dab1f04eb825a50ea76f7afc +size 58418 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_4_en.png index 19ae842b7a..4e3a60b547 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:edf7aeb5f361d1299f0c1f6466de64cea36289c3268398b2a52dac2da057497c -size 33064 +oid sha256:b837a5c050e22298a90a281402a929cd19138cc0253b775d644cf7f6ffa42e78 +size 34025 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_5_en.png index 208b57113f..30e5972cf9 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1e489a5935471f6f607e9ed7e1f18ec0bf57d8664904323fef0a4453a179a0ce -size 20387 +oid sha256:07f4562818f73384486d27207fee92b948c3d91379f8ae83526c6f014d6fbdfc +size 23635 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_6_en.png index 344f09d582..cb3793d04d 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:27186c887a4403c8e175ba40059e18635db2e2ffac8da6804b6d52a6e2d12726 -size 28110 +oid sha256:3bd7cfe56e444eb6404f18360f40102efcd151051ec8fc475569278ea851c2b6 +size 29050 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_7_en.png index bdad7df7bc..db43d58156 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:64c4173147686886d5021cdaf6480644a5a520f81392ca84aa7ab5d705211bc7 -size 38682 +oid sha256:46122301e6f4c886045e8be69182297dd41e567713f9522ee4222d493204e7c8 +size 46289 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_8_en.png index f52aac7f1c..3089d813a8 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c6c73dd018eb82fe9e54ffbe38dcc491938da69791f4ff32081b2dac7549a4b2 -size 47958 +oid sha256:4bfd98771ca84e02a54510f934f0d368a456e00e85a5f58ca93b618383b7d8d7 +size 54782 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_9_en.png index f52aac7f1c..3089d813a8 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c6c73dd018eb82fe9e54ffbe38dcc491938da69791f4ff32081b2dac7549a4b2 -size 47958 +oid sha256:4bfd98771ca84e02a54510f934f0d368a456e00e85a5f58ca93b618383b7d8d7 +size 54782 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_0_en.png index ecf38c9b24..46638c106a 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6c4499b08be7d79d0cad438c4699c055bac12f6922551a19f3cfe18568c3d065 -size 14827 +oid sha256:d0478eaa2dce7809435ec4c1e0d1f3cc70b4d515409b4ad4c9a29d5d82bf62fa +size 22658 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_10_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_10_en.png index 4d2c26d91d..c6c2bed7ec 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0b0e1f00b98e463a97c9334da018ba944414526f771aa4ceaea18ab192a36863 -size 28080 +oid sha256:10222d4eb6b76925590d0910e15ee711da8089404f7bee285f0c3eb864662264 +size 35550 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_11_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_11_en.png index a650636f24..19bacd5b43 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:87e337a40741a5c7bdcb2015b8f82282ae69e1eff98e30641a02314660ecbd73 -size 32583 +oid sha256:efdbf580fd5a8eab0606a5223255132f6f109baa0233f7d1794dd7c72a1c9770 +size 40170 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_12_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_12_en.png new file mode 100644 index 0000000000..71067cadbe --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_12_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:86675c500add0bfa1e0934a89e08d63c651f3b4d1618a56273dceeab5e6f90e8 +size 22032 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_1_en.png index 62596baf31..a872ba68dc 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:66a0dc249d2df7e52a6a5f7cb3f1a94be011164eaf23d365f548b99f093d3d14 -size 51681 +oid sha256:99b00a68566e255c32551776bd0d973d0a263487d9efd1673d2a0343efff7c2d +size 56364 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_2_en.png index f97ba2a853..a7ac05d24c 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aba88e94521e05328079fb2ac0b06fd97987f81694b3378f02c19a20bfae2572 -size 29636 +oid sha256:a5cff92d97cd7b098d408397cc7ae41579fc227c96fc82e13f885a1bd815fdbd +size 37119 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_3_en.png index 62596baf31..a872ba68dc 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:66a0dc249d2df7e52a6a5f7cb3f1a94be011164eaf23d365f548b99f093d3d14 -size 51681 +oid sha256:99b00a68566e255c32551776bd0d973d0a263487d9efd1673d2a0343efff7c2d +size 56364 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_4_en.png index 5a3527f7e9..c9bddd0204 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f66b1cb00a31cd7925f4c505b0aeda77ee8aa8b473f1b576c97d3dc0bf3bf547 -size 30984 +oid sha256:00a4053efae3a0a5e575d7261110f9e45b957609217dafa527f4689d37aa5cf2 +size 31861 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_5_en.png index 71158fba7f..a698364606 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:702604dea65bb5f398728254f624e0486fdd152adcc336736f6256df9f7a63c4 -size 19617 +oid sha256:272c9302500693f2de77995f66df4fd1f59b59da9a13ba8b6f26b59fdf5e969e +size 22888 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_6_en.png index d368f54758..c093c81f1e 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fff0f77b004d6a5d4fa8c28c0fe72221449e20c0b501ed4b82e48c04596485a7 -size 26294 +oid sha256:2fb71ef151d5da4bb0ae4ccc0ddd08c1d423708b6cc4fdcdc3d7e5c1f2c69a06 +size 27257 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_7_en.png index 17526d949c..69f867eb94 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd6d4b2d03d0e86a22c48f89f05c83b0e7622f4b6fc2a946ace1ef33e66b2e9a -size 37183 +oid sha256:1352f9f09c05070fa2ea6f728916dfc47c6679ec805c8e5fc6a3cb497c8d3967 +size 44945 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_8_en.png index bf33b63f8a..f9db4ef9af 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d8f9a50b522d34a29ec48fcef545a0880ff0f43d464f1874c3486adb9c79e202 -size 46251 +oid sha256:5038b48d5f2aec502adf2f053adb18e1d9acd1a1fad471eceaf0ce1ea6679416 +size 53350 diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_9_en.png index bf33b63f8a..f9db4ef9af 100644 --- a/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_LogoutView_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d8f9a50b522d34a29ec48fcef545a0880ff0f43d464f1874c3486adb9c79e202 -size 46251 +oid sha256:5038b48d5f2aec502adf2f053adb18e1d9acd1a1fad471eceaf0ce1ea6679416 +size 53350 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Day_0_en.png new file mode 100644 index 0000000000..21f523a482 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:edfdf1cbf1190c68bce3b77d32325105e7564f6dfbd0bea6ddc737b668f780b5 +size 10579 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Day_1_en.png new file mode 100644 index 0000000000..f01248d6c0 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Day_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:344913f57b4c0ff9f738c0545a491bd6bd1521bcfe3bf59a238ca8a28d67850d +size 8947 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Day_2_en.png new file mode 100644 index 0000000000..a209b2a775 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Day_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:164bc673bc7ea750329b4e3660f639e2ef37a5eb2bd0739359405d55d88a2bac +size 21871 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Day_3_en.png new file mode 100644 index 0000000000..707cf6cd0f --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Day_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:087cb3e50dc482a46a18c10f6bfea45e815a867f5422e6092ea66aaccc2736be +size 21497 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Night_0_en.png new file mode 100644 index 0000000000..69d467c730 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:44c4aabd8644d45a4364a9156d0d9bd3e6a10830bbbc3611ae356324b41e3202 +size 10195 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Night_1_en.png new file mode 100644 index 0000000000..a945f669a7 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Night_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6171540623e4a76987b4d1d4e0085fea34977e9b662ef450bc754dd443164e7a +size 8810 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Night_2_en.png new file mode 100644 index 0000000000..6e6745377d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Night_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c3e08ffd8241960a40e6986378028777cd98d7f86350658e0706199d191c5f21 +size 21424 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Night_3_en.png new file mode 100644 index 0000000000..9e014c83f2 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components.accountinfo_AccountInfoCard_Night_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:da063790dbc384a82b35c16887fbb389d99e823728320d7df32315746c392eeb +size 20790