diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootEvent.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootEvent.kt index 5a10a50ba6..db15f8a0b2 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootEvent.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootEvent.kt @@ -13,4 +13,5 @@ import io.element.android.libraries.matrix.api.core.SessionId sealed interface PreferencesRootEvent { data object OnVersionInfoClick : PreferencesRootEvent data class SwitchToSession(val sessionId: SessionId) : PreferencesRootEvent + data object ToggleOtherAccountsExpanded : PreferencesRootEvent } 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 3a720fc7a8..bb6a964b88 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 @@ -34,6 +34,7 @@ import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.verification.SessionVerificationService +import io.element.android.libraries.preferences.api.store.AppPreferencesStore import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.services.analytics.api.AnalyticsService import kotlinx.collections.immutable.persistentListOf @@ -57,6 +58,7 @@ class PreferencesRootPresenter( private val rageshakeFeatureAvailability: RageshakeFeatureAvailability, private val featureFlagService: FeatureFlagService, private val sessionStore: SessionStore, + private val appPreferencesStore: AppPreferencesStore, private val sessionEnterpriseService: SessionEnterpriseService, private val userStatusPresenter: Presenter, ) : Presenter { @@ -71,6 +73,9 @@ class PreferencesRootPresenter( val isMultiAccountEnabled by remember { featureFlagService.isFeatureEnabledFlow(FeatureFlags.MultiAccount) }.collectAsState(initial = false) + val isOtherAccountsSectionExpanded by remember { + appPreferencesStore.isOtherAccountsExpandedFlow() + }.collectAsState(initial = true) val showLinkNewDevice by remember { featureFlagService.isFeatureEnabledFlow(FeatureFlags.QrCodeLogin) }.collectAsState(initial = false) @@ -138,6 +143,9 @@ class PreferencesRootPresenter( is PreferencesRootEvent.SwitchToSession -> coroutineScope.launch { sessionStore.setLatestSession(event.sessionId.value) } + PreferencesRootEvent.ToggleOtherAccountsExpanded -> coroutineScope.launch { + appPreferencesStore.setOtherAccountsExpanded(!isOtherAccountsSectionExpanded) + } } } @@ -146,6 +154,7 @@ class PreferencesRootPresenter( userStatusState = userStatusState, version = remember { versionFormatter.get() }, isMultiAccountEnabled = isMultiAccountEnabled, + isOtherAccountsSectionExpanded = isOtherAccountsSectionExpanded, otherSessions = otherSessions, showSecureBackup = !canVerifyUserSession, showSecureBackupBadge = showSecureBackupIndicator, 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 72d7240f2e..3cc5f64665 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 @@ -19,6 +19,7 @@ data class PreferencesRootState( val userStatusState: UserStatusState?, val version: String, val isMultiAccountEnabled: Boolean, + val isOtherAccountsSectionExpanded: Boolean, val otherSessions: ImmutableList, val showSecureBackup: Boolean, val showSecureBackupBadge: Boolean, diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStatePreviewParam.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStatePreviewParam.kt index 80c47a33b2..280a9c1eca 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStatePreviewParam.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStatePreviewParam.kt @@ -47,6 +47,7 @@ open class PreferencesRootStatePreviewParam : PreviewParameterProvider = emptyList(), showSecureBackup: Boolean = false, showSecureBackupBadge: Boolean = false, @@ -93,6 +95,7 @@ fun aPreferencesRootState( myUser = myUser, version = version, isMultiAccountEnabled = isMultiAccountEnabled, + isOtherAccountsSectionExpanded = isOtherAccountsSectionExpanded, otherSessions = otherSessions.toImmutableList(), showSecureBackup = showSecureBackup, showSecureBackupBadge = showSecureBackupBadge, 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 82c88b16fa..5aefdf122d 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 @@ -9,17 +9,28 @@ package io.element.android.features.preferences.impl.root import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.tween +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxScope +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.rotate import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.stateDescription import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp @@ -33,13 +44,16 @@ import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.coverage.ExcludeFromCoverage import io.element.android.libraries.designsystem.components.async.AsyncActionIndicator import io.element.android.libraries.designsystem.components.async.AsyncIndicator +import io.element.android.libraries.designsystem.components.avatar.AvatarRow import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.components.avatar.AvatarType import io.element.android.libraries.designsystem.components.list.ListItemContent import io.element.android.libraries.designsystem.components.preferences.PreferencePage import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.PreviewWithLargeHeight import io.element.android.libraries.designsystem.theme.components.HorizontalDivider +import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.IconSource import io.element.android.libraries.designsystem.theme.components.ListItem import io.element.android.libraries.designsystem.theme.components.ListItemStyle @@ -51,7 +65,9 @@ import io.element.android.libraries.emoji.api.picker.EmojiPickerRenderer import io.element.android.libraries.emoji.api.picker.NoOpEmojiPickerRenderer import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.ui.components.MatrixUserRow +import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.ui.strings.CommonStrings +import kotlinx.collections.immutable.toImmutableList @Composable fun PreferencesRootView( @@ -91,19 +107,22 @@ fun PreferencesRootView( }, matrixUser = state.myUser, ) + if (state.userStatusState != null) { + UserStatusSection( + userStatusState = state.userStatusState, + emojiPickerRenderer = emojiPickerRenderer, + ) + } if (state.isMultiAccountEnabled) { MultiAccountSection( state = state, onAddAccountClick = onAddAccountClick, ) } - if (state.userStatusState != null) { - UserStatusSection( - userStatusState = state.userStatusState, - emojiPickerRenderer = emojiPickerRenderer, - showTopDivider = !state.isMultiAccountEnabled, - ) - } + HorizontalDivider( + thickness = 8.dp, + color = ElementTheme.colors.bgSubtleSecondary, + ) // 'Account' section ManageAccountSection( state = state, @@ -163,25 +182,21 @@ private fun BoxScope.UserStatusUpdateIndicator(updateStatusAction: AsyncAction - MatrixUserRow( - modifier = Modifier - .clickable { - state.eventSink(PreferencesRootEvent.SwitchToSession(matrixUser.userId)) + if (state.otherSessions.isEmpty()) { + AddAccountItem(onAddAccountClick) + } else { + val expandedStateDescription = if (state.isOtherAccountsSectionExpanded) { + stringResource(CommonStrings.a11y_state_expanded) + } else { + stringResource(CommonStrings.a11y_state_collapsed) + } + ListItem( + modifier = Modifier.semantics { + stateDescription = expandedStateDescription + }, + content = { Text(stringResource(CommonStrings.common_switch_account)) }, + onClick = { state.eventSink(PreferencesRootEvent.ToggleOtherAccountsExpanded) }, + trailingContent = ListItemContent.Custom { _ -> + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp), + ) { + AnimatedVisibility( + visible = !state.isOtherAccountsSectionExpanded, + enter = fadeIn(), + exit = fadeOut(), + ) { + AvatarRow( + avatarDataList = state.otherSessions + .take(3) + .map { it.getAvatarData(AvatarSize.OtherAccountItem) } + .toImmutableList(), + avatarType = AvatarType.User, + lastOnTop = true, + ) + } + // Animate the chevron icon to rotate when the section is expanded/collapsed + val rotation: Float by animateFloatAsState( + targetValue = if (state.isOtherAccountsSectionExpanded) -180f else 0f, + animationSpec = tween( + delayMillis = 0, + durationMillis = 300, + ), + label = "chevron" + ) + Icon( + modifier = Modifier.rotate(rotation), + imageVector = CompoundIcons.ChevronDown(), + contentDescription = null, + ) } - .padding(top = 2.dp, bottom = 2.dp, end = 8.dp), - matrixUser = matrixUser, - avatarSize = AvatarSize.AccountItem, - verticalSpaceWidth = 16.dp, + }, ) + AnimatedVisibility( + visible = state.isOtherAccountsSectionExpanded, + ) { + Column { + HorizontalDivider( + thickness = 1.dp, + color = ElementTheme.colors.bgSubtleSecondary, + ) + state.otherSessions.forEach { matrixUser -> + MatrixUserRow( + modifier = Modifier + .clickable { + state.eventSink(PreferencesRootEvent.SwitchToSession(matrixUser.userId)) + } + .padding(top = 2.dp, bottom = 2.dp, end = 8.dp), + matrixUser = matrixUser, + avatarSize = AvatarSize.AccountItem, + verticalSpaceWidth = 16.dp, + ) + } + AddAccountItem(onAddAccountClick) + } + } } +} + +@Composable +private fun AddAccountItem(onAddAccountClick: () -> Unit) { ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Plus())), content = { @@ -210,10 +291,6 @@ private fun ColumnScope.MultiAccountSection( }, onClick = onAddAccountClick, ) - HorizontalDivider( - thickness = 8.dp, - color = ElementTheme.colors.bgSubtleSecondary, - ) } @Composable diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt index c25c159f33..aab06499a4 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt @@ -7,12 +7,12 @@ package io.element.android.features.preferences.impl.userstatus +import androidx.compose.animation.AnimatedContent import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.offset -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.sizeIn import androidx.compose.foundation.shape.CircleShape @@ -72,47 +72,65 @@ fun UserStatusView( emojiPickerRenderer: EmojiPickerRenderer, modifier: Modifier = Modifier, ) { - when (val pickerState = state.pickerState) { - UserStatusPickerState.Hidden, UserStatusPickerState.ShowingPicker -> { - val displayedStatus = state.displayedStatus - if (displayedStatus != null) { - CurrentStatusRow( - displayedStatus = displayedStatus, - onClick = { state.eventSink(UserStatusEvent.OpenPicker) }, - onClear = { state.eventSink(UserStatusEvent.ClearStatus) }, - modifier = modifier, - ) - } else { - EmptyStatusRow( - onClick = { state.eventSink(UserStatusEvent.OpenPicker) }, - modifier = modifier, - ) + AnimatedContent( + targetState = state, + contentKey = { + when (it.pickerState) { + UserStatusPickerState.Hidden, + UserStatusPickerState.ShowingPicker -> if (state.displayedStatus != null) 0 else 1 + is UserStatusPickerState.CustomInput -> 2 } - if (pickerState == UserStatusPickerState.ShowingPicker) { - UserStatusPickerBottomSheet( - currentRawStatus = state.rawStatus, - onDismiss = { state.eventSink(UserStatusEvent.DismissPicker) }, - onSelectPredefinedStatus = { status -> state.eventSink(UserStatusEvent.SetStatus(status)) }, - onSelectCustomStatus = { state.eventSink(UserStatusEvent.OpenCustomInput) }, + }, + ) { userStatusState -> + when (val pickerState = userStatusState.pickerState) { + UserStatusPickerState.Hidden, + UserStatusPickerState.ShowingPicker -> { + val displayedStatus = state.displayedStatus + if (displayedStatus != null) { + CurrentStatusRow( + displayedStatus = displayedStatus, + onClick = { state.eventSink(UserStatusEvent.OpenPicker) }, + onClear = { state.eventSink(UserStatusEvent.ClearStatus) }, + modifier = modifier, + ) + } else { + EmptyStatusRow( + onClick = { state.eventSink(UserStatusEvent.OpenPicker) }, + modifier = modifier, + ) + } + } + is UserStatusPickerState.CustomInput -> { + CustomStatusInputRow( + emoji = pickerState.emoji, + textFieldState = pickerState.textFieldState, + rawStatus = state.rawStatus, + onConfirm = { + state.eventSink( + UserStatusEvent.SetStatus(UserStatus(pickerState.emoji, pickerState.textFieldState.text.toString())) + ) + }, + onCancel = { state.eventSink(UserStatusEvent.CancelCustomInput) }, + onEmojiClick = { state.eventSink(UserStatusEvent.OpenEmojiPicker) }, + modifier = modifier, ) } } - is UserStatusPickerState.CustomInput -> { - CustomStatusInputRow( - emoji = pickerState.emoji, - textFieldState = pickerState.textFieldState, - rawStatus = state.rawStatus, - onConfirm = { - state.eventSink( - UserStatusEvent.SetStatus(UserStatus(pickerState.emoji, pickerState.textFieldState.text.toString())) - ) - }, - onCancel = { state.eventSink(UserStatusEvent.CancelCustomInput) }, - onEmojiClick = { state.eventSink(UserStatusEvent.OpenEmojiPicker) }, - modifier = modifier, + } + when (val pickerState = state.pickerState) { + UserStatusPickerState.Hidden -> Unit + UserStatusPickerState.ShowingPicker -> { + UserStatusPickerBottomSheet( + currentRawStatus = state.rawStatus, + onDismiss = { state.eventSink(UserStatusEvent.DismissPicker) }, + onSelectPredefinedStatus = { status -> state.eventSink(UserStatusEvent.SetStatus(status)) }, + onSelectCustomStatus = { state.eventSink(UserStatusEvent.OpenCustomInput) }, ) + } + is UserStatusPickerState.CustomInput -> { when (val sheet = pickerState.emojiPickerSheetState) { - EmojiPickerSheetState.Hidden, EmojiPickerSheetState.Loading -> Unit + EmojiPickerSheetState.Hidden, + EmojiPickerSheetState.Loading -> Unit is EmojiPickerSheetState.Shown -> EmojiPickerBottomSheet( pickerState = sheet.state, emojiPickerRenderer = emojiPickerRenderer, @@ -133,7 +151,6 @@ private fun EmptyStatusRow( content = { Text( text = stringResource(R.string.screen_settings_user_status_placeholder), - modifier = Modifier.padding(vertical = 16.dp), ) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Reaction())), @@ -153,7 +170,7 @@ private fun CurrentStatusRow( is DisplayedStatus.InCall -> "🎧" to stringResource(CommonStrings.common_on_a_call) } ListItem( - content = { Text(text = text, modifier = Modifier.padding(vertical = 16.dp)) }, + content = { Text(text = text) }, leadingContent = ListItemContent.Custom { EmojiText(emoji) }, trailingContent = ListItemContent.Custom({ IconButton( diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt index 0bda80fe0c..051c8bd12d 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt @@ -37,17 +37,21 @@ import io.element.android.libraries.matrix.test.A_USER_NAME import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService +import io.element.android.libraries.preferences.api.store.AppPreferencesStore +import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.sessionstorage.test.InMemorySessionStore import io.element.android.libraries.sessionstorage.test.aSessionData import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.consumeItemsUntilPredicate import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value import io.element.android.tests.testutils.test import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.runTest import org.junit.Rule @@ -82,6 +86,7 @@ class PreferencesRootPresenterTest { ) assertThat(initialState.version).isEqualTo("A Version") assertThat(initialState.isMultiAccountEnabled).isFalse() + assertThat(initialState.isOtherAccountsSectionExpanded).isTrue() assertThat(initialState.otherSessions).isEmpty() assertThat(initialState.version).isEqualTo("A Version") val loadedState = awaitItem() @@ -304,6 +309,43 @@ class PreferencesRootPresenterTest { } } + @Test + fun `present - other accounts section is collapsed if the preference says so`() = runTest { + createPresenter( + matrixClient = FakeMatrixClient( + canDeactivateAccountResult = { true }, + accountManagementUrlResult = { Result.success(null) }, + ), + appPreferencesStore = InMemoryAppPreferencesStore(isOtherAccountsExpanded = false), + ).test { + consumeItemsUntilPredicate { !it.isOtherAccountsSectionExpanded } + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - toggle other accounts expanded stores the new value`() = runTest { + val appPreferencesStore = InMemoryAppPreferencesStore() + createPresenter( + matrixClient = FakeMatrixClient( + canDeactivateAccountResult = { true }, + accountManagementUrlResult = { Result.success(null) }, + ), + appPreferencesStore = appPreferencesStore, + ).test { + val initialState = awaitFirstItem() + assertThat(initialState.isOtherAccountsSectionExpanded).isTrue() + initialState.eventSink(PreferencesRootEvent.ToggleOtherAccountsExpanded) + val collapsedState = consumeItemsUntilPredicate { !it.isOtherAccountsSectionExpanded }.last() + assertThat(appPreferencesStore.isOtherAccountsExpandedFlow().first()).isFalse() + // Toggling again must expand the section back + collapsedState.eventSink(PreferencesRootEvent.ToggleOtherAccountsExpanded) + consumeItemsUntilPredicate { it.isOtherAccountsSectionExpanded } + assertThat(appPreferencesStore.isOtherAccountsExpandedFlow().first()).isTrue() + cancelAndIgnoreRemainingEvents() + } + } + @Test fun `present - link new device`() = runTest { createPresenter( @@ -333,6 +375,7 @@ class PreferencesRootPresenterTest { indicatorService: IndicatorService = FakeIndicatorService(), featureFlagService: FeatureFlagService = FakeFeatureFlagService(), sessionStore: SessionStore = InMemorySessionStore(), + appPreferencesStore: AppPreferencesStore = InMemoryAppPreferencesStore(), sessionEnterpriseService: SessionEnterpriseService = FakeSessionEnterpriseService(), ) = PreferencesRootPresenter( matrixClient = matrixClient, @@ -346,6 +389,7 @@ class PreferencesRootPresenterTest { rageshakeFeatureAvailability = rageshakeFeatureAvailability, featureFlagService = featureFlagService, sessionStore = sessionStore, + appPreferencesStore = appPreferencesStore, sessionEnterpriseService = sessionEnterpriseService, userStatusPresenter = { aUserStatusState() }, ) diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootViewTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootViewTest.kt index c6578cb494..df1633f986 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootViewTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootViewTest.kt @@ -27,6 +27,8 @@ import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EnsureNeverCalled import io.element.android.tests.testutils.EnsureNeverCalledWithParam import io.element.android.tests.testutils.EventsRecorder +import io.element.android.tests.testutils.assertNoNodeWithText +import io.element.android.tests.testutils.assertNodeWithTextIsDisplayed import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.ensureCalledOnceWithParam @@ -71,6 +73,7 @@ class PreferencesRootViewTest : RobolectricTest() { setView( aPreferencesRootState( isMultiAccountEnabled = true, + isOtherAccountsSectionExpanded = true, otherSessions = listOf( aMatrixUser( id = A_USER_ID_2.value, @@ -84,6 +87,69 @@ class PreferencesRootViewTest : RobolectricTest() { eventsRecorder.assertSingle(PreferencesRootEvent.SwitchToSession(A_USER_ID_2)) } + @Test + fun `clicking on Switch accounts sends a ToggleOtherAccountsExpanded`() = runAndroidComposeUiTest { + val eventsRecorder = EventsRecorder() + setView( + aPreferencesRootState( + isMultiAccountEnabled = true, + isOtherAccountsSectionExpanded = false, + otherSessions = listOf( + aMatrixUser( + id = A_USER_ID_2.value, + displayName = "Bob", + ) + ), + eventSink = eventsRecorder, + ), + ) + clickOn(CommonStrings.common_switch_account) + eventsRecorder.assertSingle(PreferencesRootEvent.ToggleOtherAccountsExpanded) + } + + @Test + fun `when the other accounts section is collapsed, other sessions and add account are not shown`() = runAndroidComposeUiTest { + val eventsRecorder = EventsRecorder(expectEvents = false) + setView( + aPreferencesRootState( + isMultiAccountEnabled = true, + isOtherAccountsSectionExpanded = false, + otherSessions = listOf( + aMatrixUser( + id = A_USER_ID_2.value, + displayName = "Bob", + ) + ), + eventSink = eventsRecorder, + ), + ) + assertNodeWithTextIsDisplayed(CommonStrings.common_switch_account) + onNodeWithText("Bob").assertDoesNotExist() + assertNoNodeWithText(CommonStrings.common_add_another_account) + } + + @Test + fun `click on Add account of the expanded section invokes the expected callback`() = runAndroidComposeUiTest { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + setView( + aPreferencesRootState( + isMultiAccountEnabled = true, + isOtherAccountsSectionExpanded = true, + otherSessions = listOf( + aMatrixUser( + id = A_USER_ID_2.value, + displayName = "Bob", + ) + ), + eventSink = eventsRecorder, + ), + onAddAccountClick = callback, + ) + clickOn(CommonStrings.common_add_another_account) + } + } + @Test fun `click on Add account invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) 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 b91f8c405c..e4c8ebc641 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 @@ -82,6 +82,7 @@ enum class AvatarSize(val dp: Dp) { LeaveSpaceRoom(32.dp), SelectParentSpace(32.dp), AccountItem(32.dp), + OtherAccountItem(20.dp), LocationPin(32.dp), ActiveCallItem(20.dp) } diff --git a/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/AppPreferencesStore.kt b/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/AppPreferencesStore.kt index 6285c46389..0a774443a0 100644 --- a/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/AppPreferencesStore.kt +++ b/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/AppPreferencesStore.kt @@ -44,6 +44,14 @@ interface AppPreferencesStore { /** The name of the chosen theme, or `null` when the user has not picked one and the system setting should be followed. */ fun getThemeFlow(): Flow + /** + * @param expanded true to expand the other accounts section. + */ + suspend fun setOtherAccountsExpanded(expanded: Boolean) + + /** Whether the other accounts section is expanded; defaults to `true`. */ + fun isOtherAccountsExpandedFlow(): Flow + /** * @param value the distance in metres the user must move before a new live location is published. */ diff --git a/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt b/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt index 1a14a0ea8f..66a6eaf61f 100644 --- a/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt +++ b/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt @@ -33,6 +33,7 @@ private val developerModeKey = booleanPreferencesKey("developerMode") private val customElementCallBaseUrlKey = stringPreferencesKey("elementCallBaseUrl") private val themeKey = stringPreferencesKey("theme") private val hideInviteAvatarsKey = booleanPreferencesKey("hideInviteAvatars") +private val otherAccountsExpandedKey = booleanPreferencesKey("otherAccountsExpanded") private val timelineMediaPreviewValueKey = stringPreferencesKey("timelineMediaPreviewValue") private val liveLocationMinimumDistanceUpdateKey = intPreferencesKey("liveLocationMinimumDistanceUpdate") private val logLevelKey = stringPreferencesKey("logLevel") @@ -97,6 +98,18 @@ class DefaultAppPreferencesStore( } } + override suspend fun setOtherAccountsExpanded(expanded: Boolean) { + store.edit { prefs -> + prefs[otherAccountsExpandedKey] = expanded + } + } + + override fun isOtherAccountsExpandedFlow(): Flow { + return store.data.map { prefs -> + prefs[otherAccountsExpandedKey] ?: true + } + } + override suspend fun setLiveLocationMinimumDistanceInMetersUpdate(value: Int) { store.edit { prefs -> prefs[liveLocationMinimumDistanceUpdateKey] = value diff --git a/libraries/preferences/impl/src/test/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStoreTest.kt b/libraries/preferences/impl/src/test/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStoreTest.kt index 4cf018371a..1d30278bd1 100644 --- a/libraries/preferences/impl/src/test/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStoreTest.kt +++ b/libraries/preferences/impl/src/test/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStoreTest.kt @@ -120,6 +120,24 @@ class DefaultAppPreferencesStoreTest { assertThat(history.last()).isEqualTo("https://server5.org") } + @Test + fun `other accounts section is expanded by default`() = runTest { + val store = createStore() + + assertThat(store.isOtherAccountsExpandedFlow().first()).isTrue() + } + + @Test + fun `other accounts expanded state persists updates`() = runTest { + val store = createStore() + + store.setOtherAccountsExpanded(false) + assertThat(store.isOtherAccountsExpandedFlow().first()).isFalse() + + store.setOtherAccountsExpanded(true) + assertThat(store.isOtherAccountsExpandedFlow().first()).isTrue() + } + private fun createStore() = DefaultAppPreferencesStore( buildMeta = buildMeta, preferenceDataStoreFactory = FakePreferenceDataStoreFactory(), diff --git a/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemoryAppPreferencesStore.kt b/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemoryAppPreferencesStore.kt index e8d0b0bb8e..458be27ac9 100644 --- a/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemoryAppPreferencesStore.kt +++ b/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemoryAppPreferencesStore.kt @@ -21,6 +21,7 @@ import kotlinx.coroutines.flow.updateAndGet class InMemoryAppPreferencesStore( isDeveloperModeEnabled: Boolean = false, + isOtherAccountsExpanded: Boolean = true, customElementCallBaseUrl: String? = null, hideInviteAvatars: Boolean? = null, timelineMediaPreviewValue: MediaPreviewValue? = null, @@ -37,6 +38,7 @@ class InMemoryAppPreferencesStore( callRingtoneDisplayName: String? = null, ) : AppPreferencesStore { private val isDeveloperModeEnabled = MutableStateFlow(isDeveloperModeEnabled) + private val isOtherAccountsExpanded = MutableStateFlow(isOtherAccountsExpanded) private val customElementCallBaseUrl = MutableStateFlow(customElementCallBaseUrl) private val theme = MutableStateFlow(theme) private val liveLocationMinimumDistanceUpdate = MutableStateFlow(liveLocationMinimumDistanceUpdate) @@ -60,6 +62,14 @@ class InMemoryAppPreferencesStore( return isDeveloperModeEnabled } + override suspend fun setOtherAccountsExpanded(expanded: Boolean) { + isOtherAccountsExpanded.value = expanded + } + + override fun isOtherAccountsExpandedFlow(): Flow { + return isOtherAccountsExpanded + } + override suspend fun setCustomElementCallBaseUrl(string: String?) { customElementCallBaseUrl.tryEmit(string) } diff --git a/libraries/ui-strings/src/main/res/values/temporary.xml b/libraries/ui-strings/src/main/res/values/temporary.xml index c704e811ff..6821b63d98 100644 --- a/libraries/ui-strings/src/main/res/values/temporary.xml +++ b/libraries/ui-strings/src/main/res/values/temporary.xml @@ -10,4 +10,5 @@ "Collapsed" Active Inactive + Switch accounts diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_0_en.png index f0f0bbf1b7..89f9a1f567 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2a778bf05dd64f37df2dd45437a4dc1e74199b4b9eca2d3e9078b5b956a16e20 -size 39556 +oid sha256:905abaad995d478f14106a4c434f9e9c647c3734b1483e61fc8caf58f0f5b602 +size 40449 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_1_en.png index 6647fae806..f17576d39a 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:942e5c3db0b84fe8f3125e08dafda1c0b96cdeb332afcbf217f06742f5b29a58 -size 27374 +oid sha256:581c8a8a7f7f5a7090f59199b98678268d4d948b86410459e76227f152a472cf +size 27296 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_2_en.png index 6e3ff8d5ba..82363b39d1 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4bf9154a844fe846d918f56bcacd30456973ee89f180650956c73b8837039341 -size 38530 +oid sha256:26a8a7cc6f008ee8a1caa56baa8d4041fc8baa5f58103bb49889596f6378efff +size 40578 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_3_en.png index b03f86cd17..2c2dc2a0ba 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d55a3fe4b9310220ca46db6e893017ed6f41864b48ebed8717074ec277b4765 -size 28817 +oid sha256:8ad8b15e2b3995708c162452d02d843416b1e5ef43e1d02c9c03ea024a7fec44 +size 28769 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_4_en.png index c17a10428d..02441008b1 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d410ca5322fb3c7ee10d5a489bab118fcc7cba17cf825c8d38ef3c6fde26eb6e -size 30004 +oid sha256:6a86fcfe60cce1147628632ace339ee70cf15dd11e5f78d0cd9fae81ea3780e2 +size 29947 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_5_en.png index d14f6264d7..31835bdcbc 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4f00e1c36baf1a14ce1a4d67cff18a7a8ea3732c60df5eb0e7ebeb53934387bd -size 32880 +oid sha256:3c5873298af352a2ac6eb89d2979b0ec06b56bac84175d936560768b37e3b39d +size 32891 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_6_en.png index c3a9a89399..2b11596287 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3cc2c582bc6fc6a73a8eb8e873a57d85d88f984b283f889628139021cdc6b163 -size 20042 +oid sha256:5dcc266b1dad449c1753dfb88ac045e9b638cedb53162ea4a327f354936ebe51 +size 20053 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_0_en.png index 557538595c..fc596d9e3d 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a558ea1da4ab2adaaaffad9b47ce1d21bf27bbe82074927f823dddc05d6d80ed -size 40741 +oid sha256:ca8349c4051ef40fde78a695f6f570414e9b9e65dfae3cb42a8ae16adffbe7ef +size 41651 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_1_en.png index e30896324c..009a273d3a 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b91ad54980525e9977498e22e1428f3ca172ea1e88e7c508feb84d8521e9080c -size 28423 +oid sha256:7b428fc64b1e61b040c9f4a61f19131a3c0fffd60ec4860c5ab1a298b510c474 +size 28381 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_2_en.png index 8869bfb466..d3120d0269 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7a6deb7ae2808f1cc361921d204ca4857cd085294c9df915acfbbf300fd198a7 -size 39425 +oid sha256:9d62b865885755af29b950e64aa03000cee3a3f0c74b710b10d005a02ca39282 +size 41590 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_3_en.png index ab15791ad6..b3607d204e 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:db61ad2899d3b56b7e1cbd43006b1ff03865b58e15d446a9886ffda5e35d954f -size 29774 +oid sha256:7029ee086dc8c74ea0df9ec5a4579084d6b6663b42489017eb0c2b6c1f2652eb +size 29719 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_4_en.png index 2ca32d37ad..355b03eefe 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2a52b1bfdb0cec0e8568d23a804f90ca04fd5f5d3da6e1e513b1ec5c652ca0a1 -size 30894 +oid sha256:5e589816c92f5eea1448af4dd4f1b064ab256e5050f48bef9703f79049eac590 +size 30891 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_5_en.png index e5864fb5d5..1e936b2ef9 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1e7f2cd3f6ac709ff1d37c5f212bb254a4bcbd07a71c750f0ef35cac7529d5d9 -size 34134 +oid sha256:228a8727ee1cf2c616235f65786ce16f076d54339abf2d0282094f3451117fb0 +size 34108 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_6_en.png index 2312bbcd77..668e1f5b02 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ebc219ac4bf4a804c9c8f26028374bb35264266b616db054218dcba0772197a -size 20471 +oid sha256:040665e12f7fd507b2158548b47b252b52f09635122f6227ebf8862e5832f768 +size 20508 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_0_en.png index a613668ed6..0f652b68f0 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0981d742141f7b4f0153b897638a7bdd6b20359c051d7c2176a92ebe1f1eab76 -size 9221 +oid sha256:dd734c084d5695c9325651f33412b302547f4396dba0e07874a2a6823816e237 +size 9217 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_1_en.png index bc00108ade..d80f9b4db2 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:57d41ba2f1a644081c6bddcc7e1c27c9cbadb23bff3343e0e0d9deeb6a94bb23 -size 7123 +oid sha256:14127ded6e0f090d810bd94510012a8bc37f502b65eeb79ab608193330931dba +size 7089 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_2_en.png index 44dc0d0f19..19f5be9980 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f9681df4f4000ebca0642e8a4065d23f88981707ba146adc8cbf2757175cfed6 -size 7315 +oid sha256:bf00e966da613eea4a19dbe9b656801af3619a58f37568a2e0eabb4417e265bc +size 7280 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_3_en.png index 61a7c2dad7..f34040c04c 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cf6189630f111d84674843b3970193eefd31d96d9300f36308038313de78b83c -size 28859 +oid sha256:024fd3c3bcb0c77861f11079289088c5da4cefe207804a788118651c5a45ddde +size 28858 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_4_en.png index f02e51135b..0bc9c44bf0 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cb7104ccbfcccc9f3afa027db521e8e2f11a015356d47e61e5ecfd173cd80004 -size 27295 +oid sha256:bddc6fb0bec14600007a145a62a38f11264f2b9c6d24cd4c80054dbc4e6144f5 +size 27294 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_0_en.png index bcf819a97c..d81f1e98f2 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:90cb31d24d16bc8e13c7e83f26330c9505eee02b91a5bf3ac7bf140fedfcc37d -size 8749 +oid sha256:de2ed65cbf47273fdc8eff2b62f9ade6283020386ba7c0339a124519d38bad8d +size 8776 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_1_en.png index 875d51031a..dfbbc8f314 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:771ec7723dd0b7546e7e73ac4f3f6217ab5d57366ff0309774fc483b02240320 -size 6720 +oid sha256:18f2d4633ba54e58c956d08b06b5d3bfd9e2c50d3c0882584ed249fbc4fe338f +size 6725 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_2_en.png index c96f456ac6..cd37c67cfd 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f65c054cc6876f86b6ae6689560581f2c29edcdc86fca992c30054b1f442afa -size 7000 +oid sha256:3d0e54494fb4f84a75990930d5e7bbf6fd4b89ed8b28a9651cb4a5744b4a3886 +size 6984 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_3_en.png index 1496ccac57..a47939d978 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5c367199db97f227a82bd32292176ade0dcec1633d0383b591204b63ddaf1f48 -size 27660 +oid sha256:1c57e5848ac1c196c8fcb00fdaa23f430e3f67625beaa093e8a5372fc91a91b5 +size 27713 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_4_en.png index d04157ba03..2d05c748b6 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:27efc2d19efbb978778dfbb7d87138fbbe7cb17525d03a565e4ec2523ae0a252 -size 26166 +oid sha256:e3e4bcb4a271d5e41d49064a5718cf99e423fed4445d18850cfb542615296f5b +size 26211