diff --git a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInPresenter.kt b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInPresenter.kt index 8dc2de5e4e..752d10e7a9 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInPresenter.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInPresenter.kt @@ -31,7 +31,6 @@ import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.matrix.api.MatrixClient 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.oidc.AccountManagementAction import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.api.sync.SlidingSyncVersion import io.element.android.libraries.matrix.api.sync.SyncService @@ -177,7 +176,6 @@ class LoggedInPresenter( } private fun CoroutineScope.preloadAccountManagementUrl() = launch { - matrixClient.getAccountManagementUrl(AccountManagementAction.Profile) - matrixClient.getAccountManagementUrl(AccountManagementAction.DevicesList) + matrixClient.getAccountManagementUrl(null) } } diff --git a/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt b/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt index d147a4ed68..902f446a6f 100644 --- a/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt +++ b/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt @@ -71,7 +71,7 @@ class LoggedInPresenterTest { } @Test - fun `present - ensure that account urls are preloaded`() = runTest { + fun `present - ensure that account url is preloaded`() = runTest { val accountManagementUrlResult = lambdaRecorder> { Result.success("aUrl") } val matrixClient = FakeMatrixClient( accountManagementUrlResult = accountManagementUrlResult, @@ -81,11 +81,8 @@ class LoggedInPresenterTest { ).test { awaitItem() advanceUntilIdle() - accountManagementUrlResult.assertions().isCalledExactly(2) - .withSequence( - listOf(value(AccountManagementAction.Profile)), - listOf(value(AccountManagementAction.DevicesList)), - ) + accountManagementUrlResult.assertions().isCalledOnce() + .with(value(null)) } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootEvents.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootEvent.kt similarity index 78% rename from features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootEvents.kt rename to features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootEvent.kt index be266869be..5a10a50ba6 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootEvents.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootEvent.kt @@ -10,7 +10,7 @@ package io.element.android.features.preferences.impl.root import io.element.android.libraries.matrix.api.core.SessionId -sealed interface PreferencesRootEvents { - data object OnVersionInfoClick : PreferencesRootEvents - data class SwitchToSession(val sessionId: SessionId) : PreferencesRootEvents +sealed interface PreferencesRootEvent { + data object OnVersionInfoClick : PreferencesRootEvent + data class SwitchToSession(val sessionId: SessionId) : 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 3d6a829167..43da681a37 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 @@ -30,7 +30,6 @@ import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.indicator.api.IndicatorService import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.UserId -import io.element.android.libraries.matrix.api.oidc.AccountManagementAction import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.verification.SessionVerificationService import io.element.android.libraries.sessionstorage.api.SessionStore @@ -99,9 +98,6 @@ class PreferencesRootPresenter( val accountManagementUrl: MutableState = remember { mutableStateOf(null) } - val devicesManagementUrl: MutableState = remember { - mutableStateOf(null) - } var canDeactivateAccount by remember { mutableStateOf(false) } @@ -110,9 +106,9 @@ class PreferencesRootPresenter( canDeactivateAccount = matrixClient.canDeactivateAccount() } - val showBlockedUsersItem by produceState(initialValue = false) { + val nbOfBlockedUsers by produceState(initialValue = 0) { matrixClient.ignoredUsersFlow - .onEach { value = it.isNotEmpty() } + .onEach { value = it.size } .launchIn(this) } @@ -121,17 +117,17 @@ class PreferencesRootPresenter( val directLogoutState = directLogoutPresenter.present() LaunchedEffect(Unit) { - initAccountManagementUrl(accountManagementUrl, devicesManagementUrl) + initAccountManagementUrl(accountManagementUrl) } val showDeveloperSettings by showDeveloperSettingsProvider.showDeveloperSettings.collectAsState() - fun handleEvent(event: PreferencesRootEvents) { + fun handleEvent(event: PreferencesRootEvent) { when (event) { - is PreferencesRootEvents.OnVersionInfoClick -> { + is PreferencesRootEvent.OnVersionInfoClick -> { showDeveloperSettingsProvider.unlockDeveloperSettings(coroutineScope) } - is PreferencesRootEvents.SwitchToSession -> coroutineScope.launch { + is PreferencesRootEvent.SwitchToSession -> coroutineScope.launch { sessionStore.setLatestSession(event.sessionId.value) } } @@ -146,13 +142,12 @@ class PreferencesRootPresenter( showSecureBackup = !canVerifyUserSession, showSecureBackupBadge = showSecureBackupIndicator, accountManagementUrl = accountManagementUrl.value, - devicesManagementUrl = devicesManagementUrl.value, showAnalyticsSettings = hasAnalyticsProviders, canReportBug = canReportBug, showLinkNewDevice = showLinkNewDevice, showDeveloperSettings = showDeveloperSettings, canDeactivateAccount = canDeactivateAccount, - showBlockedUsersItem = showBlockedUsersItem, + nbOfBlockedUsers = nbOfBlockedUsers, showLabsItem = showLabsItem, directLogoutState = directLogoutState, snackbarMessage = snackbarMessage, @@ -162,9 +157,7 @@ class PreferencesRootPresenter( private fun CoroutineScope.initAccountManagementUrl( accountManagementUrl: MutableState, - devicesManagementUrl: MutableState, ) = launch { - accountManagementUrl.value = matrixClient.getAccountManagementUrl(AccountManagementAction.Profile).getOrNull() - devicesManagementUrl.value = matrixClient.getAccountManagementUrl(AccountManagementAction.DevicesList).getOrNull() + accountManagementUrl.value = matrixClient.getAccountManagementUrl(null).getOrNull() } } 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 d637ae6c87..6474f07a69 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 @@ -23,15 +23,16 @@ data class PreferencesRootState( val showSecureBackup: Boolean, val showSecureBackupBadge: Boolean, val accountManagementUrl: String?, - val devicesManagementUrl: String?, val canReportBug: Boolean, val showLinkNewDevice: Boolean, val showAnalyticsSettings: Boolean, val showDeveloperSettings: Boolean, val canDeactivateAccount: Boolean, - val showBlockedUsersItem: Boolean, + val nbOfBlockedUsers: Int, val showLabsItem: Boolean, val directLogoutState: DirectLogoutState, val snackbarMessage: SnackbarMessage?, - val eventSink: (PreferencesRootEvents) -> Unit, -) + val eventSink: (PreferencesRootEvent) -> Unit, +) { + val showBlockedUsersItem = nbOfBlockedUsers > 0 +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt index b8d1f1c2b6..d53cd008e4 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt @@ -8,36 +8,103 @@ package io.element.android.features.preferences.impl.root +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.features.logout.api.direct.DirectLogoutState import io.element.android.features.logout.api.direct.aDirectLogoutState import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage 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 +import io.element.android.libraries.matrix.ui.components.aMatrixUserList import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.toImmutableList +open class PreferencesRootStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + // Nominal state, that a regular user will see if multi account is enabled + aPreferencesRootState( + myUser = aMatrixUser(avatarUrl = "anAvatarUrl"), + version = "Version 1.1 (1)", + deviceId = DeviceId("ILAKNDNASDLK"), + isMultiAccountEnabled = true, + otherSessions = aMatrixUserList().drop(1).take(1), + showSecureBackup = true, + accountManagementUrl = "aUrl", + canReportBug = true, + showLinkNewDevice = true, + showAnalyticsSettings = true, + canDeactivateAccount = false, + nbOfBlockedUsers = 3, + showLabsItem = true, + ), + aPreferencesRootState( + myUser = aMatrixUser(displayName = null), + isMultiAccountEnabled = true, + showSecureBackup = true, + canDeactivateAccount = true, + ), + aPreferencesRootState( + isMultiAccountEnabled = true, + otherSessions = aMatrixUserList().drop(1).take(3), + accountManagementUrl = "aUrl", + showSecureBackup = true, + showSecureBackupBadge = true, + ), + aPreferencesRootState( + deviceId = DeviceId("ILAKNDNASDLK"), + showLabsItem = true, + canReportBug = true, + nbOfBlockedUsers = 3, + snackbarMessage = SnackbarMessage(CommonStrings.common_verification_complete), + ), + aPreferencesRootState( + showLinkNewDevice = true, + showAnalyticsSettings = true, + showDeveloperSettings = true, + canDeactivateAccount = true, + ), + // Minimal state + aPreferencesRootState(), + ) +} + fun aPreferencesRootState( myUser: MatrixUser = aMatrixUser(), + version: String = "Version 1.1 (1)", + deviceId: DeviceId? = null, + isMultiAccountEnabled: Boolean = false, otherSessions: List = emptyList(), - eventSink: (PreferencesRootEvents) -> Unit = { _ -> }, + showSecureBackup: Boolean = false, + showSecureBackupBadge: Boolean = false, + accountManagementUrl: String? = null, + canReportBug: Boolean = false, + showLinkNewDevice: Boolean = false, + showAnalyticsSettings: Boolean = false, + showDeveloperSettings: Boolean = false, + canDeactivateAccount: Boolean = false, + nbOfBlockedUsers: Int = 0, + showLabsItem: Boolean = false, + directLogoutState: DirectLogoutState = aDirectLogoutState(), + snackbarMessage: SnackbarMessage? = null, + eventSink: (PreferencesRootEvent) -> Unit = {}, ) = PreferencesRootState( myUser = myUser, - version = "Version 1.1 (1)", - deviceId = DeviceId("ILAKNDNASDLK"), - isMultiAccountEnabled = true, + version = version, + deviceId = deviceId, + isMultiAccountEnabled = isMultiAccountEnabled, otherSessions = otherSessions.toImmutableList(), - showSecureBackup = true, - showSecureBackupBadge = true, - accountManagementUrl = "aUrl", - devicesManagementUrl = "anOtherUrl", - showAnalyticsSettings = true, - showLinkNewDevice = true, - canReportBug = true, - showDeveloperSettings = true, - showBlockedUsersItem = true, - showLabsItem = true, - canDeactivateAccount = true, - snackbarMessage = SnackbarMessage(CommonStrings.common_verification_complete), - directLogoutState = aDirectLogoutState(), + showSecureBackup = showSecureBackup, + showSecureBackupBadge = showSecureBackupBadge, + accountManagementUrl = accountManagementUrl, + canReportBug = canReportBug, + showLinkNewDevice = showLinkNewDevice, + showAnalyticsSettings = showAnalyticsSettings, + showDeveloperSettings = showDeveloperSettings, + canDeactivateAccount = canDeactivateAccount, + nbOfBlockedUsers = nbOfBlockedUsers, + showLabsItem = showLabsItem, + directLogoutState = directLogoutState, + snackbarMessage = snackbarMessage, eventSink = eventSink, ) 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 5e3c9d6759..32ecfc2b13 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,7 +9,6 @@ package io.element.android.features.preferences.impl.root import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable @@ -28,23 +27,20 @@ import io.element.android.libraries.architecture.coverage.ExcludeFromCoverage import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.list.ListItemContent import io.element.android.libraries.designsystem.components.preferences.PreferencePage -import io.element.android.libraries.designsystem.preview.ElementPreview 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.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.HorizontalDivider 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 import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.utils.CommonDrawables import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState 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.MatrixUserProvider import io.element.android.libraries.matrix.ui.components.MatrixUserRow -import io.element.android.libraries.matrix.ui.components.aMatrixUserList import io.element.android.libraries.ui.strings.CommonStrings @Composable @@ -82,22 +78,17 @@ fun PreferencesRootView( modifier = Modifier.clickable { onOpenUserProfile(state.myUser) }, - user = state.myUser, + matrixUser = state.myUser, ) if (state.isMultiAccountEnabled) { MultiAccountSection( state = state, onAddAccountClick = onAddAccountClick, ) + } else { + HorizontalDivider() } - // 'Manage my app' section - ManageAppSection( - state = state, - onOpenNotificationSettings = onOpenNotificationSettings, - onOpenLockScreenSettings = onOpenLockScreenSettings, - onSecureBackupClick = onSecureBackupClick, - ) - + // User status will be added here // 'Account' section ManageAccountSection( state = state, @@ -105,6 +96,13 @@ fun PreferencesRootView( onLinkNewDeviceClick = onLinkNewDeviceClick, onOpenBlockedUsers = onOpenBlockedUsers ) + // 'Manage my app' section + ManageAppSection( + state = state, + onOpenNotificationSettings = onOpenNotificationSettings, + onOpenLockScreenSettings = onOpenLockScreenSettings, + onSecureBackupClick = onSecureBackupClick, + ) // General section GeneralSection( @@ -118,12 +116,12 @@ fun PreferencesRootView( onSignOutClick = onSignOutClick, onDeactivateClick = onDeactivateClick, ) - + // Version Footer( version = state.version, deviceId = state.deviceId, onClick = if (!state.showDeveloperSettings) { - { state.eventSink(PreferencesRootEvents.OnVersionInfoClick) } + { state.eventSink(PreferencesRootEvent.OnVersionInfoClick) } } else { null } @@ -142,13 +140,15 @@ private fun ColumnScope.MultiAccountSection( ) state.otherSessions.forEach { matrixUser -> MatrixUserRow( - modifier = Modifier.clickable { - state.eventSink(PreferencesRootEvents.SwitchToSession(matrixUser.userId)) - }, + 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, ) - HorizontalDivider() } ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Plus())), @@ -198,6 +198,14 @@ private fun ColumnScope.ManageAccountSection( onLinkNewDeviceClick: () -> Unit, onOpenBlockedUsers: () -> Unit, ) { + state.accountManagementUrl?.let { url -> + ListItem( + headlineContent = { Text(stringResource(id = CommonStrings.action_manage_account_and_devices)) }, + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.UserProfile())), + trailingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.PopOut())), + onClick = { onManageAccountClick(url) }, + ) + } if (state.showLinkNewDevice) { ListItem( headlineContent = { Text(stringResource(id = CommonStrings.common_link_new_device)) }, @@ -205,33 +213,15 @@ private fun ColumnScope.ManageAccountSection( onClick = onLinkNewDeviceClick, ) } - state.accountManagementUrl?.let { url -> - ListItem( - headlineContent = { Text(stringResource(id = CommonStrings.action_manage_account)) }, - leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.UserProfile())), - trailingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.PopOut())), - onClick = { onManageAccountClick(url) }, - ) - } - - state.devicesManagementUrl?.let { url -> - ListItem( - headlineContent = { Text(stringResource(id = CommonStrings.action_manage_devices)) }, - leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Devices())), - trailingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.PopOut())), - onClick = { onManageAccountClick(url) }, - ) - } - if (state.showBlockedUsersItem) { ListItem( headlineContent = { Text(stringResource(id = CommonStrings.common_blocked_users)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Block())), onClick = onOpenBlockedUsers, + trailingContent = ListItemContent.Text(state.nbOfBlockedUsers.toString()), ) } - - if (state.accountManagementUrl != null || state.devicesManagementUrl != null || state.showBlockedUsersItem) { + if (state.accountManagementUrl != null || state.showLinkNewDevice || state.showBlockedUsersItem) { HorizontalDivider() } } @@ -248,6 +238,18 @@ private fun ColumnScope.GeneralSection( onSignOutClick: () -> Unit, onDeactivateClick: () -> Unit, ) { + ListItem( + headlineContent = { Text(stringResource(id = CommonStrings.common_advanced_settings)) }, + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Settings())), + onClick = onOpenAdvancedSettings, + ) + if (state.showLabsItem) { + ListItem( + headlineContent = { Text(stringResource(id = R.string.screen_labs_title)) }, + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Labs())), + onClick = onOpenLabs, + ) + } ListItem( headlineContent = { Text(stringResource(id = CommonStrings.common_about)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Info())), @@ -267,30 +269,17 @@ private fun ColumnScope.GeneralSection( onClick = onOpenAnalytics, ) } - ListItem( - headlineContent = { Text(stringResource(id = CommonStrings.common_advanced_settings)) }, - leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Settings())), - onClick = onOpenAdvancedSettings, - ) - - if (state.showLabsItem) { - ListItem( - headlineContent = { Text(stringResource(id = R.string.screen_labs_title)) }, - leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Labs())), - onClick = onOpenLabs, - ) - } - + HorizontalDivider() ListItem( headlineContent = { Text(stringResource(id = CommonStrings.action_signout)) }, - leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.SignOut())), + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Close())), style = ListItemStyle.Destructive, onClick = onSignOutClick, ) if (state.canDeactivateAccount) { ListItem( headlineContent = { Text(stringResource(id = CommonStrings.action_deactivate_account)) }, - leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Warning())), + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Delete())), style = ListItemStyle.Destructive, onClick = onDeactivateClick, ) @@ -319,9 +308,8 @@ private fun ColumnScope.Footer( Text( modifier = Modifier .align(Alignment.CenterHorizontally) - .padding(top = 16.dp) .clickable(enabled = onClick != null, onClick = onClick ?: {}) - .padding(start = 16.dp, end = 16.dp, top = 24.dp, bottom = 24.dp), + .padding(start = 16.dp, end = 16.dp, top = 16.dp, bottom = 24.dp), textAlign = TextAlign.Center, text = text, style = ElementTheme.typography.fontBodySmRegular, @@ -340,19 +328,23 @@ private fun DeveloperPreferencesView(onOpenDeveloperSettings: () -> Unit) { @PreviewWithLargeHeight @Composable -internal fun PreferencesRootViewLightPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) = - ElementPreviewLight { ContentToPreview(matrixUser) } +internal fun PreferencesRootViewLightPreview(@PreviewParameter(PreferencesRootStateProvider::class) state: PreferencesRootState) = + ElementPreviewLight( + drawableFallbackForImages = CommonDrawables.sample_avatar, + ) { ContentToPreview(state) } @PreviewWithLargeHeight @Composable -internal fun PreferencesRootViewDarkPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) = - ElementPreviewDark { ContentToPreview(matrixUser) } +internal fun PreferencesRootViewDarkPreview(@PreviewParameter(PreferencesRootStateProvider::class) state: PreferencesRootState) = + ElementPreviewDark( + drawableFallbackForImages = CommonDrawables.sample_avatar, + ) { ContentToPreview(state) } @ExcludeFromCoverage @Composable -private fun ContentToPreview(matrixUser: MatrixUser) { +private fun ContentToPreview(state: PreferencesRootState) { PreferencesRootView( - state = aPreferencesRootState(myUser = matrixUser), + state = state, onBackClick = {}, onAddAccountClick = {}, onOpenAnalytics = {}, @@ -372,16 +364,3 @@ private fun ContentToPreview(matrixUser: MatrixUser) { onDeactivateClick = {}, ) } - -@PreviewsDayNight -@Composable -internal fun MultiAccountSectionPreview() = ElementPreview { - Column { - MultiAccountSection( - state = aPreferencesRootState( - otherSessions = aMatrixUserList(), - ), - onAddAccountClick = {}, - ) - } -} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/UserPreferences.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/UserPreferences.kt index a9066dcd73..43c7e8dacf 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/UserPreferences.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/UserPreferences.kt @@ -15,21 +15,21 @@ import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.ui.components.MatrixUserHeader -import io.element.android.libraries.matrix.ui.components.MatrixUserWithNullProvider +import io.element.android.libraries.matrix.ui.components.MatrixUserProvider @Composable fun UserPreferences( - user: MatrixUser?, + matrixUser: MatrixUser, modifier: Modifier = Modifier, ) { MatrixUserHeader( modifier = modifier, - matrixUser = user + matrixUser = matrixUser, ) } @PreviewsDayNight @Composable -internal fun UserPreferencesPreview(@PreviewParameter(MatrixUserWithNullProvider::class) matrixUser: MatrixUser?) = ElementPreview { +internal fun UserPreferencesPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) = ElementPreview { UserPreferences(matrixUser) } 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 f0dc58ef22..e5d48ec175 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 @@ -28,6 +28,8 @@ import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.test.AN_AVATAR_URL import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.A_SESSION_ID_2 +import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.libraries.matrix.test.A_USER_ID_2 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 @@ -40,7 +42,9 @@ import io.element.android.tests.testutils.WarmUpRule 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.flowOf import kotlinx.coroutines.test.runTest import org.junit.Rule @@ -73,6 +77,7 @@ class PreferencesRootPresenterTest { assertThat(initialState.version).isEqualTo("A Version") assertThat(initialState.isMultiAccountEnabled).isFalse() assertThat(initialState.otherSessions).isEmpty() + assertThat(initialState.version).isEqualTo("A Version") val loadedState = awaitItem() assertThat(loadedState.myUser).isEqualTo( MatrixUser( @@ -81,27 +86,21 @@ class PreferencesRootPresenterTest { avatarUrl = AN_AVATAR_URL ) ) - assertThat(initialState.version).isEqualTo("A Version") assertThat(loadedState.showSecureBackup).isFalse() assertThat(loadedState.showSecureBackupBadge).isFalse() assertThat(loadedState.accountManagementUrl).isNull() - assertThat(loadedState.devicesManagementUrl).isNull() assertThat(loadedState.showAnalyticsSettings).isFalse() assertThat(loadedState.showLinkNewDevice).isFalse() assertThat(loadedState.showDeveloperSettings).isTrue() assertThat(loadedState.canDeactivateAccount).isTrue() assertThat(loadedState.canReportBug).isTrue() + assertThat(loadedState.nbOfBlockedUsers).isEqualTo(0) assertThat(loadedState.directLogoutState).isEqualTo(aDirectLogoutState()) assertThat(loadedState.snackbarMessage).isNull() - skipItems(1) val finalState = awaitItem() - accountManagementUrlResult.assertions().isCalledExactly(2) - .withSequence( - listOf(value(AccountManagementAction.Profile)), - listOf(value(AccountManagementAction.DevicesList)), - ) - assertThat(finalState.accountManagementUrl).isEqualTo("Profile url") - assertThat(finalState.devicesManagementUrl).isEqualTo("DevicesList url") + accountManagementUrlResult.assertions().isCalledOnce() + .with(value(null)) + assertThat(finalState.accountManagementUrl).isEqualTo("null url") } } @@ -121,6 +120,22 @@ class PreferencesRootPresenterTest { } } + @Test + fun `present - number of blocked users`() = runTest { + val matrixClient = FakeMatrixClient( + canDeactivateAccountResult = { true }, + accountManagementUrlResult = { Result.success("") }, + ignoredUsersFlow = MutableStateFlow(persistentListOf(A_USER_ID, A_USER_ID_2)), + ) + createPresenter( + matrixClient = matrixClient, + ).test { + skipItems(1) + val initialState = awaitItem() + assertThat(initialState.nbOfBlockedUsers).isEqualTo(2) + } + } + @Test fun `present - secure backup badge`() = runTest { val matrixClient = FakeMatrixClient( @@ -181,12 +196,36 @@ class PreferencesRootPresenterTest { val loadedState = awaitFirstItem() repeat(times = ShowDeveloperSettingsProvider.DEVELOPER_SETTINGS_COUNTER) { assertThat(loadedState.showDeveloperSettings).isFalse() - loadedState.eventSink(PreferencesRootEvents.OnVersionInfoClick) + loadedState.eventSink(PreferencesRootEvent.OnVersionInfoClick) } assertThat(awaitItem().showDeveloperSettings).isTrue() } } + @Test + fun `present - switch session invoke method on the session store`() = runTest { + val setLatestSessionResult = lambdaRecorder { } + val sessionStore = InMemorySessionStore( + initialList = listOf( + aSessionData(sessionId = A_SESSION_ID.value), + aSessionData(sessionId = A_SESSION_ID_2.value), + ), + setLatestSessionResult = setLatestSessionResult, + ) + createPresenter( + matrixClient = FakeMatrixClient( + canDeactivateAccountResult = { true }, + accountManagementUrlResult = { Result.success(null) }, + ), + sessionStore = sessionStore, + ).test { + val loadedState = awaitFirstItem() + loadedState.eventSink(PreferencesRootEvent.SwitchToSession(A_SESSION_ID_2)) + setLatestSessionResult.assertions().isCalledOnce() + .with(value(A_SESSION_ID_2.value)) + } + } + @Test fun `present - labs can be shown if any feature flag is in labs and not finished`() = runTest { createPresenter( 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 new file mode 100644 index 0000000000..e3c0d6e44d --- /dev/null +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootViewTest.kt @@ -0,0 +1,483 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.preferences.impl.root + +import androidx.activity.ComponentActivity +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import androidx.test.ext.junit.runners.AndroidJUnit4 +import io.element.android.features.preferences.impl.R +import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.test.A_USER_ID_2 +import io.element.android.libraries.matrix.ui.components.aMatrixUser +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.clickOn +import io.element.android.tests.testutils.ensureCalledOnce +import io.element.android.tests.testutils.ensureCalledOnceWithParam +import io.element.android.tests.testutils.pressBack +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TestRule +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class PreferencesRootViewTest { + @get:Rule val rule = createAndroidComposeRule() + + @Test + fun `clicking on back invokes back callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + eventSink = eventsRecorder + ), + onBackClick = callback, + ) + rule.pressBack() + } + } + + @Test + fun `click on User profile invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + val user = aMatrixUser() + ensureCalledOnceWithParam(user) { callback -> + rule.setView( + aPreferencesRootState( + myUser = user, + eventSink = eventsRecorder, + ), + onOpenUserProfile = callback, + ) + rule.onNodeWithText("Alice").performClick() + } + } + + @Test + fun `clicking on other session sends a SwitchToSession`() { + val eventsRecorder = EventsRecorder() + rule.setView( + aPreferencesRootState( + isMultiAccountEnabled = true, + otherSessions = listOf( + aMatrixUser( + id = A_USER_ID_2.value, + displayName = "Bob", + ) + ), + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText("Bob").performClick() + eventsRecorder.assertSingle(PreferencesRootEvent.SwitchToSession(A_USER_ID_2)) + } + + @Test + fun `click on Add account invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + isMultiAccountEnabled = true, + eventSink = eventsRecorder, + ), + onAddAccountClick = callback, + ) + rule.clickOn(CommonStrings.common_add_another_account) + } + } + + @Test + fun `when multi account is not enabled, item is not shown`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + rule.setView( + aPreferencesRootState( + isMultiAccountEnabled = false, + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText(rule.activity.getString(CommonStrings.common_add_another_account)).assertDoesNotExist() + } + + @Test + fun `click on Encryption invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + showSecureBackup = true, + eventSink = eventsRecorder, + ), + onSecureBackupClick = callback, + ) + rule.clickOn(CommonStrings.common_encryption) + } + } + + @Test + fun `when showSecureBackup is false, item is not shown`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + rule.setView( + aPreferencesRootState( + showSecureBackup = false, + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText(rule.activity.getString(CommonStrings.common_encryption)).assertDoesNotExist() + } + + @Test + fun `click on Manage account invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnceWithParam("aUrl") { callback -> + rule.setView( + aPreferencesRootState( + accountManagementUrl = "aUrl", + eventSink = eventsRecorder, + ), + onManageAccountClick = callback, + ) + rule.clickOn(CommonStrings.action_manage_account_and_devices) + } + } + + @Test + fun `when accountManagementUrl is null, item is not shown`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + rule.setView( + aPreferencesRootState( + accountManagementUrl = null, + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText(rule.activity.getString(CommonStrings.action_manage_account_and_devices)).assertDoesNotExist() + } + + @Test + fun `click on Link new devices invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + showLinkNewDevice = true, + eventSink = eventsRecorder, + ), + onLinkNewDeviceClick = callback, + ) + rule.clickOn(CommonStrings.common_link_new_device) + } + } + + @Test + fun `when showLinkNewDevice is false, item is not shown`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + rule.setView( + aPreferencesRootState( + showLinkNewDevice = false, + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText(rule.activity.getString(CommonStrings.common_link_new_device)).assertDoesNotExist() + } + + @Test + fun `click on Analytics invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + showAnalyticsSettings = true, + eventSink = eventsRecorder, + ), + onOpenAnalytics = callback, + ) + rule.clickOn(CommonStrings.common_analytics) + } + } + + @Test + fun `when showAnalyticsSettings is false, item is not shown`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + rule.setView( + aPreferencesRootState( + showAnalyticsSettings = false, + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText(rule.activity.getString(CommonStrings.common_analytics)).assertDoesNotExist() + } + + @Test + fun `click on Report a problem invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + canReportBug = true, + eventSink = eventsRecorder, + ), + onOpenRageShake = callback, + ) + rule.clickOn(CommonStrings.common_report_a_problem) + } + } + + @Test + fun `when canReportBug is false, item is not shown`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + rule.setView( + aPreferencesRootState( + canReportBug = false, + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText(rule.activity.getString(CommonStrings.common_report_a_problem)).assertDoesNotExist() + } + + @Test + fun `click on Screen lock invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + eventSink = eventsRecorder, + ), + onOpenLockScreenSettings = callback, + ) + rule.clickOn(CommonStrings.common_screen_lock) + } + } + + @Test + fun `click on About invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + eventSink = eventsRecorder, + ), + onOpenAbout = callback, + ) + rule.clickOn(CommonStrings.common_about) + } + } + + @Test + fun `click on Developer settings invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + showDeveloperSettings = true, + eventSink = eventsRecorder, + ), + onOpenDeveloperSettings = callback, + ) + rule.clickOn(CommonStrings.common_developer_options) + } + } + + @Test + fun `when showDeveloperSettings is false, item is not shown`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + rule.setView( + aPreferencesRootState( + showDeveloperSettings = false, + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText(rule.activity.getString(CommonStrings.common_developer_options)).assertDoesNotExist() + } + + @Test + fun `click on Advanced settings invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + eventSink = eventsRecorder, + ), + onOpenAdvancedSettings = callback, + ) + rule.clickOn(CommonStrings.common_advanced_settings) + } + } + + @Test + fun `click on Labs invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + showLabsItem = true, + eventSink = eventsRecorder, + ), + onOpenLabs = callback, + ) + rule.clickOn(R.string.screen_labs_title) + } + } + + @Test + fun `when showLabsItem is false, item is not shown`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + rule.setView( + aPreferencesRootState( + showLabsItem = false, + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText(rule.activity.getString(R.string.screen_labs_title)).assertDoesNotExist() + } + + @Test + fun `click on Notification invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + eventSink = eventsRecorder, + ), + onOpenNotificationSettings = callback, + ) + rule.clickOn(R.string.screen_notification_settings_title) + } + } + + @Test + fun `click on Blocked users invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + nbOfBlockedUsers = 1, + eventSink = eventsRecorder, + ), + onOpenBlockedUsers = callback, + ) + rule.clickOn(CommonStrings.common_blocked_users) + } + } + + @Test + fun `when nbOfBlockedUsers is 0, item is not shown`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + rule.setView( + aPreferencesRootState( + nbOfBlockedUsers = 0, + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText(rule.activity.getString(CommonStrings.common_blocked_users)).assertDoesNotExist() + } + + @Test + fun `click on Remove this device invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + eventSink = eventsRecorder, + ), + onSignOutClick = callback, + ) + rule.clickOn(CommonStrings.action_signout) + } + } + + @Test + fun `click on Deactivate invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + canDeactivateAccount = true, + eventSink = eventsRecorder, + ), + onDeactivateClick = callback, + ) + rule.clickOn(CommonStrings.action_deactivate_account) + } + } + + @Test + fun `when canDeactivateAccount is false, item is not shown`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + rule.setView( + aPreferencesRootState( + canDeactivateAccount = false, + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText(rule.activity.getString(CommonStrings.action_deactivate_account)).assertDoesNotExist() + } + + @Test + fun `clicking on version sends a PreferencesRootEvents`() { + val version = "VERSION" + val eventsRecorder = EventsRecorder() + rule.setView( + aPreferencesRootState( + version = version, + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText(version).performClick() + eventsRecorder.assertSingle(PreferencesRootEvent.OnVersionInfoClick) + } +} + +private fun AndroidComposeTestRule.setView( + state: PreferencesRootState, + onBackClick: () -> Unit = EnsureNeverCalled(), + onAddAccountClick: () -> Unit = EnsureNeverCalled(), + onSecureBackupClick: () -> Unit = EnsureNeverCalled(), + onManageAccountClick: (url: String) -> Unit = EnsureNeverCalledWithParam(), + onLinkNewDeviceClick: () -> Unit = EnsureNeverCalled(), + onOpenAnalytics: () -> Unit = EnsureNeverCalled(), + onOpenRageShake: () -> Unit = EnsureNeverCalled(), + onOpenLockScreenSettings: () -> Unit = EnsureNeverCalled(), + onOpenAbout: () -> Unit = EnsureNeverCalled(), + onOpenDeveloperSettings: () -> Unit = EnsureNeverCalled(), + onOpenAdvancedSettings: () -> Unit = EnsureNeverCalled(), + onOpenLabs: () -> Unit = EnsureNeverCalled(), + onOpenNotificationSettings: () -> Unit = EnsureNeverCalled(), + onOpenUserProfile: (MatrixUser) -> Unit = EnsureNeverCalledWithParam(), + onOpenBlockedUsers: () -> Unit = EnsureNeverCalled(), + onSignOutClick: () -> Unit = EnsureNeverCalled(), + onDeactivateClick: () -> Unit = EnsureNeverCalled(), +) { + setContent { + PreferencesRootView( + state = state, + onBackClick = onBackClick, + onAddAccountClick = onAddAccountClick, + onSecureBackupClick = onSecureBackupClick, + onManageAccountClick = onManageAccountClick, + onLinkNewDeviceClick = onLinkNewDeviceClick, + onOpenAnalytics = onOpenAnalytics, + onOpenRageShake = onOpenRageShake, + onOpenLockScreenSettings = onOpenLockScreenSettings, + onOpenAbout = onOpenAbout, + onOpenDeveloperSettings = onOpenDeveloperSettings, + onOpenAdvancedSettings = onOpenAdvancedSettings, + onOpenLabs = onOpenLabs, + onOpenNotificationSettings = onOpenNotificationSettings, + onOpenUserProfile = onOpenUserProfile, + onOpenBlockedUsers = onOpenBlockedUsers, + onSignOutClick = onSignOutClick, + onDeactivateClick = onDeactivateClick, + ) + } +} 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 b1e3356fc3..660b071983 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 @@ -24,7 +24,7 @@ enum class AvatarSize(val dp: Dp) { RoomSelectRoomListItem(36.dp), - UserPreference(56.dp), + UserPreference(52.dp), UserHeader(96.dp), UserListItem(36.dp), diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewDark.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewDark.kt index c054b318f3..4d2db383a7 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewDark.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewDark.kt @@ -8,16 +8,21 @@ package io.element.android.libraries.designsystem.preview +import androidx.annotation.DrawableRes import androidx.compose.runtime.Composable +import io.element.android.libraries.designsystem.utils.CommonDrawables @Composable fun ElementPreviewDark( showBackground: Boolean = true, - content: @Composable () -> Unit + @DrawableRes + drawableFallbackForImages: Int = CommonDrawables.sample_background, + content: @Composable () -> Unit, ) { ElementPreview( darkTheme = true, showBackground = showBackground, - content = content + drawableFallbackForImages = drawableFallbackForImages, + content = content, ) } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewLight.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewLight.kt index 1c2bdf3cef..19b40f3520 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewLight.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewLight.kt @@ -8,16 +8,21 @@ package io.element.android.libraries.designsystem.preview +import androidx.annotation.DrawableRes import androidx.compose.runtime.Composable +import io.element.android.libraries.designsystem.utils.CommonDrawables @Composable fun ElementPreviewLight( showBackground: Boolean = true, - content: @Composable () -> Unit + @DrawableRes + drawableFallbackForImages: Int = CommonDrawables.sample_background, + content: @Composable () -> Unit, ) { ElementPreview( darkTheme = false, showBackground = showBackground, - content = content + drawableFallbackForImages = drawableFallbackForImages, + content = content, ) } diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeader.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeader.kt index 5b44b50ce9..0b9bde0fb9 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeader.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeader.kt @@ -8,6 +8,7 @@ package io.element.android.libraries.matrix.ui.components +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -34,51 +35,34 @@ import io.element.android.libraries.matrix.ui.model.getBestName @Composable fun MatrixUserHeader( - matrixUser: MatrixUser?, - modifier: Modifier = Modifier, - // TODO handle click on this item, to let the user be able to update their profile. - // onClick: () -> Unit, -) { - if (matrixUser == null) { - MatrixUserHeaderPlaceholder(modifier = modifier) - } else { - MatrixUserHeaderContent( - matrixUser = matrixUser, - modifier = modifier, - // onClick = onClick - ) - } -} - -@Composable -private fun MatrixUserHeaderContent( matrixUser: MatrixUser, modifier: Modifier = Modifier, - // onClick: () -> Unit, ) { Row( modifier = modifier - // .clickable(onClick = onClick) .fillMaxWidth() - .padding(horizontal = 16.dp), - verticalAlignment = Alignment.CenterVertically + .padding(horizontal = 16.dp, vertical = 6.dp), + verticalAlignment = Alignment.CenterVertically, ) { Avatar( modifier = Modifier - .padding(vertical = 12.dp), + .padding(vertical = 7.dp), avatarData = matrixUser.getAvatarData(size = AvatarSize.UserPreference), avatarType = AvatarType.User, ) - Spacer(modifier = Modifier.width(16.dp)) + Spacer(modifier = Modifier.width(13.dp)) Column( - modifier = Modifier.weight(1f) + modifier = Modifier + .weight(1f) + .padding(vertical = 8.dp), + verticalArrangement = Arrangement.spacedBy(2.dp) ) { // Name Text( modifier = Modifier.clipToBounds(), text = matrixUser.getBestName(), maxLines = 1, - style = ElementTheme.typography.fontHeadingSmMedium, + style = ElementTheme.typography.fontHeadingMdRegular, overflow = TextOverflow.Ellipsis, color = ElementTheme.colors.textPrimary, ) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeaderPlaceholder.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeaderPlaceholder.kt deleted file mode 100644 index 08f8a37cc1..0000000000 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeaderPlaceholder.kt +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2023-2025 New Vector 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 - -import androidx.compose.foundation.background -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.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import io.element.android.compound.theme.ElementTheme -import io.element.android.libraries.designsystem.atomic.atoms.PlaceholderAtom -import io.element.android.libraries.designsystem.components.avatar.AvatarSize -import io.element.android.libraries.designsystem.preview.ElementPreview -import io.element.android.libraries.designsystem.preview.PreviewsDayNight -import io.element.android.libraries.designsystem.theme.placeholderBackground - -@Composable -fun MatrixUserHeaderPlaceholder( - modifier: Modifier = Modifier, -) { - Row( - modifier = modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Box( - modifier = Modifier - .padding(vertical = 12.dp) - .size(AvatarSize.UserPreference.dp) - .background(color = ElementTheme.colors.placeholderBackground, shape = CircleShape) - ) - Spacer(modifier = Modifier.width(16.dp)) - Column( - modifier = Modifier.weight(1f) - ) { - PlaceholderAtom(width = 80.dp, height = 7.dp) - Spacer(modifier = Modifier.height(16.dp)) - PlaceholderAtom(width = 180.dp, height = 6.dp) - } - } -} - -@PreviewsDayNight -@Composable -internal fun MatrixUserHeaderPlaceholderPreview() = ElementPreview { - MatrixUserHeaderPlaceholder() -} diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserProvider.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserProvider.kt index 4d5a1cd222..5e9f29496e 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserProvider.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserProvider.kt @@ -20,15 +20,6 @@ open class MatrixUserProvider : PreviewParameterProvider { ) } -open class MatrixUserWithNullProvider : PreviewParameterProvider { - override val values: Sequence - get() = sequenceOf( - aMatrixUser(), - aMatrixUser(displayName = null), - null, - ) -} - open class MatrixUserWithAvatarProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserRow.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserRow.kt index cf89074737..ed7fd63435 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserRow.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserRow.kt @@ -11,6 +11,8 @@ package io.element.android.libraries.matrix.ui.components import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight @@ -23,12 +25,14 @@ fun MatrixUserRow( matrixUser: MatrixUser, modifier: Modifier = Modifier, avatarSize: AvatarSize = AvatarSize.UserListItem, + verticalSpaceWidth: Dp = 12.dp, trailingContent: @Composable (() -> Unit)? = null, ) = UserRow( avatarData = matrixUser.getAvatarData(avatarSize), name = matrixUser.getBestName(), subtext = if (matrixUser.displayName.isNullOrEmpty()) null else matrixUser.userId.value, modifier = modifier, + verticalSpaceWidth = verticalSpaceWidth, trailingContent = trailingContent, ) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UserRow.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UserRow.kt index 9bcf0b323f..8d236d1a2a 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UserRow.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UserRow.kt @@ -10,13 +10,16 @@ package io.element.android.libraries.matrix.ui.components 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.padding +import androidx.compose.foundation.layout.width 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.text.style.TextOverflow +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.libraries.designsystem.components.avatar.Avatar @@ -31,22 +34,22 @@ internal fun UserRow( subtext: String?, modifier: Modifier = Modifier, enabled: Boolean = true, + verticalSpaceWidth: Dp = 12.dp, trailingContent: @Composable (() -> Unit)? = null, ) { Row( modifier = modifier .fillMaxWidth() - .padding(start = 16.dp, top = 12.dp, end = 16.dp, bottom = 12.dp), + .padding(horizontal = 16.dp, vertical = 12.dp), verticalAlignment = Alignment.CenterVertically ) { Avatar( avatarData = avatarData, avatarType = AvatarType.User, ) + Spacer(modifier = Modifier.width(verticalSpaceWidth)) Column( - modifier = Modifier - .padding(start = 12.dp) - .weight(1f), + modifier = Modifier.weight(1f), ) { // Name Text( diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_MultiAccountSection_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_MultiAccountSection_Day_0_en.png deleted file mode 100644 index 29b7fa324c..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_MultiAccountSection_Day_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:df19ce5a967143e2cb6d1fe021663f72e36f20c32e912894a2fbad628f03c3e5 -size 53561 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_MultiAccountSection_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_MultiAccountSection_Night_0_en.png deleted file mode 100644 index 2ba5234dc6..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_MultiAccountSection_Night_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8fd24e865907b5c9240829710a910e445954bef9b8575f5115a52837e00d817f -size 54591 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 bc97d5a5c7..4a62c517f0 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:369c835c46e19d3e3171add57055624cf672a9d34109e6c831e0c1bce234c605 -size 39513 +oid sha256:712c1fca10ed7655634d300c03615c6c4dd2f71b74c178398d72fa0427f0d766 +size 41537 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 c6b82b8385..3ee64a4d09 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:3d9f6763de5b844eeace37bedb25b125976625394d69d7843eedb26319e926aa -size 39316 +oid sha256:da47d339d9b8712aa13c394482f8aa5d2e1fb4fcb8eb10df473394bfec1ef507 +size 25980 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 new file mode 100644 index 0000000000..4a56ec8135 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:324ce7d935816d87fea7b70bc7ebaacb0ac1d007b08dba85f03c03a1f045e450 +size 36764 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 new file mode 100644 index 0000000000..f1b39a0d35 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9176ee2b5b78032639d9f51f7680d82f7d3ca916fb587d914f12d075382d65f0 +size 27077 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 new file mode 100644 index 0000000000..5e115162c8 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_4_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:821a13ed4effd98ad459e3697a33d9d42500d7f1f46115a97c9b7444303a3bb2 +size 27645 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 new file mode 100644 index 0000000000..31a44423ce --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_5_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e457b722fe403205f1394e7347dedb3aba308e48c979ea002399425c9a130fd2 +size 20667 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 dccf28ff97..d2e319b028 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:dce8486726293027aedcdd2e67d10a39a1a2c439ca67d81ae247b60119675ada -size 40385 +oid sha256:2c149288a8ef258f65292f673b9a15ea34910db6d3bfe2402b2a3264227f2b0d +size 42547 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 6f2381c6f4..cdd9ef1a41 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:93ee581f59c79e03b9c9311765da4c828c5009d14e92f7cca9bbcee418fdfc63 -size 40442 +oid sha256:7ecf19446d8a0cf57431f13cbac9331ff72c93637c1cd1b442ed6330566debb2 +size 26879 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 new file mode 100644 index 0000000000..a83adbff85 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:00c7c42f1e6dde16916ae12a889b728c0fb321aa2c3fc6af80ec01d99a3af7a6 +size 37164 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 new file mode 100644 index 0000000000..15c12f4836 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:74a4913734d0648115d5056052fa2de8a839bb5a4d2dfdaa3d8ed5f0eef2793d +size 27728 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 new file mode 100644 index 0000000000..3346ad327d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_4_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e6c20d715bfa287ca0fa78bab1166ff0370b5124455c87f1956e7dc3cb9b3d36 +size 28253 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 new file mode 100644 index 0000000000..c325a4e7b5 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_5_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3d5b500d6275bc6ead5e8644b1afb1a0a829e91d4912444e5e0d431322343855 +size 20700 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_0_en.png index 4c4d183956..c6e079dee2 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ccaa7f88a9e46bdc526bfe3d5c2163bf3d963c0661179db97f62559edfd3189 -size 11042 +oid sha256:0805bac4bf9e1c5bb16b4f81b004bcc952563eef98101d8c9c6e856a414977d0 +size 11219 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_1_en.png index 0edaae43b6..74bc9743d7 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f37e1587ba12f9b6326b5b7398982fc663ca913da8c0ee83dfbd5e9decbd4362 -size 10906 +oid sha256:b61c5a72e8e63a1775d20717c78d8e68e46c7c22b8e4ab8c24154dc3d48d7d0e +size 11428 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_2_en.png deleted file mode 100644 index 3a7abad03f..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_2_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b494ecdb4962772dd548339a4ac57be40b273b513697ed6d039d1c905617d54f -size 4987 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_0_en.png index 741a708fe7..f21d99fffc 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bcb0063babe7091368af6b5bc7e8929c54ea879bd78043d9128db2dcea9d79fa -size 11191 +oid sha256:070163694fe10b465f2903ce2cc88f9ffc67d9489aa5a4e204cd087fd02b8642 +size 11281 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_1_en.png index c4e8dfdd29..9413b91e88 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f34e63a88464ddc817d1ffe0324352199ae1821dfa846cceac129a656ece2eb6 -size 10911 +oid sha256:da4e1512cd7a58ede774755b6e3ac427e90c437bbbadaea8479506af776999c3 +size 11323 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_2_en.png deleted file mode 100644 index 17d1ff9d1b..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_2_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f0618a9f769e15b4e682d763224cc1fe0abf62c58f3b9a6b4059153f8805671e -size 4740 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Day_0_en.png deleted file mode 100644 index 3a7abad03f..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Day_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b494ecdb4962772dd548339a4ac57be40b273b513697ed6d039d1c905617d54f -size 4987 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Night_0_en.png deleted file mode 100644 index 17d1ff9d1b..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Night_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f0618a9f769e15b4e682d763224cc1fe0abf62c58f3b9a6b4059153f8805671e -size 4740 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Day_0_en.png index 4c4d183956..c6e079dee2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ccaa7f88a9e46bdc526bfe3d5c2163bf3d963c0661179db97f62559edfd3189 -size 11042 +oid sha256:0805bac4bf9e1c5bb16b4f81b004bcc952563eef98101d8c9c6e856a414977d0 +size 11219 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Day_1_en.png index 0edaae43b6..74bc9743d7 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f37e1587ba12f9b6326b5b7398982fc663ca913da8c0ee83dfbd5e9decbd4362 -size 10906 +oid sha256:b61c5a72e8e63a1775d20717c78d8e68e46c7c22b8e4ab8c24154dc3d48d7d0e +size 11428 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Night_0_en.png index 741a708fe7..f21d99fffc 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bcb0063babe7091368af6b5bc7e8929c54ea879bd78043d9128db2dcea9d79fa -size 11191 +oid sha256:070163694fe10b465f2903ce2cc88f9ffc67d9489aa5a4e204cd087fd02b8642 +size 11281 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Night_1_en.png index c4e8dfdd29..9413b91e88 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f34e63a88464ddc817d1ffe0324352199ae1821dfa846cceac129a656ece2eb6 -size 10911 +oid sha256:da4e1512cd7a58ede774755b6e3ac427e90c437bbbadaea8479506af776999c3 +size 11323