From e8b80b9a551b269a7690c1b759d5f9d2a7216bfd Mon Sep 17 00:00:00 2001 From: yostyle Date: Tue, 8 Aug 2023 15:22:49 +0200 Subject: [PATCH 001/234] Add Notifications section in app settings --- changelog.d/510.misc | 1 + .../features/preferences/impl/PreferencesFlowNode.kt | 4 ++++ .../features/preferences/impl/root/PreferencesRootNode.kt | 6 ++++++ .../features/preferences/impl/root/PreferencesRootView.kt | 8 ++++++++ 4 files changed, 19 insertions(+) create mode 100644 changelog.d/510.misc diff --git a/changelog.d/510.misc b/changelog.d/510.misc new file mode 100644 index 0000000000..556aeab74f --- /dev/null +++ b/changelog.d/510.misc @@ -0,0 +1 @@ +Add a sub-screen "Notifications" in the existing application Settings diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt index e5b8254488..66f9d45ebd 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt @@ -90,6 +90,10 @@ class PreferencesFlowNode @AssistedInject constructor( override fun onOpenDeveloperSettings() { backstack.push(NavTarget.DeveloperSettings) } + + override fun onOpenNotificationSettings() { + TODO("Not yet implemented") + } } createNode(buildContext, plugins = listOf(callback)) } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt index e90569b40e..0f297d14dd 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt @@ -44,6 +44,7 @@ class PreferencesRootNode @AssistedInject constructor( fun onOpenAnalytics() fun onOpenAbout() fun onOpenDeveloperSettings() + fun onOpenNotificationSettings() } private fun onOpenBugReport() { @@ -72,6 +73,10 @@ class PreferencesRootNode @AssistedInject constructor( } } + private fun onOpenNotificationSettings() { + plugins().forEach { it.onOpenNotificationSettings() } + } + @Composable override fun View(modifier: Modifier) { val state = presenter.present() @@ -87,6 +92,7 @@ class PreferencesRootNode @AssistedInject constructor( onOpenDeveloperSettings = this::onOpenDeveloperSettings, onSuccessLogout = { onSuccessLogout(activity, it) }, onManageAccountClicked = { onManageAccountClicked(activity, state.accountManagementUrl) }, + onOpenNotificationSettings = this::onOpenNotificationSettings ) } 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 c24a2ec875..24f489628c 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 @@ -24,6 +24,7 @@ import androidx.compose.material.icons.outlined.DeveloperMode import androidx.compose.material.icons.outlined.Help import androidx.compose.material.icons.outlined.InsertChart import androidx.compose.material.icons.outlined.ManageAccounts +import androidx.compose.material.icons.outlined.Notifications import androidx.compose.material.icons.outlined.VerifiedUser import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -58,6 +59,7 @@ fun PreferencesRootView( onOpenAbout: () -> Unit, onOpenDeveloperSettings: () -> Unit, onSuccessLogout: (String?) -> Unit, + onOpenNotificationSettings: () -> Unit, modifier: Modifier = Modifier, ) { val snackbarHostState = rememberSnackbarHostState(snackbarMessage = state.snackbarMessage) @@ -92,6 +94,11 @@ fun PreferencesRootView( onClick = onOpenAnalytics, ) } + PreferenceText( + title = "Notifications", + icon = Icons.Outlined.Notifications, + onClick = onOpenNotificationSettings, + ) PreferenceText( title = stringResource(id = CommonStrings.action_report_bug), icon = Icons.Outlined.BugReport, @@ -153,5 +160,6 @@ private fun ContentToPreview(matrixUser: MatrixUser) { onVerifyClicked = {}, onSuccessLogout = {}, onManageAccountClicked = {}, + onOpenNotificationSettings = {}, ) } From 5ef53a99f2b1fa966bd5b0a364cd75b6f442a2a2 Mon Sep 17 00:00:00 2001 From: yostyle Date: Tue, 8 Aug 2023 16:02:08 +0200 Subject: [PATCH 002/234] Update string --- .../features/preferences/impl/root/PreferencesRootView.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 24f489628c..d4783cde1f 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 @@ -95,7 +95,7 @@ fun PreferencesRootView( ) } PreferenceText( - title = "Notifications", + title = stringResource(id = CommonStrings.screen_notification_settings_title), icon = Icons.Outlined.Notifications, onClick = onOpenNotificationSettings, ) From aac6fb2c91a49a0405e87f92b745437fc6387d45 Mon Sep 17 00:00:00 2001 From: yostyle Date: Tue, 8 Aug 2023 16:18:38 +0200 Subject: [PATCH 003/234] Refactoring --- .../preferences/impl/PreferencesFlowNode.kt | 11 ++++-- .../NotificationsSettingsNode.kt | 35 +++++++++++++++++++ .../impl/root/PreferencesRootNode.kt | 2 +- .../impl/root/PreferencesRootView.kt | 2 +- 4 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsNode.kt diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt index 66f9d45ebd..f6e4a88f87 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt @@ -33,6 +33,7 @@ import io.element.android.features.preferences.api.PreferencesEntryPoint import io.element.android.features.preferences.impl.about.AboutNode import io.element.android.features.preferences.impl.analytics.AnalyticsSettingsNode import io.element.android.features.preferences.impl.developer.DeveloperSettingsNode +import io.element.android.features.preferences.impl.notifications.NotificationsSettingsNode import io.element.android.features.preferences.impl.root.PreferencesRootNode import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler @@ -65,6 +66,9 @@ class PreferencesFlowNode @AssistedInject constructor( @Parcelize object About : NavTarget + + @Parcelize + object NotificationsSettings : NavTarget } override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { @@ -91,8 +95,8 @@ class PreferencesFlowNode @AssistedInject constructor( backstack.push(NavTarget.DeveloperSettings) } - override fun onOpenNotificationSettings() { - TODO("Not yet implemented") + override fun onOpenNotificationsSettings() { + backstack.push(NavTarget.NotificationsSettings) } } createNode(buildContext, plugins = listOf(callback)) @@ -106,6 +110,9 @@ class PreferencesFlowNode @AssistedInject constructor( NavTarget.AnalyticsSettings -> { createNode(buildContext) } + NavTarget.NotificationsSettings -> { + createNode(buildContext) + } } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsNode.kt new file mode 100644 index 0000000000..7dca1f38da --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsNode.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.notifications + +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode +import io.element.android.features.preferences.impl.developer.DeveloperSettingsPresenter +import io.element.android.libraries.di.SessionScope + +@ContributesNode(SessionScope::class) +class NotificationsSettingsNode @AssistedInject constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + private val presenter: DeveloperSettingsPresenter, +) : Node(buildContext, plugins = plugins) { + +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt index 0f297d14dd..09b488294e 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt @@ -44,7 +44,7 @@ class PreferencesRootNode @AssistedInject constructor( fun onOpenAnalytics() fun onOpenAbout() fun onOpenDeveloperSettings() - fun onOpenNotificationSettings() + fun onOpenNotificationsSettings() } private fun onOpenBugReport() { 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 d4783cde1f..7c2e80ef52 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 @@ -97,7 +97,7 @@ fun PreferencesRootView( PreferenceText( title = stringResource(id = CommonStrings.screen_notification_settings_title), icon = Icons.Outlined.Notifications, - onClick = onOpenNotificationSettings, + onClick = onOpenNotificationsSettings, ) PreferenceText( title = stringResource(id = CommonStrings.action_report_bug), From a4d99f3c2dad88dcb70c80fbc12c392c1386f984 Mon Sep 17 00:00:00 2001 From: yostyle Date: Tue, 8 Aug 2023 16:46:11 +0200 Subject: [PATCH 004/234] Prepare node --- .../NotificationsSettingsNode.kt | 3 +- .../NotificationsSettingsPresenter.kt | 29 +++++++++++++++++++ .../NotificationsSettingsState.kt | 21 ++++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsPresenter.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsState.kt diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsNode.kt index 7dca1f38da..409b2e4af3 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsNode.kt @@ -22,14 +22,13 @@ import com.bumble.appyx.core.plugin.Plugin import dagger.assisted.Assisted import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode -import io.element.android.features.preferences.impl.developer.DeveloperSettingsPresenter import io.element.android.libraries.di.SessionScope @ContributesNode(SessionScope::class) class NotificationsSettingsNode @AssistedInject constructor( @Assisted buildContext: BuildContext, @Assisted plugins: List, - private val presenter: DeveloperSettingsPresenter, + private val presenter: NotificationsSettingsPresenter, ) : Node(buildContext, plugins = plugins) { } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsPresenter.kt new file mode 100644 index 0000000000..03be72757f --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsPresenter.kt @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.notifications + +import androidx.compose.runtime.Composable +import io.element.android.libraries.architecture.Presenter +import javax.inject.Inject + +class NotificationsSettingsPresenter @Inject constructor() : Presenter { + + @Composable + override fun present(): NotificationsSettingsState { + return NotificationsSettingsState() + } +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsState.kt new file mode 100644 index 0000000000..a0d3499eb6 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsState.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.notifications + +class NotificationsSettingsState { + +} From d1f147d675486034495e9375402be2df477b7638 Mon Sep 17 00:00:00 2001 From: yostyle Date: Tue, 8 Aug 2023 18:10:00 +0200 Subject: [PATCH 005/234] Add view --- .../preferences/AnalyticsPreferencesState.kt | 1 - .../NotificationsSettingsPresenter.kt | 7 +- .../NotificationsSettingsState.kt | 10 +- .../NotificationsSettingsStateProvider.kt | 33 +++++ .../NotificationsSettingsView.kt | 117 ++++++++++++++++++ 5 files changed, 163 insertions(+), 5 deletions(-) create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsStateProvider.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsView.kt diff --git a/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/preferences/AnalyticsPreferencesState.kt b/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/preferences/AnalyticsPreferencesState.kt index 7cf0f51dfd..11622ea20d 100644 --- a/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/preferences/AnalyticsPreferencesState.kt +++ b/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/preferences/AnalyticsPreferencesState.kt @@ -21,5 +21,4 @@ import io.element.android.features.analytics.api.AnalyticsOptInEvents data class AnalyticsPreferencesState( val applicationName: String, val isEnabled: Boolean, - val eventSink: (AnalyticsOptInEvents) -> Unit, ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsPresenter.kt index 03be72757f..e9ed425e40 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsPresenter.kt @@ -24,6 +24,11 @@ class NotificationsSettingsPresenter @Inject constructor() : Presenter Unit, +) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsStateProvider.kt new file mode 100644 index 0000000000..5d74a519e9 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsStateProvider.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.notifications + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider + +open class NotificationsSettingsStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + aNotificationsSettingsState(), + ) +} + +fun aNotificationsSettingsState() = NotificationsSettingsState( + isEnabled = true, + hasSystemPermission = false, + notifyMeOnRoom = true, + acceptCalls = true +) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsView.kt new file mode 100644 index 0000000000..7b0fb6aa46 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsView.kt @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.notifications + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.NotificationsOff +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory +import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch +import io.element.android.libraries.designsystem.components.preferences.PreferenceText +import io.element.android.libraries.designsystem.components.preferences.PreferenceView +import io.element.android.libraries.designsystem.preview.ElementPreviewDark +import io.element.android.libraries.designsystem.preview.ElementPreviewLight +import io.element.android.libraries.ui.strings.CommonStrings + +@Composable +fun NotificationsSettingsView( + state: NotificationsSettingsState, + onBackPressed: () -> Unit, + modifier: Modifier = Modifier, +) { + PreferenceView( + modifier = modifier, + onBackPressed = onBackPressed, + title = stringResource(id = CommonStrings.screen_notification_settings_title) + ) { + + if (state.isEnabled && !state.hasSystemPermission) { + PreferenceText( + icon = Icons.Filled.NotificationsOff, + title = stringResource(id = CommonStrings.screen_notification_settings_system_notifications_turned_off), + subtitle = stringResource(id = CommonStrings.screen_notification_settings_system_notifications_action_required, + stringResource(id = CommonStrings.screen_notification_settings_system_notifications_action_required_content_link)), + onClick = {} + ) + } + + PreferenceSwitch( + modifier = modifier, + title = stringResource(id = CommonStrings.screen_notification_settings_enable_notifications), + isChecked = state.isEnabled, +// onCheckedChange = ::onEnabledChanged, + switchAlignment = Alignment.Top, + ) + + if (state.isEnabled) { + PreferenceCategory(title = stringResource(id = CommonStrings.screen_notification_settings_notification_section_title)) { + PreferenceText( + title = stringResource(id = CommonStrings.screen_notification_settings_group_chats), + subtitle = "All messages" + ) + + PreferenceText( + title = stringResource(id = CommonStrings.screen_notification_settings_direct_chats), + subtitle = "Mentions and Keywords" + ) + } + + PreferenceCategory(title = stringResource(id = CommonStrings.screen_notification_settings_mode_mentions)) { + PreferenceSwitch( + modifier = modifier, + title = stringResource(id = CommonStrings.screen_notification_settings_room_mention_label), + isChecked = state.notifyMeOnRoom, +// onCheckedChange = ::onEnabledChanged, + switchAlignment = Alignment.Top, + ) + } + + PreferenceCategory(title = stringResource(id = CommonStrings.screen_notification_settings_additional_settings_section_title)) { + PreferenceSwitch( + modifier = modifier, + title = stringResource(id = CommonStrings.screen_notification_settings_calls_label), + isChecked = state.acceptCalls, +// onCheckedChange = ::onEnabledChanged, + switchAlignment = Alignment.Top, + ) + } + } + } +} + +@Preview +@Composable +internal fun AboutViewLightPreview(@PreviewParameter(NotificationsSettingsStateProvider::class) state: NotificationsSettingsState) = + ElementPreviewLight { ContentToPreview(state) } + +@Preview +@Composable +internal fun AboutViewDarkPreview(@PreviewParameter(NotificationsSettingsStateProvider::class) state: NotificationsSettingsState) = + ElementPreviewDark { ContentToPreview(state) } + +@Composable +private fun ContentToPreview(state: NotificationsSettingsState) { + NotificationsSettingsView( + state = state, + onBackPressed = {}, + ) +} From 83e45adfa58b86b32faa450e616bcc6f639108b6 Mon Sep 17 00:00:00 2001 From: yostyle Date: Thu, 6 Jul 2023 18:49:14 +0200 Subject: [PATCH 006/234] Add room notification settings --- changelog.d/506.feature | 2 + .../roomdetails/impl/RoomDetailsEvent.kt | 3 + .../roomdetails/impl/RoomDetailsFlowNode.kt | 12 ++ .../roomdetails/impl/RoomDetailsNode.kt | 6 + .../roomdetails/impl/RoomDetailsPresenter.kt | 36 +++- .../roomdetails/impl/RoomDetailsState.kt | 2 + .../impl/RoomDetailsStateProvider.kt | 3 + .../roomdetails/impl/RoomDetailsView.kt | 47 ++++- .../RoomNotificationSettingsEvents.kt | 24 +++ .../RoomNotificationSettingsItem.kt | 49 +++++ .../RoomNotificationSettingsNode.kt | 57 ++++++ .../RoomNotificationSettingsOption.kt | 102 +++++++++++ .../RoomNotificationSettingsPresenter.kt | 95 ++++++++++ .../RoomNotificationSettingsState.kt | 26 +++ .../RoomNotificationSettingsStateProvider.kt | 34 ++++ .../RoomNotificationSettingsView.kt | 169 ++++++++++++++++++ .../components/preferences/PreferenceText.kt | 25 ++- .../libraries/matrix/api/MatrixClient.kt | 2 + .../NotificationSettingsService.kt | 36 ++++ .../libraries/matrix/api/room/MatrixRoom.kt | 5 + .../MatrixRoomNotificationSettingsState.kt | 33 ++++ .../api/room/RoomNotificationSettings.kt | 26 +++ .../libraries/matrix/impl/RustMatrixClient.kt | 6 + .../matrix/impl/di/SessionMatrixModule.kt | 8 + .../RoomNotificationSettingsMapper.kt | 44 +++++ .../RustNotificationSettingsService.kt | 94 ++++++++++ .../matrix/impl/room/RustMatrixRoom.kt | 21 +++ .../libraries/matrix/test/FakeMatrixClient.kt | 4 + .../android/libraries/matrix/test/TestData.kt | 3 + .../FakeNotificationSettingsService.kt | 59 ++++++ .../matrix/test/room/FakeMatrixRoom.kt | 11 ++ 31 files changed, 1037 insertions(+), 7 deletions(-) create mode 100644 changelog.d/506.feature create mode 100644 features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsEvents.kt create mode 100644 features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsItem.kt create mode 100644 features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsNode.kt create mode 100644 features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt create mode 100644 features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt create mode 100644 features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsState.kt create mode 100644 features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsStateProvider.kt create mode 100644 features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomNotificationSettingsState.kt create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomNotificationSettings.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RoomNotificationSettingsMapper.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt create mode 100644 libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt diff --git a/changelog.d/506.feature b/changelog.d/506.feature new file mode 100644 index 0000000000..1b4d7c50cc --- /dev/null +++ b/changelog.d/506.feature @@ -0,0 +1,2 @@ + Add a "Mute" shortcut icon and a "Notifications" section in the room details screen + \ No newline at end of file diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsEvent.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsEvent.kt index b7bb31757e..7abb9d40e7 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsEvent.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsEvent.kt @@ -18,4 +18,7 @@ package io.element.android.features.roomdetails.impl sealed interface RoomDetailsEvent { object LeaveRoom : RoomDetailsEvent + object MuteNotification : RoomDetailsEvent + + object UnmuteNotification : RoomDetailsEvent } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt index 7298e0eda6..a588c9f3a5 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt @@ -33,6 +33,7 @@ import io.element.android.features.roomdetails.impl.edit.RoomDetailsEditNode import io.element.android.features.roomdetails.impl.invite.RoomInviteMembersNode import io.element.android.features.roomdetails.impl.members.RoomMemberListNode import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsNode +import io.element.android.features.roomdetails.impl.notificationsettings.RoomNotificationSettingsNode import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.createNode @@ -66,6 +67,9 @@ class RoomDetailsFlowNode @AssistedInject constructor( @Parcelize object InviteMembers : NavTarget + @Parcelize + object RoomNotificationSettings : NavTarget + @Parcelize data class RoomMemberDetails(val roomMemberId: UserId) : NavTarget } @@ -85,6 +89,10 @@ class RoomDetailsFlowNode @AssistedInject constructor( override fun openInviteMembers() { backstack.push(NavTarget.InviteMembers) } + + override fun openRoomNotificationSettings() { + backstack.push(NavTarget.RoomNotificationSettings) + } } createNode(buildContext, listOf(roomDetailsCallback)) } @@ -110,6 +118,10 @@ class RoomDetailsFlowNode @AssistedInject constructor( createNode(buildContext) } + NavTarget.RoomNotificationSettings -> { + createNode(buildContext) + } + is NavTarget.RoomMemberDetails -> { val plugins = listOf(RoomMemberDetailsNode.RoomMemberDetailsInput(navTarget.roomMemberId)) createNode(buildContext, plugins) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt index b74cf7aaf1..65c2ed0f89 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt @@ -51,6 +51,7 @@ class RoomDetailsNode @AssistedInject constructor( fun openRoomMemberList() fun openInviteMembers() fun editRoomDetails() + fun openRoomNotificationSettings() } private val callbacks = plugins() @@ -67,6 +68,10 @@ class RoomDetailsNode @AssistedInject constructor( callbacks.forEach { it.openRoomMemberList() } } + private fun openRoomNotificationSettings() { + callbacks.forEach { it.openRoomNotificationSettings() } + } + private fun invitePeople() { callbacks.forEach { it.openInviteMembers() } } @@ -133,6 +138,7 @@ class RoomDetailsNode @AssistedInject constructor( onShareRoom = ::onShareRoom, onShareMember = ::onShareMember, openRoomMemberList = ::openRoomMemberList, + openRoomNotificationSettings = ::openRoomNotificationSettings, invitePeople = ::invitePeople, ) } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt index 2612c24365..91d11bfc19 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt @@ -24,30 +24,45 @@ import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.produceState import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import io.element.android.features.leaveroom.api.LeaveRoomEvent import io.element.android.features.leaveroom.api.LeaveRoomPresenter import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsPresenter import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.core.coroutine.CoroutineDispatchers +import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.powerlevels.canInvite import io.element.android.libraries.matrix.api.room.powerlevels.canSendState +import io.element.android.libraries.matrix.api.room.roomNotificationSettings import io.element.android.libraries.matrix.ui.room.getDirectRoomMember +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch import javax.inject.Inject class RoomDetailsPresenter @Inject constructor( + private val client: MatrixClient, private val room: MatrixRoom, + private val notificationSettingsService: NotificationSettingsService, private val roomMembersDetailsPresenterFactory: RoomMemberDetailsPresenter.Factory, private val leaveRoomPresenter: LeaveRoomPresenter, + private val dispatchers: CoroutineDispatchers, ) : Presenter { @Composable override fun present(): RoomDetailsState { + val scope = rememberCoroutineScope() val leaveRoomState = leaveRoomPresenter.present() LaunchedEffect(Unit) { room.updateMembers() + room.updateRoomNotificationSettings() + observeNotificationSettings() } val membersState by room.membersStateFlow.collectAsState() @@ -69,10 +84,22 @@ class RoomDetailsPresenter @Inject constructor( } } + val roomNotificationSettingsState by room.roomNotificationSettingsStateFlow.collectAsState() + fun handleEvents(event: RoomDetailsEvent) { when (event) { - is RoomDetailsEvent.LeaveRoom -> + RoomDetailsEvent.LeaveRoom -> leaveRoomState.eventSink(LeaveRoomEvent.ShowConfirmation(room.roomId)) + RoomDetailsEvent.MuteNotification -> { + scope.launch(dispatchers.io) { + client.notificationSettingsService().muteRoom(room.roomId) + } + } + RoomDetailsEvent.UnmuteNotification -> { + scope.launch(dispatchers.io) { + client.notificationSettingsService().unmuteRoom(room.roomId, room.isEncrypted, room.joinedMemberCount.toULong()) + } + } } } @@ -91,6 +118,7 @@ class RoomDetailsPresenter @Inject constructor( roomType = roomType, roomMemberDetailsState = roomMemberDetailsState, leaveRoomState = leaveRoomState, + roomNotificationSettings = roomNotificationSettingsState.roomNotificationSettings(), eventSink = ::handleEvents, ) } @@ -122,4 +150,10 @@ class RoomDetailsPresenter @Inject constructor( private fun getCanSendState(membersState: MatrixRoomMembersState, type: StateEventType) = produceState(false, membersState) { value = room.canSendState(type).getOrElse { false } } + + private fun CoroutineScope.observeNotificationSettings() { + notificationSettingsService.notificationSettingsChangeFlow.onEach { + room.updateRoomNotificationSettings() + }.launchIn(this) + } } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt index f146181bb6..125f1b8968 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt @@ -19,6 +19,7 @@ package io.element.android.features.roomdetails.impl import io.element.android.features.leaveroom.api.LeaveRoomState import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsState import io.element.android.libraries.matrix.api.room.RoomMember +import io.element.android.libraries.matrix.api.room.RoomNotificationSettings data class RoomDetailsState( val roomId: String, @@ -33,6 +34,7 @@ data class RoomDetailsState( val canEdit: Boolean, val canInvite: Boolean, val leaveRoomState: LeaveRoomState, + val roomNotificationSettings: RoomNotificationSettings?, val eventSink: (RoomDetailsEvent) -> Unit ) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt index cc4c4a6b1b..bafb1923c9 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt @@ -22,6 +22,8 @@ import io.element.android.features.roomdetails.impl.members.details.aRoomMemberD import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMembershipState +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.api.room.RoomNotificationSettings open class RoomDetailsStateProvider : PreviewParameterProvider { override val values: Sequence @@ -78,6 +80,7 @@ fun aRoomDetailsState() = RoomDetailsState( roomType = RoomDetailsType.Room, roomMemberDetailsState = null, leaveRoomState = LeaveRoomState(), + roomNotificationSettings = RoomNotificationSettings(mode = RoomNotificationMode.MUTE, isDefault = false), eventSink = {} ) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt index 51754ca6de..263bb4df12 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt @@ -26,12 +26,15 @@ 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.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material.icons.outlined.Add import androidx.compose.material.icons.outlined.Lock +import androidx.compose.material.icons.outlined.Notifications +import androidx.compose.material.icons.outlined.NotificationsOff import androidx.compose.material.icons.outlined.Person import androidx.compose.material.icons.outlined.PersonAddAlt import androidx.compose.material.icons.outlined.Share @@ -73,6 +76,7 @@ import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.matrix.api.room.RoomMember +import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.ui.strings.CommonStrings @@ -85,6 +89,7 @@ fun RoomDetailsView( onShareRoom: () -> Unit, onShareMember: (RoomMember) -> Unit, openRoomMemberList: () -> Unit, + openRoomNotificationSettings: () -> Unit, invitePeople: () -> Unit, modifier: Modifier = Modifier, ) { @@ -118,7 +123,10 @@ fun RoomDetailsView( roomName = state.roomName, roomAlias = state.roomAlias ) - MainActionsSection(onShareRoom = onShareRoom) + MainActionsSection( + state = state, + onShareRoom = onShareRoom + ) } is RoomDetailsType.Dm -> { @@ -140,6 +148,12 @@ fun RoomDetailsView( ) } + if (state.roomNotificationSettings != null) { + NotificationSection( + state = state, + openRoomNotificationSettings = openRoomNotificationSettings) + } + if (state.roomType is RoomDetailsType.Room) { MembersSection( memberCount = state.memberCount, @@ -209,8 +223,21 @@ internal fun RoomDetailsTopBar( } @Composable -internal fun MainActionsSection(onShareRoom: () -> Unit, modifier: Modifier = Modifier) { +internal fun MainActionsSection(state: RoomDetailsState, onShareRoom: () -> Unit, modifier: Modifier = Modifier) { Row(modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) { + val roomNotificationSettings = state.roomNotificationSettings + if (roomNotificationSettings != null) { + if (roomNotificationSettings.mode == RoomNotificationMode.MUTE) { + MainActionButton(title = stringResource(CommonStrings.common_unmute), icon = Icons.Outlined.NotificationsOff, onClick = { + state.eventSink(RoomDetailsEvent.UnmuteNotification) + }) + } else { + MainActionButton(title = stringResource(CommonStrings.common_mute), icon = Icons.Outlined.Notifications, onClick = { + state.eventSink(RoomDetailsEvent.MuteNotification) + }) + } + } + Spacer(modifier = Modifier.width(20.dp)) MainActionButton(title = stringResource(R.string.screen_room_details_share_room_title), icon = Icons.Outlined.Share, onClick = onShareRoom) } } @@ -276,6 +303,21 @@ internal fun TopicSection( } } +@Composable +internal fun NotificationSection(state: RoomDetailsState, openRoomNotificationSettings: () -> Unit, modifier: Modifier = Modifier) { + state.roomNotificationSettings?.let { + val subtitle = if (it.isDefault) "Default" else "Custom" + PreferenceCategory(modifier = modifier) { + PreferenceText( + title = stringResource(R.string.screen_room_details_notification_title), + subtitle = subtitle, + icon = Icons.Outlined.Notifications, + onClick = openRoomNotificationSettings, + ) + } + } +} + @Composable internal fun MembersSection( memberCount: Long, @@ -348,6 +390,7 @@ private fun ContentToPreview(state: RoomDetailsState) { onShareRoom = {}, onShareMember = {}, openRoomMemberList = {}, + openRoomNotificationSettings = {}, invitePeople = {}, ) } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsEvents.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsEvents.kt new file mode 100644 index 0000000000..4b511a5be0 --- /dev/null +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsEvents.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomdetails.impl.notificationsettings + +import io.element.android.libraries.matrix.api.room.RoomNotificationMode + +sealed interface RoomNotificationSettingsEvents { + data class RoomNotificationModeChanged(val mode: RoomNotificationMode) : RoomNotificationSettingsEvents + object DefaultNotificationModeSelected: RoomNotificationSettingsEvents +} diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsItem.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsItem.kt new file mode 100644 index 0000000000..6ff8b0985b --- /dev/null +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsItem.kt @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomdetails.impl.notificationsettings + +import androidx.compose.runtime.Composable +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.toImmutableList + +data class RoomNotificationSettingsItem( + val mode: RoomNotificationMode, + val title: String, +) + +@Composable +fun roomNotificationSettingsItems(): ImmutableList { + return RoomNotificationMode.values() + .map { + when (it) { + RoomNotificationMode.ALL_MESSAGES -> RoomNotificationSettingsItem( + mode = it, + title = "All messages", + ) + RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> RoomNotificationSettingsItem( + mode = it, + title = "Mentions and keywords", + ) + RoomNotificationMode.MUTE -> RoomNotificationSettingsItem( + mode = it, + title = "Mute", + ) + } + } + .toImmutableList() +} diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsNode.kt new file mode 100644 index 0000000000..d6846343dc --- /dev/null +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsNode.kt @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomdetails.impl.notificationsettings + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.bumble.appyx.core.lifecycle.subscribe +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import im.vector.app.features.analytics.plan.MobileScreen +import io.element.android.anvilannotations.ContributesNode +import io.element.android.libraries.di.RoomScope +import io.element.android.services.analytics.api.AnalyticsService + +@ContributesNode(RoomScope::class) +class RoomNotificationSettingsNode @AssistedInject constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + private val presenter: RoomNotificationSettingsPresenter, + private val analyticsService: AnalyticsService, +) : Node(buildContext, plugins = plugins) { + + init { + lifecycle.subscribe( + onResume = { + analyticsService.screen(MobileScreen(screenName = MobileScreen.ScreenName.RoomNotifications)) + } + ) + } + + @Composable + override fun View(modifier: Modifier) { + val state = presenter.present() + RoomNotificationSettingsView( + state = state, + modifier = modifier, + onBackPressed = { navigateUp() }, + ) + } +} diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt new file mode 100644 index 0000000000..c1eaef5a98 --- /dev/null +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomdetails.impl.notificationsettings + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.selection.selectable +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import io.element.android.libraries.designsystem.preview.ElementPreviewDark +import io.element.android.libraries.designsystem.preview.ElementPreviewLight +import io.element.android.libraries.designsystem.theme.components.RadioButton +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.toEnabledColor + +@Composable +fun RoomNotificationSettingsOption( + roomNotificationSettingsItem: RoomNotificationSettingsItem, + modifier: Modifier = Modifier, + enabled: Boolean = true, + isSelected: Boolean = false, + onOptionSelected: (RoomNotificationSettingsItem) -> Unit = {}, +) { + Row( + modifier + .fillMaxWidth() + .selectable( + selected = isSelected, + onClick = { onOptionSelected(roomNotificationSettingsItem) }, + role = Role.RadioButton, + ) + .padding(8.dp), + ) { + Column( + Modifier + .weight(1f) + .padding(horizontal = 8.dp) + .align(Alignment.CenterVertically) + ) { + Text( + text = roomNotificationSettingsItem.title, + fontSize = 16.sp, + color = enabled.toEnabledColor(), + ) + } + + RadioButton( + modifier = Modifier + .align(Alignment.CenterVertically) + .size(48.dp), + selected = isSelected, + enabled = enabled, + onClick = null // null recommended for accessibility with screenreaders + ) + } +} + +@Preview +@Composable +fun RoomPrivacyOptionLightPreview() = ElementPreviewLight { ContentToPreview() } + +@Preview +@Composable +fun RoomPrivacyOptionDarkPreview() = ElementPreviewDark { ContentToPreview() } + +@Composable +private fun ContentToPreview() { + Column { + RoomNotificationSettingsOption( + roomNotificationSettingsItem = roomNotificationSettingsItems().first(), + isSelected = true, + ) + RoomNotificationSettingsOption( + roomNotificationSettingsItem = roomNotificationSettingsItems().last(), + isSelected = false, + enabled = false, + ) + } +} diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt new file mode 100644 index 0000000000..32f4b860c4 --- /dev/null +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomdetails.impl.notificationsettings + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.saveable.rememberSaveable +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService +import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.api.room.roomNotificationSettings +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch +import javax.inject.Inject + +class RoomNotificationSettingsPresenter @Inject constructor( + private val room: MatrixRoom, + private val notificationSettingsService: NotificationSettingsService, +) : Presenter { + + @Composable + override fun present(): RoomNotificationSettingsState { + val defaultRoomNotificationMode: MutableState = rememberSaveable { + mutableStateOf(null) + } + val localCoroutineScope = rememberCoroutineScope() + + LaunchedEffect(Unit) { + getDefaultRoomNotificationMode(defaultRoomNotificationMode) + observeNotificationSettings() + } + + val roomNotificationSettingsState by room.roomNotificationSettingsStateFlow.collectAsState() + + fun handleEvents(event: RoomNotificationSettingsEvents) { + when (event) { + is RoomNotificationSettingsEvents.RoomNotificationModeChanged -> { + localCoroutineScope.setRoomNotificationMode(event.mode) + } + RoomNotificationSettingsEvents.DefaultNotificationModeSelected -> { + localCoroutineScope.restoreDefaultRoomNotificationMode() + } + } + } + + return RoomNotificationSettingsState( + roomNotificationSettings = roomNotificationSettingsState.roomNotificationSettings(), + defaultRoomNotificationMode = defaultRoomNotificationMode.value, + eventSink = ::handleEvents, + ) + } + + private fun CoroutineScope.observeNotificationSettings() { + notificationSettingsService.notificationSettingsChangeFlow.onEach { + room.updateRoomNotificationSettings() + }.launchIn(this) + } + + private fun CoroutineScope.getDefaultRoomNotificationMode(defaultRoomNotificationMode: MutableState) = launch { + defaultRoomNotificationMode.value = notificationSettingsService.getDefaultRoomNotificationMode( + room.isEncrypted, + room.joinedMemberCount.toULong() + ).getOrThrow() + } + + private fun CoroutineScope.setRoomNotificationMode(mode: RoomNotificationMode) = launch { + notificationSettingsService.setRoomNotificationMode(room.roomId, mode) + } + + private fun CoroutineScope.restoreDefaultRoomNotificationMode() = launch { + notificationSettingsService.restoreDefaultRoomNotificationMode(room.roomId) + } +} diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsState.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsState.kt new file mode 100644 index 0000000000..04742781b5 --- /dev/null +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsState.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomdetails.impl.notificationsettings + +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.api.room.RoomNotificationSettings + +data class RoomNotificationSettingsState( + val roomNotificationSettings: RoomNotificationSettings?, + val defaultRoomNotificationMode: RoomNotificationMode?, + val eventSink: (RoomNotificationSettingsEvents) -> Unit +) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsStateProvider.kt new file mode 100644 index 0000000000..df1dd7977b --- /dev/null +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsStateProvider.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomdetails.impl.notificationsettings + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.api.room.RoomNotificationSettings + +internal class RoomNotificationSettingsStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + RoomNotificationSettingsState( + RoomNotificationSettings( + mode = RoomNotificationMode.MUTE, + isDefault = true), + RoomNotificationMode.ALL_MESSAGES, + eventSink = { }, + ), + ) +} diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt new file mode 100644 index 0000000000..8b661a0e27 --- /dev/null +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomdetails.impl.notificationsettings + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.consumeWindowInsets +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.selection.selectableGroup +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import io.element.android.features.roomdetails.impl.R +import io.element.android.libraries.core.bool.orTrue +import io.element.android.libraries.designsystem.components.button.BackButton +import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory +import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch +import io.element.android.libraries.designsystem.components.preferences.PreferenceText +import io.element.android.libraries.designsystem.preview.ElementPreviewDark +import io.element.android.libraries.designsystem.preview.ElementPreviewLight +import io.element.android.libraries.designsystem.theme.components.CenterAlignedTopAppBar +import io.element.android.libraries.designsystem.theme.components.Scaffold +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.matrix.api.room.RoomNotificationMode + +@OptIn(ExperimentalLayoutApi::class) +@Composable +fun RoomNotificationSettingsView( + state: RoomNotificationSettingsState, + modifier: Modifier = Modifier, + onBackPressed: () -> Unit = {}, +) { + Scaffold( + topBar = { + RoomNotificationSettingsTopBar( + onBackPressed = { onBackPressed() } + ) + } + ) { padding -> + Column( + modifier = modifier + .fillMaxWidth() + .padding(padding) + .consumeWindowInsets(padding), + verticalArrangement = Arrangement.spacedBy(16.dp), + ) { +// PreferenceSwitch( +// isChecked = state.formState.sendLogs, +// onCheckedChange = { eventSink(BugReportEvents.SetSendLog(it)) }, +// enabled = isFormEnabled, +// title = stringResource(id = R.string.screen_bug_report_include_logs), +// subtitle = stringResource(id = R.string.screen_bug_report_logs_description), +// ) + val subtitle = when(state.defaultRoomNotificationMode) { + RoomNotificationMode.ALL_MESSAGES -> "All messages" + RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> "Mentions and keywords" + RoomNotificationMode.MUTE -> "Mute" + null -> "" + } + + + PreferenceCategory(title = "Notify me in this chat for") { + PreferenceSwitch( + isChecked = state.roomNotificationSettings?.isDefault.orTrue(), + onCheckedChange = { + state.eventSink(RoomNotificationSettingsEvents.DefaultNotificationModeSelected) + }, + title = "Match default setting", + subtitle = subtitle, + enabled = state.roomNotificationSettings != null + ) + + PreferenceText( + title = "Allow custom setting", + subtitle = "Turning this on will override yout default setting", + enabled = state.roomNotificationSettings != null && !state.roomNotificationSettings.isDefault, + ) + + if (state.roomNotificationSettings != null) { + RoomNotificationSettingsOptions( + modifier = modifier, + selected = state.roomNotificationSettings.mode, + enabled = !state.roomNotificationSettings.isDefault, + onOptionSelected = { + state.eventSink(RoomNotificationSettingsEvents.RoomNotificationModeChanged(it.mode)) + }, + ) + } + } + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun RoomNotificationSettingsTopBar( + modifier: Modifier = Modifier, + onBackPressed: () -> Unit = {}, +) { + CenterAlignedTopAppBar( + modifier = modifier, + title = { + Text( + text = stringResource(R.string.screen_room_details_notification_title), + fontSize = 16.sp, + fontWeight = FontWeight.SemiBold, + ) + }, + navigationIcon = { BackButton(onClick = onBackPressed) }, + ) +} + +@Composable +fun RoomNotificationSettingsOptions( + selected: RoomNotificationMode?, + modifier: Modifier = Modifier, + enabled: Boolean, + onOptionSelected: (RoomNotificationSettingsItem) -> Unit = {}, +) { + val items = roomNotificationSettingsItems() + Column(modifier = modifier.selectableGroup()) { + items.forEach { item -> + RoomNotificationSettingsOption( + roomNotificationSettingsItem = item, + isSelected = selected == item.mode, + onOptionSelected = onOptionSelected, + enabled = enabled + ) + } + } +} + +@Preview +@Composable +fun RoomNotificationSettingsLightPreview(@PreviewParameter(RoomNotificationSettingsStateProvider::class) state: RoomNotificationSettingsState) = + ElementPreviewLight { ContentToPreview(state) } + +@Preview +@Composable +fun RoomNotificationSettingsDarkPreview(@PreviewParameter(RoomNotificationSettingsStateProvider::class) state: RoomNotificationSettingsState) = + ElementPreviewDark { ContentToPreview(state) } + +@Composable +private fun ContentToPreview(state: RoomNotificationSettingsState) { + RoomNotificationSettingsView(state) +} diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceText.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceText.kt index 3f204ee847..c8ae7487a6 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceText.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceText.kt @@ -28,17 +28,25 @@ import androidx.compose.foundation.progressSemantics import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.BugReport import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.ExperimentalTextApi +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.rememberTextMeasurer import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import io.element.android.libraries.designsystem.components.preferences.components.PreferenceIcon import io.element.android.libraries.designsystem.preview.ElementThemedPreview import io.element.android.libraries.designsystem.preview.PreviewGroup import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.toEnabledColor +import io.element.android.libraries.designsystem.toSecondaryEnabledColor import io.element.android.libraries.theme.ElementTheme /** @@ -48,6 +56,7 @@ import io.element.android.libraries.theme.ElementTheme fun PreferenceText( title: String, modifier: Modifier = Modifier, + enabled: Boolean = true, subtitle: String? = null, currentValue: String? = null, loadingCurrentValue: Boolean = false, @@ -68,8 +77,9 @@ fun PreferenceText( ) { PreferenceIcon( icon = icon, + enabled = enabled, isVisible = showIconAreaIfNoIcon, - tintColor = tintColor ?: ElementTheme.materialColors.secondary + tintColor = tintColor ?: enabled.toSecondaryEnabledColor(), ) Column( modifier = Modifier @@ -79,13 +89,13 @@ fun PreferenceText( Text( style = ElementTheme.typography.fontBodyLgRegular, text = title, - color = tintColor ?: ElementTheme.materialColors.primary, + color = tintColor ?: enabled.toEnabledColor(), ) if (subtitle != null) { Text( style = ElementTheme.typography.fontBodyMdRegular, text = subtitle, - color = tintColor ?: ElementTheme.materialColors.secondary, + color = tintColor ?: enabled.toSecondaryEnabledColor(), ) } } @@ -96,7 +106,7 @@ fun PreferenceText( .padding(start = 16.dp, end = 8.dp), text = currentValue, style = ElementTheme.typography.fontBodyXsMedium, - color = ElementTheme.materialColors.secondary, + color = enabled.toSecondaryEnabledColor(), ) } else if (loadingCurrentValue) { CircularProgressIndicator( @@ -135,6 +145,13 @@ private fun ContentToPreview() { icon = Icons.Default.BugReport, currentValue = "123", ) + PreferenceText( + title = "Title", + subtitle = "Some content", + icon = Icons.Default.BugReport, + currentValue = "123", + enabled = false, + ) PreferenceText( title = "Title", subtitle = "Some content", diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt index be64a3371f..6a76d2bf88 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt @@ -23,6 +23,7 @@ import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters import io.element.android.libraries.matrix.api.media.MatrixMediaLoader import io.element.android.libraries.matrix.api.notification.NotificationService +import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.pusher.PushersService import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.RoomMembershipObserver @@ -49,6 +50,7 @@ interface MatrixClient : Closeable { fun sessionVerificationService(): SessionVerificationService fun pushersService(): PushersService fun notificationService(): NotificationService + fun notificationSettingsService(): NotificationSettingsService suspend fun getCacheSize(): Long /** diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt new file mode 100644 index 0000000000..a0cc4d08fd --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.api.notificationsettings + +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.room.MatrixRoomNotificationSettingsState +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.api.room.RoomNotificationSettings +import kotlinx.coroutines.flow.SharedFlow + +interface NotificationSettingsService { + /** + * State of the current room notification settings flow ([MatrixRoomNotificationSettingsState.Unknown] if not started). + */ + val notificationSettingsChangeFlow : SharedFlow + suspend fun getRoomNotificationSettings(roomId: RoomId): Result + suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, membersCount: ULong): Result + suspend fun setRoomNotificationMode(roomId: RoomId, mode: RoomNotificationMode): Result + suspend fun restoreDefaultRoomNotificationMode(roomId: RoomId): Result + suspend fun muteRoom(roomId: RoomId): Result + suspend fun unmuteRoom(roomId: RoomId, isEncrypted: Boolean, membersCount: ULong): Result +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt index 88d35c83d4..3338990d08 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt @@ -30,6 +30,7 @@ import io.element.android.libraries.matrix.api.media.VideoInfo import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.timeline.MatrixTimeline +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow import java.io.Closeable import java.io.File @@ -56,11 +57,15 @@ interface MatrixRoom : Closeable { */ val membersStateFlow: StateFlow + val roomNotificationSettingsStateFlow: StateFlow + /** * Try to load the room members and update the membersFlow. */ suspend fun updateMembers(): Result + suspend fun updateRoomNotificationSettings(): Result + val syncUpdateFlow: StateFlow val timeline: MatrixTimeline diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomNotificationSettingsState.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomNotificationSettingsState.kt new file mode 100644 index 0000000000..d98a3a83d2 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomNotificationSettingsState.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.api.room + +sealed interface MatrixRoomNotificationSettingsState { + object Unknown : MatrixRoomNotificationSettingsState + data class Pending(val prevRoomNotificationSettings: RoomNotificationSettings? = null) : MatrixRoomNotificationSettingsState + data class Error(val failure: Throwable, val prevRoomNotificationSettings: RoomNotificationSettings? = null) : MatrixRoomNotificationSettingsState + data class Ready(val roomNotificationSettings: RoomNotificationSettings) : MatrixRoomNotificationSettingsState +} + +fun MatrixRoomNotificationSettingsState.roomNotificationSettings(): RoomNotificationSettings? { + return when (this) { + is MatrixRoomNotificationSettingsState.Ready -> roomNotificationSettings + is MatrixRoomNotificationSettingsState.Pending -> prevRoomNotificationSettings + is MatrixRoomNotificationSettingsState.Error -> prevRoomNotificationSettings + else -> null + } +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomNotificationSettings.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomNotificationSettings.kt new file mode 100644 index 0000000000..23f2b41797 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomNotificationSettings.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.api.room + +data class RoomNotificationSettings( + val mode: RoomNotificationMode, + val isDefault: Boolean, +) + +enum class RoomNotificationMode { + ALL_MESSAGES, MENTIONS_AND_KEYWORDS_ONLY, MUTE +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index 4b0afb0b4f..da64259468 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -29,6 +29,7 @@ import io.element.android.libraries.matrix.api.createroom.RoomPreset import io.element.android.libraries.matrix.api.createroom.RoomVisibility import io.element.android.libraries.matrix.api.media.MatrixMediaLoader import io.element.android.libraries.matrix.api.notification.NotificationService +import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.pusher.PushersService import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.RoomMembershipObserver @@ -42,6 +43,7 @@ import io.element.android.libraries.matrix.impl.core.toProgressWatcher import io.element.android.libraries.matrix.impl.mapper.toSessionData import io.element.android.libraries.matrix.impl.media.RustMediaLoader import io.element.android.libraries.matrix.impl.notification.RustNotificationService +import io.element.android.libraries.matrix.impl.notificationsettings.RustNotificationSettingsService import io.element.android.libraries.matrix.impl.pushers.RustPushersService import io.element.android.libraries.matrix.impl.room.RoomContentForwarder import io.element.android.libraries.matrix.impl.room.RustMatrixRoom @@ -103,6 +105,7 @@ class RustMatrixClient constructor( } private val notificationService = RustNotificationService(sessionId, notificationClient, dispatchers, clock) + private val notificationSettingsService = RustNotificationSettingsService(client) private val isLoggingOut = AtomicBoolean(false) @@ -168,6 +171,7 @@ class RustMatrixClient constructor( sessionId = sessionId, roomListItem = roomListItem, innerRoom = fullRoom, + roomNotificationSettingsService = notificationSettingsService, sessionCoroutineScope = sessionCoroutineScope, coroutineDispatchers = dispatchers, systemClock = clock, @@ -272,6 +276,8 @@ class RustMatrixClient constructor( override fun notificationService(): NotificationService = notificationService + override fun notificationSettingsService(): NotificationSettingsService = notificationSettingsService + override fun close() { sessionCoroutineScope.cancel() client.setDelegate(null) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/di/SessionMatrixModule.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/di/SessionMatrixModule.kt index dba1dbd0a3..476f1c3421 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/di/SessionMatrixModule.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/di/SessionMatrixModule.kt @@ -22,6 +22,7 @@ import dagger.Provides import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.media.MatrixMediaLoader +import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.api.verification.SessionVerificationService @@ -35,6 +36,13 @@ object SessionMatrixModule { } @Provides + @SingleIn(SessionScope::class) + fun providesNotificationSettingsService(matrixClient: MatrixClient): NotificationSettingsService { + return matrixClient.notificationSettingsService() + } + + @Provides + @SingleIn(SessionScope::class) fun provideRoomMembershipObserver(matrixClient: MatrixClient): RoomMembershipObserver { return matrixClient.roomMembershipObserver() } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RoomNotificationSettingsMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RoomNotificationSettingsMapper.kt new file mode 100644 index 0000000000..084a6f973e --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RoomNotificationSettingsMapper.kt @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.impl.notificationsettings + +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.api.room.RoomNotificationSettings +import org.matrix.rustcomponents.sdk.RoomNotificationMode as RustRoomNotificationMode +import org.matrix.rustcomponents.sdk.RoomNotificationSettings as RustRoomNotificationSettings + +object RoomNotificationSettingsMapper { + fun map(roomNotificationSettings: RustRoomNotificationSettings): RoomNotificationSettings = + RoomNotificationSettings( + mode = mapMode(roomNotificationSettings.mode), + isDefault = roomNotificationSettings.isDefault + ) + + fun mapMode(mode: RustRoomNotificationMode): RoomNotificationMode = + when (mode) { + RustRoomNotificationMode.ALL_MESSAGES -> RoomNotificationMode.ALL_MESSAGES + RustRoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY + RustRoomNotificationMode.MUTE -> RoomNotificationMode.MUTE + } + + fun mapMode(mode: RoomNotificationMode): RustRoomNotificationMode = + when (mode) { + RoomNotificationMode.ALL_MESSAGES -> RustRoomNotificationMode.ALL_MESSAGES + RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> RustRoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY + RoomNotificationMode.MUTE -> RustRoomNotificationMode.MUTE + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt new file mode 100644 index 0000000000..fa95497a50 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.impl.notificationsettings + +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService +import io.element.android.libraries.matrix.api.room.RoomMembershipObserver +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.api.room.RoomNotificationSettings +import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.channels.trySendBlocking +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.flow.buffer +import kotlinx.coroutines.flow.callbackFlow +import org.matrix.rustcomponents.sdk.Client +import org.matrix.rustcomponents.sdk.NotificationSettings +import org.matrix.rustcomponents.sdk.NotificationSettingsDelegate +import org.matrix.rustcomponents.sdk.RoomNotificationMode as RustRoomNotificationMode + +class RustNotificationSettingsService( + private val client: Client, +) : NotificationSettingsService, NotificationSettingsDelegate { + + private val notificationSettings: NotificationSettings = client.getNotificationSettings() + + private val _notificationSettingsChangeFlow = MutableSharedFlow() + override val notificationSettingsChangeFlow: SharedFlow = _notificationSettingsChangeFlow.asSharedFlow() + +// override val notificationSettingsChangeFlow = callbackFlow { +// val delegate = object:NotificationSettingsDelegate { +// override fun notificationSettingsDidChange() { +// trySendBlocking(Unit) +// } +// } +// send(Unit) +// notificationSettings.setDelegate(delegate) +// awaitClose { +// // notificationSettings.setDelegate(null) +// } +// }.buffer(Channel.UNLIMITED) + + init { + notificationSettings.setDelegate(this) + } + + override suspend fun getRoomNotificationSettings(roomId: RoomId): Result = + runCatching { + notificationSettings.getRoomNotificationMode(roomId.value).let(RoomNotificationSettingsMapper::map) + } + + override suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, membersCount: ULong): Result = + runCatching { + notificationSettings.getDefaultRoomNotificationMode(isEncrypted, membersCount).let(RoomNotificationSettingsMapper::mapMode) + } + + override suspend fun setRoomNotificationMode(roomId: RoomId, mode: RoomNotificationMode): Result = + runCatching { + notificationSettings.setRoomNotificationMode(roomId.value, mode.let(RoomNotificationSettingsMapper::mapMode)) + } + + override suspend fun restoreDefaultRoomNotificationMode(roomId: RoomId): Result = + runCatching { + notificationSettings.restoreDefaultRoomNotificationMode(roomId.value) + } + + override suspend fun muteRoom(roomId: RoomId): Result = setRoomNotificationMode(roomId, RoomNotificationMode.MUTE) + + override suspend fun unmuteRoom(roomId: RoomId, isEncrypted: Boolean, membersCount: ULong) = + runCatching { + notificationSettings.unmuteRoom(roomId.value, isEncrypted, membersCount) + } + + override fun notificationSettingsDidChange() { + _notificationSettingsChangeFlow.tryEmit(Unit) + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt index ffe06379d3..9e425c4d25 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt @@ -33,16 +33,19 @@ import io.element.android.libraries.matrix.api.media.VideoInfo import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState +import io.element.android.libraries.matrix.api.room.MatrixRoomNotificationSettingsState import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.room.roomMembers +import io.element.android.libraries.matrix.api.room.roomNotificationSettings import io.element.android.libraries.matrix.api.timeline.MatrixTimeline import io.element.android.libraries.matrix.api.timeline.item.event.EventType import io.element.android.libraries.matrix.impl.core.toProgressWatcher import io.element.android.libraries.matrix.impl.media.MediaUploadHandlerImpl import io.element.android.libraries.matrix.impl.media.map import io.element.android.libraries.matrix.impl.poll.toInner +import io.element.android.libraries.matrix.impl.notificationsettings.RustNotificationSettingsService import io.element.android.libraries.matrix.impl.room.location.toInner import io.element.android.libraries.matrix.impl.timeline.RustMatrixTimeline import io.element.android.libraries.matrix.impl.util.destroyAll @@ -72,6 +75,7 @@ class RustMatrixRoom( override val sessionId: SessionId, private val roomListItem: RoomListItem, private val innerRoom: Room, + private val roomNotificationSettingsService: RustNotificationSettingsService, sessionCoroutineScope: CoroutineScope, private val coroutineDispatchers: CoroutineDispatchers, private val systemClock: SystemClock, @@ -90,6 +94,10 @@ class RustMatrixRoom( private val roomCoroutineScope = sessionCoroutineScope.childScope(coroutineDispatchers.main, "RoomScope-$roomId") private val _membersStateFlow = MutableStateFlow(MatrixRoomMembersState.Unknown) private val _syncUpdateFlow = MutableStateFlow(0L) + + private val _roomNotificationSettingsStateFlow = MutableStateFlow(MatrixRoomNotificationSettingsState.Unknown) + override val roomNotificationSettingsStateFlow: StateFlow = _roomNotificationSettingsStateFlow + private val _timeline by lazy { RustMatrixTimeline( matrixRoom = this, @@ -197,6 +205,19 @@ class RustMatrixRoom( } } + override suspend fun updateRoomNotificationSettings(): Result = withContext(coroutineDispatchers.io) { + val currentState = _roomNotificationSettingsStateFlow.value + val currentRoomNotificationSettings = currentState.roomNotificationSettings() + _roomNotificationSettingsStateFlow.value = MatrixRoomNotificationSettingsState.Pending(prevRoomNotificationSettings = currentRoomNotificationSettings) + runCatching { + roomNotificationSettingsService.getRoomNotificationSettings(roomId).getOrThrow() + }.map { + _roomNotificationSettingsStateFlow.value = MatrixRoomNotificationSettingsState.Ready(it) + }.onFailure { + _roomNotificationSettingsStateFlow.value = MatrixRoomNotificationSettingsState.Error(prevRoomNotificationSettings = currentRoomNotificationSettings, failure = it) + } + } + override suspend fun userAvatarUrl(userId: UserId): Result = withContext(roomDispatcher) { runCatching { innerRoom.memberAvatarUrl(userId.value) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt index 83f7f3ad79..9ef50ecda5 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt @@ -24,6 +24,7 @@ import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters import io.element.android.libraries.matrix.api.media.MatrixMediaLoader import io.element.android.libraries.matrix.api.notification.NotificationService +import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.pusher.PushersService import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.RoomMembershipObserver @@ -33,6 +34,7 @@ import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.verification.SessionVerificationService import io.element.android.libraries.matrix.test.media.FakeMediaLoader import io.element.android.libraries.matrix.test.notification.FakeNotificationService +import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService import io.element.android.libraries.matrix.test.pushers.FakePushersService import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService @@ -50,6 +52,7 @@ class FakeMatrixClient( private val sessionVerificationService: FakeSessionVerificationService = FakeSessionVerificationService(), private val pushersService: FakePushersService = FakePushersService(), private val notificationService: FakeNotificationService = FakeNotificationService(), + private val notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(), private val syncService: FakeSyncService = FakeSyncService(), private val accountManagementUrlString: Result = Result.success(null), ) : MatrixClient { @@ -142,6 +145,7 @@ class FakeMatrixClient( override fun pushersService(): PushersService = pushersService override fun notificationService(): NotificationService = notificationService + override fun notificationSettingsService(): NotificationSettingsService = notificationSettingsService override fun roomMembershipObserver(): RoomMembershipObserver { return RoomMembershipObserver() diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt index 677774afe4..c5ea7f1106 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt @@ -24,6 +24,8 @@ import io.element.android.libraries.matrix.api.core.SpaceId import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.core.TransactionId import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.api.room.RoomNotificationSettings const val A_USER_NAME = "alice" const val A_PASSWORD = "password" @@ -51,6 +53,7 @@ const val A_HOMESERVER_URL_2 = "matrix-client.org" val A_HOMESERVER = MatrixHomeServerDetails(A_HOMESERVER_URL, supportsPasswordLogin = true, supportsOidcLogin = false) val A_HOMESERVER_OIDC = MatrixHomeServerDetails(A_HOMESERVER_URL, supportsPasswordLogin = false, supportsOidcLogin = true) +val A_ROOM_NOTIFICATION_SETTINGS = RoomNotificationSettings(mode = RoomNotificationMode.MUTE, isDefault = false) const val AN_AVATAR_URL = "mxc://data" diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt new file mode 100644 index 0000000000..298e4af241 --- /dev/null +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.test.notificationsettings + +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.api.room.RoomNotificationSettings +import io.element.android.libraries.matrix.test.A_ROOM_NOTIFICATION_SETTINGS +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharedFlow + +class FakeNotificationSettingsService : NotificationSettingsService { + private var _roomNotificationSettingsStateFlow = MutableStateFlow(Unit) + private val muteRoomResult: Result = Result.success(Unit) + private val unmuteRoomResult: Result = Result.success(Unit) + private val getRoomNotificationSettingsResult: Result = Result.success(A_ROOM_NOTIFICATION_SETTINGS) + override val notificationSettingsChangeFlow: SharedFlow + get() = _roomNotificationSettingsStateFlow + + override suspend fun getRoomNotificationSettings(roomId: RoomId): Result { + return getRoomNotificationSettingsResult + } + + override suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, membersCount: ULong): Result { + TODO("Not yet implemented") + } + + override suspend fun setRoomNotificationMode(roomId: RoomId, mode: RoomNotificationMode): Result { + TODO("Not yet implemented") + } + + override suspend fun restoreDefaultRoomNotificationMode(roomId: RoomId): Result { + TODO("Not yet implemented") + } + + override suspend fun muteRoom(roomId: RoomId): Result { + return muteRoomResult + } + + override suspend fun unmuteRoom(roomId: RoomId, isEncrypted: Boolean, membersCount: ULong): Result { + return unmuteRoomResult + } +} diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index 88f705162e..5f922c234f 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -31,6 +31,7 @@ import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState import io.element.android.libraries.matrix.api.room.MessageEventType +import io.element.android.libraries.matrix.api.room.MatrixRoomNotificationSettingsState import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.timeline.MatrixTimeline @@ -68,6 +69,9 @@ class FakeMatrixRoom( private var userAvatarUrlResult = Result.success(null) private var updateMembersResult: Result = Result.success(Unit) private var joinRoomResult = Result.success(Unit) + private var updateRoomNotificationSettingsResult: Result = Result.success(Unit) + private var acceptInviteResult = Result.success(Unit) + private var rejectInviteResult = Result.success(Unit) private var inviteUserResult = Result.success(Unit) private var canInviteResult = Result.success(true) private var canRedactResult = Result.success(canRedact) @@ -128,10 +132,17 @@ class FakeMatrixRoom( override val membersStateFlow: MutableStateFlow = MutableStateFlow(MatrixRoomMembersState.Unknown) + override val roomNotificationSettingsStateFlow: MutableStateFlow = + MutableStateFlow(MatrixRoomNotificationSettingsState.Unknown) + override suspend fun updateMembers(): Result = simulateLongTask { updateMembersResult } + override suspend fun updateRoomNotificationSettings(): Result = simulateLongTask { + updateRoomNotificationSettingsResult + } + override val syncUpdateFlow: StateFlow = MutableStateFlow(0L) override val timeline: MatrixTimeline = matrixTimeline From 2c81384894b820023e76069f65c7969bbbc0c087 Mon Sep 17 00:00:00 2001 From: yostyle Date: Tue, 18 Jul 2023 11:51:28 +0200 Subject: [PATCH 007/234] Rebase on develop --- .../RoomNotificationSettingsOption.kt | 5 ++--- .../RoomNotificationSettingsView.kt | 12 +++++------- .../NotificationSettingsService.kt | 2 +- .../RustNotificationSettingsService.kt | 14 +++----------- .../libraries/matrix/impl/room/RustMatrixRoom.kt | 2 +- .../FakeNotificationSettingsService.kt | 3 +-- 6 files changed, 13 insertions(+), 25 deletions(-) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt index c1eaef5a98..7cdd74f974 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt @@ -22,19 +22,18 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.selection.selectable -import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.Role import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.theme.components.RadioButton import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.toEnabledColor +import io.element.android.libraries.theme.ElementTheme @Composable fun RoomNotificationSettingsOption( @@ -62,7 +61,7 @@ fun RoomNotificationSettingsOption( ) { Text( text = roomNotificationSettingsItem.title, - fontSize = 16.sp, + style = ElementTheme.typography.fontBodyLgRegular, color = enabled.toEnabledColor(), ) } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt index 8b661a0e27..7c9bf11fc6 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt @@ -26,13 +26,10 @@ import androidx.compose.foundation.selection.selectableGroup import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import io.element.android.features.roomdetails.impl.R import io.element.android.libraries.core.bool.orTrue import io.element.android.libraries.designsystem.components.button.BackButton @@ -41,10 +38,12 @@ import io.element.android.libraries.designsystem.components.preferences.Preferen import io.element.android.libraries.designsystem.components.preferences.PreferenceText import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewLight -import io.element.android.libraries.designsystem.theme.components.CenterAlignedTopAppBar +import io.element.android.libraries.designsystem.theme.aliasScreenTitle import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.theme.ElementTheme @OptIn(ExperimentalLayoutApi::class) @Composable @@ -120,13 +119,12 @@ fun RoomNotificationSettingsTopBar( modifier: Modifier = Modifier, onBackPressed: () -> Unit = {}, ) { - CenterAlignedTopAppBar( + TopAppBar( modifier = modifier, title = { Text( text = stringResource(R.string.screen_room_details_notification_title), - fontSize = 16.sp, - fontWeight = FontWeight.SemiBold, + style = ElementTheme.typography.aliasScreenTitle, ) }, navigationIcon = { BackButton(onClick = onBackPressed) }, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt index a0cc4d08fd..b24fffdd4f 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt @@ -27,7 +27,7 @@ interface NotificationSettingsService { * State of the current room notification settings flow ([MatrixRoomNotificationSettingsState.Unknown] if not started). */ val notificationSettingsChangeFlow : SharedFlow - suspend fun getRoomNotificationSettings(roomId: RoomId): Result + suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, membersCount: ULong): Result suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, membersCount: ULong): Result suspend fun setRoomNotificationMode(roomId: RoomId, mode: RoomNotificationMode): Result suspend fun restoreDefaultRoomNotificationMode(roomId: RoomId): Result diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt index fa95497a50..4ba2f2642e 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt @@ -18,22 +18,14 @@ package io.element.android.libraries.matrix.impl.notificationsettings import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService -import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.RoomNotificationSettings -import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange -import kotlinx.coroutines.channels.Channel -import kotlinx.coroutines.channels.awaitClose -import kotlinx.coroutines.channels.trySendBlocking import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow -import kotlinx.coroutines.flow.buffer -import kotlinx.coroutines.flow.callbackFlow import org.matrix.rustcomponents.sdk.Client import org.matrix.rustcomponents.sdk.NotificationSettings import org.matrix.rustcomponents.sdk.NotificationSettingsDelegate -import org.matrix.rustcomponents.sdk.RoomNotificationMode as RustRoomNotificationMode class RustNotificationSettingsService( private val client: Client, @@ -61,9 +53,9 @@ class RustNotificationSettingsService( notificationSettings.setDelegate(this) } - override suspend fun getRoomNotificationSettings(roomId: RoomId): Result = + override suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, membersCount: ULong): Result = runCatching { - notificationSettings.getRoomNotificationMode(roomId.value).let(RoomNotificationSettingsMapper::map) + notificationSettings.getRoomNotificationSettings(roomId.value, isEncrypted, membersCount).let(RoomNotificationSettingsMapper::map) } override suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, membersCount: ULong): Result = @@ -88,7 +80,7 @@ class RustNotificationSettingsService( notificationSettings.unmuteRoom(roomId.value, isEncrypted, membersCount) } - override fun notificationSettingsDidChange() { + override fun settingsDidChange() { _notificationSettingsChangeFlow.tryEmit(Unit) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt index 9e425c4d25..8db300548f 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt @@ -210,7 +210,7 @@ class RustMatrixRoom( val currentRoomNotificationSettings = currentState.roomNotificationSettings() _roomNotificationSettingsStateFlow.value = MatrixRoomNotificationSettingsState.Pending(prevRoomNotificationSettings = currentRoomNotificationSettings) runCatching { - roomNotificationSettingsService.getRoomNotificationSettings(roomId).getOrThrow() + roomNotificationSettingsService.getRoomNotificationSettings(roomId, isEncrypted, innerRoom.activeMembersCount()).getOrThrow() }.map { _roomNotificationSettingsStateFlow.value = MatrixRoomNotificationSettingsState.Ready(it) }.onFailure { diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt index 298e4af241..da4c49da69 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt @@ -21,7 +21,6 @@ import io.element.android.libraries.matrix.api.notificationsettings.Notification import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.RoomNotificationSettings import io.element.android.libraries.matrix.test.A_ROOM_NOTIFICATION_SETTINGS -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharedFlow @@ -33,7 +32,7 @@ class FakeNotificationSettingsService : NotificationSettingsService { override val notificationSettingsChangeFlow: SharedFlow get() = _roomNotificationSettingsStateFlow - override suspend fun getRoomNotificationSettings(roomId: RoomId): Result { + override suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, membersCount: ULong): Result { return getRoomNotificationSettingsResult } From 856c674361c5a59254560bc3a590f1309c893248 Mon Sep 17 00:00:00 2001 From: yostyle Date: Tue, 18 Jul 2023 13:49:51 +0200 Subject: [PATCH 008/234] Update unit tests --- .../RoomNotificationSettingsOption.kt | 1 + .../element/android/libraries/matrix/test/TestData.kt | 3 ++- .../FakeNotificationSettingsService.kt | 10 +++++++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt index 7cdd74f974..e0303bf474 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt @@ -48,6 +48,7 @@ fun RoomNotificationSettingsOption( .fillMaxWidth() .selectable( selected = isSelected, + enabled = enabled, onClick = { onOptionSelected(roomNotificationSettingsItem) }, role = Role.RadioButton, ) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt index c5ea7f1106..ed8a7614e4 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt @@ -53,7 +53,8 @@ const val A_HOMESERVER_URL_2 = "matrix-client.org" val A_HOMESERVER = MatrixHomeServerDetails(A_HOMESERVER_URL, supportsPasswordLogin = true, supportsOidcLogin = false) val A_HOMESERVER_OIDC = MatrixHomeServerDetails(A_HOMESERVER_URL, supportsPasswordLogin = false, supportsOidcLogin = true) -val A_ROOM_NOTIFICATION_SETTINGS = RoomNotificationSettings(mode = RoomNotificationMode.MUTE, isDefault = false) +val A_ROOM_NOTIFICATION_MODE = RoomNotificationMode.MUTE +val A_ROOM_NOTIFICATION_SETTINGS = RoomNotificationSettings(mode = A_ROOM_NOTIFICATION_MODE, isDefault = false) const val AN_AVATAR_URL = "mxc://data" diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt index da4c49da69..5166978c3e 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt @@ -20,6 +20,7 @@ import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.RoomNotificationSettings +import io.element.android.libraries.matrix.test.A_ROOM_NOTIFICATION_MODE import io.element.android.libraries.matrix.test.A_ROOM_NOTIFICATION_SETTINGS import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharedFlow @@ -28,7 +29,10 @@ class FakeNotificationSettingsService : NotificationSettingsService { private var _roomNotificationSettingsStateFlow = MutableStateFlow(Unit) private val muteRoomResult: Result = Result.success(Unit) private val unmuteRoomResult: Result = Result.success(Unit) + private val setRoomNotificationMode: Result = Result.success(Unit) + private val restoreDefaultRoomNotificationMode: Result = Result.success(Unit) private val getRoomNotificationSettingsResult: Result = Result.success(A_ROOM_NOTIFICATION_SETTINGS) + private val getDefaultRoomNotificationMode: Result = Result.success(A_ROOM_NOTIFICATION_MODE) override val notificationSettingsChangeFlow: SharedFlow get() = _roomNotificationSettingsStateFlow @@ -37,15 +41,15 @@ class FakeNotificationSettingsService : NotificationSettingsService { } override suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, membersCount: ULong): Result { - TODO("Not yet implemented") + return getDefaultRoomNotificationMode } override suspend fun setRoomNotificationMode(roomId: RoomId, mode: RoomNotificationMode): Result { - TODO("Not yet implemented") + return setRoomNotificationMode } override suspend fun restoreDefaultRoomNotificationMode(roomId: RoomId): Result { - TODO("Not yet implemented") + return restoreDefaultRoomNotificationMode } override suspend fun muteRoom(roomId: RoomId): Result { From a3aac9f66a8eb54be2962244531d604da75026b8 Mon Sep 17 00:00:00 2001 From: yostyle Date: Wed, 19 Jul 2023 15:12:20 +0200 Subject: [PATCH 009/234] Rebase on develop --- .../RoomNotificationSettingsPresenter.kt | 8 ++++++-- .../matrix/impl/di/SessionMatrixModule.kt | 2 -- .../RustNotificationSettingsService.kt | 20 ++++++++++++------- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt index 32f4b860c4..c2528ca6d5 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt @@ -30,9 +30,12 @@ import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.roomNotificationSettings import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.flow.buffer import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch +import timber.log.Timber import javax.inject.Inject class RoomNotificationSettingsPresenter @Inject constructor( @@ -73,8 +76,9 @@ class RoomNotificationSettingsPresenter @Inject constructor( } private fun CoroutineScope.observeNotificationSettings() { - notificationSettingsService.notificationSettingsChangeFlow.onEach { - room.updateRoomNotificationSettings() + notificationSettingsService.notificationSettingsChangeFlow.buffer(Channel.UNLIMITED).onEach { + //room.updateRoomNotificationSettings() + Timber.d("emit is called") }.launchIn(this) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/di/SessionMatrixModule.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/di/SessionMatrixModule.kt index 476f1c3421..1159f668e6 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/di/SessionMatrixModule.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/di/SessionMatrixModule.kt @@ -36,13 +36,11 @@ object SessionMatrixModule { } @Provides - @SingleIn(SessionScope::class) fun providesNotificationSettingsService(matrixClient: MatrixClient): NotificationSettingsService { return matrixClient.notificationSettingsService() } @Provides - @SingleIn(SessionScope::class) fun provideRoomMembershipObserver(matrixClient: MatrixClient): RoomMembershipObserver { return matrixClient.roomMembershipObserver() } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt index 4ba2f2642e..e8342952a9 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt @@ -20,22 +20,32 @@ import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.RoomNotificationSettings +import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow import org.matrix.rustcomponents.sdk.Client import org.matrix.rustcomponents.sdk.NotificationSettings import org.matrix.rustcomponents.sdk.NotificationSettingsDelegate +import timber.log.Timber class RustNotificationSettingsService( private val client: Client, -) : NotificationSettingsService, NotificationSettingsDelegate { +) : NotificationSettingsService { private val notificationSettings: NotificationSettings = client.getNotificationSettings() - private val _notificationSettingsChangeFlow = MutableSharedFlow() + private val _notificationSettingsChangeFlow = MutableSharedFlow(onBufferOverflow = BufferOverflow.DROP_OLDEST) override val notificationSettingsChangeFlow: SharedFlow = _notificationSettingsChangeFlow.asSharedFlow() + private var notificationSettingsDelegate = object : NotificationSettingsDelegate { + override fun settingsDidChange() { + Timber.d("emit ${_notificationSettingsChangeFlow.subscriptionCount.value}") + val ok = _notificationSettingsChangeFlow.tryEmit(Unit) + Timber.d("emit $ok") + } + } + // override val notificationSettingsChangeFlow = callbackFlow { // val delegate = object:NotificationSettingsDelegate { // override fun notificationSettingsDidChange() { @@ -50,7 +60,7 @@ class RustNotificationSettingsService( // }.buffer(Channel.UNLIMITED) init { - notificationSettings.setDelegate(this) + notificationSettings.setDelegate(notificationSettingsDelegate) } override suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, membersCount: ULong): Result = @@ -79,8 +89,4 @@ class RustNotificationSettingsService( runCatching { notificationSettings.unmuteRoom(roomId.value, isEncrypted, membersCount) } - - override fun settingsDidChange() { - _notificationSettingsChangeFlow.tryEmit(Unit) - } } From a61176647684d4840a1830081c7e61d6fa483f0a Mon Sep 17 00:00:00 2001 From: yostyle Date: Tue, 1 Aug 2023 15:20:20 +0200 Subject: [PATCH 010/234] Fix edition --- .../RoomNotificationSettingsEvents.kt | 2 +- .../RoomNotificationSettingsPresenter.kt | 18 ++++++++++-------- .../RoomNotificationSettingsView.kt | 9 +-------- .../RustNotificationSettingsService.kt | 19 ++----------------- 4 files changed, 14 insertions(+), 34 deletions(-) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsEvents.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsEvents.kt index 4b511a5be0..bbe756b154 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsEvents.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsEvents.kt @@ -20,5 +20,5 @@ import io.element.android.libraries.matrix.api.room.RoomNotificationMode sealed interface RoomNotificationSettingsEvents { data class RoomNotificationModeChanged(val mode: RoomNotificationMode) : RoomNotificationSettingsEvents - object DefaultNotificationModeSelected: RoomNotificationSettingsEvents + data class SetNotificationMode(val isDefault: Boolean): RoomNotificationSettingsEvents } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt index c2528ca6d5..0b9442fd47 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt @@ -30,12 +30,9 @@ import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.roomNotificationSettings import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.channels.Channel -import kotlinx.coroutines.flow.buffer import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch -import timber.log.Timber import javax.inject.Inject class RoomNotificationSettingsPresenter @Inject constructor( @@ -62,8 +59,14 @@ class RoomNotificationSettingsPresenter @Inject constructor( is RoomNotificationSettingsEvents.RoomNotificationModeChanged -> { localCoroutineScope.setRoomNotificationMode(event.mode) } - RoomNotificationSettingsEvents.DefaultNotificationModeSelected -> { - localCoroutineScope.restoreDefaultRoomNotificationMode() + is RoomNotificationSettingsEvents.SetNotificationMode -> { + if (event.isDefault) { + localCoroutineScope.restoreDefaultRoomNotificationMode() + } else { + defaultRoomNotificationMode.value?.let { + localCoroutineScope.setRoomNotificationMode(it) + } + } } } } @@ -76,9 +79,8 @@ class RoomNotificationSettingsPresenter @Inject constructor( } private fun CoroutineScope.observeNotificationSettings() { - notificationSettingsService.notificationSettingsChangeFlow.buffer(Channel.UNLIMITED).onEach { - //room.updateRoomNotificationSettings() - Timber.d("emit is called") + notificationSettingsService.notificationSettingsChangeFlow.onEach { + room.updateRoomNotificationSettings() }.launchIn(this) } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt index 7c9bf11fc6..6452b412a0 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt @@ -66,13 +66,6 @@ fun RoomNotificationSettingsView( .consumeWindowInsets(padding), verticalArrangement = Arrangement.spacedBy(16.dp), ) { -// PreferenceSwitch( -// isChecked = state.formState.sendLogs, -// onCheckedChange = { eventSink(BugReportEvents.SetSendLog(it)) }, -// enabled = isFormEnabled, -// title = stringResource(id = R.string.screen_bug_report_include_logs), -// subtitle = stringResource(id = R.string.screen_bug_report_logs_description), -// ) val subtitle = when(state.defaultRoomNotificationMode) { RoomNotificationMode.ALL_MESSAGES -> "All messages" RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> "Mentions and keywords" @@ -85,7 +78,7 @@ fun RoomNotificationSettingsView( PreferenceSwitch( isChecked = state.roomNotificationSettings?.isDefault.orTrue(), onCheckedChange = { - state.eventSink(RoomNotificationSettingsEvents.DefaultNotificationModeSelected) + state.eventSink(RoomNotificationSettingsEvents.SetNotificationMode(it)) }, title = "Match default setting", subtitle = subtitle, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt index e8342952a9..dc2fb33372 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt @@ -35,30 +35,15 @@ class RustNotificationSettingsService( private val notificationSettings: NotificationSettings = client.getNotificationSettings() - private val _notificationSettingsChangeFlow = MutableSharedFlow(onBufferOverflow = BufferOverflow.DROP_OLDEST) + private val _notificationSettingsChangeFlow = MutableSharedFlow(extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST) override val notificationSettingsChangeFlow: SharedFlow = _notificationSettingsChangeFlow.asSharedFlow() private var notificationSettingsDelegate = object : NotificationSettingsDelegate { override fun settingsDidChange() { - Timber.d("emit ${_notificationSettingsChangeFlow.subscriptionCount.value}") - val ok = _notificationSettingsChangeFlow.tryEmit(Unit) - Timber.d("emit $ok") + _notificationSettingsChangeFlow.tryEmit(Unit) } } -// override val notificationSettingsChangeFlow = callbackFlow { -// val delegate = object:NotificationSettingsDelegate { -// override fun notificationSettingsDidChange() { -// trySendBlocking(Unit) -// } -// } -// send(Unit) -// notificationSettings.setDelegate(delegate) -// awaitClose { -// // notificationSettings.setDelegate(null) -// } -// }.buffer(Channel.UNLIMITED) - init { notificationSettings.setDelegate(notificationSettingsDelegate) } From 82c8acd3dca96505ab5769d0d34bfa09fe0bd3a5 Mon Sep 17 00:00:00 2001 From: yostyle Date: Mon, 7 Aug 2023 16:33:45 +0200 Subject: [PATCH 011/234] Update strings --- .../impl/src/main/res/values-ru/translations.xml | 5 +++++ .../RoomNotificationSettingsView.kt | 13 +++++++------ .../impl/src/main/res/values-fr/translations.xml | 10 ++++++++++ .../impl/src/main/res/values-ru/translations.xml | 13 ++++++++++++- .../impl/src/main/res/values-sk/translations.xml | 11 +++++++++++ .../impl/src/main/res/values/localazy.xml | 11 +++++++++++ .../components/preferences/PreferenceText.kt | 6 ------ .../src/main/res/values-ru/translations.xml | 2 +- .../src/main/res/values-sk/translations.xml | 2 -- tools/localazy/config.json | 3 ++- 10 files changed, 59 insertions(+), 17 deletions(-) diff --git a/features/messages/impl/src/main/res/values-ru/translations.xml b/features/messages/impl/src/main/res/values-ru/translations.xml index c3ed526564..996c4d0aa0 100644 --- a/features/messages/impl/src/main/res/values-ru/translations.xml +++ b/features/messages/impl/src/main/res/values-ru/translations.xml @@ -5,6 +5,11 @@ "%1$d изменения в комнате" "%1$d изменений в комнате" + + "одно" + "%1$d" + "более %1$d" + "Камера" "Сделать фото" "Записать видео" diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt index 6452b412a0..b078f29ded 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt @@ -44,6 +44,7 @@ import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.theme.ElementTheme +import io.element.android.libraries.ui.strings.CommonStrings @OptIn(ExperimentalLayoutApi::class) @Composable @@ -67,14 +68,14 @@ fun RoomNotificationSettingsView( verticalArrangement = Arrangement.spacedBy(16.dp), ) { val subtitle = when(state.defaultRoomNotificationMode) { - RoomNotificationMode.ALL_MESSAGES -> "All messages" - RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> "Mentions and keywords" - RoomNotificationMode.MUTE -> "Mute" + RoomNotificationMode.ALL_MESSAGES -> stringResource(id = R.string.screen_room_notification_settings_mode_all_messages) + RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> stringResource(id = R.string.screen_room_notification_settings_mode_mentions_and_keywords) + RoomNotificationMode.MUTE -> stringResource(id = CommonStrings.common_mute) null -> "" } - PreferenceCategory(title = "Notify me in this chat for") { + PreferenceCategory(title = stringResource(id = R.string.screen_room_notification_settings_custom_settings_title)) { PreferenceSwitch( isChecked = state.roomNotificationSettings?.isDefault.orTrue(), onCheckedChange = { @@ -86,8 +87,8 @@ fun RoomNotificationSettingsView( ) PreferenceText( - title = "Allow custom setting", - subtitle = "Turning this on will override yout default setting", + title = stringResource(id = R.string.screen_room_notification_settings_allow_custom), + subtitle = stringResource(id = R.string.screen_room_notification_settings_allow_custom_footnote), enabled = state.roomNotificationSettings != null && !state.roomNotificationSettings.isDefault, ) diff --git a/features/roomdetails/impl/src/main/res/values-fr/translations.xml b/features/roomdetails/impl/src/main/res/values-fr/translations.xml index 2696cc99ea..34fae4fea9 100644 --- a/features/roomdetails/impl/src/main/res/values-fr/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-fr/translations.xml @@ -23,6 +23,16 @@ "Partager le salon" "Mise à jour du salon…" "En attente" + "Autoriser les paramètres personnalisés" + "Activer cette option remplacera votre paramètre par défaut" + "Me notifier dans ce chat pour" + "paramètres généraux" + "Paramètre par défaut" + "Une erreur s’est produite lors du chargement des paramètres de notification." + "Impossible de restaurer le mode par défaut, veuillez réessayer." + "Impossible de régler le mode, veuillez réessayer." + "Tous les messages" + "Mentions et mots-clés uniquement" "Bloquer" "Les utilisateurs bloqués ne pourront pas vous envoyer de messages et tous leurs messages seront masqués. Vous pouvez les débloquer à tout moment." "Bloquer l\'utilisateur" diff --git a/features/roomdetails/impl/src/main/res/values-ru/translations.xml b/features/roomdetails/impl/src/main/res/values-ru/translations.xml index 4d2664ab30..e1fe6dcd90 100644 --- a/features/roomdetails/impl/src/main/res/values-ru/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ru/translations.xml @@ -1,7 +1,7 @@ - "%1$d пользователь" + "1 пользователь" "%1$d пользователя" "%1$d пользователей" @@ -25,6 +25,17 @@ "Обновление комнаты…" "В ожидании" "Участники комнаты" + "Разрешить пользовательские настройки" + "Включение этого параметра отменяет настройки по умолчанию" + "Уведомить меня в этом чате" + "Вы можете изменить его в своем %1$s." + "Основные Настройки" + "Настройка по умолчанию" + "Произошла ошибка при загрузке настроек уведомлений." + "Не удалось восстановить режим по умолчанию, попробуйте еще раз." + "Не удалось настроить режим, попробуйте еще раз." + "Все сообщения" + "Только упоминания и ключевые слова" "Заблокировать" "Заблокированные пользователи не смогут отправлять вам сообщения, а все их сообщения будут скрыты. Вы можете разблокировать их в любое время." "Заблокировать пользователя" diff --git a/features/roomdetails/impl/src/main/res/values-sk/translations.xml b/features/roomdetails/impl/src/main/res/values-sk/translations.xml index 1d744fba30..687c495ce7 100644 --- a/features/roomdetails/impl/src/main/res/values-sk/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-sk/translations.xml @@ -25,6 +25,17 @@ "Aktualizácia miestnosti…" "Čaká sa" "Členovia miestnosti" + "Povoliť vlastné nastavenie" + "Zapnutím tohto nastavenia sa prepíše vaše predvolené nastavenie" + "Upozorniť ma v tejto konverzácii na" + "Môžete to zmeniť vo svojich %1$s." + "všeobecných nastaveniach" + "Predvolené nastavenie" + "Pri načítavaní nastavení oznámení došlo k chybe." + "Nepodarilo sa obnoviť predvolený režim, skúste to prosím znova." + "Nepodarilo sa nastaviť režim, skúste to prosím znova." + "Všetky správy" + "Iba zmienky a kľúčové slová" "Zablokovať" "Blokovaní používatelia vám nebudú môcť posielať správy a všetky ich správy budú skryté. Môžete ich kedykoľvek odblokovať." "Zablokovať používateľa" diff --git a/features/roomdetails/impl/src/main/res/values/localazy.xml b/features/roomdetails/impl/src/main/res/values/localazy.xml index b1f67dab1e..717f503e22 100644 --- a/features/roomdetails/impl/src/main/res/values/localazy.xml +++ b/features/roomdetails/impl/src/main/res/values/localazy.xml @@ -24,6 +24,17 @@ "Updating room…" "Pending" "Room members" + "Allow custom setting" + "Turning this on will override your default setting" + "Notify me in this chat for" + "You can change it in your %1$s." + "global settings" + "Default setting" + "An error occurred while loading notification settings." + "Failed restoring the default mode, please try again." + "Failed setting the mode, please try again." + "All messages" + "Mentions and Keywords only" "Block" "Blocked users won\'t be able to send you messages and all their messages will be hidden. You can unblock them anytime." "Block user" diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceText.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceText.kt index c8ae7487a6..9a5f6b9a41 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceText.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceText.kt @@ -28,18 +28,12 @@ import androidx.compose.foundation.progressSemantics import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.BugReport import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.text.ExperimentalTextApi -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.rememberTextMeasurer import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import io.element.android.libraries.designsystem.components.preferences.components.PreferenceIcon import io.element.android.libraries.designsystem.preview.ElementThemedPreview import io.element.android.libraries.designsystem.preview.PreviewGroup diff --git a/libraries/ui-strings/src/main/res/values-ru/translations.xml b/libraries/ui-strings/src/main/res/values-ru/translations.xml index 77c2df4268..9f6d7322c3 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -163,7 +163,7 @@ "%1$d участников" - "%d голос" + "1 голос" "%d голоса" "%d голосов" diff --git a/libraries/ui-strings/src/main/res/values-sk/translations.xml b/libraries/ui-strings/src/main/res/values-sk/translations.xml index 14dd5626c8..fce3fadd01 100644 --- a/libraries/ui-strings/src/main/res/values-sk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml @@ -183,8 +183,6 @@ "Ďalšie nastavenia" "Audio a video hovory" "Priame konverzácie" - "Pri priamych rozhovoroch ma upozorniť na" - "Pri skupinových rozhovoroch ma upozorniť na" "Povoliť oznámenia na tomto zariadení" "Skupinové rozhovory" "Zmienky" diff --git a/tools/localazy/config.json b/tools/localazy/config.json index fce6b317b5..b2568c7cd4 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -92,7 +92,8 @@ "includeRegex": [ "screen_room_details_.*", "screen_room_member_list_.*", - "screen_dm_details_.*" + "screen_dm_details_.*", + "screen_room_notification_settings_.*" ] }, { From a5b15c40c35bbdd02cc699c0a9ffa430aebdb92f Mon Sep 17 00:00:00 2001 From: yostyle Date: Mon, 7 Aug 2023 17:54:05 +0200 Subject: [PATCH 012/234] Update room details tests --- .../roomdetails/RoomDetailsPresenterTests.kt | 44 ++++++++++++------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt index 08d6a58535..7825f0cbf0 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt @@ -29,6 +29,7 @@ import io.element.android.features.roomdetails.impl.RoomDetailsType import io.element.android.features.roomdetails.impl.RoomTopicState import io.element.android.features.roomdetails.impl.members.aRoomMember import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsPresenter +import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.MatrixRoom @@ -40,6 +41,7 @@ import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.A_USER_ID_2 import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest import org.junit.Test @@ -47,19 +49,27 @@ import org.junit.Test @ExperimentalCoroutinesApi class RoomDetailsPresenterTests { - private fun aRoomDetailsPresenter(room: MatrixRoom, leaveRoomPresenter: LeaveRoomPresenter = LeaveRoomPresenterFake()): RoomDetailsPresenter { + private fun aRoomDetailsPresenter(room: MatrixRoom, leaveRoomPresenter: LeaveRoomPresenter = LeaveRoomPresenterFake(), dispatchers: CoroutineDispatchers): RoomDetailsPresenter { + val matrixClient = FakeMatrixClient() val roomMemberDetailsPresenterFactory = object : RoomMemberDetailsPresenter.Factory { override fun create(roomMemberId: UserId): RoomMemberDetailsPresenter { - return RoomMemberDetailsPresenter(FakeMatrixClient(), room, roomMemberId) + return RoomMemberDetailsPresenter(matrixClient, room, roomMemberId) } } - return RoomDetailsPresenter(room, roomMemberDetailsPresenterFactory, leaveRoomPresenter) + return RoomDetailsPresenter( + matrixClient, + room, + matrixClient.notificationSettingsService(), + roomMemberDetailsPresenterFactory, + leaveRoomPresenter, + dispatchers + ) } @Test fun `present - initial state is created from room info`() = runTest { val room = aMatrixRoom() - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -78,7 +88,7 @@ class RoomDetailsPresenterTests { @Test fun `present - initial state with no room name`() = runTest { val room = aMatrixRoom(name = null) - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -100,7 +110,7 @@ class RoomDetailsPresenterTests { val roomMembers = listOf(myRoomMember, otherRoomMember) givenRoomMembersState(MatrixRoomMembersState.Ready(roomMembers)) } - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -116,7 +126,7 @@ class RoomDetailsPresenterTests { val room = aMatrixRoom().apply { givenCanInviteResult(Result.success(true)) } - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -134,7 +144,7 @@ class RoomDetailsPresenterTests { val room = aMatrixRoom().apply { givenCanInviteResult(Result.success(false)) } - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -147,7 +157,7 @@ class RoomDetailsPresenterTests { val room = aMatrixRoom().apply { givenCanInviteResult(Result.failure(Throwable("Whoops"))) } - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -163,7 +173,7 @@ class RoomDetailsPresenterTests { givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.failure(Throwable("Whelp"))) givenCanInviteResult(Result.success(false)) } - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -192,7 +202,7 @@ class RoomDetailsPresenterTests { givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(true)) givenCanInviteResult(Result.success(false)) } - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -221,7 +231,7 @@ class RoomDetailsPresenterTests { givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.success(true)) } - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -242,7 +252,7 @@ class RoomDetailsPresenterTests { givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(true)) givenCanInviteResult(Result.success(false)) } - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -263,7 +273,7 @@ class RoomDetailsPresenterTests { givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(false)) givenCanInviteResult(Result.success(false)) } - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -279,7 +289,7 @@ class RoomDetailsPresenterTests { givenCanInviteResult(Result.success(false)) } - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -295,7 +305,7 @@ class RoomDetailsPresenterTests { givenCanInviteResult(Result.success(false)) } - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -313,7 +323,7 @@ class RoomDetailsPresenterTests { fun `present - leave room event is passed on to leave room presenter`() = runTest { val leaveRoomPresenter = LeaveRoomPresenterFake() val room = aMatrixRoom() - val presenter = aRoomDetailsPresenter(room, leaveRoomPresenter) + val presenter = aRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { From 4a412ffef2e84a051af08b48739336401f9df1d7 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 8 Aug 2023 08:12:28 +0000 Subject: [PATCH 013/234] Update screenshots --- ...tificationSettingsDarkPreview_0_null_0,NEXUS_5,1.0,en].png | 3 +++ ...ificationSettingsLightPreview_0_null_0,NEXUS_5,1.0,en].png | 3 +++ ...up_RoomPrivacyOptionDarkPreview_0_null,NEXUS_5,1.0,en].png | 3 +++ ...p_RoomPrivacyOptionLightPreview_0_null,NEXUS_5,1.0,en].png | 3 +++ ....impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png | 4 ++-- ...null_Preferences_PreferenceText_0_null,NEXUS_5,1.0,en].png | 4 ++-- 23 files changed, 50 insertions(+), 38 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsDarkPreview_0_null_0,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsLightPreview_0_null_0,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionDarkPreview_0_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview_0_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsDarkPreview_0_null_0,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..65b8a980c1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsDarkPreview_0_null_0,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c57663a744ba0f4540010178555fa292dfe612635d0a63a8171b68edc2b2111e +size 35856 diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsLightPreview_0_null_0,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..49d29b4841 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsLightPreview_0_null_0,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:00aaf1c59bb14f67d646f5b8575945fb5f87597b5c7d2da3ac62db9bc963bab0 +size 39327 diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionDarkPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionDarkPreview_0_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..5c2f5dfcc1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionDarkPreview_0_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:33599a03653428869e9fc4d05b7c5df84c16ca4c88b241ad2dfd953f5549f03b +size 10272 diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview_0_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..0b32d94f0e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview_0_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c21066278c5c4369efce37c0c3a438ad6a16c60301bf93bb8e920930d4bcae60 +size 10535 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png index 77c1b4c04a..0a3a6a39dc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8502e633bb26a506693f80ccd438d47280aeb7bc238f25a3834d06a290e7c2ce -size 54613 +oid sha256:05c4c3c8521dcf15028f844003f78bfb28dd09c66805e87a6a3cb35611fe245c +size 51857 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png index fbcbc79691..2e2650588a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f82980c426b2374c6c7de0c1d0cabc56d721b34660a0bc2902871a6c4556f7d2 -size 45257 +oid sha256:34583e5fbea24bcb5e45dcfc05751d9644720b0cd4b073b7f4ebc5351daf5305 +size 51183 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png index f651181262..6897c3c29a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:15de254bfc9ed30f47d3195a95082af0da1feea68ab703e29ca5c0cdb28533c8 -size 46092 +oid sha256:311ca6ae5f3795e7e65341d23983219386b56e390adadf9c25f2dff5022c62a0 +size 44318 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png index bb20f8c8c4..680eeddcbc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9b94c7bc6ff6b3e525507529b73088e8f73c2f094ad1e521c7c1f1d556c6e935 -size 48496 +oid sha256:637b7d31e9535fdae43f812d57e74bdcad414ac8d4dd9e3736a9defeab027b5c +size 52344 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png index bfec221901..92b3a29c59 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:91062f451f97a21fbf1ca703dc595a093433b02e7ad87651c6b4499cc374143f -size 60188 +oid sha256:858207549f027feeaebb4faf38a4f338bd81453980219225e3a30855127db7c1 +size 49727 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png index e49accd332..1ceb8c9610 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:62925d3679c26248a8a8dd3f71d226cef760e2191ff018d71f482ff302c81980 -size 60411 +oid sha256:3808e9dd6e257c4c4ff3eaf00d547b7bbaeec5265e3acc849646bf017dffc7e6 +size 51380 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png index e49accd332..1ceb8c9610 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:62925d3679c26248a8a8dd3f71d226cef760e2191ff018d71f482ff302c81980 -size 60411 +oid sha256:3808e9dd6e257c4c4ff3eaf00d547b7bbaeec5265e3acc849646bf017dffc7e6 +size 51380 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png index c5e5b9bd70..94efae7996 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6c444b237d087b863b2ee7279a97433c0e66e80f3561e195453625f508075633 -size 49413 +oid sha256:7edfd18330ae8af2702170ac70c02af640f1fbd64fb3a0dc9c98e37e496e77b2 +size 52635 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png index 508dee85bb..0950153454 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d4f35b517edf875a7d9b780e050ff409cef3b1fe15d42571d85256adede78998 -size 54870 +oid sha256:528aa69e661bb486c5c613be3dccc375c705cde19bd044b1c39be508ca10959d +size 52104 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png index b15a56c1e8..7b779ecc40 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fc94103988c32e43ea7cf0f350637641b2a3687ced38eb6a5c9deec449cc5b45 -size 56789 +oid sha256:c518d3c46816b64f613598092849b08ba34e43cb82e9317c98824fa1932fc7ea +size 53234 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png index 54f59b053a..a9f751e3ae 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:375b26ca9b248a7d60aed3c3b1c270971e0c944ae281c03aa33fc40d3c151d32 -size 47297 +oid sha256:f170a23e6855cd1921c9a24fba211a091ab801fbd8dd68f66b7fe0086bfdb8d2 +size 53607 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png index 22a8280dd8..fc7c1b342a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:19607983cd3005f2d187f40f92ff4fe654ee4fe7d1a579246a5c54af34043210 -size 48370 +oid sha256:bc1b26fc7fdd135fd40aaebaeedc58534dd36bf08a888706ad3a06b4bd2e30b3 +size 46576 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png index c417113267..49ab11015a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8835bd5edacdbf3db313af13f811f9d5e832cb0d248e29ca19d46f22a2e995f9 -size 49660 +oid sha256:884fc3f5e223360f7d355669197e437baf7ebc164dae52f7f3ee3dc8e9812ed1 +size 53764 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png index 278b704bbc..de5f1721bf 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7654d7ca36112fa73bbb03904cdb93fdbee9507dcd23c7998659a7f0185eccce -size 62479 +oid sha256:e58089acad2a88d2148e817e788d6cc3eb6a7a8a73ffc22f44d81af4e3c899cb +size 51116 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png index 8a06e354c4..990b58d72f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a0adc2b1ae404c4c1cc54fe70326043df9c68ed23029e679461f2294b6df8f3d -size 62518 +oid sha256:db6c0275cb05e7d2752661d6b20e7da5cbe595850bd9b48fd13d9e086111f0f1 +size 53496 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png index 8a06e354c4..990b58d72f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a0adc2b1ae404c4c1cc54fe70326043df9c68ed23029e679461f2294b6df8f3d -size 62518 +oid sha256:db6c0275cb05e7d2752661d6b20e7da5cbe595850bd9b48fd13d9e086111f0f1 +size 53496 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png index 2070b2135a..008c6be0fb 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2790af60ce68930b750508f433cbea718366ee8efc7a310af10719f0f2fe6c25 -size 50726 +oid sha256:bd55e3de1e7cb632bffffb83085d368af26c0df7c0398c8882d31624a3391d76 +size 54029 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png index 3ad38a0cd5..36d7f1dadc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:062d7de096cebe935df18f5daf9b8bcdf93057d6979659f6bd9ed1ab8d7b0c7f -size 57035 +oid sha256:14337cee877263d02f59009c6e7ff2d730e9df6f9c3824d0ed56bdd6da485755 +size 53509 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.preferences_null_Preferences_PreferenceText_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.preferences_null_Preferences_PreferenceText_0_null,NEXUS_5,1.0,en].png index 15e7b55fa2..a380f808d7 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.preferences_null_Preferences_PreferenceText_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.preferences_null_Preferences_PreferenceText_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:08af9a706d579b4632c70265b6f1529008bd483cb4924c341e3a9f0172cc8cd4 -size 39251 +oid sha256:3af00eb3bc0f8229ca23b49df21b4f0188272175621947e383b74713743f4be0 +size 38735 From 01a0175d40c235da4add1dad44561b2eb4def171 Mon Sep 17 00:00:00 2001 From: yostyle Date: Tue, 8 Aug 2023 10:46:17 +0200 Subject: [PATCH 014/234] Update strings --- .../notificationsettings/RoomNotificationSettingsItem.kt | 9 ++++++--- .../android/libraries/matrix/impl/RustMatrixClient.kt | 3 ++- .../RustNotificationSettingsService.kt | 6 ++---- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsItem.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsItem.kt index 6ff8b0985b..182944c70e 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsItem.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsItem.kt @@ -17,7 +17,10 @@ package io.element.android.features.roomdetails.impl.notificationsettings import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import io.element.android.features.roomdetails.impl.R import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList @@ -33,15 +36,15 @@ fun roomNotificationSettingsItems(): ImmutableList when (it) { RoomNotificationMode.ALL_MESSAGES -> RoomNotificationSettingsItem( mode = it, - title = "All messages", + title = stringResource(R.string.screen_room_notification_settings_mode_all_messages), ) RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> RoomNotificationSettingsItem( mode = it, - title = "Mentions and keywords", + title = stringResource(R.string.screen_room_notification_settings_mode_mentions_and_keywords), ) RoomNotificationMode.MUTE -> RoomNotificationSettingsItem( mode = it, - title = "Mute", + title = stringResource(CommonStrings.common_mute), ) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index da64259468..39fc07d055 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -103,9 +103,10 @@ class RustMatrixClient constructor( private val notificationClient = client.notificationClient().use { builder -> builder.filterByPushRules().finish() } + private val notificationSettings = client.getNotificationSettings() private val notificationService = RustNotificationService(sessionId, notificationClient, dispatchers, clock) - private val notificationSettingsService = RustNotificationSettingsService(client) + private val notificationSettingsService = RustNotificationSettingsService(notificationSettings) private val isLoggingOut = AtomicBoolean(false) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt index dc2fb33372..009cbd25d9 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt @@ -25,16 +25,14 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow import org.matrix.rustcomponents.sdk.Client +import org.matrix.rustcomponents.sdk.NotificationClient import org.matrix.rustcomponents.sdk.NotificationSettings import org.matrix.rustcomponents.sdk.NotificationSettingsDelegate -import timber.log.Timber class RustNotificationSettingsService( - private val client: Client, + private val notificationSettings: NotificationSettings ) : NotificationSettingsService { - private val notificationSettings: NotificationSettings = client.getNotificationSettings() - private val _notificationSettingsChangeFlow = MutableSharedFlow(extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST) override val notificationSettingsChangeFlow: SharedFlow = _notificationSettingsChangeFlow.asSharedFlow() From 0214ca66a6883aa68ab09d547e158379b35637f5 Mon Sep 17 00:00:00 2001 From: yostyle Date: Fri, 11 Aug 2023 14:07:59 +0200 Subject: [PATCH 015/234] Fix PR comments --- .../roomdetails/impl/RoomDetailsPresenter.kt | 2 +- .../features/roomdetails/impl/RoomDetailsView.kt | 6 +++++- .../RoomNotificationSettingsNode.kt | 2 +- .../RoomNotificationSettingsOption.kt | 13 ++++--------- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt index 91d11bfc19..79540e4ee4 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt @@ -60,9 +60,9 @@ class RoomDetailsPresenter @Inject constructor( val scope = rememberCoroutineScope() val leaveRoomState = leaveRoomPresenter.present() LaunchedEffect(Unit) { - room.updateMembers() room.updateRoomNotificationSettings() observeNotificationSettings() + room.updateMembers() } val membersState by room.membersStateFlow.collectAsState() diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt index 263bb4df12..d5f3c99c43 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt @@ -306,7 +306,11 @@ internal fun TopicSection( @Composable internal fun NotificationSection(state: RoomDetailsState, openRoomNotificationSettings: () -> Unit, modifier: Modifier = Modifier) { state.roomNotificationSettings?.let { - val subtitle = if (it.isDefault) "Default" else "Custom" + val subtitle = if (it.isDefault) { + stringResource(R.string.screen_room_details_notification_mode_default) + } else { + stringResource(R.string.screen_room_details_notification_mode_custom) + } PreferenceCategory(modifier = modifier) { PreferenceText( title = stringResource(R.string.screen_room_details_notification_title), diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsNode.kt index d6846343dc..224f850e28 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsNode.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsNode.kt @@ -51,7 +51,7 @@ class RoomNotificationSettingsNode @AssistedInject constructor( RoomNotificationSettingsView( state = state, modifier = modifier, - onBackPressed = { navigateUp() }, + onBackPressed = this::navigateUp, ) } } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt index e0303bf474..bab2558c07 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt @@ -26,10 +26,9 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.Role -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import io.element.android.libraries.designsystem.preview.ElementPreviewDark -import io.element.android.libraries.designsystem.preview.ElementPreviewLight +import io.element.android.libraries.designsystem.preview.DayNightPreviews +import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.theme.components.RadioButton import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.toEnabledColor @@ -78,13 +77,9 @@ fun RoomNotificationSettingsOption( } } -@Preview +@DayNightPreviews @Composable -fun RoomPrivacyOptionLightPreview() = ElementPreviewLight { ContentToPreview() } - -@Preview -@Composable -fun RoomPrivacyOptionDarkPreview() = ElementPreviewDark { ContentToPreview() } +fun RoomPrivacyOptionLightPreview() = ElementPreview { ContentToPreview() } @Composable private fun ContentToPreview() { From 07f36b902db46a4842073f16dab34750c459a0de Mon Sep 17 00:00:00 2001 From: ElementBot Date: Mon, 14 Aug 2023 06:28:14 +0000 Subject: [PATCH 016/234] Update screenshots --- ...tificationSettingsDarkPreview_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ificationSettingsLightPreview_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...up_RoomPrivacyOptionDarkPreview_0_null,NEXUS_5,1.0,en].png | 3 --- ...mPrivacyOptionLightPreview-D-0_1_null,NEXUS_5,1.0,en].png} | 0 ...omPrivacyOptionLightPreview-N-0_2_null,NEXUS_5,1.0,en].png | 3 +++ 5 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionDarkPreview_0_null,NEXUS_5,1.0,en].png rename tests/uitests/src/test/snapshots/images/{io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview_0_null,NEXUS_5,1.0,en].png => io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview-D-0_1_null,NEXUS_5,1.0,en].png} (100%) create mode 100644 tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview-N-0_2_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsDarkPreview_0_null_0,NEXUS_5,1.0,en].png index 65b8a980c1..6c225aab04 100644 --- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsDarkPreview_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsDarkPreview_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c57663a744ba0f4540010178555fa292dfe612635d0a63a8171b68edc2b2111e -size 35856 +oid sha256:4d20b64ea5f339c5856f8180f482cdd914856703a82f1f9709473186c346073c +size 36426 diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsLightPreview_0_null_0,NEXUS_5,1.0,en].png index 49d29b4841..49364f8bda 100644 --- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsLightPreview_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsLightPreview_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:00aaf1c59bb14f67d646f5b8575945fb5f87597b5c7d2da3ac62db9bc963bab0 -size 39327 +oid sha256:db3da8ff68a4279a13c8f9d3d160d5c371c7d18bc8d77b49b7b84e36d6280912 +size 39973 diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionDarkPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionDarkPreview_0_null,NEXUS_5,1.0,en].png deleted file mode 100644 index 5c2f5dfcc1..0000000000 --- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionDarkPreview_0_null,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:33599a03653428869e9fc4d05b7c5df84c16ca4c88b241ad2dfd953f5549f03b -size 10272 diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview-D-0_1_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview_0_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview-D-0_1_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview-N-0_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview-N-0_2_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..61d01c6b68 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview-N-0_2_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3a96c2856b4021f3c1941e4596494363e203d92c697e5e1c698e932f03000f26 +size 9758 From eeb6c3f61c336412253e912b207c22f8c48904a2 Mon Sep 17 00:00:00 2001 From: yostyle Date: Thu, 17 Aug 2023 09:32:06 +0200 Subject: [PATCH 017/234] Add feature flag --- features/roomdetails/impl/build.gradle.kts | 1 + .../roomdetails/impl/RoomDetailsPresenter.kt | 14 ++++++++++++-- .../features/roomdetails/impl/RoomDetailsState.kt | 1 + .../roomdetails/impl/RoomDetailsStateProvider.kt | 1 + .../features/roomdetails/impl/RoomDetailsView.kt | 4 ++-- .../libraries/featureflag/api/FeatureFlags.kt | 4 ++++ .../impl/BuildtimeFeatureFlagProvider.kt | 1 + 7 files changed, 22 insertions(+), 4 deletions(-) diff --git a/features/roomdetails/impl/build.gradle.kts b/features/roomdetails/impl/build.gradle.kts index 0965cf484a..4509018db6 100644 --- a/features/roomdetails/impl/build.gradle.kts +++ b/features/roomdetails/impl/build.gradle.kts @@ -42,6 +42,7 @@ dependencies { implementation(projects.libraries.androidutils) implementation(projects.libraries.mediapickers.api) implementation(projects.libraries.mediaupload.api) + implementation(projects.libraries.featureflag.api) api(projects.features.roomdetails.api) api(projects.libraries.usersearch.api) api(projects.services.apperror.api) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt index 79540e4ee4..b21fe0ca4d 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt @@ -22,6 +22,7 @@ import androidx.compose.runtime.State import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.produceState import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope @@ -30,6 +31,8 @@ import io.element.android.features.leaveroom.api.LeaveRoomPresenter import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsPresenter import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.coroutine.CoroutineDispatchers +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.room.MatrixRoom @@ -49,6 +52,7 @@ import javax.inject.Inject class RoomDetailsPresenter @Inject constructor( private val client: MatrixClient, private val room: MatrixRoom, + private val featureFlagService: FeatureFlagService, private val notificationSettingsService: NotificationSettingsService, private val roomMembersDetailsPresenterFactory: RoomMemberDetailsPresenter.Factory, private val leaveRoomPresenter: LeaveRoomPresenter, @@ -59,9 +63,14 @@ class RoomDetailsPresenter @Inject constructor( override fun present(): RoomDetailsState { val scope = rememberCoroutineScope() val leaveRoomState = leaveRoomPresenter.present() + val canShowNotificationSettings = remember { mutableStateOf(false) } + LaunchedEffect(Unit) { - room.updateRoomNotificationSettings() - observeNotificationSettings() + canShowNotificationSettings.value = featureFlagService.isFeatureEnabled(FeatureFlags.NotificationSettings) + if (canShowNotificationSettings.value) { + room.updateRoomNotificationSettings() + observeNotificationSettings() + } room.updateMembers() } @@ -115,6 +124,7 @@ class RoomDetailsPresenter @Inject constructor( isEncrypted = room.isEncrypted, canInvite = canInvite, canEdit = (canEditAvatar || canEditName || canEditTopic) && roomType == RoomDetailsType.Room, + canShowNotificationSettings = canShowNotificationSettings.value, roomType = roomType, roomMemberDetailsState = roomMemberDetailsState, leaveRoomState = leaveRoomState, diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt index 125f1b8968..21b3b0fe18 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt @@ -33,6 +33,7 @@ data class RoomDetailsState( val roomMemberDetailsState: RoomMemberDetailsState?, val canEdit: Boolean, val canInvite: Boolean, + val canShowNotificationSettings: Boolean, val leaveRoomState: LeaveRoomState, val roomNotificationSettings: RoomNotificationSettings?, val eventSink: (RoomDetailsEvent) -> Unit diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt index bafb1923c9..c580e6d677 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt @@ -77,6 +77,7 @@ fun aRoomDetailsState() = RoomDetailsState( isEncrypted = true, canInvite = false, canEdit = false, + canShowNotificationSettings = true, roomType = RoomDetailsType.Room, roomMemberDetailsState = null, leaveRoomState = LeaveRoomState(), diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt index d5f3c99c43..f5a1146da5 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt @@ -148,7 +148,7 @@ fun RoomDetailsView( ) } - if (state.roomNotificationSettings != null) { + if (state.canShowNotificationSettings && state.roomNotificationSettings != null) { NotificationSection( state = state, openRoomNotificationSettings = openRoomNotificationSettings) @@ -226,7 +226,7 @@ internal fun RoomDetailsTopBar( internal fun MainActionsSection(state: RoomDetailsState, onShareRoom: () -> Unit, modifier: Modifier = Modifier) { Row(modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) { val roomNotificationSettings = state.roomNotificationSettings - if (roomNotificationSettings != null) { + if (state.canShowNotificationSettings && roomNotificationSettings != null) { if (roomNotificationSettings.mode == RoomNotificationMode.MUTE) { MainActionButton(title = stringResource(CommonStrings.common_unmute), icon = Icons.Outlined.NotificationsOff, onClick = { state.eventSink(RoomDetailsEvent.UnmuteNotification) diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt index 176bacb2c4..d881aed257 100644 --- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt +++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt @@ -32,4 +32,8 @@ enum class FeatureFlags( description = "Render poll events in the timeline", defaultValue = false, ) + NotificationSettings( + key = "feature.notificationsettings", + title = "Show notification settings", + ) } diff --git a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/BuildtimeFeatureFlagProvider.kt b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/BuildtimeFeatureFlagProvider.kt index 83913cbac5..0117a4aa22 100644 --- a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/BuildtimeFeatureFlagProvider.kt +++ b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/BuildtimeFeatureFlagProvider.kt @@ -31,6 +31,7 @@ class BuildtimeFeatureFlagProvider @Inject constructor() : when (feature) { FeatureFlags.LocationSharing -> true FeatureFlags.Polls -> false + FeatureFlags.NotificationSettings -> false } } else { false From eefecaec8bf976652028931bcf6768f4b29c5cc6 Mon Sep 17 00:00:00 2001 From: yostyle Date: Thu, 17 Aug 2023 09:46:59 +0200 Subject: [PATCH 018/234] Update strings --- .../messages/impl/src/main/res/values-ru/translations.xml | 5 ----- .../impl/src/main/res/values-ru/translations.xml | 2 +- .../impl/src/main/res/values-zh-rTW/translations.xml | 6 ++++++ .../ui-strings/src/main/res/values-ru/translations.xml | 2 +- .../ui-strings/src/main/res/values-sk/translations.xml | 2 ++ libraries/ui-strings/src/main/res/values/localazy.xml | 5 +++++ 6 files changed, 15 insertions(+), 7 deletions(-) diff --git a/features/messages/impl/src/main/res/values-ru/translations.xml b/features/messages/impl/src/main/res/values-ru/translations.xml index 996c4d0aa0..c3ed526564 100644 --- a/features/messages/impl/src/main/res/values-ru/translations.xml +++ b/features/messages/impl/src/main/res/values-ru/translations.xml @@ -5,11 +5,6 @@ "%1$d изменения в комнате" "%1$d изменений в комнате" - - "одно" - "%1$d" - "более %1$d" - "Камера" "Сделать фото" "Записать видео" diff --git a/features/roomdetails/impl/src/main/res/values-ru/translations.xml b/features/roomdetails/impl/src/main/res/values-ru/translations.xml index e1fe6dcd90..4154f041ff 100644 --- a/features/roomdetails/impl/src/main/res/values-ru/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ru/translations.xml @@ -1,7 +1,7 @@ - "1 пользователь" + "%1$d пользователь" "%1$d пользователя" "%1$d пользователей" diff --git a/features/roomdetails/impl/src/main/res/values-zh-rTW/translations.xml b/features/roomdetails/impl/src/main/res/values-zh-rTW/translations.xml index fb7872844a..7b4eb895ea 100644 --- a/features/roomdetails/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-zh-rTW/translations.xml @@ -18,6 +18,12 @@ "正在更新聊天室…" "待定" "聊天室成員" + "全域設定" + "預設" + "無法重設為預設模式,請再試一次。" + "無法設定模式,請再試一次。" + "所有訊息" + "只限提及與關鍵字" "封鎖" "封鎖使用者" "解除封鎖" diff --git a/libraries/ui-strings/src/main/res/values-ru/translations.xml b/libraries/ui-strings/src/main/res/values-ru/translations.xml index 9f6d7322c3..77c2df4268 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -163,7 +163,7 @@ "%1$d участников" - "1 голос" + "%d голос" "%d голоса" "%d голосов" diff --git a/libraries/ui-strings/src/main/res/values-sk/translations.xml b/libraries/ui-strings/src/main/res/values-sk/translations.xml index fce3fadd01..14dd5626c8 100644 --- a/libraries/ui-strings/src/main/res/values-sk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml @@ -183,6 +183,8 @@ "Ďalšie nastavenia" "Audio a video hovory" "Priame konverzácie" + "Pri priamych rozhovoroch ma upozorniť na" + "Pri skupinových rozhovoroch ma upozorniť na" "Povoliť oznámenia na tomto zariadení" "Skupinové rozhovory" "Zmienky" diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index e38c4fc6b8..aad13c4370 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -1,5 +1,6 @@ + "Use an identity server to invite by email. ""Use the default (%(defaultIdentityServerName)s)"" or manage in ""Settings""." "Hide password" "Send files" "Show password" @@ -157,6 +158,10 @@ "Are you sure that you want to leave this room? This room is not public and you won\'t be able to rejoin without an invite." "Are you sure that you want to leave the room?" "%1$s Android" + + "%(count)s room" + "%(count)s rooms" + "%1$d member" "%1$d members" From 1c4198db5ad8927807b40fde922be9c5bfe5bdc5 Mon Sep 17 00:00:00 2001 From: yostyle Date: Thu, 17 Aug 2023 09:55:05 +0200 Subject: [PATCH 019/234] Update dispatcher --- .../android/libraries/featureflag/api/FeatureFlags.kt | 2 +- .../android/libraries/matrix/impl/RustMatrixClient.kt | 2 +- .../RustNotificationSettingsService.kt | 8 ++++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt index d881aed257..dbbbc0368f 100644 --- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt +++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt @@ -31,7 +31,7 @@ enum class FeatureFlags( title = "Polls", description = "Render poll events in the timeline", defaultValue = false, - ) + ), NotificationSettings( key = "feature.notificationsettings", title = "Show notification settings", diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index 39fc07d055..e3f675cc2b 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -106,7 +106,7 @@ class RustMatrixClient constructor( private val notificationSettings = client.getNotificationSettings() private val notificationService = RustNotificationService(sessionId, notificationClient, dispatchers, clock) - private val notificationSettingsService = RustNotificationSettingsService(notificationSettings) + private val notificationSettingsService = RustNotificationSettingsService(notificationSettings, dispatchers) private val isLoggingOut = AtomicBoolean(false) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt index 009cbd25d9..b15b25c042 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt @@ -16,6 +16,7 @@ package io.element.android.libraries.matrix.impl.notificationsettings +import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.room.RoomNotificationMode @@ -24,13 +25,15 @@ import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.withContext import org.matrix.rustcomponents.sdk.Client import org.matrix.rustcomponents.sdk.NotificationClient import org.matrix.rustcomponents.sdk.NotificationSettings import org.matrix.rustcomponents.sdk.NotificationSettingsDelegate class RustNotificationSettingsService( - private val notificationSettings: NotificationSettings + private val notificationSettings: NotificationSettings, + private val dispatchers: CoroutineDispatchers, ) : NotificationSettingsService { private val _notificationSettingsChangeFlow = MutableSharedFlow(extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST) @@ -56,10 +59,11 @@ class RustNotificationSettingsService( notificationSettings.getDefaultRoomNotificationMode(isEncrypted, membersCount).let(RoomNotificationSettingsMapper::mapMode) } - override suspend fun setRoomNotificationMode(roomId: RoomId, mode: RoomNotificationMode): Result = + override suspend fun setRoomNotificationMode(roomId: RoomId, mode: RoomNotificationMode): Result = withContext(dispatchers.io) { runCatching { notificationSettings.setRoomNotificationMode(roomId.value, mode.let(RoomNotificationSettingsMapper::mapMode)) } + } override suspend fun restoreDefaultRoomNotificationMode(roomId: RoomId): Result = runCatching { From 85dd36a681cd00cf32cd4a52118f14f9fa29561c Mon Sep 17 00:00:00 2001 From: yostyle Date: Thu, 17 Aug 2023 11:38:41 +0200 Subject: [PATCH 020/234] Update notification settings service interface to match rust SDK --- .../roomdetails/impl/RoomDetailsPresenter.kt | 2 +- .../RoomNotificationSettingsPresenter.kt | 2 +- .../NotificationSettingsService.kt | 6 +++--- .../RustNotificationSettingsService.kt | 19 +++++++++++++------ .../matrix/impl/room/RustMatrixRoom.kt | 2 +- .../FakeNotificationSettingsService.kt | 6 +++--- 6 files changed, 22 insertions(+), 15 deletions(-) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt index b21fe0ca4d..b12d4710a0 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt @@ -106,7 +106,7 @@ class RoomDetailsPresenter @Inject constructor( } RoomDetailsEvent.UnmuteNotification -> { scope.launch(dispatchers.io) { - client.notificationSettingsService().unmuteRoom(room.roomId, room.isEncrypted, room.joinedMemberCount.toULong()) + client.notificationSettingsService().unmuteRoom(room.roomId, room.isEncrypted, room.activeMemberCount) } } } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt index 0b9442fd47..13b0e00b1e 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt @@ -87,7 +87,7 @@ class RoomNotificationSettingsPresenter @Inject constructor( private fun CoroutineScope.getDefaultRoomNotificationMode(defaultRoomNotificationMode: MutableState) = launch { defaultRoomNotificationMode.value = notificationSettingsService.getDefaultRoomNotificationMode( room.isEncrypted, - room.joinedMemberCount.toULong() + room.activeMemberCount ).getOrThrow() } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt index b24fffdd4f..0f82604aba 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt @@ -27,10 +27,10 @@ interface NotificationSettingsService { * State of the current room notification settings flow ([MatrixRoomNotificationSettingsState.Unknown] if not started). */ val notificationSettingsChangeFlow : SharedFlow - suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, membersCount: ULong): Result - suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, membersCount: ULong): Result + suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, membersCount: Long): Result + suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, membersCount: Long): Result suspend fun setRoomNotificationMode(roomId: RoomId, mode: RoomNotificationMode): Result suspend fun restoreDefaultRoomNotificationMode(roomId: RoomId): Result suspend fun muteRoom(roomId: RoomId): Result - suspend fun unmuteRoom(roomId: RoomId, isEncrypted: Boolean, membersCount: ULong): Result + suspend fun unmuteRoom(roomId: RoomId, isEncrypted: Boolean, membersCount: Long): Result } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt index b15b25c042..aa3fff8608 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt @@ -49,14 +49,14 @@ class RustNotificationSettingsService( notificationSettings.setDelegate(notificationSettingsDelegate) } - override suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, membersCount: ULong): Result = + override suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, membersCount: Long): Result = runCatching { - notificationSettings.getRoomNotificationSettings(roomId.value, isEncrypted, membersCount).let(RoomNotificationSettingsMapper::map) + notificationSettings.getRoomNotificationSettings(roomId.value, isEncrypted, isOneToOne(membersCount)).let(RoomNotificationSettingsMapper::map) } - override suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, membersCount: ULong): Result = + override suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, membersCount: Long): Result = runCatching { - notificationSettings.getDefaultRoomNotificationMode(isEncrypted, membersCount).let(RoomNotificationSettingsMapper::mapMode) + notificationSettings.getDefaultRoomNotificationMode(isEncrypted, isOneToOne(membersCount)).let(RoomNotificationSettingsMapper::mapMode) } override suspend fun setRoomNotificationMode(roomId: RoomId, mode: RoomNotificationMode): Result = withContext(dispatchers.io) { @@ -72,8 +72,15 @@ class RustNotificationSettingsService( override suspend fun muteRoom(roomId: RoomId): Result = setRoomNotificationMode(roomId, RoomNotificationMode.MUTE) - override suspend fun unmuteRoom(roomId: RoomId, isEncrypted: Boolean, membersCount: ULong) = + override suspend fun unmuteRoom(roomId: RoomId, isEncrypted: Boolean, membersCount: Long) = runCatching { - notificationSettings.unmuteRoom(roomId.value, isEncrypted, membersCount) + notificationSettings.unmuteRoom(roomId.value, isEncrypted, isOneToOne(membersCount)) } + + /** + * A one-to-one is a room with exactly 2 members. + * See [the Matrix spec](https://spec.matrix.org/latest/client-server-api/#default-underride-rules). + * @param membersCount The active members count in a room + */ + private fun isOneToOne(membersCount: Long) = membersCount == 2L } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt index 8db300548f..e5cbe76896 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt @@ -210,7 +210,7 @@ class RustMatrixRoom( val currentRoomNotificationSettings = currentState.roomNotificationSettings() _roomNotificationSettingsStateFlow.value = MatrixRoomNotificationSettingsState.Pending(prevRoomNotificationSettings = currentRoomNotificationSettings) runCatching { - roomNotificationSettingsService.getRoomNotificationSettings(roomId, isEncrypted, innerRoom.activeMembersCount()).getOrThrow() + roomNotificationSettingsService.getRoomNotificationSettings(roomId, isEncrypted, activeMemberCount).getOrThrow() }.map { _roomNotificationSettingsStateFlow.value = MatrixRoomNotificationSettingsState.Ready(it) }.onFailure { diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt index 5166978c3e..5e06d08de5 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt @@ -36,11 +36,11 @@ class FakeNotificationSettingsService : NotificationSettingsService { override val notificationSettingsChangeFlow: SharedFlow get() = _roomNotificationSettingsStateFlow - override suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, membersCount: ULong): Result { + override suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, membersCount: Long): Result { return getRoomNotificationSettingsResult } - override suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, membersCount: ULong): Result { + override suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, membersCount: Long): Result { return getDefaultRoomNotificationMode } @@ -56,7 +56,7 @@ class FakeNotificationSettingsService : NotificationSettingsService { return muteRoomResult } - override suspend fun unmuteRoom(roomId: RoomId, isEncrypted: Boolean, membersCount: ULong): Result { + override suspend fun unmuteRoom(roomId: RoomId, isEncrypted: Boolean, membersCount: Long): Result { return unmuteRoomResult } } From 9e17d8f46807c4cc520c6c23322861b85161c8ac Mon Sep 17 00:00:00 2001 From: yostyle Date: Thu, 17 Aug 2023 13:50:49 +0200 Subject: [PATCH 021/234] Fix PR comments --- .../roomdetails/impl/RoomDetailsView.kt | 34 ++++++++++--------- .../libraries/matrix/impl/RustMatrixClient.kt | 2 ++ .../RustNotificationSettingsService.kt | 8 ++--- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt index f5a1146da5..0ad5778cb2 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt @@ -150,7 +150,7 @@ fun RoomDetailsView( if (state.canShowNotificationSettings && state.roomNotificationSettings != null) { NotificationSection( - state = state, + isDefaultMode = state.roomNotificationSettings.isDefault, openRoomNotificationSettings = openRoomNotificationSettings) } @@ -304,21 +304,23 @@ internal fun TopicSection( } @Composable -internal fun NotificationSection(state: RoomDetailsState, openRoomNotificationSettings: () -> Unit, modifier: Modifier = Modifier) { - state.roomNotificationSettings?.let { - val subtitle = if (it.isDefault) { - stringResource(R.string.screen_room_details_notification_mode_default) - } else { - stringResource(R.string.screen_room_details_notification_mode_custom) - } - PreferenceCategory(modifier = modifier) { - PreferenceText( - title = stringResource(R.string.screen_room_details_notification_title), - subtitle = subtitle, - icon = Icons.Outlined.Notifications, - onClick = openRoomNotificationSettings, - ) - } +internal fun NotificationSection( + isDefaultMode: Boolean, + openRoomNotificationSettings: () -> Unit, + modifier: Modifier = Modifier +) { + val subtitle = if (isDefaultMode) { + stringResource(R.string.screen_room_details_notification_mode_default) + } else { + stringResource(R.string.screen_room_details_notification_mode_custom) + } + PreferenceCategory(modifier = modifier) { + PreferenceText( + title = stringResource(R.string.screen_room_details_notification_title), + subtitle = subtitle, + icon = Icons.Outlined.Notifications, + onClick = openRoomNotificationSettings, + ) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index e3f675cc2b..408e0aeef7 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -282,6 +282,8 @@ class RustMatrixClient constructor( override fun close() { sessionCoroutineScope.cancel() client.setDelegate(null) + notificationSettings.setDelegate(null) + notificationSettings.destroy() verificationService.destroy() syncService.destroy() innerRoomListService.destroy() diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt index aa3fff8608..1b1d51214f 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt @@ -26,8 +26,6 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.withContext -import org.matrix.rustcomponents.sdk.Client -import org.matrix.rustcomponents.sdk.NotificationClient import org.matrix.rustcomponents.sdk.NotificationSettings import org.matrix.rustcomponents.sdk.NotificationSettingsDelegate @@ -65,17 +63,19 @@ class RustNotificationSettingsService( } } - override suspend fun restoreDefaultRoomNotificationMode(roomId: RoomId): Result = + override suspend fun restoreDefaultRoomNotificationMode(roomId: RoomId): Result = withContext(dispatchers.io) { runCatching { notificationSettings.restoreDefaultRoomNotificationMode(roomId.value) } + } override suspend fun muteRoom(roomId: RoomId): Result = setRoomNotificationMode(roomId, RoomNotificationMode.MUTE) - override suspend fun unmuteRoom(roomId: RoomId, isEncrypted: Boolean, membersCount: Long) = + override suspend fun unmuteRoom(roomId: RoomId, isEncrypted: Boolean, membersCount: Long) = withContext(dispatchers.io) { runCatching { notificationSettings.unmuteRoom(roomId.value, isEncrypted, isOneToOne(membersCount)) } + } /** * A one-to-one is a room with exactly 2 members. From f247337fce2b27aec6f2f9d34b323cd5c3ddeec2 Mon Sep 17 00:00:00 2001 From: yostyle Date: Thu, 17 Aug 2023 14:12:23 +0200 Subject: [PATCH 022/234] Fix tests --- features/roomdetails/impl/build.gradle.kts | 1 + .../features/roomdetails/RoomDetailsPresenterTests.kt | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/features/roomdetails/impl/build.gradle.kts b/features/roomdetails/impl/build.gradle.kts index 4509018db6..2137b1401d 100644 --- a/features/roomdetails/impl/build.gradle.kts +++ b/features/roomdetails/impl/build.gradle.kts @@ -60,6 +60,7 @@ dependencies { testImplementation(projects.libraries.mediaupload.test) testImplementation(projects.libraries.mediapickers.test) testImplementation(projects.libraries.usersearch.test) + testImplementation(projects.libraries.featureflag.test) testImplementation(projects.tests.testutils) testImplementation(projects.features.leaveroom.fake) diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt index 7825f0cbf0..1b8c425289 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt @@ -30,6 +30,8 @@ import io.element.android.features.roomdetails.impl.RoomTopicState import io.element.android.features.roomdetails.impl.members.aRoomMember import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsPresenter import io.element.android.libraries.core.coroutine.CoroutineDispatchers +import io.element.android.libraries.featureflag.api.FeatureFlags +import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.MatrixRoom @@ -56,9 +58,13 @@ class RoomDetailsPresenterTests { return RoomMemberDetailsPresenter(matrixClient, room, roomMemberId) } } + val featureFlagService = FakeFeatureFlagService( + mapOf(FeatureFlags.NotificationSettings.key to true) + ) return RoomDetailsPresenter( matrixClient, room, + featureFlagService, matrixClient.notificationSettingsService(), roomMemberDetailsPresenterFactory, leaveRoomPresenter, From a210945bb15c41894db4f3a60f855bd7f977e170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 17 Aug 2023 15:23:34 +0200 Subject: [PATCH 023/234] Add debouncing to `observeNotificationSettings`. This should conceal a bit the issue with notification settings 'flashing' when we receive an update. --- .../RoomNotificationSettingsPresenter.kt | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt index 13b0e00b1e..d5c88e53d4 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt @@ -30,10 +30,14 @@ import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.roomNotificationSettings import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.FlowPreview +import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch +import timber.log.Timber import javax.inject.Inject +import kotlin.time.Duration.Companion.seconds class RoomNotificationSettingsPresenter @Inject constructor( private val room: MatrixRoom, @@ -71,6 +75,8 @@ class RoomNotificationSettingsPresenter @Inject constructor( } } + Timber.d("NotifState: $roomNotificationSettingsState") + return RoomNotificationSettingsState( roomNotificationSettings = roomNotificationSettingsState.roomNotificationSettings(), defaultRoomNotificationMode = defaultRoomNotificationMode.value, @@ -78,10 +84,14 @@ class RoomNotificationSettingsPresenter @Inject constructor( ) } + @OptIn(FlowPreview::class) private fun CoroutineScope.observeNotificationSettings() { - notificationSettingsService.notificationSettingsChangeFlow.onEach { - room.updateRoomNotificationSettings() - }.launchIn(this) + notificationSettingsService.notificationSettingsChangeFlow + .debounce(0.5.seconds) + .onEach { + room.updateRoomNotificationSettings() + } + .launchIn(this) } private fun CoroutineScope.getDefaultRoomNotificationMode(defaultRoomNotificationMode: MutableState) = launch { From 4b0f9213d3798be625de31b80a5e94f8f3eed683 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 17 Aug 2023 15:31:14 +0200 Subject: [PATCH 024/234] Fix lint issues --- .../RoomNotificationSettingsOption.kt | 2 +- .../RoomNotificationSettingsView.kt | 10 +++++----- .../features/roomdetails/RoomDetailsPresenterTests.kt | 6 +++++- .../android/libraries/matrix/api/room/MatrixRoom.kt | 1 - .../libraries/matrix/impl/room/RustMatrixRoom.kt | 5 ++++- .../libraries/matrix/test/room/FakeMatrixRoom.kt | 2 -- 6 files changed, 15 insertions(+), 11 deletions(-) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt index bab2558c07..28592b3b7e 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt @@ -79,7 +79,7 @@ fun RoomNotificationSettingsOption( @DayNightPreviews @Composable -fun RoomPrivacyOptionLightPreview() = ElementPreview { ContentToPreview() } +internal fun RoomPrivacyOptionLightPreview() = ElementPreview { ContentToPreview() } @Composable private fun ContentToPreview() { diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt index b078f29ded..3709280477 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt @@ -54,6 +54,7 @@ fun RoomNotificationSettingsView( onBackPressed: () -> Unit = {}, ) { Scaffold( + modifier = modifier, topBar = { RoomNotificationSettingsTopBar( onBackPressed = { onBackPressed() } @@ -61,7 +62,7 @@ fun RoomNotificationSettingsView( } ) { padding -> Column( - modifier = modifier + modifier = Modifier .fillMaxWidth() .padding(padding) .consumeWindowInsets(padding), @@ -94,7 +95,6 @@ fun RoomNotificationSettingsView( if (state.roomNotificationSettings != null) { RoomNotificationSettingsOptions( - modifier = modifier, selected = state.roomNotificationSettings.mode, enabled = !state.roomNotificationSettings.isDefault, onOptionSelected = { @@ -128,8 +128,8 @@ fun RoomNotificationSettingsTopBar( @Composable fun RoomNotificationSettingsOptions( selected: RoomNotificationMode?, - modifier: Modifier = Modifier, enabled: Boolean, + modifier: Modifier = Modifier, onOptionSelected: (RoomNotificationSettingsItem) -> Unit = {}, ) { val items = roomNotificationSettingsItems() @@ -147,12 +147,12 @@ fun RoomNotificationSettingsOptions( @Preview @Composable -fun RoomNotificationSettingsLightPreview(@PreviewParameter(RoomNotificationSettingsStateProvider::class) state: RoomNotificationSettingsState) = +internal fun RoomNotificationSettingsLightPreview(@PreviewParameter(RoomNotificationSettingsStateProvider::class) state: RoomNotificationSettingsState) = ElementPreviewLight { ContentToPreview(state) } @Preview @Composable -fun RoomNotificationSettingsDarkPreview(@PreviewParameter(RoomNotificationSettingsStateProvider::class) state: RoomNotificationSettingsState) = +internal fun RoomNotificationSettingsDarkPreview(@PreviewParameter(RoomNotificationSettingsStateProvider::class) state: RoomNotificationSettingsState) = ElementPreviewDark { ContentToPreview(state) } @Composable diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt index 1b8c425289..c247686219 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt @@ -51,7 +51,11 @@ import org.junit.Test @ExperimentalCoroutinesApi class RoomDetailsPresenterTests { - private fun aRoomDetailsPresenter(room: MatrixRoom, leaveRoomPresenter: LeaveRoomPresenter = LeaveRoomPresenterFake(), dispatchers: CoroutineDispatchers): RoomDetailsPresenter { + private fun aRoomDetailsPresenter( + room: MatrixRoom, + leaveRoomPresenter: LeaveRoomPresenter = LeaveRoomPresenterFake(), + dispatchers: CoroutineDispatchers + ): RoomDetailsPresenter { val matrixClient = FakeMatrixClient() val roomMemberDetailsPresenterFactory = object : RoomMemberDetailsPresenter.Factory { override fun create(roomMemberId: UserId): RoomMemberDetailsPresenter { diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt index 3338990d08..698d996e08 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt @@ -30,7 +30,6 @@ import io.element.android.libraries.matrix.api.media.VideoInfo import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.timeline.MatrixTimeline -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow import java.io.Closeable import java.io.File diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt index e5cbe76896..0305eed0cc 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt @@ -214,7 +214,10 @@ class RustMatrixRoom( }.map { _roomNotificationSettingsStateFlow.value = MatrixRoomNotificationSettingsState.Ready(it) }.onFailure { - _roomNotificationSettingsStateFlow.value = MatrixRoomNotificationSettingsState.Error(prevRoomNotificationSettings = currentRoomNotificationSettings, failure = it) + _roomNotificationSettingsStateFlow.value = MatrixRoomNotificationSettingsState.Error( + prevRoomNotificationSettings = currentRoomNotificationSettings, + failure = it + ) } } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index 5f922c234f..7f4440f9a3 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -70,8 +70,6 @@ class FakeMatrixRoom( private var updateMembersResult: Result = Result.success(Unit) private var joinRoomResult = Result.success(Unit) private var updateRoomNotificationSettingsResult: Result = Result.success(Unit) - private var acceptInviteResult = Result.success(Unit) - private var rejectInviteResult = Result.success(Unit) private var inviteUserResult = Result.success(Unit) private var canInviteResult = Result.success(true) private var canRedactResult = Result.success(canRedact) From 5be6814ee5daeed3503677f307df0cdc1749582e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 17 Aug 2023 16:09:46 +0200 Subject: [PATCH 025/234] Try to fix tests --- .../features/roomdetails/RoomDetailsPresenterTests.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt index c247686219..61da711d51 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt @@ -159,6 +159,8 @@ class RoomDetailsPresenterTests { presenter.present() }.test { assertThat(awaitItem().canInvite).isFalse() + + cancelAndIgnoreRemainingEvents() } } @@ -172,6 +174,8 @@ class RoomDetailsPresenterTests { presenter.present() }.test { assertThat(awaitItem().canInvite).isFalse() + + cancelAndIgnoreRemainingEvents() } } @@ -289,6 +293,8 @@ class RoomDetailsPresenterTests { }.test { // Initially false, and no further events assertThat(awaitItem().canEdit).isFalse() + + cancelAndIgnoreRemainingEvents() } } @@ -305,6 +311,8 @@ class RoomDetailsPresenterTests { }.test { // The initial state is "hidden" and no further state changes happen assertThat(awaitItem().roomTopic).isEqualTo(RoomTopicState.Hidden) + + cancelAndIgnoreRemainingEvents() } } From 538a229fc7784e6d1a24be7ead6f4e2cb4fd7671 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 17 Aug 2023 14:53:47 +0000 Subject: [PATCH 026/234] Update screenshots --- ...tificationSettingsDarkPreview_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ificationSettingsLightPreview_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...omPrivacyOptionLightPreview-D-0_1_null,NEXUS_5,1.0,en].png | 4 ++-- ...omPrivacyOptionLightPreview-N-0_2_null,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png | 4 ++-- ...null_Preferences_PreferenceText_0_null,NEXUS_5,1.0,en].png | 4 ++-- 23 files changed, 46 insertions(+), 46 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsDarkPreview_0_null_0,NEXUS_5,1.0,en].png index 6c225aab04..352d1a95e1 100644 --- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsDarkPreview_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsDarkPreview_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4d20b64ea5f339c5856f8180f482cdd914856703a82f1f9709473186c346073c -size 36426 +oid sha256:7d1c7b862db8afe25dd958c9011de82e1439d298a95ec15a86dfbae0457f7937 +size 36436 diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsLightPreview_0_null_0,NEXUS_5,1.0,en].png index 49364f8bda..4dc3771f2f 100644 --- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsLightPreview_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsLightPreview_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:db3da8ff68a4279a13c8f9d3d160d5c371c7d18bc8d77b49b7b84e36d6280912 -size 39973 +oid sha256:c1900985fb6b9d25eee44af5cdc0c6fcdee994ffc3da8dae5a6e742c3d0b7127 +size 40016 diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview-D-0_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview-D-0_1_null,NEXUS_5,1.0,en].png index 0b32d94f0e..38c517ea47 100644 --- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview-D-0_1_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview-D-0_1_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c21066278c5c4369efce37c0c3a438ad6a16c60301bf93bb8e920930d4bcae60 -size 10535 +oid sha256:62418ebe7afa2c1c7eda2b1251fb189a75527aa7a4289a9478c531fac7dee8bd +size 10666 diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview-N-0_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview-N-0_2_null,NEXUS_5,1.0,en].png index 61d01c6b68..cecfc09f64 100644 --- a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview-N-0_2_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview-N-0_2_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3a96c2856b4021f3c1941e4596494363e203d92c697e5e1c698e932f03000f26 -size 9758 +oid sha256:e5a32b1baaaad0bf266e190084a64b3d382a2d6d472a55b1c3653ee948e100c9 +size 9756 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png index 0a3a6a39dc..27b587680b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:05c4c3c8521dcf15028f844003f78bfb28dd09c66805e87a6a3cb35611fe245c -size 51857 +oid sha256:4e0c2f56556261e230a67520883b44701df6f08cf8233fc71a2940003844faa3 +size 51945 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png index 2e2650588a..40e4c913af 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:34583e5fbea24bcb5e45dcfc05751d9644720b0cd4b073b7f4ebc5351daf5305 -size 51183 +oid sha256:732cb944620c44a48fcbe3a70d5fc5f427283c053bd25bd4a4a303d6276fa0eb +size 51283 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png index 6897c3c29a..88da6c0c95 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:311ca6ae5f3795e7e65341d23983219386b56e390adadf9c25f2dff5022c62a0 -size 44318 +oid sha256:acb6b76239953cb510ac7848e449782022720c1495c93c87326d162c7bd4c55c +size 44390 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png index 680eeddcbc..01e9b8640d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:637b7d31e9535fdae43f812d57e74bdcad414ac8d4dd9e3736a9defeab027b5c -size 52344 +oid sha256:ace15551dd4cbc5420182ed7165074dd1bf95c379f7f98d382eba928a766d1ef +size 52747 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png index 92b3a29c59..79f29d60d9 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:858207549f027feeaebb4faf38a4f338bd81453980219225e3a30855127db7c1 -size 49727 +oid sha256:8f5367624ae4b43f93d54d261937e0118110479564ca6f89f67949596951d243 +size 49777 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png index 1ceb8c9610..c91b29060f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3808e9dd6e257c4c4ff3eaf00d547b7bbaeec5265e3acc849646bf017dffc7e6 -size 51380 +oid sha256:1b86d2aa08e76a8b9cd4c74a03de6781683088116a0eea422787c1c3344a843b +size 51343 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png index 1ceb8c9610..c91b29060f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3808e9dd6e257c4c4ff3eaf00d547b7bbaeec5265e3acc849646bf017dffc7e6 -size 51380 +oid sha256:1b86d2aa08e76a8b9cd4c74a03de6781683088116a0eea422787c1c3344a843b +size 51343 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png index 94efae7996..c8a0cd40da 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7edfd18330ae8af2702170ac70c02af640f1fbd64fb3a0dc9c98e37e496e77b2 -size 52635 +oid sha256:99348af52a09443f557621ea57afda20ea76e572f47553e313a877d0486bc46f +size 53068 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png index 0950153454..1b3b6c3759 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:528aa69e661bb486c5c613be3dccc375c705cde19bd044b1c39be508ca10959d -size 52104 +oid sha256:13762c8b336a89af7a924eafa3eea24b4f193fcbd83564a6dab716d80cf18a0f +size 52166 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png index 7b779ecc40..75e0cd672e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c518d3c46816b64f613598092849b08ba34e43cb82e9317c98824fa1932fc7ea -size 53234 +oid sha256:674f0c52fa19856603915157a4578db1235e109417a903b755e1595945adb3b9 +size 53383 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png index a9f751e3ae..04586f43c5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f170a23e6855cd1921c9a24fba211a091ab801fbd8dd68f66b7fe0086bfdb8d2 -size 53607 +oid sha256:80cda3451466a778252da05114c6f1db0520641d5b5a3412ed8fc43b593cfaa3 +size 53840 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png index fc7c1b342a..0d78d7f0ef 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bc1b26fc7fdd135fd40aaebaeedc58534dd36bf08a888706ad3a06b4bd2e30b3 -size 46576 +oid sha256:2c428774b6365a2a17fe497f9aaa1de8b4ce7ad5ef907dc2ae9aef5cc1dcb5fd +size 46678 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png index 49ab11015a..16f614f322 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:884fc3f5e223360f7d355669197e437baf7ebc164dae52f7f3ee3dc8e9812ed1 -size 53764 +oid sha256:182f3e1fa1ccce51a718b421a405e0768d2069c72357993e02d52082824b2c18 +size 54250 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png index de5f1721bf..b7a28b64bc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e58089acad2a88d2148e817e788d6cc3eb6a7a8a73ffc22f44d81af4e3c899cb -size 51116 +oid sha256:679e7277ece67229a1506c45ec151b0d12c63a3082b406602bf909e1cedc2d57 +size 51392 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png index 990b58d72f..f325cd808d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:db6c0275cb05e7d2752661d6b20e7da5cbe595850bd9b48fd13d9e086111f0f1 -size 53496 +oid sha256:522318ca0416b6b2d440c3282ff1f93b593225b313c85b73c1bdaba4f55759f2 +size 53556 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png index 990b58d72f..f325cd808d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:db6c0275cb05e7d2752661d6b20e7da5cbe595850bd9b48fd13d9e086111f0f1 -size 53496 +oid sha256:522318ca0416b6b2d440c3282ff1f93b593225b313c85b73c1bdaba4f55759f2 +size 53556 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png index 008c6be0fb..f69babbcbe 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bd55e3de1e7cb632bffffb83085d368af26c0df7c0398c8882d31624a3391d76 -size 54029 +oid sha256:b7059167b4526675b8b4c1c3ed226900df50c46064be87c5ae71801386c1b0f2 +size 54554 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png index 36d7f1dadc..a1e86d2acc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:14337cee877263d02f59009c6e7ff2d730e9df6f9c3824d0ed56bdd6da485755 -size 53509 +oid sha256:cc7f8911844eae722d9d858c70524b329e312ade14ac031cc8e7ecb682024c0c +size 53657 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.preferences_null_Preferences_PreferenceText_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.preferences_null_Preferences_PreferenceText_0_null,NEXUS_5,1.0,en].png index a380f808d7..f757da3a86 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.preferences_null_Preferences_PreferenceText_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.preferences_null_Preferences_PreferenceText_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3af00eb3bc0f8229ca23b49df21b4f0188272175621947e383b74713743f4be0 -size 38735 +oid sha256:bd05144d4b3527a44e1c9f3fb92d227ccc38fd7afce5436f32b59f14f0b54e27 +size 39028 From 69905afbd903f1d73e1e6c3d434a0609385a5094 Mon Sep 17 00:00:00 2001 From: yostyle Date: Thu, 24 Aug 2023 15:43:10 +0200 Subject: [PATCH 027/234] Rebase on develop and refactoring --- .../api/preferences/AnalyticsPreferencesState.kt | 1 + .../preferences/impl/PreferencesFlowNode.kt | 12 ++++++------ ...ttingsNode.kt => NotificationSettingsNode.kt} | 16 +++++++++++++--- ...enter.kt => NotificationSettingsPresenter.kt} | 6 +++--- ...ingsState.kt => NotificationSettingsState.kt} | 2 +- ...r.kt => NotificationSettingsStateProvider.kt} | 8 ++++---- ...ttingsView.kt => NotificationSettingsView.kt} | 12 ++++++------ .../preferences/impl/root/PreferencesRootNode.kt | 2 +- .../preferences/impl/root/PreferencesRootView.kt | 2 +- .../impl/tasks/ComputeCacheSizeUseCase.kt | 2 +- 10 files changed, 37 insertions(+), 26 deletions(-) rename features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/{NotificationsSettingsNode.kt => NotificationSettingsNode.kt} (71%) rename features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/{NotificationsSettingsPresenter.kt => NotificationSettingsPresenter.kt} (82%) rename features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/{NotificationsSettingsState.kt => NotificationSettingsState.kt} (95%) rename features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/{NotificationsSettingsStateProvider.kt => NotificationSettingsStateProvider.kt} (76%) rename features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/{NotificationsSettingsView.kt => NotificationSettingsView.kt} (93%) diff --git a/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/preferences/AnalyticsPreferencesState.kt b/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/preferences/AnalyticsPreferencesState.kt index 11622ea20d..7cf0f51dfd 100644 --- a/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/preferences/AnalyticsPreferencesState.kt +++ b/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/preferences/AnalyticsPreferencesState.kt @@ -21,4 +21,5 @@ import io.element.android.features.analytics.api.AnalyticsOptInEvents data class AnalyticsPreferencesState( val applicationName: String, val isEnabled: Boolean, + val eventSink: (AnalyticsOptInEvents) -> Unit, ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt index f6e4a88f87..00684dde13 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt @@ -33,7 +33,7 @@ import io.element.android.features.preferences.api.PreferencesEntryPoint import io.element.android.features.preferences.impl.about.AboutNode import io.element.android.features.preferences.impl.analytics.AnalyticsSettingsNode import io.element.android.features.preferences.impl.developer.DeveloperSettingsNode -import io.element.android.features.preferences.impl.notifications.NotificationsSettingsNode +import io.element.android.features.preferences.impl.notifications.NotificationSettingsNode import io.element.android.features.preferences.impl.root.PreferencesRootNode import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler @@ -68,7 +68,7 @@ class PreferencesFlowNode @AssistedInject constructor( object About : NavTarget @Parcelize - object NotificationsSettings : NavTarget + object NotificationSettings : NavTarget } override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { @@ -95,8 +95,8 @@ class PreferencesFlowNode @AssistedInject constructor( backstack.push(NavTarget.DeveloperSettings) } - override fun onOpenNotificationsSettings() { - backstack.push(NavTarget.NotificationsSettings) + override fun onOpenNotificationSettings() { + backstack.push(NavTarget.NotificationSettings) } } createNode(buildContext, plugins = listOf(callback)) @@ -110,8 +110,8 @@ class PreferencesFlowNode @AssistedInject constructor( NavTarget.AnalyticsSettings -> { createNode(buildContext) } - NavTarget.NotificationsSettings -> { - createNode(buildContext) + NavTarget.NotificationSettings -> { + createNode(buildContext) } } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsNode.kt similarity index 71% rename from features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsNode.kt rename to features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsNode.kt index 409b2e4af3..d0db81ea7a 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsNode.kt @@ -16,6 +16,8 @@ package io.element.android.features.preferences.impl.notifications +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin @@ -25,10 +27,18 @@ import io.element.android.anvilannotations.ContributesNode import io.element.android.libraries.di.SessionScope @ContributesNode(SessionScope::class) -class NotificationsSettingsNode @AssistedInject constructor( +class NotificationSettingsNode @AssistedInject constructor( @Assisted buildContext: BuildContext, @Assisted plugins: List, - private val presenter: NotificationsSettingsPresenter, + private val presenter: NotificationSettingsPresenter, ) : Node(buildContext, plugins = plugins) { - + @Composable + override fun View(modifier: Modifier) { + val state = presenter.present() + NotificationSettingsView( + state = state, + onBackPressed = ::navigateUp, + modifier = modifier + ) + } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt similarity index 82% rename from features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsPresenter.kt rename to features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt index e9ed425e40..255284f003 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt @@ -20,11 +20,11 @@ import androidx.compose.runtime.Composable import io.element.android.libraries.architecture.Presenter import javax.inject.Inject -class NotificationsSettingsPresenter @Inject constructor() : Presenter { +class NotificationSettingsPresenter @Inject constructor() : Presenter { @Composable - override fun present(): NotificationsSettingsState { - return NotificationsSettingsState( + override fun present(): NotificationSettingsState { + return NotificationSettingsState( isEnabled = true, hasSystemPermission = true, notifyMeOnRoom = true, diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsState.kt similarity index 95% rename from features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsState.kt rename to features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsState.kt index 33c9cfc2f0..ca65fcf5d0 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsState.kt @@ -16,7 +16,7 @@ package io.element.android.features.preferences.impl.notifications -data class NotificationsSettingsState( +data class NotificationSettingsState( val hasSystemPermission: Boolean, val isEnabled: Boolean, val notifyMeOnRoom: Boolean, diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsStateProvider.kt similarity index 76% rename from features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsStateProvider.kt rename to features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsStateProvider.kt index 5d74a519e9..c6c72f3acc 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsStateProvider.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsStateProvider.kt @@ -18,14 +18,14 @@ package io.element.android.features.preferences.impl.notifications import androidx.compose.ui.tooling.preview.PreviewParameterProvider -open class NotificationsSettingsStateProvider : PreviewParameterProvider { - override val values: Sequence +open class NotificationSettingsStateProvider : PreviewParameterProvider { + override val values: Sequence get() = sequenceOf( - aNotificationsSettingsState(), + aNotificationSettingsState(), ) } -fun aNotificationsSettingsState() = NotificationsSettingsState( +fun aNotificationSettingsState() = NotificationSettingsState( isEnabled = true, hasSystemPermission = false, notifyMeOnRoom = true, diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt similarity index 93% rename from features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsView.kt rename to features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt index 7b0fb6aa46..8789e70cc5 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationsSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt @@ -33,8 +33,8 @@ import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.ui.strings.CommonStrings @Composable -fun NotificationsSettingsView( - state: NotificationsSettingsState, +fun NotificationSettingsView( + state: NotificationSettingsState, onBackPressed: () -> Unit, modifier: Modifier = Modifier, ) { @@ -100,17 +100,17 @@ fun NotificationsSettingsView( @Preview @Composable -internal fun AboutViewLightPreview(@PreviewParameter(NotificationsSettingsStateProvider::class) state: NotificationsSettingsState) = +internal fun AboutViewLightPreview(@PreviewParameter(NotificationSettingsStateProvider::class) state: NotificationSettingsState) = ElementPreviewLight { ContentToPreview(state) } @Preview @Composable -internal fun AboutViewDarkPreview(@PreviewParameter(NotificationsSettingsStateProvider::class) state: NotificationsSettingsState) = +internal fun AboutViewDarkPreview(@PreviewParameter(NotificationSettingsStateProvider::class) state: NotificationSettingsState) = ElementPreviewDark { ContentToPreview(state) } @Composable -private fun ContentToPreview(state: NotificationsSettingsState) { - NotificationsSettingsView( +private fun ContentToPreview(state: NotificationSettingsState) { + NotificationSettingsView( state = state, onBackPressed = {}, ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt index 09b488294e..0f297d14dd 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt @@ -44,7 +44,7 @@ class PreferencesRootNode @AssistedInject constructor( fun onOpenAnalytics() fun onOpenAbout() fun onOpenDeveloperSettings() - fun onOpenNotificationsSettings() + fun onOpenNotificationSettings() } private fun onOpenBugReport() { 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 7c2e80ef52..d4783cde1f 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 @@ -97,7 +97,7 @@ fun PreferencesRootView( PreferenceText( title = stringResource(id = CommonStrings.screen_notification_settings_title), icon = Icons.Outlined.Notifications, - onClick = onOpenNotificationsSettings, + onClick = onOpenNotificationSettings, ) PreferenceText( title = stringResource(id = CommonStrings.action_report_bug), diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ComputeCacheSizeUseCase.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ComputeCacheSizeUseCase.kt index 661f6493ec..0eb6e5b613 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ComputeCacheSizeUseCase.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ComputeCacheSizeUseCase.kt @@ -18,8 +18,8 @@ package io.element.android.features.preferences.impl.tasks import android.content.Context import com.squareup.anvil.annotations.ContributesBinding -import io.element.android.libraries.androidutils.filesize.FileSizeFormatter import io.element.android.libraries.androidutils.file.getSizeOfFiles +import io.element.android.libraries.androidutils.filesize.FileSizeFormatter import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.di.ApplicationContext import io.element.android.libraries.di.SessionScope From 171f6db338e2900e83e2b219a2594d2cbd67fc1d Mon Sep 17 00:00:00 2001 From: David Langley Date: Wed, 30 Aug 2023 16:54:59 +0100 Subject: [PATCH 028/234] Hide Notification Settings with feature flag and lint - Hide Notification Settings with feature flag - lint --- .../features/preferences/impl/PreferencesFlowNode.kt | 2 +- .../impl/notifications/NotificationSettingsView.kt | 9 +++------ .../impl/root/PreferencesRootPresenter.kt | 9 +++++++++ .../preferences/impl/root/PreferencesRootState.kt | 1 + .../impl/root/PreferencesRootStateProvider.kt | 1 + .../preferences/impl/root/PreferencesRootView.kt | 12 +++++++----- 6 files changed, 22 insertions(+), 12 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt index 51e25fbebf..5470a788e9 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt @@ -69,7 +69,7 @@ class PreferencesFlowNode @AssistedInject constructor( data object About : NavTarget @Parcelize - object NotificationSettings : NavTarget + data object NotificationSettings : NavTarget } override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt index 8789e70cc5..e8c15f6843 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt @@ -55,10 +55,9 @@ fun NotificationSettingsView( } PreferenceSwitch( - modifier = modifier, + modifier = Modifier, title = stringResource(id = CommonStrings.screen_notification_settings_enable_notifications), isChecked = state.isEnabled, -// onCheckedChange = ::onEnabledChanged, switchAlignment = Alignment.Top, ) @@ -77,20 +76,18 @@ fun NotificationSettingsView( PreferenceCategory(title = stringResource(id = CommonStrings.screen_notification_settings_mode_mentions)) { PreferenceSwitch( - modifier = modifier, + modifier = Modifier, title = stringResource(id = CommonStrings.screen_notification_settings_room_mention_label), isChecked = state.notifyMeOnRoom, -// onCheckedChange = ::onEnabledChanged, switchAlignment = Alignment.Top, ) } PreferenceCategory(title = stringResource(id = CommonStrings.screen_notification_settings_additional_settings_section_title)) { PreferenceSwitch( - modifier = modifier, + modifier = Modifier, title = stringResource(id = CommonStrings.screen_notification_settings_calls_label), isChecked = state.acceptCalls, -// onCheckedChange = ::onEnabledChanged, switchAlignment = Alignment.Top, ) } 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 af82a3ab2a..37ea66b31f 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 @@ -29,6 +29,8 @@ import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.meta.BuildType import io.element.android.libraries.designsystem.utils.SnackbarDispatcher import io.element.android.libraries.designsystem.utils.collectSnackbarMessageAsState +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.getCurrentUser @@ -46,6 +48,7 @@ class PreferencesRootPresenter @Inject constructor( private val buildType: BuildType, private val versionFormatter: VersionFormatter, private val snackbarDispatcher: SnackbarDispatcher, + private val featureFlagService: FeatureFlagService, ) : Presenter { @Composable @@ -60,6 +63,11 @@ class PreferencesRootPresenter @Inject constructor( val snackbarMessage by snackbarDispatcher.collectSnackbarMessageAsState() val hasAnalyticsProviders = remember { analyticsService.getAvailableAnalyticsProviders().isNotEmpty() } + val showNotificationSettings = remember { mutableStateOf(false) } + LaunchedEffect(Unit) { + showNotificationSettings.value = featureFlagService.isFeatureEnabled(FeatureFlags.NotificationSettings) + } + // We should display the 'complete verification' option if the current session can be verified val showCompleteVerification by sessionVerificationService.canVerifySessionFlow.collectAsState(false) @@ -81,6 +89,7 @@ class PreferencesRootPresenter @Inject constructor( accountManagementUrl = accountManagementUrl.value, showAnalyticsSettings = hasAnalyticsProviders, showDeveloperSettings = showDeveloperSettings, + showNotificationSettings = showNotificationSettings.value, snackbarMessage = snackbarMessage, ) } 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 af3a090630..967450031a 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 @@ -28,5 +28,6 @@ data class PreferencesRootState( val accountManagementUrl: String?, val showAnalyticsSettings: Boolean, val showDeveloperSettings: Boolean, + val showNotificationSettings: Boolean, val snackbarMessage: SnackbarMessage?, ) 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 931a560c1d..8dd6b807f8 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 @@ -28,5 +28,6 @@ fun aPreferencesRootState() = PreferencesRootState( accountManagementUrl = "aUrl", showAnalyticsSettings = true, showDeveloperSettings = true, + showNotificationSettings = true, snackbarMessage = SnackbarMessage(CommonStrings.common_verification_complete), ) 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 c601041a7d..a2449424e6 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 @@ -94,11 +94,13 @@ fun PreferencesRootView( onClick = onOpenAnalytics, ) } - PreferenceText( - title = stringResource(id = CommonStrings.screen_notification_settings_title), - icon = Icons.Outlined.Notifications, - onClick = onOpenNotificationSettings, - ) + if(state.showNotificationSettings) { + PreferenceText( + title = stringResource(id = CommonStrings.screen_notification_settings_title), + icon = Icons.Outlined.Notifications, + onClick = onOpenNotificationSettings, + ) + } PreferenceText( title = stringResource(id = CommonStrings.action_report_bug), icon = Icons.Outlined.BugReport, From e64f0bd7d9fa98da23ad82ca4839c2ad6ad2ff3a Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 30 Aug 2023 16:08:13 +0000 Subject: [PATCH 029/234] Update screenshots --- ...ll_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ll_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...l_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...l_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...RoomNotificationSettingsDark_0_null_0,NEXUS_5,1.0,en].png} | 0 ...oomNotificationSettingsLight_0_null_0,NEXUS_5,1.0,en].png} | 0 ...ull_RoomPrivacyOptionLight-D-0_1_null,NEXUS_5,1.0,en].png} | 0 ...ull_RoomPrivacyOptionLight-N-0_2_null,NEXUS_5,1.0,en].png} | 0 8 files changed, 8 insertions(+), 8 deletions(-) rename tests/uitests/src/test/snapshots/images/{io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsDarkPreview_0_null_0,NEXUS_5,1.0,en].png => ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomNotificationSettingsDark_0_null_0,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsLightPreview_0_null_0,NEXUS_5,1.0,en].png => ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomNotificationSettingsLight_0_null_0,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview-D-0_1_null,NEXUS_5,1.0,en].png => ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomPrivacyOptionLight-D-0_1_null,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview-N-0_2_null,NEXUS_5,1.0,en].png => ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomPrivacyOptionLight-N-0_2_null,NEXUS_5,1.0,en].png} (100%) diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png index d590c4eb8e..415ea715ea 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:72eee76cc8244eb54f147fc589c7b200dc3a46db4ea7306dbd6757918e4fffde -size 39744 +oid sha256:cb2dacfe6f7e3a3ea7bf0fbe39cd1e0c4d3d0b35c8eefffb3af4fd02426c496e +size 41504 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png index a3449da98e..f2c8a21ef9 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8796e5f70cdd09087ed22ede78c3aed985dcd57e073f68d83dd5884e4f29a2c8 -size 39042 +oid sha256:0ab65a8d762003ed2bb22efac17f0c4c04e0e8313292e9777c384fa4fd2a0b96 +size 40803 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png index 370689a2fc..5b8d2fed5f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:97250f48dfa0cf2320f837eb87ad90d8a1e73642fbb2d571f326d689c4fc10e0 -size 42373 +oid sha256:389470ddc9cecf1134d18f4de75e9307632af041c5fa82f786e212258616ebeb +size 44408 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png index 6bf7f8fdb0..4631940184 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:73f2811197c014d91834d39dad1fe18abdaea9b2510d8deccead39c10a1b5aa8 -size 42473 +oid sha256:9c9adadd46650c0c8c9768c5383ae6cf3beef220dadb42b49a4df935058061a6 +size 44508 diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsDarkPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomNotificationSettingsDark_0_null_0,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsDarkPreview_0_null_0,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomNotificationSettingsDark_0_null_0,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsLightPreview_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomNotificationSettingsLight_0_null_0,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomNotificationSettingsLightPreview_0_null_0,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomNotificationSettingsLight_0_null_0,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview-D-0_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomPrivacyOptionLight-D-0_1_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview-D-0_1_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomPrivacyOptionLight-D-0_1_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview-N-0_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomPrivacyOptionLight-N-0_2_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/io.element.android.tests.uitests_ScreenshotTest_preview_tests[io.element.android.features.roomdetails.impl.notificationsettings_null_DefaultGroup_RoomPrivacyOptionLightPreview-N-0_2_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomPrivacyOptionLight-N-0_2_null,NEXUS_5,1.0,en].png From ff3fd793ff6c899d40424c6ebfbd6af55cbca3d8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 12:50:03 +0000 Subject: [PATCH 030/234] Update actions/checkout action to v4 --- .github/workflows/build.yml | 2 +- .github/workflows/danger.yml | 2 +- .github/workflows/gradle-wrapper-update.yml | 2 +- .github/workflows/gradle-wrapper-validation.yml | 2 +- .github/workflows/maestro.yml | 2 +- .github/workflows/nightly.yml | 2 +- .github/workflows/nightlyReports.yml | 2 +- .github/workflows/quality.yml | 4 ++-- .github/workflows/release.yml | 2 +- .github/workflows/sonar.yml | 2 +- .github/workflows/sync-localazy.yml | 2 +- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1df2119bf9..709d7ccd58 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,7 +27,7 @@ jobs: group: ${{ github.ref == 'refs/heads/develop' && format('build-develop-{0}-{1}', matrix.variant, github.sha) || format('build-{0}-{1}', matrix.variant, github.ref) }} cancel-in-progress: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 with: # Ensure we are building the branch and not the branch after being merged on develop # https://github.com/actions/checkout/issues/881 diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml index 8551cb44c0..e2aa8e1266 100644 --- a/.github/workflows/danger.yml +++ b/.github/workflows/danger.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest name: Danger main check steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 - run: | npm install --save-dev @babel/plugin-transform-flow-strip-types - name: Danger diff --git a/.github/workflows/gradle-wrapper-update.yml b/.github/workflows/gradle-wrapper-update.yml index 33a12d3c54..f9e998b1a0 100644 --- a/.github/workflows/gradle-wrapper-update.yml +++ b/.github/workflows/gradle-wrapper-update.yml @@ -8,7 +8,7 @@ jobs: update-gradle-wrapper: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 - name: Update Gradle Wrapper uses: gradle-update/update-gradle-wrapper-action@v1 # Skip in forks diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index 271c5399f6..bf1ca46700 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -11,5 +11,5 @@ jobs: runs-on: ubuntu-latest # No concurrency required, this is a prerequisite to other actions and should run every time. steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 - uses: gradle/wrapper-validation-action@v1 diff --git a/.github/workflows/maestro.yml b/.github/workflows/maestro.yml index 46ee84896f..6f6edd9a31 100644 --- a/.github/workflows/maestro.yml +++ b/.github/workflows/maestro.yml @@ -24,7 +24,7 @@ jobs: group: ${{ format('maestro-{0}', github.ref) }} cancel-in-progress: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 with: # Ensure we are building the branch and not the branch after being merged on develop # https://github.com/actions/checkout/issues/881 diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 85c9ed1422..e2b027aebe 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest if: ${{ github.repository == 'vector-im/element-x-android' }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 - name: Use JDK 17 uses: actions/setup-java@v3 with: diff --git a/.github/workflows/nightlyReports.yml b/.github/workflows/nightlyReports.yml index 65f3cbb53c..c1d73117b9 100644 --- a/.github/workflows/nightlyReports.yml +++ b/.github/workflows/nightlyReports.yml @@ -55,7 +55,7 @@ jobs: name: Dependency analysis runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 - name: Use JDK 17 uses: actions/setup-java@v3 with: diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 9c0aac7aef..fad3b13cb2 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -17,7 +17,7 @@ jobs: name: Search for forbidden patterns runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 - name: Run code quality check suite run: ./tools/check/check_code_quality.sh @@ -29,7 +29,7 @@ jobs: group: ${{ github.ref == 'refs/heads/main' && format('check-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('check-develop-{0}', github.sha) || format('check-{0}', github.ref) }} cancel-in-progress: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 with: # Ensure we are building the branch and not the branch after being merged on develop # https://github.com/actions/checkout/issues/881 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7e535a1467..b701b7d69e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,7 +18,7 @@ jobs: group: ${{ github.ref == 'refs/head/main' && format('build-release-main-{0}', github.sha) }} cancel-in-progress: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 - name: Use JDK 17 uses: actions/setup-java@v3 with: diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index 42846c2cd5..3a37e9ead1 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -21,7 +21,7 @@ jobs: group: ${{ github.ref == 'refs/heads/main' && format('sonar-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('sonar-develop-{0}', github.sha) || format('sonar-{0}', github.ref) }} cancel-in-progress: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 with: # Ensure we are building the branch and not the branch after being merged on develop # https://github.com/actions/checkout/issues/881 diff --git a/.github/workflows/sync-localazy.yml b/.github/workflows/sync-localazy.yml index 3d63f8b542..e4242aa634 100644 --- a/.github/workflows/sync-localazy.yml +++ b/.github/workflows/sync-localazy.yml @@ -11,7 +11,7 @@ jobs: # Skip in forks if: github.repository == 'vector-im/element-x-android' steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 - name: Set up Python 3.9 uses: actions/setup-python@v4 with: From a0ff636d0b9f487b07bd108f36b2ae6002bb864a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 4 Sep 2023 15:55:38 +0200 Subject: [PATCH 031/234] Exclude some groups related to analytics to be included. #1191 --- changelog.d/1191.misc | 1 + libraries/pushproviders/firebase/build.gradle.kts | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 changelog.d/1191.misc diff --git a/changelog.d/1191.misc b/changelog.d/1191.misc new file mode 100644 index 0000000000..0b91374f77 --- /dev/null +++ b/changelog.d/1191.misc @@ -0,0 +1 @@ +Exclude some groups related to analytics to be included. diff --git a/libraries/pushproviders/firebase/build.gradle.kts b/libraries/pushproviders/firebase/build.gradle.kts index 96faa3197b..cdb55b1119 100644 --- a/libraries/pushproviders/firebase/build.gradle.kts +++ b/libraries/pushproviders/firebase/build.gradle.kts @@ -38,7 +38,11 @@ dependencies { implementation(projects.libraries.pushproviders.api) api(platform(libs.google.firebase.bom)) - api("com.google.firebase:firebase-messaging-ktx") + api("com.google.firebase:firebase-messaging-ktx") { + exclude(group = "com.google.firebase", module = "firebase-core") + exclude(group = "com.google.firebase", module = "firebase-analytics") + exclude(group = "com.google.firebase", module = "firebase-measurement-connector") + } testImplementation(libs.test.junit) testImplementation(libs.test.truth) From fe9c7b3d432f7ae32b053b2e60cfcf75476ed8dc Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 4 Sep 2023 16:14:45 +0200 Subject: [PATCH 032/234] version++ --- plugins/src/main/kotlin/Versions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index 0e9d807014..98ebdc5f6f 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -56,7 +56,7 @@ private const val versionMinor = 1 // Note: even values are reserved for regular release, odd values for hotfix release. // When creating a hotfix, you should decrease the value, since the current value // is the value for the next regular release. -private const val versionPatch = 6 +private const val versionPatch = 7 object Versions { val versionCode = 4_000_000 + versionMajor * 1_00_00 + versionMinor * 1_00 + versionPatch From 74b2ddebfd04f35dd765aa46a45655f11419dde9 Mon Sep 17 00:00:00 2001 From: jmartinesp Date: Tue, 5 Sep 2023 06:37:36 +0000 Subject: [PATCH 033/234] Sync Strings from Localazy --- .../src/main/res/values-cs/translations.xml | 2 +- .../src/main/res/values-ro/translations.xml | 11 +++ .../src/main/res/values-ro/translations.xml | 5 +- .../src/main/res/values-ru/translations.xml | 1 + .../src/main/res/values-cs/translations.xml | 5 -- .../src/main/res/values-fr/translations.xml | 4 -- .../src/main/res/values-ro/translations.xml | 20 ++++++ .../src/main/res/values-ru/translations.xml | 5 -- .../src/main/res/values-sk/translations.xml | 5 -- .../main/res/values-zh-rTW/translations.xml | 3 - .../impl/src/main/res/values/localazy.xml | 4 +- .../src/main/res/values-cs/translations.xml | 10 +++ .../src/main/res/values-ro/translations.xml | 12 ++++ .../src/main/res/values-ru/translations.xml | 10 +++ .../impl/src/main/res/values/localazy.xml | 3 +- .../src/main/res/values-ro/translations.xml | 3 +- .../src/main/res/values-ro/translations.xml | 7 +- .../src/main/res/values-ro/translations.xml | 6 +- .../src/main/res/values-cs/translations.xml | 14 ---- .../src/main/res/values-de/translations.xml | 14 ---- .../src/main/res/values-es/translations.xml | 17 ----- .../src/main/res/values-fr/translations.xml | 17 ----- .../src/main/res/values-it/translations.xml | 17 ----- .../src/main/res/values-ro/translations.xml | 15 +--- .../src/main/res/values-ru/translations.xml | 14 ---- .../src/main/res/values-sk/translations.xml | 14 ---- .../main/res/values-zh-rTW/translations.xml | 13 ---- .../src/main/res/values/localazy.xml | 14 ---- .../src/main/res/values-cs/translations.xml | 15 ++++ .../src/main/res/values-de/translations.xml | 14 ++++ .../src/main/res/values-es/translations.xml | 14 ++++ .../src/main/res/values-fr/translations.xml | 14 ++++ .../src/main/res/values-it/translations.xml | 14 ++++ .../src/main/res/values-ro/translations.xml | 69 ++++++++++++++++++- .../src/main/res/values-ru/translations.xml | 14 ++++ .../src/main/res/values-sk/translations.xml | 14 ++++ .../main/res/values-zh-rTW/translations.xml | 13 ++++ .../src/main/res/values/localazy.xml | 24 ++++++- 38 files changed, 287 insertions(+), 183 deletions(-) create mode 100644 features/ftue/impl/src/main/res/values-ro/translations.xml create mode 100644 features/poll/impl/src/main/res/values-cs/translations.xml create mode 100644 features/poll/impl/src/main/res/values-ro/translations.xml create mode 100644 features/poll/impl/src/main/res/values-ru/translations.xml delete mode 100644 libraries/textcomposer/src/main/res/values-es/translations.xml delete mode 100644 libraries/textcomposer/src/main/res/values-fr/translations.xml delete mode 100644 libraries/textcomposer/src/main/res/values-it/translations.xml diff --git a/features/ftue/impl/src/main/res/values-cs/translations.xml b/features/ftue/impl/src/main/res/values-cs/translations.xml index f1734c9c75..724f3793cd 100644 --- a/features/ftue/impl/src/main/res/values-cs/translations.xml +++ b/features/ftue/impl/src/main/res/values-cs/translations.xml @@ -1,6 +1,6 @@ - "Toto je jednorázový proces, děkujeme za čekání." + "Jedná se o jednorázový proces, prosíme o strpení." "Nastavení vašeho účtu" "Hovory, hlasování, vyhledávání a další budou přidány koncem tohoto roku." "Historie zpráv šifrovaných místností nebude v této aktualizaci k dispozici." diff --git a/features/ftue/impl/src/main/res/values-ro/translations.xml b/features/ftue/impl/src/main/res/values-ro/translations.xml new file mode 100644 index 0000000000..f932256318 --- /dev/null +++ b/features/ftue/impl/src/main/res/values-ro/translations.xml @@ -0,0 +1,11 @@ + + + "Acesta este un proces care se desfășoară o singură dată, vă mulțumim pentru așteptare." + "Contul dumneavoastră se configurează" + "Apelurile, sondajele, căutare și multe altele vor fi adăugate în cursul acestui an." + "Istoricul mesajelor pentru camerele criptate nu va fi disponibil în această actualizare." + "Ne-ar plăcea să auzim de la dumneavoastră, spuneți-ne ce părere aveți prin intermediul paginii de setări." + "Să începem!" + "Iată ce trebuie să știți:" + "Bun venit la%1$s!" + diff --git a/features/login/impl/src/main/res/values-ro/translations.xml b/features/login/impl/src/main/res/values-ro/translations.xml index 0c58c45d03..e780269a39 100644 --- a/features/login/impl/src/main/res/values-ro/translations.xml +++ b/features/login/impl/src/main/res/values-ro/translations.xml @@ -5,10 +5,11 @@ "Introduceţi un termen de căutare sau o adresă de domeniu." "Căutați o companie, o comunitate sau un server privat." "Găsiți un furnizor de cont" - "Aici vor trăi conversațiile - la fel cum ați folosi un furnizor de e-mail pentru a vă păstra e-mailurile." + "Aici vor trăi conversațiile dumneavoastră - la fel cum ați folosi un furnizor de e-mail pentru a vă păstra e-mailurile." "Sunteți pe cale să vă conectați la %s" - "Aici vor trăi conversațiile - la fel cum ați folosi un furnizor de e-mail pentru a vă păstra e-mailurile." + "Aici vor trăi conversațiile dumneavoastră - la fel cum ați folosi un furnizor de e-mail pentru a vă păstra e-mailurile." "Sunteți pe cale să creați un cont pe %s" + "Matrix.org este un server mare și gratuit din rețeaua publică Matrix pentru comunicații sigure și descentralizate, administrat de Fundația Matrix.org." "Altul" "Utilizați un alt furnizor de cont, cum ar fi propriul server privat sau un cont de serviciu." "Schimbați furnizorul contului" diff --git a/features/login/impl/src/main/res/values-ru/translations.xml b/features/login/impl/src/main/res/values-ru/translations.xml index 242ec4bb2c..3ecb8a52d0 100644 --- a/features/login/impl/src/main/res/values-ru/translations.xml +++ b/features/login/impl/src/main/res/values-ru/translations.xml @@ -9,6 +9,7 @@ "Вы собираетесь войти в %s" "Здесь будут храниться ваши разговоры - точно так же, как вы используете почтового провайдера для хранения своих писем." "Вы собираетесь создать учетную запись на %s" + "Matrix.org — это большой бесплатный сервер в общедоступной сети Matrix для безопасной децентрализованной связи, управляемый Matrix.org Foundation." "Другое" "Используйте другого поставщика учетных записей, например, собственный частный сервер или рабочую учетную запись." "Сменить поставщика учетной записи" diff --git a/features/messages/impl/src/main/res/values-cs/translations.xml b/features/messages/impl/src/main/res/values-cs/translations.xml index 7ca02ef21c..1543101f6d 100644 --- a/features/messages/impl/src/main/res/values-cs/translations.xml +++ b/features/messages/impl/src/main/res/values-cs/translations.xml @@ -5,11 +5,6 @@ "%1$d změny místnosti" "%1$d změn místnosti" - - "%1$d další" - "%1$d další" - "%1$d dalších" - "Fotoaparát" "Vyfotit" "Natočit video" diff --git a/features/messages/impl/src/main/res/values-fr/translations.xml b/features/messages/impl/src/main/res/values-fr/translations.xml index 5f9f0223aa..e88ddc43cb 100644 --- a/features/messages/impl/src/main/res/values-fr/translations.xml +++ b/features/messages/impl/src/main/res/values-fr/translations.xml @@ -4,10 +4,6 @@ "%1$d changement dans la conversation" "%1$d changements dans la conversation" - - "%1$d de plus" - "%1$d de plus" - "Appareil photo" "Prendre une photo" "Enregistrer une vidéo" diff --git a/features/messages/impl/src/main/res/values-ro/translations.xml b/features/messages/impl/src/main/res/values-ro/translations.xml index 54774ca172..c351eb29cb 100644 --- a/features/messages/impl/src/main/res/values-ro/translations.xml +++ b/features/messages/impl/src/main/res/values-ro/translations.xml @@ -11,13 +11,33 @@ "Atașament" "Bibliotecă foto și video" "Locație" + "Sondaj" + "Formatarea textului" + "Istoricul mesajelor este momentan indisponibil în această cameră" "Nu am putut găsi detaliile utilizatorului" "Doriți să îi invitați înapoi?" "Sunteți singur în această cameră" "Mesaj copiat" "Nu aveți permisiunea de a posta în această cameră" + "Permiteți setări personalizate" + "Activarea acestei opțiuni va anula setările implicite." + "Anunțați-mă în acestă cameră pentru" + "Îl puteți schimba în %1$s." + "Setări generale" + "Setare implicită" + "Stergeți setarea personalizată" + "A apărut o eroare la încărcarea setărilor pentry notificari." + "Nu s-a reușit restaurarea modului implicit, vă rugăm să încercați din nou." + "Nu s-a reușit setarea modului, vă rugăm să încercați din nou." + "Toate mesajele" + "Numai mențiuni și cuvinte cheie" + "În această cameră, anunțați-mă pentru" + "Afișați mai puțin" + "Afișați mai mult" "Trimiteți din nou" "Mesajul dvs. nu a putut fi trimis" + "Adăugați emoji" + "Afișați mai puțin" "Procesarea datelor media a eșuat, vă rugăm să încercați din nou." "Ștergeți" diff --git a/features/messages/impl/src/main/res/values-ru/translations.xml b/features/messages/impl/src/main/res/values-ru/translations.xml index 33147f8ea2..8c96074f1b 100644 --- a/features/messages/impl/src/main/res/values-ru/translations.xml +++ b/features/messages/impl/src/main/res/values-ru/translations.xml @@ -5,11 +5,6 @@ "%1$d изменения в комнате" "%1$d изменений в комнате" - - "И ещё %1$d" - "И ещё %1$d" - "И ещё %1$d" - "Камера" "Сделать фото" "Записать видео" diff --git a/features/messages/impl/src/main/res/values-sk/translations.xml b/features/messages/impl/src/main/res/values-sk/translations.xml index 03a32f847f..2390e1e25e 100644 --- a/features/messages/impl/src/main/res/values-sk/translations.xml +++ b/features/messages/impl/src/main/res/values-sk/translations.xml @@ -5,11 +5,6 @@ "%1$d zmeny miestnosti" "%1$d zmien miestnosti" - - "%1$d ďalší" - "%1$d ďalšie" - "%1$d ďalších" - "Kamera" "Odfotiť" "Nahrať video" diff --git a/features/messages/impl/src/main/res/values-zh-rTW/translations.xml b/features/messages/impl/src/main/res/values-zh-rTW/translations.xml index 88f97cd2bf..ac4725896e 100644 --- a/features/messages/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/messages/impl/src/main/res/values-zh-rTW/translations.xml @@ -3,9 +3,6 @@ "%1$d 個聊天室變更" - - "還有 %1$d 個" - "照相機" "拍照" "錄影" diff --git a/features/messages/impl/src/main/res/values/localazy.xml b/features/messages/impl/src/main/res/values/localazy.xml index 105cb1fc7b..81cd4933e4 100644 --- a/features/messages/impl/src/main/res/values/localazy.xml +++ b/features/messages/impl/src/main/res/values/localazy.xml @@ -4,9 +4,6 @@ "%1$d room change" "%1$d room changes" - - "%1$d more" - "Camera" "Take photo" "Record a video" @@ -14,6 +11,7 @@ "Photo & Video Library" "Location" "Poll" + "Text Formatting" "Message history is currently unavailable in this room" "Could not retrieve user details" "Would you like to invite them back?" diff --git a/features/poll/impl/src/main/res/values-cs/translations.xml b/features/poll/impl/src/main/res/values-cs/translations.xml new file mode 100644 index 0000000000..d199df993f --- /dev/null +++ b/features/poll/impl/src/main/res/values-cs/translations.xml @@ -0,0 +1,10 @@ + + + "Přidat volbu" + "Zobrazit výsledky až po skončení hlasování" + "Anonymní hlasování" + "Volba %1$d" + "Otázka nebo téma" + "Čeho se hlasování týká?" + "Vytvořit hlasování" + diff --git a/features/poll/impl/src/main/res/values-ro/translations.xml b/features/poll/impl/src/main/res/values-ro/translations.xml new file mode 100644 index 0000000000..b552a68024 --- /dev/null +++ b/features/poll/impl/src/main/res/values-ro/translations.xml @@ -0,0 +1,12 @@ + + + "Adăugați o opțiune" + "Afișați rezultatele numai după încheierea sondajului" + "Sondaj anonim" + "Opțiune %1$d" + "Sunteți sigur că doriți să renunțați la acest sondaj?" + "Renunțați la sondaj" + "Întrebare sau subiect" + "Despre ce este sondajul?" + "Creați un sondaj" + diff --git a/features/poll/impl/src/main/res/values-ru/translations.xml b/features/poll/impl/src/main/res/values-ru/translations.xml new file mode 100644 index 0000000000..f1a518b0e7 --- /dev/null +++ b/features/poll/impl/src/main/res/values-ru/translations.xml @@ -0,0 +1,10 @@ + + + "Добавить опцию" + "Показывать результаты только после окончания опроса" + "Анонимный опрос" + "Настройка %1$d" + "Вопрос или тема" + "Тема опроса?" + "Создать опрос" + diff --git a/features/poll/impl/src/main/res/values/localazy.xml b/features/poll/impl/src/main/res/values/localazy.xml index 876dd0ee44..4c80a4ce45 100644 --- a/features/poll/impl/src/main/res/values/localazy.xml +++ b/features/poll/impl/src/main/res/values/localazy.xml @@ -4,7 +4,8 @@ "Show results only after poll ends" "Anonymous Poll" "Option %1$d" - "Are you sure you would like to go back?" + "Are you sure you want to discard this poll?" + "Discard Poll" "Question or topic" "What is the poll about?" "Create Poll" diff --git a/features/rageshake/impl/src/main/res/values-ro/translations.xml b/features/rageshake/impl/src/main/res/values-ro/translations.xml index db0398c0db..e82c06826e 100644 --- a/features/rageshake/impl/src/main/res/values-ro/translations.xml +++ b/features/rageshake/impl/src/main/res/values-ro/translations.xml @@ -2,12 +2,13 @@ "Atașați o captură de ecran" "Puteți să mă contactați dacă aveți întrebări suplimentare" + "Contactați-mă" "Editați captura de ecran" "Vă rugăm să descrieți eroarea. Ce ați făcut? Ce vă aşteptați să se întâmple? Ce s-a întâmplat de fapt. Vă rugam să intrați în cât mai multe detalii cu putință." "Descrieți eroarea…" "Dacă posibil, vă rugăm să scrieți descrierea în engleză." "Trimiteți log-uri" - "Trimiteți log-uri pentru a ajuta" + "Permiteți log-uri" "Trimiteți captură de ecran" "Pentru a verifica că lucrurile funcționează conform așteptărilor, log-uri vor fi trimise împreună cu mesajul. Acestea vor fi private. Pentru a trimite doar mesajul, dezactivați această setare." "%1$s s-a blocat ultima dată când a fost folosit. Doriți să ne trimiteți un raport?" diff --git a/features/roomdetails/impl/src/main/res/values-ro/translations.xml b/features/roomdetails/impl/src/main/res/values-ro/translations.xml index c20cdab3f9..a2be94aee9 100644 --- a/features/roomdetails/impl/src/main/res/values-ro/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ro/translations.xml @@ -12,8 +12,13 @@ "Nu s-a putut actualiza camera" "Mesajele sunt securizate cu încuietori. Doar dumneavoastră și destinatarii aveți cheile unice pentru a le debloca." "Criptarea mesajelor este activată" + "A apărut o eroare la încărcarea setărilor pentru notificari." + "Dezactivarea notificarilor pentru această cameră a eșuat, încercați din nou." + "Activarea notificarilor pentru această cameră a eșuat, încercați din nou." "Invitați persoane" - "Notificare" + "Personalizat" + "Implicit" + "Notificări" "Numele camerei" "Partajați camera" "Se actualizează camera…" diff --git a/features/roomlist/impl/src/main/res/values-ro/translations.xml b/features/roomlist/impl/src/main/res/values-ro/translations.xml index b8ffc57090..e1f43a02ca 100644 --- a/features/roomlist/impl/src/main/res/values-ro/translations.xml +++ b/features/roomlist/impl/src/main/res/values-ro/translations.xml @@ -1,7 +1,9 @@ "Creați o conversație sau o cameră nouă" + "Începeți prin a trimite mesaje cuiva." + "Nu există încă discuții." "Toate conversatiile" - "Se pare că folosiți un dispozitiv nou. Verificați-vă identitatea pentru acces la mesajele dumneavoastră criptate." - "Accesați istoricul mesajelor" + "Se pare că folosiți un dispozitiv nou. Verificați-vă identitatea cu un alt dispozitiv pentru a accesa mesajele dumneavoastră criptate." + "Verificați că sunteți dumneavoastră" diff --git a/libraries/textcomposer/src/main/res/values-cs/translations.xml b/libraries/textcomposer/src/main/res/values-cs/translations.xml index c37f419ec4..dbac717093 100644 --- a/libraries/textcomposer/src/main/res/values-cs/translations.xml +++ b/libraries/textcomposer/src/main/res/values-cs/translations.xml @@ -1,18 +1,4 @@ "Přidat přílohu" - "Přepnout seznam s odrážkami" - "Přepnout blok kódu" - "Zpráva…" - "Použít tučný text" - "Použít kurzívu" - "Použít přeškrtnutí" - "Použít podtržení" - "Přepnout režim celé obrazovky" - "Odsazení" - "Použít formát inline kódu" - "Nastavit odkaz" - "Přepnout číslovaný seznam" - "Přepnout citaci" - "Zrušit odsazení" diff --git a/libraries/textcomposer/src/main/res/values-de/translations.xml b/libraries/textcomposer/src/main/res/values-de/translations.xml index dea872d7c0..6b75a1c9a7 100644 --- a/libraries/textcomposer/src/main/res/values-de/translations.xml +++ b/libraries/textcomposer/src/main/res/values-de/translations.xml @@ -1,18 +1,4 @@ "Anhang hinzufügen" - "Aufzählungsliste ein-/ausschalten" - "Codeblock umschalten" - "Nachricht…" - "Fettformatierung anwenden" - "Kursivformat anwenden" - "Durchgestrichenes Format anwenden" - "Unterstreichungsformat anwenden" - "Vollbildmodus umschalten" - "Einrücken" - "Inline-Codeformat anwenden" - "Link setzen" - "Nummerierte Liste ein-/ausschalten" - "Zitat umschalten" - "Einrücken aufheben" diff --git a/libraries/textcomposer/src/main/res/values-es/translations.xml b/libraries/textcomposer/src/main/res/values-es/translations.xml deleted file mode 100644 index 606e3bde8e..0000000000 --- a/libraries/textcomposer/src/main/res/values-es/translations.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - "Lista de puntos" - "Bloque de código" - "Mensaje…" - "Aplicar formato negrita" - "Aplicar formato cursiva" - "Aplicar formato tachado" - "Aplicar formato de subrayado" - "Pantalla completa" - "Añadir sangría" - "Código" - "Enlazar" - "Lista numérica" - "Cita" - "Quitar sangría" - diff --git a/libraries/textcomposer/src/main/res/values-fr/translations.xml b/libraries/textcomposer/src/main/res/values-fr/translations.xml deleted file mode 100644 index 4b239c0f93..0000000000 --- a/libraries/textcomposer/src/main/res/values-fr/translations.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - "Afficher une liste à puces" - "Afficher le bloc de code" - "Envoyer un message…" - "Appliquer le format gras" - "Appliquer le format italique" - "Appliquer le format barré" - "Appliquer le format souligné" - "Afficher en mode plein écran" - "Décaler vers la droite" - "Appliquer le formatage de code en ligne" - "Définir un lien" - "Afficher une liste numérotée" - "Afficher une citation" - "Décaler vers la gauche" - diff --git a/libraries/textcomposer/src/main/res/values-it/translations.xml b/libraries/textcomposer/src/main/res/values-it/translations.xml deleted file mode 100644 index e3034e8dfe..0000000000 --- a/libraries/textcomposer/src/main/res/values-it/translations.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - "Attiva/disattiva l\'elenco puntato" - "Attiva/disattiva il blocco di codice" - "Messaggio…" - "Applica il formato in grassetto" - "Applicare il formato corsivo" - "Applica il formato barrato" - "Applicare il formato di sottolineatura" - "Attiva/disattiva la modalità a schermo intero" - "Rientro a destra" - "Applicare il formato del codice in linea" - "Imposta collegamento" - "Attiva/disattiva elenco numerato" - "Attiva/disattiva citazione" - "Rientro a sinistra" - diff --git a/libraries/textcomposer/src/main/res/values-ro/translations.xml b/libraries/textcomposer/src/main/res/values-ro/translations.xml index a7e1a7135c..25f0b025ca 100644 --- a/libraries/textcomposer/src/main/res/values-ro/translations.xml +++ b/libraries/textcomposer/src/main/res/values-ro/translations.xml @@ -1,17 +1,4 @@ - "Comutați lista cu puncte" - "Comutați blocul de cod" - "Mesaj…" - "Aplicați formatul aldin" - "Aplicați formatul italic" - "Aplicați formatul barat" - "Aplică formatul de subliniere" - "Comutați modul ecran complet" - "Indentare" - "Aplicați formatul de cod inline" - "Setați linkul" - "Comutați lista numerotată" - "Aplicați citatul" - "Dez-identare" + "Adăugați un atașament" diff --git a/libraries/textcomposer/src/main/res/values-ru/translations.xml b/libraries/textcomposer/src/main/res/values-ru/translations.xml index 9f7324f086..318cf9dadd 100644 --- a/libraries/textcomposer/src/main/res/values-ru/translations.xml +++ b/libraries/textcomposer/src/main/res/values-ru/translations.xml @@ -1,18 +1,4 @@ "Прикрепить файл" - "Переключить список маркеров" - "Переключить блок кода" - "Сообщение" - "Применить жирный шрифт" - "Применить курсивный формат" - "Применить формат зачеркивания" - "Применить формат подчеркивания" - "Переключение полноэкранного режима" - "Отступ" - "Применить встроенный формат кода" - "Установить ссылку" - "Переключить нумерованный список" - "Переключить цитату" - "Без отступа" diff --git a/libraries/textcomposer/src/main/res/values-sk/translations.xml b/libraries/textcomposer/src/main/res/values-sk/translations.xml index 26ac1df436..9d1daf99b6 100644 --- a/libraries/textcomposer/src/main/res/values-sk/translations.xml +++ b/libraries/textcomposer/src/main/res/values-sk/translations.xml @@ -1,18 +1,4 @@ "Pridať prílohu" - "Prepnúť zoznam odrážok" - "Prepnúť blok kódu" - "Správa…" - "Použiť tučný formát" - "Použiť formát kurzívy" - "Použiť formát prečiarknutia" - "Použiť formát podčiarknutia" - "Prepnúť režim celej obrazovky" - "Odsadenie" - "Použiť formát riadkového kódu" - "Nastaviť odkaz" - "Prepnúť číslovaný zoznam" - "Prepnúť citáciu" - "Zrušiť odsadenie" diff --git a/libraries/textcomposer/src/main/res/values-zh-rTW/translations.xml b/libraries/textcomposer/src/main/res/values-zh-rTW/translations.xml index 93777d4ca5..5aeda1b9e2 100644 --- a/libraries/textcomposer/src/main/res/values-zh-rTW/translations.xml +++ b/libraries/textcomposer/src/main/res/values-zh-rTW/translations.xml @@ -1,17 +1,4 @@ "新增附件" - "切換項目編號" - "切換程式碼區塊" - "訊息" - "套用粗體" - "套用斜體" - "套用刪除線" - "套用底線" - "切換全螢幕模式" - "增加縮排" - "設定連結" - "切換數字編號" - "切換引用" - "減少縮排" diff --git a/libraries/textcomposer/src/main/res/values/localazy.xml b/libraries/textcomposer/src/main/res/values/localazy.xml index 0bd53c3bee..11af785e8c 100644 --- a/libraries/textcomposer/src/main/res/values/localazy.xml +++ b/libraries/textcomposer/src/main/res/values/localazy.xml @@ -1,18 +1,4 @@ "Add attachment" - "Toggle bullet list" - "Toggle code block" - "Message…" - "Apply bold format" - "Apply italic format" - "Apply strikethrough format" - "Apply underline format" - "Toggle full screen mode" - "Indent" - "Apply inline code format" - "Set link" - "Toggle numbered list" - "Toggle quote" - "Unindent" diff --git a/libraries/ui-strings/src/main/res/values-cs/translations.xml b/libraries/ui-strings/src/main/res/values-cs/translations.xml index 1ace446132..bbb68b53e8 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -23,6 +23,7 @@ "Hotovo" "Upravit" "Povolit" + "Ukončit hlasování" "Zapomněli jste heslo?" "Přeposlat" "Pozvat" @@ -171,6 +172,20 @@ "Zdá se, že jste frustrovaně třásli telefonem. Chcete otevřít obrazovku pro nahlášení chyby?" "Tato zpráva bude nahlášena správci vašeho domovského serveru. Nebude si moci přečíst žádné šifrované zprávy." "Důvod nahlášení tohoto obsahu" + "Přepnout seznam s odrážkami" + "Přepnout blok kódu" + "Zpráva…" + "Použít tučný text" + "Použít kurzívu" + "Použít přeškrtnutí" + "Použít podtržení" + "Přepnout režim celé obrazovky" + "Odsazení" + "Použít formát inline kódu" + "Nastavit odkaz" + "Přepnout číslovaný seznam" + "Přepnout citaci" + "Zrušit odsazení" "Toto je začátek %1$s." "Toto je začátek této konverzace." "Nové" diff --git a/libraries/ui-strings/src/main/res/values-de/translations.xml b/libraries/ui-strings/src/main/res/values-de/translations.xml index 00979596a9..7aa02bddae 100644 --- a/libraries/ui-strings/src/main/res/values-de/translations.xml +++ b/libraries/ui-strings/src/main/res/values-de/translations.xml @@ -169,6 +169,20 @@ "Du scheinst frustriert das Telefon zu schütteln. Möchtest du den Fehlerberichtsbildschirm öffnen?" "Diese Nachricht wird an deinen Heimserver-Admin gemeldet. Er wird nicht in der Lage sein, verschlüsselte Nachrichten zu lesen." "Grund für die Meldung dieses Inhalts" + "Aufzählungsliste ein-/ausschalten" + "Codeblock umschalten" + "Nachricht…" + "Fettformatierung anwenden" + "Kursivformat anwenden" + "Durchgestrichenes Format anwenden" + "Unterstreichungsformat anwenden" + "Vollbildmodus umschalten" + "Einrücken" + "Inline-Codeformat anwenden" + "Link setzen" + "Nummerierte Liste ein-/ausschalten" + "Zitat umschalten" + "Einrücken aufheben" "Dies ist der Anfang von %1$s." "Dies ist der Beginn dieser Konversation." "Neu" diff --git a/libraries/ui-strings/src/main/res/values-es/translations.xml b/libraries/ui-strings/src/main/res/values-es/translations.xml index fa8a80f953..b56e1dfc7c 100644 --- a/libraries/ui-strings/src/main/res/values-es/translations.xml +++ b/libraries/ui-strings/src/main/res/values-es/translations.xml @@ -120,6 +120,20 @@ "Parece que sacudes el teléfono con frustración. ¿Quieres abrir la pantalla de informe de errores?" "Este mensaje se notificará al administrador de su homeserver. No podrán leer ningún mensaje cifrado." "Motivo para denunciar este contenido" + "Lista de puntos" + "Bloque de código" + "Mensaje…" + "Aplicar formato negrita" + "Aplicar formato cursiva" + "Aplicar formato tachado" + "Aplicar formato de subrayado" + "Pantalla completa" + "Añadir sangría" + "Código" + "Enlazar" + "Lista numérica" + "Cita" + "Quitar sangría" "Este es el principio de %1$s." "Este es el principio de esta conversación." "Nuevos" diff --git a/libraries/ui-strings/src/main/res/values-fr/translations.xml b/libraries/ui-strings/src/main/res/values-fr/translations.xml index e7020bc47b..745bde6497 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -158,6 +158,20 @@ "Vous semblez secouer le téléphone de frustration. Voulez-vous ouvrir le formulaire de rapport de problème ?" "Ce message sera signalé à l’administrateur de votre serveur d\'accueil. Ils ne pourront lire aucun message chiffré." "Raison du signalement de ce contenu" + "Afficher une liste à puces" + "Afficher le bloc de code" + "Envoyer un message…" + "Appliquer le format gras" + "Appliquer le format italique" + "Appliquer le format barré" + "Appliquer le format souligné" + "Afficher en mode plein écran" + "Décaler vers la droite" + "Appliquer le formatage de code en ligne" + "Définir un lien" + "Afficher une liste numérotée" + "Afficher une citation" + "Décaler vers la gauche" "Ceci est le début de %1$s." "Ceci est le début de cette conversation." "Nouveau" diff --git a/libraries/ui-strings/src/main/res/values-it/translations.xml b/libraries/ui-strings/src/main/res/values-it/translations.xml index b15d570dfc..740fe81b55 100644 --- a/libraries/ui-strings/src/main/res/values-it/translations.xml +++ b/libraries/ui-strings/src/main/res/values-it/translations.xml @@ -120,6 +120,20 @@ "Sembra che tu stia scuotendo il telefono per la frustrazione. Vuoi aprire la schermata di segnalazione dei problemi?" "Questo messaggio verrà segnalato all\'amministratore dell\'homeserver. Questi non sarà in grado di leggere i messaggi criptati." "Motivo della segnalazione di questo contenuto" + "Attiva/disattiva l\'elenco puntato" + "Attiva/disattiva il blocco di codice" + "Messaggio…" + "Applica il formato in grassetto" + "Applicare il formato corsivo" + "Applica il formato barrato" + "Applicare il formato di sottolineatura" + "Attiva/disattiva la modalità a schermo intero" + "Rientro a destra" + "Applicare il formato del codice in linea" + "Imposta collegamento" + "Attiva/disattiva elenco numerato" + "Attiva/disattiva citazione" + "Rientro a sinistra" "Questo è l\'inizio di %1$s." "Questo è l\'inizio della conversazione." "Nuovo" diff --git a/libraries/ui-strings/src/main/res/values-ro/translations.xml b/libraries/ui-strings/src/main/res/values-ro/translations.xml index d90a7a6cfc..d96abca3cc 100644 --- a/libraries/ui-strings/src/main/res/values-ro/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ro/translations.xml @@ -1,6 +1,8 @@ "Ascundeți parola" + "Doar mențiuni" + "Notificări dezactivate" "Trimiteți fișiere" "Afișați parola" "Meniu utilizator" @@ -23,6 +25,7 @@ "Efectuat" "Editați" "Activați" + "Închideți sondajul" "Ați uitat parola?" "Redirecționați" "Invitați" @@ -40,6 +43,7 @@ "Deschideți cu" "Raspuns rapid" "Citat" + "Reacționați" "Ștergeți" "Răspundeți" "Raportați o eroare" @@ -94,6 +98,9 @@ "Parola" "Persoane" "Permalink" + "Voturi finale: %1$s" + "Total voturi: %1$s" + "Rezultatele vor fi afișate după încheierea sondajului" "Politica de confidențialitate" "Reacții" "Se actualizează" @@ -116,11 +123,12 @@ "Succes" "Sugestii" "Se sincronizează…" + "Text" "Notificări despre software de la terți" "Subiect" "Despre ce este vorba în această cameră?" "Nu s-a putut decripta" - "Nu am putut trimite cu succes invitații unuia sau mai multor utilizatori." + "Nu am putut trimite invitații unuia sau mai multor utilizatori." "Nu s-a putut trimite invitația (invitațiile)" "Activați sunetul" "Eveniment neacceptat" @@ -140,7 +148,11 @@ "Călătorii & Locuri" "Simboluri" "Crearea permalink-ului a eșuat" + "%1$s nu a putut încărca harta. Vă rugăm să încercați din nou mai târziu." "Încărcarea mesajelor a eșuat" + "%1$s nu a putut accesa locația dumneavoastră. Vă rugăm să încercați din nou mai târziu." + "%1$s nu are permisiuni pentru a accesa locația dumneavoastră. Puteți permite accesul în Setări." + "%1$s nu are permisiuni pentru a accesa locația dumneavoastră. Permiteți accesul mai jos." "Unele mesaje nu au fost trimise" "Ne pare rău, a apărut o eroare" "🔐️ Alăturați-vă mie pe %1$s" @@ -154,10 +166,34 @@ "%1$d membri" "%1$d membri" + + "%d vot" + "%d voturi" + "%d voturi" + "Rageshake pentru a raporta erori" "Se pare că scuturați telefonul de frustrare. Doriți să deschdeți ecranul de raportare a unei erori?" "Acest mesaj va fi raportat administratorilor homeserver-ului tau. Ei nu vor putea citi niciun mesaj criptat." "Motivul raportării acestui conținut" + "Comutați lista cu puncte" + "Închideți opțiunile de formatare" + "Comutați blocul de cod" + "Mesaj…" + "Creați un link" + "Editați link-ul" + "Aplicați formatul aldin" + "Aplicați formatul italic" + "Aplicați formatul barat" + "Aplică formatul de subliniere" + "Comutați modul ecran complet" + "Indentare" + "Aplicați formatul de cod inline" + "Setați linkul" + "Comutați lista numerotată" + "Deschideți opțiunile de compunere" + "Aplicați citatul" + "Dez-identare" + "Link" "Acesta este începutul conversației %1$s." "Acesta este începutul acestei conversații." "Nou" @@ -165,9 +201,40 @@ "Selectarea fișierelor media a eșuat, încercați din nou." "Procesarea datelor media a eșuat, vă rugăm să încercați din nou." "Încărcarea fișierelor media a eșuat, încercați din nou." + "Setări adiționale" + "Apeluri audio și video" + "Nepotrivire de configurație" + "Am simplificat Setările pentru notificări pentru a face opțiunile mai ușor de găsit. + +Unele setări personalizate pe care le-ați ales în trecut nu sunt afișate aici, dar sunt încă active. + +Dacă continuați, unele dintre setările dumneavoastră pot fi modificate." + "Discuții directe" + "Setare personalizată per chat" + "A apărut o eroare în timpul actualizării setărilor pentru notificari." + "Toate mesajele" + "Numai mențiuni și cuvinte cheie" + "În conversațiile directe, anunță-mă pentru" + "În conversațiile de grup, anunțați-mă pentru" + "Activați notificările pe acest dispozitiv" + "Configurația nu a fost corectată, vă rugăm să încercați din nou." + "Discuții de grup" + "Mențiuni" + "Toate" + "Mențiuni" + "Anunță-mă pentru" + "Anunțați-mă pentru @room" + "Pentru a primi notificări, vă rugăm să vă schimbați %1$s." + "Setări de sistem" + "Notificările de sistem sunt dezactivate" + "Notificări" "Confirmați că doriți să ascundeți toate mesajele curente și viitoare de la acest utilizator" + "Cont și dispozitive" "Partajați locația" "Distribuiți locația mea" + "Deschideți în Apple Maps" + "Deschideți în Google Maps" + "Deschideți în OpenStreetMap" "Distribuiți această locație" "Locație" "Rageshake" diff --git a/libraries/ui-strings/src/main/res/values-ru/translations.xml b/libraries/ui-strings/src/main/res/values-ru/translations.xml index 23df74fff5..28284f6347 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -171,6 +171,20 @@ "Кажется, вы трясли телефон. Хотите открыть экран отчета об ошибке?" "Это сообщение будет передано администратору вашего домашнего сервера. Они не смогут прочитать зашифрованные сообщения." "Причина, по которой вы пожаловались на этот контент" + "Переключить список маркеров" + "Переключить блок кода" + "Сообщение" + "Применить жирный шрифт" + "Применить курсивный формат" + "Применить формат зачеркивания" + "Применить формат подчеркивания" + "Переключение полноэкранного режима" + "Отступ" + "Применить встроенный формат кода" + "Установить ссылку" + "Переключить нумерованный список" + "Переключить цитату" + "Без отступа" "Это начало %1$s." "Это начало разговора." "Новый" diff --git a/libraries/ui-strings/src/main/res/values-sk/translations.xml b/libraries/ui-strings/src/main/res/values-sk/translations.xml index b8d919faa0..cad1b5a564 100644 --- a/libraries/ui-strings/src/main/res/values-sk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml @@ -171,6 +171,20 @@ "Zdá sa, že zúrivo trasiete telefónom. Chcete otvoriť obrazovku s nahlásením chýb?" "Táto správa bude nahlásená správcovi vášho domovského servera. Nebude môcť prečítať žiadne šifrované správy." "Dôvod nahlásenia tohto obsahu" + "Prepnúť zoznam odrážok" + "Prepnúť blok kódu" + "Správa…" + "Použiť tučný formát" + "Použiť formát kurzívy" + "Použiť formát prečiarknutia" + "Použiť formát podčiarknutia" + "Prepnúť režim celej obrazovky" + "Odsadenie" + "Použiť formát riadkového kódu" + "Nastaviť odkaz" + "Prepnúť číslovaný zoznam" + "Prepnúť citáciu" + "Zrušiť odsadenie" "Toto je začiatok %1$s." "Toto je začiatok tejto konverzácie." "Nové" diff --git a/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml b/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml index 32f8a23086..ddaaed0d33 100644 --- a/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml @@ -141,6 +141,19 @@ "%d 票" "檢舉這個內容的原因" + "切換項目編號" + "切換程式碼區塊" + "訊息" + "套用粗體" + "套用斜體" + "套用刪除線" + "套用底線" + "切換全螢幕模式" + "增加縮排" + "設定連結" + "切換數字編號" + "切換引用" + "減少縮排" "新訊息" "分享分析數據" "無法上傳媒體檔案,請稍後再試。" diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 95ae43dd21..8a9f1cee2f 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -1,6 +1,8 @@ "Hide password" + "Mentions only" + "Muted" "Send files" "Show password" "User menu" @@ -23,6 +25,7 @@ "Done" "Edit" "Enable" + "End poll" "Forgot password?" "Forward" "Invite" @@ -61,7 +64,6 @@ "Take photo" "View Source" "Yes" - "End poll" "About" "Acceptable use policy" "Analytics" @@ -121,6 +123,7 @@ "Success" "Suggestions" "Syncing" + "Text" "Third-party notices" "Topic" "What is this room about?" @@ -170,6 +173,25 @@ "You seem to be shaking the phone in frustration. Would you like to open the bug report screen?" "This message will be reported to your homeserver’s administrator. They will not be able to read any encrypted messages." "Reason for reporting this content" + "Toggle bullet list" + "Close formatting options" + "Toggle code block" + "Message…" + "Create a link" + "Edit link" + "Apply bold format" + "Apply italic format" + "Apply strikethrough format" + "Apply underline format" + "Toggle full screen mode" + "Indent" + "Apply inline code format" + "Set link" + "Toggle numbered list" + "Open compose options" + "Toggle quote" + "Unindent" + "Link" "This is the beginning of %1$s." "This is the beginning of this conversation." "New" From 1f167e9eca3443581f48d35174b4a967dc7e4317 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 5 Sep 2023 07:35:15 +0000 Subject: [PATCH 034/234] Update screenshots --- ...reate_null_CreatePollView-D-0_1_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...reate_null_CreatePollView-N-0_2_null_2,NEXUS_5,1.0,en].png | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-D-0_1_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-D-0_1_null_2,NEXUS_5,1.0,en].png index cc49158545..8e47757aa3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-D-0_1_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-D-0_1_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:155cee63d3e031c912786b95bcc8e28dc4d1b296f8f0e4c01bd96398bb2dd040 -size 40623 +oid sha256:636e6c2494e69d7f1383e0c2ef178db484cfa6802c6714ee20a66aad10f4421f +size 40500 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-N-0_2_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-N-0_2_null_2,NEXUS_5,1.0,en].png index 127289d30b..96707cb507 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-N-0_2_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-N-0_2_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b682b0025c98d9d37ab8dc67cbc8a637f672ae2bf9e4a26e48209188d612c0c -size 36455 +oid sha256:58ced9ebe2a161167f5515efa18b87eb02c340b75db47af84f91eab0866b113f +size 36370 From 9bf3521f39459b873a2f5347f8d52068689cccc5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 5 Sep 2023 12:05:42 +0200 Subject: [PATCH 035/234] Compute avatar color of users and apply foreground color to the sender displayname. --- .../components/TimelineItemEventRow.kt | 4 +- .../designsystem/colors/AvatarColor.kt | 47 +++++++++++++++++++ .../theme/colors/AvatarColorsDark.kt | 35 ++++++++++++++ .../theme/colors/AvatarColorsLight.kt | 35 ++++++++++++++ 4 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColor.kt create mode 100644 libraries/theme/src/main/kotlin/io/element/android/libraries/theme/colors/AvatarColorsDark.kt create mode 100644 libraries/theme/src/main/kotlin/io/element/android/libraries/theme/colors/AvatarColorsLight.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index 10671ee00f..e1c6b746d2 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -75,6 +75,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemPollContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent +import io.element.android.libraries.designsystem.colors.AvatarColor import io.element.android.libraries.designsystem.components.EqualWidthColumn import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData @@ -327,6 +328,7 @@ private fun MessageSenderInformation( ) { val avatarStrokeColor = MaterialTheme.colorScheme.background val avatarSize = senderAvatar.size.dp + val avatarColor = AvatarColor(senderAvatar.id) Box( modifier = modifier ) { @@ -350,7 +352,7 @@ private fun MessageSenderInformation( text = sender, maxLines = 1, overflow = TextOverflow.Ellipsis, - color = MaterialTheme.colorScheme.primary, + color = avatarColor.foreground, style = ElementTheme.typography.fontBodyMdMedium, ) } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColor.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColor.kt new file mode 100644 index 0000000000..0edd90132a --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColor.kt @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.designsystem.colors + +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color +import io.element.android.libraries.theme.ElementTheme +import io.element.android.libraries.theme.colors.avatarColorsDark +import io.element.android.libraries.theme.colors.avatarColorsLight + +data class AvatarColor( + val background: Color, + val foreground: Color, +) + +@Composable +fun AvatarColor(userId: String): AvatarColor { + val hash = userId.toHash() + val colors = if (ElementTheme.isLightTheme) { + avatarColorsLight[hash % avatarColorsLight.size] + } else { + avatarColorsDark[hash % avatarColorsDark.size] + } + return AvatarColor( + background = colors.first, + foreground = colors.second, + ) +} + +private fun String.toHash(): Int { + return toList().sumOf { it.code } % 8 + 1 +} + diff --git a/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/colors/AvatarColorsDark.kt b/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/colors/AvatarColorsDark.kt new file mode 100644 index 0000000000..a18721a60b --- /dev/null +++ b/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/colors/AvatarColorsDark.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.theme.colors + +import io.element.android.libraries.theme.compound.generated.internal.DarkDesignTokens + +/** + * Avatar colors are not yet part of SemanticColors, so create list here. + * DarkDesignTokens is internal to the module. + */ + +val avatarColorsDark = listOf( + DarkDesignTokens.colorBlue300 to DarkDesignTokens.colorBlue1200, + DarkDesignTokens.colorFuchsia300 to DarkDesignTokens.colorFuchsia1200, + DarkDesignTokens.colorGreen300 to DarkDesignTokens.colorGreen1200, + DarkDesignTokens.colorPink300 to DarkDesignTokens.colorPink1200, + DarkDesignTokens.colorOrange300 to DarkDesignTokens.colorOrange1200, + DarkDesignTokens.colorCyan300 to DarkDesignTokens.colorCyan1200, + DarkDesignTokens.colorPurple300 to DarkDesignTokens.colorPurple1200, + DarkDesignTokens.colorLime300 to DarkDesignTokens.colorLime1200, +) diff --git a/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/colors/AvatarColorsLight.kt b/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/colors/AvatarColorsLight.kt new file mode 100644 index 0000000000..d2c320d479 --- /dev/null +++ b/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/colors/AvatarColorsLight.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.theme.colors + +import io.element.android.libraries.theme.compound.generated.internal.LightDesignTokens + +/** + * Avatar colors are not yet part of SemanticColors, so create list here. + * LightDesignTokens is internal to the module. + */ + +val avatarColorsLight = listOf( + LightDesignTokens.colorBlue300 to LightDesignTokens.colorBlue1200, + LightDesignTokens.colorFuchsia300 to LightDesignTokens.colorFuchsia1200, + LightDesignTokens.colorGreen300 to LightDesignTokens.colorGreen1200, + LightDesignTokens.colorPink300 to LightDesignTokens.colorPink1200, + LightDesignTokens.colorOrange300 to LightDesignTokens.colorOrange1200, + LightDesignTokens.colorCyan300 to LightDesignTokens.colorCyan1200, + LightDesignTokens.colorPurple300 to LightDesignTokens.colorPurple1200, + LightDesignTokens.colorLime300 to LightDesignTokens.colorLime1200, +) From e301d606482714e5a0e999c14bb77b59faf45700 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 5 Sep 2023 12:12:59 +0200 Subject: [PATCH 036/234] Compute avatar color of users and apply foreground color to the sender displayname. --- .../components/TimelineItemEventRow.kt | 6 +-- .../{AvatarColor.kt => AvatarColors.kt} | 14 +++---- .../designsystem/colors/AvatarColorsTest.kt | 40 +++++++++++++++++++ 3 files changed, 50 insertions(+), 10 deletions(-) rename libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/{AvatarColor.kt => AvatarColors.kt} (80%) create mode 100644 libraries/designsystem/src/test/kotlin/io/element/android/libraries/designsystem/colors/AvatarColorsTest.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index e1c6b746d2..56ad1c338e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -75,7 +75,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemPollContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent -import io.element.android.libraries.designsystem.colors.AvatarColor +import io.element.android.libraries.designsystem.colors.AvatarColors import io.element.android.libraries.designsystem.components.EqualWidthColumn import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData @@ -328,7 +328,7 @@ private fun MessageSenderInformation( ) { val avatarStrokeColor = MaterialTheme.colorScheme.background val avatarSize = senderAvatar.size.dp - val avatarColor = AvatarColor(senderAvatar.id) + val avatarColors = AvatarColors(senderAvatar.id) Box( modifier = modifier ) { @@ -352,7 +352,7 @@ private fun MessageSenderInformation( text = sender, maxLines = 1, overflow = TextOverflow.Ellipsis, - color = avatarColor.foreground, + color = avatarColors.foreground, style = ElementTheme.typography.fontBodyMdMedium, ) } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColor.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColors.kt similarity index 80% rename from libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColor.kt rename to libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColors.kt index 0edd90132a..e73cbf3218 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColor.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColors.kt @@ -22,26 +22,26 @@ import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.colors.avatarColorsDark import io.element.android.libraries.theme.colors.avatarColorsLight -data class AvatarColor( +data class AvatarColors( val background: Color, val foreground: Color, ) @Composable -fun AvatarColor(userId: String): AvatarColor { +fun AvatarColors(userId: String): AvatarColors { val hash = userId.toHash() val colors = if (ElementTheme.isLightTheme) { - avatarColorsLight[hash % avatarColorsLight.size] + avatarColorsLight[hash] } else { - avatarColorsDark[hash % avatarColorsDark.size] + avatarColorsDark[hash] } - return AvatarColor( + return AvatarColors( background = colors.first, foreground = colors.second, ) } -private fun String.toHash(): Int { - return toList().sumOf { it.code } % 8 + 1 +internal fun String.toHash(): Int { + return toList().sumOf { it.code } % 8 } diff --git a/libraries/designsystem/src/test/kotlin/io/element/android/libraries/designsystem/colors/AvatarColorsTest.kt b/libraries/designsystem/src/test/kotlin/io/element/android/libraries/designsystem/colors/AvatarColorsTest.kt new file mode 100644 index 0000000000..2b91a9e490 --- /dev/null +++ b/libraries/designsystem/src/test/kotlin/io/element/android/libraries/designsystem/colors/AvatarColorsTest.kt @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.designsystem.colors + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.theme.colors.avatarColorsDark +import io.element.android.libraries.theme.colors.avatarColorsLight +import org.junit.Test + +class AvatarColorsTest { + + @Test + fun `ensure list size`() { + // avatarColorsDark and avatarColorsLight size must not be modified. + // 8 is used as a hard-coded modulo in `String.toHash()` extension. + assertThat(avatarColorsDark.size).isEqualTo(8) + assertThat(avatarColorsLight.size).isEqualTo(8) + } + + @Test + fun `compute string hash`() { + assertThat("@alice:domain.org".toHash()).isEqualTo(6) + assertThat("@bob:domain.org".toHash()).isEqualTo(3) + assertThat("@charlie:domain.org".toHash()).isEqualTo(0) + } +} From 1cffbbdca745168f6ed98ac73d699ff27066e40e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 5 Sep 2023 12:44:36 +0200 Subject: [PATCH 037/234] Apply colors to default user avatar in the timeline. --- .../components/TimelineItemEventRow.kt | 2 +- .../designsystem/components/avatar/Avatar.kt | 8 ++- .../components/avatar/UserAvatarPreview.kt | 51 +++++++++++++++++++ .../designsystem/colors/AvatarColorsTest.kt | 12 +++++ 4 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/UserAvatarPreview.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index 56ad1c338e..b5229c2656 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -346,7 +346,7 @@ private fun MessageSenderInformation( } // Content Row { - Avatar(senderAvatar) + Avatar(senderAvatar, avatarColors = avatarColors) Spacer(modifier = Modifier.width(4.dp)) Text( text = sender, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt index 2e2d98ddbb..cfc2efd6ae 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt @@ -33,6 +33,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import coil.compose.AsyncImage +import io.element.android.libraries.designsystem.colors.AvatarColors import io.element.android.libraries.designsystem.preview.ElementThemedPreview import io.element.android.libraries.designsystem.preview.PreviewGroup import io.element.android.libraries.designsystem.preview.debugPlaceholderAvatar @@ -45,6 +46,7 @@ import timber.log.Timber fun Avatar( avatarData: AvatarData, modifier: Modifier = Modifier, + avatarColors: AvatarColors? = null, contentDescription: String? = null, ) { val commonModifier = modifier @@ -53,6 +55,7 @@ fun Avatar( if (avatarData.url.isNullOrBlank()) { InitialsAvatar( avatarData = avatarData, + avatarColors = avatarColors, modifier = commonModifier, ) } else { @@ -85,12 +88,13 @@ private fun ImageAvatar( @Composable private fun InitialsAvatar( avatarData: AvatarData, + avatarColors: AvatarColors?, modifier: Modifier = Modifier, ) { // Use temporary color for default avatar background val avatarColor = ElementTheme.colors.bgActionPrimaryDisabled Box( - modifier.background(color = avatarColor), + modifier.background(color = avatarColors?.background ?: avatarColor) ) { val fontSize = avatarData.size.dp.toSp() / 2 val originalFont = ElementTheme.typography.fontBodyMdRegular @@ -100,7 +104,7 @@ private fun InitialsAvatar( modifier = Modifier.align(Alignment.Center), text = avatarData.initial, style = originalFont.copy(fontSize = fontSize, lineHeight = lineHeight, letterSpacing = 0.sp), - color = Color.White, + color = avatarColors?.foreground ?: Color.White, ) } } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/UserAvatarPreview.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/UserAvatarPreview.kt new file mode 100644 index 0000000000..f47ee9bb7a --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/UserAvatarPreview.kt @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.designsystem.components.avatar + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +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.libraries.designsystem.colors.AvatarColors +import io.element.android.libraries.designsystem.preview.DayNightPreviews +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.theme.colors.avatarColorsLight + +@DayNightPreviews +@Composable +internal fun UserAvatarPreview() = ElementPreview { + Column( + modifier = Modifier.padding(8.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + ) { + repeat(avatarColorsLight.size) { + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + // Note: it's OK, since the hash of "0" is 0, the hash of "1" is 1, etc. + Avatar(anAvatarData(), avatarColors = AvatarColors("$it")) + Text(text = "Color index $it") + } + } + } +} diff --git a/libraries/designsystem/src/test/kotlin/io/element/android/libraries/designsystem/colors/AvatarColorsTest.kt b/libraries/designsystem/src/test/kotlin/io/element/android/libraries/designsystem/colors/AvatarColorsTest.kt index 2b91a9e490..8e92e8186c 100644 --- a/libraries/designsystem/src/test/kotlin/io/element/android/libraries/designsystem/colors/AvatarColorsTest.kt +++ b/libraries/designsystem/src/test/kotlin/io/element/android/libraries/designsystem/colors/AvatarColorsTest.kt @@ -37,4 +37,16 @@ class AvatarColorsTest { assertThat("@bob:domain.org".toHash()).isEqualTo(3) assertThat("@charlie:domain.org".toHash()).isEqualTo(0) } + + @Test + fun `compute string hash reverse`() { + assertThat("0".toHash()).isEqualTo(0) + assertThat("1".toHash()).isEqualTo(1) + assertThat("2".toHash()).isEqualTo(2) + assertThat("3".toHash()).isEqualTo(3) + assertThat("4".toHash()).isEqualTo(4) + assertThat("5".toHash()).isEqualTo(5) + assertThat("6".toHash()).isEqualTo(6) + assertThat("7".toHash()).isEqualTo(7) + } } From 29f5373e71bb8bc689bc10952cf8478edf7b6175 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 5 Sep 2023 14:04:38 +0200 Subject: [PATCH 038/234] changelog. --- changelog.d/1224.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/1224.feature diff --git a/changelog.d/1224.feature b/changelog.d/1224.feature new file mode 100644 index 0000000000..c921977df4 --- /dev/null +++ b/changelog.d/1224.feature @@ -0,0 +1 @@ +Set color on display name and default avatar in the timeline. From 74fc570708cf0c0777c4969271b2bfd08e62f252 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 5 Sep 2023 14:21:14 +0200 Subject: [PATCH 039/234] Composable functions that return a value should start with a lowercase letter --- .../messages/impl/timeline/components/TimelineItemEventRow.kt | 4 ++-- .../android/libraries/designsystem/colors/AvatarColors.kt | 2 +- .../designsystem/components/avatar/UserAvatarPreview.kt | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index b5229c2656..fd9676653f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -75,7 +75,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemPollContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent -import io.element.android.libraries.designsystem.colors.AvatarColors +import io.element.android.libraries.designsystem.colors.avatarColors import io.element.android.libraries.designsystem.components.EqualWidthColumn import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData @@ -328,7 +328,7 @@ private fun MessageSenderInformation( ) { val avatarStrokeColor = MaterialTheme.colorScheme.background val avatarSize = senderAvatar.size.dp - val avatarColors = AvatarColors(senderAvatar.id) + val avatarColors = avatarColors(senderAvatar.id) Box( modifier = modifier ) { diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColors.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColors.kt index e73cbf3218..26e255194c 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColors.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColors.kt @@ -28,7 +28,7 @@ data class AvatarColors( ) @Composable -fun AvatarColors(userId: String): AvatarColors { +fun avatarColors(userId: String): AvatarColors { val hash = userId.toHash() val colors = if (ElementTheme.isLightTheme) { avatarColorsLight[hash] diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/UserAvatarPreview.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/UserAvatarPreview.kt index f47ee9bb7a..b9b8f42062 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/UserAvatarPreview.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/UserAvatarPreview.kt @@ -24,7 +24,7 @@ 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.libraries.designsystem.colors.AvatarColors +import io.element.android.libraries.designsystem.colors.avatarColors import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.theme.components.Text @@ -43,7 +43,7 @@ internal fun UserAvatarPreview() = ElementPreview { verticalAlignment = Alignment.CenterVertically, ) { // Note: it's OK, since the hash of "0" is 0, the hash of "1" is 1, etc. - Avatar(anAvatarData(), avatarColors = AvatarColors("$it")) + Avatar(anAvatarData(), avatarColors = avatarColors("$it")) Text(text = "Color index $it") } } From ff77fca34d24415b402f59754f1fc363c762bd02 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 5 Sep 2023 14:55:53 +0200 Subject: [PATCH 040/234] Avoid hard-coded number and update the related test. --- .../android/libraries/designsystem/colors/AvatarColors.kt | 2 +- .../libraries/designsystem/colors/AvatarColorsTest.kt | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColors.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColors.kt index 26e255194c..fb379c751e 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColors.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColors.kt @@ -42,6 +42,6 @@ fun avatarColors(userId: String): AvatarColors { } internal fun String.toHash(): Int { - return toList().sumOf { it.code } % 8 + return toList().sumOf { it.code } % avatarColorsLight.size } diff --git a/libraries/designsystem/src/test/kotlin/io/element/android/libraries/designsystem/colors/AvatarColorsTest.kt b/libraries/designsystem/src/test/kotlin/io/element/android/libraries/designsystem/colors/AvatarColorsTest.kt index 8e92e8186c..7b3392607d 100644 --- a/libraries/designsystem/src/test/kotlin/io/element/android/libraries/designsystem/colors/AvatarColorsTest.kt +++ b/libraries/designsystem/src/test/kotlin/io/element/android/libraries/designsystem/colors/AvatarColorsTest.kt @@ -24,11 +24,8 @@ import org.junit.Test class AvatarColorsTest { @Test - fun `ensure list size`() { - // avatarColorsDark and avatarColorsLight size must not be modified. - // 8 is used as a hard-coded modulo in `String.toHash()` extension. - assertThat(avatarColorsDark.size).isEqualTo(8) - assertThat(avatarColorsLight.size).isEqualTo(8) + fun `ensure the size of the avatar color are equal for light and dark theme`() { + assertThat(avatarColorsDark.size).isEqualTo(avatarColorsLight.size) } @Test From d383590910bf8c37f4a32057a5f8b221a3bb9be8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 5 Sep 2023 15:39:21 +0200 Subject: [PATCH 041/234] Use bolder font for fallback avatar. --- .../android/libraries/designsystem/components/avatar/Avatar.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt index cfc2efd6ae..dc6149d0f6 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt @@ -97,7 +97,7 @@ private fun InitialsAvatar( modifier.background(color = avatarColors?.background ?: avatarColor) ) { val fontSize = avatarData.size.dp.toSp() / 2 - val originalFont = ElementTheme.typography.fontBodyMdRegular + val originalFont = ElementTheme.typography.fontHeadingMdBold val ratio = fontSize.value / originalFont.fontSize.value val lineHeight = originalFont.lineHeight * ratio Text( From 6ef288c26d64c0b9988fce2b8bb873c2767b6605 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 5 Sep 2023 15:45:12 +0200 Subject: [PATCH 042/234] Rename parameter and update comment. --- .../impl/timeline/components/TimelineItemEventRow.kt | 2 +- .../libraries/designsystem/components/avatar/Avatar.kt | 6 +++--- .../designsystem/components/avatar/UserAvatarPreview.kt | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index fd9676653f..30478c6ef0 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -346,7 +346,7 @@ private fun MessageSenderInformation( } // Content Row { - Avatar(senderAvatar, avatarColors = avatarColors) + Avatar(senderAvatar, initialAvatarColors = avatarColors) Spacer(modifier = Modifier.width(4.dp)) Text( text = sender, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt index dc6149d0f6..958f4ca29e 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt @@ -46,7 +46,7 @@ import timber.log.Timber fun Avatar( avatarData: AvatarData, modifier: Modifier = Modifier, - avatarColors: AvatarColors? = null, + initialAvatarColors: AvatarColors? = null, contentDescription: String? = null, ) { val commonModifier = modifier @@ -55,7 +55,7 @@ fun Avatar( if (avatarData.url.isNullOrBlank()) { InitialsAvatar( avatarData = avatarData, - avatarColors = avatarColors, + avatarColors = initialAvatarColors, modifier = commonModifier, ) } else { @@ -91,7 +91,7 @@ private fun InitialsAvatar( avatarColors: AvatarColors?, modifier: Modifier = Modifier, ) { - // Use temporary color for default avatar background + // Use temporary color for default avatar background, if avatarColors is not provided val avatarColor = ElementTheme.colors.bgActionPrimaryDisabled Box( modifier.background(color = avatarColors?.background ?: avatarColor) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/UserAvatarPreview.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/UserAvatarPreview.kt index b9b8f42062..817650ffa7 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/UserAvatarPreview.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/UserAvatarPreview.kt @@ -43,7 +43,7 @@ internal fun UserAvatarPreview() = ElementPreview { verticalAlignment = Alignment.CenterVertically, ) { // Note: it's OK, since the hash of "0" is 0, the hash of "1" is 1, etc. - Avatar(anAvatarData(), avatarColors = avatarColors("$it")) + Avatar(anAvatarData(), initialAvatarColors = avatarColors("$it")) Text(text = "Color index $it") } } From a8b9d0529f26cb41a5718a6ea9c310a62a297a0c Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 5 Sep 2023 13:55:40 +0000 Subject: [PATCH 043/234] Update screenshots --- ...people_null_AddPeopleViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...eople_null_AddPeopleViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...l_SearchMultipleUsersResultItem_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...null_SearchSingleUserResultItem_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...ponents_null_UserListViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...ponents_null_UserListViewDark_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...ponents_null_UserListViewDark_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...onents_null_UserListViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...onents_null_UserListViewLight_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...onents_null_UserListViewLight_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...om_null_ConfigureRoomViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...m_null_ConfigureRoomViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...t_null_CreateRoomRootViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...t_null_CreateRoomRootViewDark_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ..._null_CreateRoomRootViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ..._null_CreateRoomRootViewLight_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...nts_null_InviteSummaryRowDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...nts_null_InviteSummaryRowDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...nts_null_InviteSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...nts_null_InviteSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...nts_null_InviteSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...ts_null_InviteSummaryRowLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ts_null_InviteSummaryRowLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...ts_null_InviteSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...ts_null_InviteSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...ts_null_InviteSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_InviteListViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_InviteListViewDark_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_InviteListViewDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_InviteListViewDark_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_InviteListViewDark_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_InviteListViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_InviteListViewLight_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_InviteListViewLight_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_InviteListViewLight_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_InviteListViewLight_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...ionlist_null_SheetContent-D-0_1_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...ionlist_null_SheetContent-D-0_1_null_8,NEXUS_5,1.0,en].png | 4 ++-- ...ionlist_null_SheetContent-N-0_2_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...ionlist_null_SheetContent-N-0_2_null_8,NEXUS_5,1.0,en].png | 4 ++-- ..._null_ForwardMessagesViewDark_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ..._null_ForwardMessagesViewDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ..._null_ForwardMessagesViewDark_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ..._null_ForwardMessagesViewDark_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ..._null_ForwardMessagesViewDark_0_null_7,NEXUS_5,1.0,en].png | 4 ++-- ...null_ForwardMessagesViewLight_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...null_ForwardMessagesViewLight_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...null_ForwardMessagesViewLight_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...null_ForwardMessagesViewLight_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...null_ForwardMessagesViewLight_0_null_7,NEXUS_5,1.0,en].png | 4 ++-- ...mmary_null_SheetContent-D-14_15_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...mmary_null_SheetContent-N-14_16_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...s_null_TimelineItemEventRowDark_0_null,NEXUS_5,1.0,en].png | 4 ++-- ..._null_TimelineItemEventRowLight_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...elineItemEventRowLongSenderName_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...lineItemEventRowTimestampDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...lineItemEventRowTimestampDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...lineItemEventRowTimestampDark_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...lineItemEventRowTimestampDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...ineItemEventRowTimestampLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ineItemEventRowTimestampLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...ineItemEventRowTimestampLight_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...ineItemEventRowTimestampLight_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...emEventRowWithManyReactionsDark_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...mEventRowWithManyReactionsLight_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...melineItemEventRowWithReplyDark_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...elineItemEventRowWithReplyLight_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...TimelineItemEventTimestampBelow_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...imeline_null_TimelineView-D-2_3_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...imeline_null_TimelineView-D-2_3_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...meline_null_TimelineView-D-2_3_null_10,NEXUS_5,1.0,en].png | 4 ++-- ...meline_null_TimelineView-D-2_3_null_11,NEXUS_5,1.0,en].png | 4 ++-- ...meline_null_TimelineView-D-2_3_null_12,NEXUS_5,1.0,en].png | 4 ++-- ...imeline_null_TimelineView-D-2_3_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...imeline_null_TimelineView-D-2_3_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...imeline_null_TimelineView-D-2_3_null_8,NEXUS_5,1.0,en].png | 4 ++-- ...imeline_null_TimelineView-D-2_3_null_9,NEXUS_5,1.0,en].png | 4 ++-- ...imeline_null_TimelineView-N-2_4_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...imeline_null_TimelineView-N-2_4_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...meline_null_TimelineView-N-2_4_null_10,NEXUS_5,1.0,en].png | 4 ++-- ...meline_null_TimelineView-N-2_4_null_11,NEXUS_5,1.0,en].png | 4 ++-- ...meline_null_TimelineView-N-2_4_null_12,NEXUS_5,1.0,en].png | 4 ++-- ...imeline_null_TimelineView-N-2_4_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...imeline_null_TimelineView-N-2_4_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...imeline_null_TimelineView-N-2_4_null_8,NEXUS_5,1.0,en].png | 4 ++-- ...imeline_null_TimelineView-N-2_4_null_9,NEXUS_5,1.0,en].png | 4 ++-- ...es.impl_null_MessagesViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...es.impl_null_MessagesViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...es.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...es.impl_null_MessagesViewDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...es.impl_null_MessagesViewDark_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...es.impl_null_MessagesViewDark_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...s.impl_null_MessagesViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...s.impl_null_MessagesViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...s.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...s.impl_null_MessagesViewLight_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...s.impl_null_MessagesViewLight_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...s.impl_null_MessagesViewLight_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...ll_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ll_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...l_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...l_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...user_null_UserPreferencesDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...user_null_UserPreferencesDark_0_null_1,NEXUS_5,1.0,en].png | 2 +- ...ser_null_UserPreferencesLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ser_null_UserPreferencesLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ..._null_RoomDetailsEditViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ..._null_RoomDetailsEditViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ..._null_RoomDetailsEditViewDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ..._null_RoomDetailsEditViewDark_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ..._null_RoomDetailsEditViewDark_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ..._null_RoomDetailsEditViewDark_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...null_RoomDetailsEditViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...null_RoomDetailsEditViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...null_RoomDetailsEditViewLight_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...null_RoomDetailsEditViewLight_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...null_RoomDetailsEditViewLight_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...null_RoomDetailsEditViewLight_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...te_null_RoomInviteMembersDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...te_null_RoomInviteMembersDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...te_null_RoomInviteMembersDark_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...te_null_RoomInviteMembersDark_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...e_null_RoomInviteMembersLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...e_null_RoomInviteMembersLight_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...e_null_RoomInviteMembersLight_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...e_null_RoomInviteMembersLight_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ..._RoomMemberDetailsViewDark--3_3_null_0,NEXUS_5,1.0,en].png | 4 ++-- ..._RoomMemberDetailsViewDark--3_3_null_1,NEXUS_5,1.0,en].png | 4 ++-- ..._RoomMemberDetailsViewDark--3_3_null_2,NEXUS_5,1.0,en].png | 4 ++-- ..._RoomMemberDetailsViewDark--3_3_null_3,NEXUS_5,1.0,en].png | 4 ++-- ..._RoomMemberDetailsViewDark--3_3_null_4,NEXUS_5,1.0,en].png | 4 ++-- ..._RoomMemberDetailsViewDark--3_3_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...RoomMemberDetailsViewLight--2_2_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...RoomMemberDetailsViewLight--2_2_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...RoomMemberDetailsViewLight--2_2_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...RoomMemberDetailsViewLight--2_2_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...RoomMemberDetailsViewLight--2_2_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...RoomMemberDetailsViewLight--2_2_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...mbers_null_RoomMemberListDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...mbers_null_RoomMemberListDark_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...bers_null_RoomMemberListLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...bers_null_RoomMemberListLight_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png | 2 +- ....impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png | 2 +- ....impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png | 2 +- ...impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png | 4 ++-- ..._null_DefaultRoomListTopBarDark_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...null_DefaultRoomListTopBarLight_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...nents_null_RoomSummaryRowDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...nents_null_RoomSummaryRowDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...nents_null_RoomSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...nents_null_RoomSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...nents_null_RoomSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...nents_null_RoomSummaryRowDark_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...ents_null_RoomSummaryRowLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ents_null_RoomSummaryRowLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...ents_null_RoomSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...ents_null_RoomSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...ents_null_RoomSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...ents_null_RoomSummaryRowLight_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...list.impl.search_null_ContentTo_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...RoomListSearchResultContentDark_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...oomListSearchResultContentLight_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...st.impl_null_RoomListViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...st.impl_null_RoomListViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...st.impl_null_RoomListViewDark_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...st.impl_null_RoomListViewDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...st.impl_null_RoomListViewDark_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...st.impl_null_RoomListViewDark_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...st.impl_null_RoomListViewDark_0_null_7,NEXUS_5,1.0,en].png | 4 ++-- ...t.impl_null_RoomListViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...t.impl_null_RoomListViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...t.impl_null_RoomListViewLight_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...t.impl_null_RoomListViewLight_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...t.impl_null_RoomListViewLight_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...t.impl_null_RoomListViewLight_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...t.impl_null_RoomListViewLight_0_null_7,NEXUS_5,1.0,en].png | 4 ++-- ...ts.avatar_null_Avatars_Avatar_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ts.avatar_null_Avatars_Avatar_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_10,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_12,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_13,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_15,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_16,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_18,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_19,NEXUS_5,1.0,en].png | 2 +- ...s.avatar_null_Avatars_Avatar_0_null_21,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_22,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_24,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_25,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_27,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_28,NEXUS_5,1.0,en].png | 4 ++-- ...ts.avatar_null_Avatars_Avatar_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_30,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_31,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_33,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_34,NEXUS_5,1.0,en].png | 2 +- ...s.avatar_null_Avatars_Avatar_0_null_36,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_37,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_39,NEXUS_5,1.0,en].png | 4 ++-- ...ts.avatar_null_Avatars_Avatar_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_40,NEXUS_5,1.0,en].png | 4 ++-- ...ts.avatar_null_Avatars_Avatar_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...ts.avatar_null_Avatars_Avatar_0_null_7,NEXUS_5,1.0,en].png | 4 ++-- ...ts.avatar_null_Avatars_Avatar_0_null_9,NEXUS_5,1.0,en].png | 4 ++-- ...onents.avatar_null_UserAvatar-D_0_null,NEXUS_5,1.0,en].png | 3 +++ ...onents.avatar_null_UserAvatar-N_1_null,NEXUS_5,1.0,en].png | 3 +++ ...ll_CheckableMatrixUserRowDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ll_CheckableMatrixUserRowDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...l_CheckableMatrixUserRowLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...l_CheckableMatrixUserRowLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...null_CheckableUnresolvedUserRow_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...nts_null_MatrixUserHeaderDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...nts_null_MatrixUserHeaderDark_0_null_1,NEXUS_5,1.0,en].png | 2 +- ...ts_null_MatrixUserHeaderLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ts_null_MatrixUserHeaderLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...onents_null_MatrixUserRowDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...onents_null_MatrixUserRowDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...nents_null_MatrixUserRowLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...nents_null_MatrixUserRowLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...omponents_null_SelectedRoomDark_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...mponents_null_SelectedRoomLight_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...omponents_null_SelectedUserDark_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...mponents_null_SelectedUserLight_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...ents_null_SelectedUsersListDark_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...nts_null_SelectedUsersListLight_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...mponents_null_UnresolvedUserRow_0_null,NEXUS_5,1.0,en].png | 4 ++-- 241 files changed, 477 insertions(+), 471 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_UserAvatar-D_0_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_UserAvatar-N_1_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewDark_0_null_1,NEXUS_5,1.0,en].png index 7631149941..9031993cc7 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:208bb2b2743d33d15741f502329ac9ed67eb73c0556c14803edf33eafeadbc06 -size 28586 +oid sha256:ff5cb940c05656ed7debf230c7c2d780395e30f20c5d3da3abef136afb5359fe +size 28541 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewLight_0_null_1,NEXUS_5,1.0,en].png index f95d150d54..d65aa5499e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:abc707d2ec2e23878e78126063ea31c5eaa93559d2803fba5cf453e4a02a01bb -size 29293 +oid sha256:edf63c7ae4b058c94cd611948f2bb3c3304c2646af0200e08f7b480f1ba965d8 +size 29245 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_SearchMultipleUsersResultItem_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_SearchMultipleUsersResultItem_0_null,NEXUS_5,1.0,en].png index 9005d6750d..b027f127c4 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_SearchMultipleUsersResultItem_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_SearchMultipleUsersResultItem_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:013b3e67d39a895fb391b82a633d85bc5e372e2b209854dcda9a72db0c243812 -size 86646 +oid sha256:3fe351b3d0b78473fdab1d4bc806468485939734e46cb3fa6d9f9058513d4dba +size 86421 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_SearchSingleUserResultItem_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_SearchSingleUserResultItem_0_null,NEXUS_5,1.0,en].png index 349c6d27ac..0f8dfab3d3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_SearchSingleUserResultItem_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_SearchSingleUserResultItem_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1a72958cbdae4807f345d98501420e8f6ac1409ac534f8434341df4c3e53cd5e -size 45342 +oid sha256:9dbfb671a112ae3bab099db959b30dcd4185d48bd365f63373da62971df51e00 +size 45246 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_1,NEXUS_5,1.0,en].png index fd8b3f3e85..1b3c77ebaa 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f66d2db6c718056a13f463f0f0f62321250222039c234d267d788351a051ed4d -size 25777 +oid sha256:137a71939d978e2f10d94d49faed208c54a5fa82b32d9ba2b47a3946641d361f +size 25688 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_5,NEXUS_5,1.0,en].png index ef70f98f62..ee833eae85 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e688c0f31238dd9870c8634409f854b29cb5ab43ca251fb41466f959103627af -size 64149 +oid sha256:eb84e5f7f23db39d8d2d162f0d55d8129ae88e984dcde816c86682981226bf4f +size 64074 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_6,NEXUS_5,1.0,en].png index 97a7dd126d..1a18f078da 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:421f94cb97db6395d5b53188e7084599c2adba2ae44d38004d3e088bcc0daad2 -size 67968 +oid sha256:eeeb724c3797679434f580261071602e2b8991b466e0e47806c7d7b0e4e4be2a +size 67838 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_1,NEXUS_5,1.0,en].png index e84042b3eb..ed8846c5f4 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:44a6cda760e51d3710a951f38d14e1cc17a4fdcb91f281e8c002d424e53b82d6 -size 25829 +oid sha256:c2044763a0297a9d89c2a4ebb7fbd3ba967a5ac99a28375aeccf4766bc1a3be3 +size 25762 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_5,NEXUS_5,1.0,en].png index 4d4ea9cb15..b014ceeaa4 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:251f0553c3b80a4ca7c1c21fbf776c74ec6f0c85233d0481e0a6859c5f7fa53b -size 65976 +oid sha256:675584b016f10890e13008152ade861de50b3463de9a253353f0d1af4f57c200 +size 65789 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_6,NEXUS_5,1.0,en].png index 6b00bf5b03..3160672512 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:71639d6a2869732e57c682158360c1bf281a3c3ed3522007139200606794b3ec -size 69992 +oid sha256:708d5201ded559e388a453d0df87d97aa7068f4892d6acb8a3bf50497a6754eb +size 69831 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.configureroom_null_ConfigureRoomViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.configureroom_null_ConfigureRoomViewDark_0_null_1,NEXUS_5,1.0,en].png index 780a9a189a..aebe6c0c19 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.configureroom_null_ConfigureRoomViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.configureroom_null_ConfigureRoomViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:71255625dff4f333e8c8e0fe3cb77435dc552fdc756b8b517e2a783cf6c4677e -size 83540 +oid sha256:7816a99e6460155c0d4c8f74fec6b2f09ec724f3442f5b1e77b45e98b5d43be1 +size 83585 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.configureroom_null_ConfigureRoomViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.configureroom_null_ConfigureRoomViewLight_0_null_1,NEXUS_5,1.0,en].png index 6ecce2c456..2b4f8e8e26 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.configureroom_null_ConfigureRoomViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.configureroom_null_ConfigureRoomViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0af148880e1609550dca835b9ca7d18ca277f19c056d5acc160d6877dc2192e0 -size 87215 +oid sha256:ec1b567e5175c9e83aee05623270f2f2d5497c901438042075a2b57a1284a368 +size 87153 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewDark_0_null_1,NEXUS_5,1.0,en].png index c45576d5cc..11393a5279 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e49f264556720e31a6974923f38765a4612f65a6be682dcb30cb65b4693c1171 -size 20738 +oid sha256:a59a7d481cdcc7b3fa216bc3ec4a20195730d27fe518a6610d9a61fb4a3b347f +size 20753 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewDark_0_null_2,NEXUS_5,1.0,en].png index 5bf0a8b17f..786c163f1e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fdc6810543c33b89da0d3ed0242d36ae4f33d3d16c73a6d4a6169abbbe28d8e3 -size 27046 +oid sha256:22ac66742c1e14c8f9ddf8f56f86fd155f6f8d3adfc90483772f4f78c71fe81c +size 27063 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewLight_0_null_1,NEXUS_5,1.0,en].png index 8d4037d07b..a4ed8eb2e3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:97dd59ac203eab2b727c3ceeb5191db5c4ad2d75eb1bc6676694ed06db7081ff -size 23810 +oid sha256:fd1cce3d0a456d3501f0f5c5160821210fd1060c24a66f1cacb65f9f95b44bb8 +size 23792 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewLight_0_null_2,NEXUS_5,1.0,en].png index 02d70404c1..05509fabe3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5288dbf84bb4f976917d7be59c469306397d97cc42065ad085dbe10ee75aa20f -size 31185 +oid sha256:2f26d62e7ca9b98ca9314305b0659f7919b58f5d7805684832e91d5f3cb6ece4 +size 31162 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_0,NEXUS_5,1.0,en].png index ee189e660a..16876034a0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e13873cff0df39c7aec90c64041d8eb557bd2cd65935a34fb7122951b7cc0b87 -size 28452 +oid sha256:5740c7f4d76a786612c5a1cb9e58c29c87778f3e8d11878f310cfda3da1bed8a +size 28445 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_1,NEXUS_5,1.0,en].png index cc4b32b204..9f6e875358 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6128ba7f2b0b5389be5310bf3778c093ea30a92fa3f78173e7d3aafce834b14d -size 32920 +oid sha256:fbb6813f970b0fcfa9489d06b28b2e17d6d0fc97d2f0494553a629df930af48c +size 32919 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png index 8b95e73430..da5124b675 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5cb2252cfbd249fdb47c17881410f44fbdc8cbc0f8a8e79b8c973a311f77f3a9 -size 33053 +oid sha256:633165e86d70889024469309db5a4f44eaa00456f0452e6c1447ed7e24b7bc4b +size 33059 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png index dd98b758bb..e3e06b6a66 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5c57803651c508e3d041a1a99cb3454935f2d7ae36ef82f8d0099c00089c96af -size 14041 +oid sha256:6fb2d663532efdd393063f3a1a53ad0da2bad91033dec2d6bad971f681a56a45 +size 14016 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png index 82f1f4484f..986ba9ee23 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9a3693f62c718cb061106b0c33e162d4eb82efc766aa81d164dc860ec4394a17 -size 28611 +oid sha256:1e030b3d98c9d4e6a37a983b180e664b45697705a966bc9348ea432e123a3b6d +size 28604 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_0,NEXUS_5,1.0,en].png index 48f2d5d109..27daa2fd10 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cb11c46a91a1fe4e2227a6de21d418e698bb70ce68afafaefc5280a979a86bf3 -size 29114 +oid sha256:d75bae2ae2ee8a407d2b4652d699e664e619cffa5a7888cdf6169395abb97c6a +size 29142 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_1,NEXUS_5,1.0,en].png index 900343f7d4..c1dc2207c0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2229208fd03717884b2af74aebdce70411f50c0b69a47093a6e8346dd9766610 -size 34892 +oid sha256:13fa1f840184a20cea94d1cd9d76480eda1c458225b4514e37213080c936d3fd +size 34888 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png index 5b4967d6f0..c45e89835f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:02fd7d1c9b3f982c2fbfad109c55bd444ef183855800490cf9117606b493c314 -size 35018 +oid sha256:5abcb5badc21e715c6f7c4330e5721b0275fdcc678ca3920ce64ae5d34829250 +size 35005 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png index bccbae96c0..23a8c73c75 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:18589707589516bd02024a4989b47bb57204bdc77b882ebbcfc0b79be6314c9d -size 14173 +oid sha256:772d4d50bbed5bc5cebc8f636ce952fdc4951b714e4d621030a87db7a1df9c01 +size 14162 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png index 8615c02572..1ce40f977b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aaaa719eafbd61ad499b9dbc7d1ce1afa3d1b3dfc8e3a170b2f785a51684802a -size 29424 +oid sha256:e3cd5c467381c74c579e62405bc6016da1b9b050365d04a335845a19d1ae2c41 +size 29448 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_0,NEXUS_5,1.0,en].png index 12c6450dea..3552000829 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4bef80d54bce17851bbc1d003055743e1c7e95b0ee069261aa5e2732e7b722e6 -size 52319 +oid sha256:2aad1e4a3ba3691a37c9a2df872609ce7b7cbfb326deca6e5a81e6a0a50fb19b +size 52305 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_2,NEXUS_5,1.0,en].png index 41adebbccb..fb13cb54ab 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6814fb800186b8c0e6d2c4c07f2f959a5962a94fbbfd1c15d83d2a789457d930 -size 49646 +oid sha256:bb5f62cf093e48c40732d801cb27c51005c82f84aaf96ce86e5dc50c54ff27cb +size 49589 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_3,NEXUS_5,1.0,en].png index 322b98f06b..42cdd40e09 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:09b31e87abee30225e796c3232b84c4670d57feb19c056de4238f60329e036d9 -size 50315 +oid sha256:d4954c0ae06d16a0058b88eb9b648911eb0c8b36eba19e40031bcf5ec6c262ff +size 50257 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_4,NEXUS_5,1.0,en].png index c685dd2cba..568bdb2d89 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:90ff5065ec23e1c835ac395015e0f5491d44722262951f72a19a184d9e3a47da -size 40245 +oid sha256:0623f68ed17b1d7e39b2737255a2f3d5448a984bcef00ee58558a7581af84074 +size 40173 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_5,NEXUS_5,1.0,en].png index c685dd2cba..568bdb2d89 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:90ff5065ec23e1c835ac395015e0f5491d44722262951f72a19a184d9e3a47da -size 40245 +oid sha256:0623f68ed17b1d7e39b2737255a2f3d5448a984bcef00ee58558a7581af84074 +size 40173 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_0,NEXUS_5,1.0,en].png index cff979f7a8..44650d97d4 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7a348097d43335133ff83958b0b1dc24de2e4aae0fa2be6d000a7ca78516964b -size 55172 +oid sha256:9357fbad1987326b891699fb5e176e4458d1b7dbe660df95d20c079d8f38bc52 +size 55154 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_2,NEXUS_5,1.0,en].png index aa81a4ff8d..0e6271869c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a0aa744f1d069c68202a087789328c1ac46c45d6fb9bae8b5593bc477c182dde -size 54182 +oid sha256:840b7a0a23d458680f59f328d2a8b756e80ab76e368d749a511e7352d31d0f4f +size 54196 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_3,NEXUS_5,1.0,en].png index cb710c9dcd..7c71ef8088 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b7edbfc8e9e8bdcea6897860d1872fb8fabce139ec8610ec6180b28ca9ce9007 -size 54976 +oid sha256:062f857b2b2339f54543b70a864786b1463747cb7e45db54f76b1831938dd98f +size 54984 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_4,NEXUS_5,1.0,en].png index 7b79f5ff42..31b2eb0efb 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:380ae6ad1fa6f00427eb7267a338964b6f77a4d5f8c45c25f535502481e34cc6 -size 44834 +oid sha256:63070cf809fe17adedc37b9df0b9a421c453d09e8edd95869fb62f4b1b066a16 +size 44827 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_5,NEXUS_5,1.0,en].png index 7b79f5ff42..31b2eb0efb 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:380ae6ad1fa6f00427eb7267a338964b6f77a4d5f8c45c25f535502481e34cc6 -size 44834 +oid sha256:63070cf809fe17adedc37b9df0b9a421c453d09e8edd95869fb62f4b1b066a16 +size 44827 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_2,NEXUS_5,1.0,en].png index 50a0dbc183..0ccf45d0dd 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:830ead63e3965435fc6fff2c8aa0c83d2654dd151972d8d88ad025dab2ff2902 -size 38536 +oid sha256:b64a7ad8a711dcb67a5b130bac5f3083421ff79b4476060fa5f54f3b14dac173 +size 38511 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_8,NEXUS_5,1.0,en].png index cb2e25b07f..3b48d22222 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3598515dc84276014c2f3827f533c808a2683191a67e7a68191501bb848b8293 -size 28326 +oid sha256:4e335de03505f63e0b02ef98b916a1fd979b32a58f3c91bf0dc6194d6b66d671 +size 28302 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_2,NEXUS_5,1.0,en].png index 7902cce465..1e64e85760 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e433bf7d2f96067dc0743e262d8907a45f0e404cfb307a018fe671dcee9d5f02 -size 37054 +oid sha256:5366117e506df73eb6073bfcdc76738a89262c4ff83182a381c50b98230c71c2 +size 37051 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_8,NEXUS_5,1.0,en].png index 0311150ab0..53b1988ad5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d00152b1ff92d93564af11537dcb8d77116e943cfa2b45dee2c66260284b8807 -size 26875 +oid sha256:286f4ed93711fe203aace6e629971b6681ed74cb2a9cd7cb8544125144d4fb17 +size 26867 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_2,NEXUS_5,1.0,en].png index d6ec63a2fc..d41ab12fd3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d5e4d1ba12c6372c7d53e3d6a8a4d11e2882a16d1dad0899248b5663557bc359 -size 26999 +oid sha256:98bfdfa99e207e5f50aa6a6aa08914b8f2be407d5547f39984a0a3e05d41bab7 +size 26932 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_3,NEXUS_5,1.0,en].png index dfdc242956..a6fc15351a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e10d7e07f854017d9fe902649d66dd30b39624a0667023962004236986c30b2 -size 26540 +oid sha256:05e62d2584c3eda7e22068731de56223393e869c8e91ac547a148a7f84e870dc +size 26485 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_4,NEXUS_5,1.0,en].png index f2759edd0a..e7d3a908ec 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:57776151ae74ec98a498b59ee05841cfa50c6cb657c2706e54a7deba058a2a0a -size 26530 +oid sha256:e72e276a8a0fefafe36314ec82f6ea1ca8f9bcb077afecc49f65ba977a59595f +size 26473 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_5,NEXUS_5,1.0,en].png index f2759edd0a..e7d3a908ec 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:57776151ae74ec98a498b59ee05841cfa50c6cb657c2706e54a7deba058a2a0a -size 26530 +oid sha256:e72e276a8a0fefafe36314ec82f6ea1ca8f9bcb077afecc49f65ba977a59595f +size 26473 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_7,NEXUS_5,1.0,en].png index f2759edd0a..e7d3a908ec 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:57776151ae74ec98a498b59ee05841cfa50c6cb657c2706e54a7deba058a2a0a -size 26530 +oid sha256:e72e276a8a0fefafe36314ec82f6ea1ca8f9bcb077afecc49f65ba977a59595f +size 26473 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_2,NEXUS_5,1.0,en].png index 6ed0384bfd..6b74783202 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e1503c710bf466e643720c73387d92b38c34aed007b34153dc5170066688dee -size 28759 +oid sha256:080d58220454a98725f418f931c6e18c4af11821076d8cd446525098a52db6d2 +size 28739 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_3,NEXUS_5,1.0,en].png index 0754809b7f..2ce5fc6bc0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a104e7f7fa15a31d9d6ebf30e6a8e59ba6cdc3155cc7e7274ef63ab6bc884473 -size 28164 +oid sha256:7da900d8aab1134bbcc472104a876c390f156a9531f1f3f7d57e2e9211be5ba6 +size 28146 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_4,NEXUS_5,1.0,en].png index bcf6d823ab..24919e87b8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da0a285163516046676b6a0f5d2660f03be7a9c08209e7198d2d5726df2cafa3 -size 28230 +oid sha256:3f70d7796f416ec68599128d2da46304150b57d83262aa706e70fcf85d3b80a3 +size 28198 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_5,NEXUS_5,1.0,en].png index bcf6d823ab..24919e87b8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da0a285163516046676b6a0f5d2660f03be7a9c08209e7198d2d5726df2cafa3 -size 28230 +oid sha256:3f70d7796f416ec68599128d2da46304150b57d83262aa706e70fcf85d3b80a3 +size 28198 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_7,NEXUS_5,1.0,en].png index bcf6d823ab..24919e87b8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da0a285163516046676b6a0f5d2660f03be7a9c08209e7198d2d5726df2cafa3 -size 28230 +oid sha256:3f70d7796f416ec68599128d2da46304150b57d83262aa706e70fcf85d3b80a3 +size 28198 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_null_SheetContent-D-14_15_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_null_SheetContent-D-14_15_null_0,NEXUS_5,1.0,en].png index 1e577f0904..9572127bae 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_null_SheetContent-D-14_15_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_null_SheetContent-D-14_15_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d0c32a81b2e3c751a7eb8c60ba71ed4b53e73fee920f02aab63d35fa492be87a -size 25266 +oid sha256:094a0f5436527308d2a37b52f6e0c5f12e267f214b79fae980e409da116a07ec +size 25277 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_null_SheetContent-N-14_16_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_null_SheetContent-N-14_16_null_0,NEXUS_5,1.0,en].png index 5f41e9dfef..73180b7d05 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_null_SheetContent-N-14_16_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_null_SheetContent-N-14_16_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c47835cf1fc4cf11f183ee7e658d2a4d16a83b17b6a03750f16e660867442b51 -size 24948 +oid sha256:f0a29a48138febe8b13b1e1099fbeab2280f1b0567233614187d97117df05de0 +size 24943 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowDark_0_null,NEXUS_5,1.0,en].png index 9158fb98e9..722bd8c6a5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ad2c0bb00b406a7fc3497117a89be7422390c7be16aa1f078c5be3791f8fcfd8 -size 151481 +oid sha256:f0ad6895582183b697732ef032f89a6a0cad32106c9bbf30925c390dcab65ee6 +size 151752 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowLight_0_null,NEXUS_5,1.0,en].png index cf59c8c1a2..fb9457779e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowLight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowLight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cb32728cfcad251e3bd2ddee2a40456f329e8e3a910d145b58a3323322c8a721 -size 156825 +oid sha256:676b62ab782652c45a7267aac5df12943fd181bea48964d28dce664884ae4182 +size 156619 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowLongSenderName_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowLongSenderName_0_null,NEXUS_5,1.0,en].png index 56d35e8f11..4011a2572a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowLongSenderName_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowLongSenderName_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cb071f845598b35931253304f4c9f4c865b5fe9f57662c03c88a0c94a7835d83 -size 18615 +oid sha256:82459b6a9a3882bcdba78e89f8938f3749d6fabb4673bd0a4cc953d2b7f069d9 +size 18215 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_0,NEXUS_5,1.0,en].png index 1bba8742c9..923bbeea49 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:860bc20fb4c847183290adcf1f76d1a382b0dad4d3f11a987924a816e6b5609a -size 62000 +oid sha256:c196f9cb2da2366e4e67d59012f61c5f50a5775475230c3a0cbc8d823ba53dcd +size 63317 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_1,NEXUS_5,1.0,en].png index dcb828c9db..b59ac27461 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:70f4e9bff2565317041fd037c2a0d9bf596b0c67d04927e64e89f7674f4a9966 -size 64038 +oid sha256:59773d8a5435a37b3d47bf0c41412299b0b277af4be7a1a25ccb33b4b60a32db +size 65397 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_2,NEXUS_5,1.0,en].png index bc89b7cde5..c586722f7b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:474628a1247dc41f3b17dfaa0174fd47b4468f075fc728d14419b7299d7952a1 -size 68584 +oid sha256:ee692fa3f3dbe4500cff084526a4537fef6444440c78f63a03d990a6a027f794 +size 69844 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_3,NEXUS_5,1.0,en].png index 740f11b5bf..b518541c41 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d30f7b8de3ba0b44350eff2ebb8cd0d2572b435208673edbaf6c9914cf79a703 -size 70541 +oid sha256:0b8155faa2599615048193667f540664c7185ac7b6a9159afdc14dfb6286d62e +size 71826 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_0,NEXUS_5,1.0,en].png index dd47e9ed26..7cc47ddfae 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:705c1bdcd680cd85759b9644f266eb0c1d343f76001bea1ac667b21ca9b9e390 -size 63441 +oid sha256:771343ea6a9d83160284b3a9248f744c68ab25c2ad64817269c3628a5ca67972 +size 62319 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_1,NEXUS_5,1.0,en].png index 2744202175..903f4965cc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8307f0003cea667faf6d8fd57b4b650a00c6728d7bebebed22d7991a0c2f158a -size 65924 +oid sha256:4663107c550f193aa9bb23b6bccf9229aed5ad30c380ce6b9a326e6a3fe5def7 +size 64854 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_2,NEXUS_5,1.0,en].png index 19023b2f69..60029246ea 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b519caf1e062d1fd9f3f6b0b122efcbe77775508fe272283cda71cc76eff9b8a -size 70408 +oid sha256:ca51c27cb553709458343bf16d8402a55eb1b7187b4b85191c3318f5b88c29db +size 69312 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_3,NEXUS_5,1.0,en].png index a7f9730ab8..08348ad401 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e15b3ac5a03ddcd0bdd72528541a8f95e4fd40ccfa3bad2269b878890dc4aeac -size 73123 +oid sha256:b0a825d8090414c617780bf2d7332b8e80e5e4de066cd117c53f5e90cae8d4f6 +size 72112 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithManyReactionsDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithManyReactionsDark_0_null,NEXUS_5,1.0,en].png index 6052944bf4..ee5176435a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithManyReactionsDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithManyReactionsDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a5edcd092587b8c006f32f5da93b2658ca0ab6f0fecb17f617b93cd1fb5f4b03 -size 81123 +oid sha256:21f0f4844935aec3102efc6bda98be54f48e8dedbdc539907199e5f4edc3a9b9 +size 81343 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithManyReactionsLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithManyReactionsLight_0_null,NEXUS_5,1.0,en].png index 757252b315..37620fce39 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithManyReactionsLight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithManyReactionsLight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:40fee515ef4e1bbc3cda0ccedf7b9c6fa48e040db79de5c9c40bdae6461cd018 -size 84907 +oid sha256:155baab65e9a3431f7afc8320e0b9ff12454a5faaef6c34701e50e7b0d1c3c0f +size 84763 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyDark_0_null,NEXUS_5,1.0,en].png index 7484490f6d..c39b41db87 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fe770a92f211c69118868e0fa8c451680ee30f64c9ddc99c426c13690a4b8c8e -size 127240 +oid sha256:b991a34a137d82ff4dedf48316a05ebbc008233984b11af70e64889a5fb5eda8 +size 127438 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyLight_0_null,NEXUS_5,1.0,en].png index 8b506e4e44..a6500ca748 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyLight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyLight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fe1687609b8da30cea710072927512219d628e40b74ca53751c0560b5c72a9d6 -size 132412 +oid sha256:43b6514716d18382c8962520928d9d2ff6d0f665b2471e8a24e5d2e44a25c88c +size 132295 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventTimestampBelow_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventTimestampBelow_0_null,NEXUS_5,1.0,en].png index c1d740b8cb..6f6070772e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventTimestampBelow_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventTimestampBelow_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f689d80043e7d5121d072b928c866a3bde0358b5d5df06e1d4f0ceeb9a11dfef -size 56344 +oid sha256:fe0a95b6c94668709c75052feec2953d310b8bcfda42758b2898e28b384ce193 +size 56189 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_0,NEXUS_5,1.0,en].png index 8474499ecc..93b0744c82 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:af68664850a3604c8df21d0395a0ea06ad7286a5ca6889c4a2814e61003f14a2 -size 52312 +oid sha256:e40acbd30f8d9f815161b6a3ed1646733568015f03ffb0f24efaf6ec7fcdad6e +size 52145 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_1,NEXUS_5,1.0,en].png index b9c07b4b9e..021bf7cada 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1dbc2fec7de4e8ec1cddce4f2c8522b74c3ff4c8688170f8188412ca7dc7b561 -size 64049 +oid sha256:fd2166469e00817c11b429c3e4c8508f56aba93696bb182310a277873e8ef080 +size 63847 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_10,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_10,NEXUS_5,1.0,en].png index b2ab3a2244..f3e8bdfb28 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_10,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_10,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9329845bb7ddd9cbdf6756061a442d5a227b0acfffc4d372570245422ed2766e -size 50300 +oid sha256:53c5d2bce5d3502d5b09610faefeb68d20514076ba4a8189f7fc8f41c8e3174c +size 50150 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_11,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_11,NEXUS_5,1.0,en].png index fd56993e7a..2c4900d9e7 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_11,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_11,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aa69e3166a92a13a1b263f4040fc2431a33d52a6542bc809fc026e5a7dad3cbd -size 67359 +oid sha256:1223ea8bca4d42e8f5a6cace4a530055df5f6f0eea02c62e9b35104aff7408ad +size 67145 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_12,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_12,NEXUS_5,1.0,en].png index 9ffdb4df92..3138d3ee2a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_12,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_12,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ef257207d4497ea056fa37bff1ce9bff7793517d1ed83bda82fdaf2792147ce -size 57441 +oid sha256:48784809032f7474179742d8cf83986a366c62e1678a2d2f4a94e09856ff6302 +size 57274 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_4,NEXUS_5,1.0,en].png index 411213a72b..ef3c05fdb1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b03bb08a6cebdc1adece3deaecc07964d29f893d151ab693b490af1c9b4078d1 -size 72362 +oid sha256:ed11b0598ea4b2a991bbf6188372c33f35a3a661785ffdaefe4ef5257576e460 +size 72181 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_5,NEXUS_5,1.0,en].png index a41c9434c0..83b1c4316c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:160f3917d6918f0f5be4bc39d537528dd654c8e26ac6e3d5b8020bb2ef132ac5 -size 87912 +oid sha256:5c1d4fa3e1f403c0e5cd7583f9204759a0cba7dc63b4d1bb5d6a889cfcd10ab8 +size 87675 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_8,NEXUS_5,1.0,en].png index c071274718..0e34e05ec5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e0725e61bc775166de6d82f5730e223ff9d10f6ffa3e7598a17fd3cc4c2af434 -size 53848 +oid sha256:edcc8b013786ec7b316161deb347278085fa196520b2d4acee74b5e2b426efc6 +size 53677 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_9,NEXUS_5,1.0,en].png index 30335490d1..89f5efe6e2 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_9,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_9,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1bc72ead6dc9f348f5bf2dd1cba24e2903c990a85414f6f155437bc0237e7ddf -size 66060 +oid sha256:d9ee29be03d3e25834cfa50194ae8280b09fcac2dbf8fc79416638b36ffd07eb +size 65852 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_0,NEXUS_5,1.0,en].png index 2b0a249003..a9b5cc33de 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e28eec0e60cef1d1234ccae1031413105e2291f1367537b9eb36b038402dd29e -size 50314 +oid sha256:bdd5697196181f91a5d36f8ec4170d5d8668052f67478d22f0c2f1d39ed3cf37 +size 50397 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_1,NEXUS_5,1.0,en].png index 38fd06b5d1..15a02387b7 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ef4295d36c3fc110ba5b04032e4fa71f39879d05e368f6eb88fadba7ffd501a5 -size 61306 +oid sha256:b029a486993477abddf2cd602c5b935dd1fa4b22d1df5ef918c428f5714ca6bf +size 61327 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_10,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_10,NEXUS_5,1.0,en].png index 066d89473d..7b2dc3f516 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_10,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_10,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:23703da549937fc871388f12a07f0aca70095273cd90f0eb21bce9e89500bf81 -size 48528 +oid sha256:d9c28c48732089f547388c779922c3cf3dfe1c41d5d38df93366ab6c0a546327 +size 48617 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_11,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_11,NEXUS_5,1.0,en].png index a08f83f399..9e476a55e1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_11,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_11,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:015afae65070b8df055542730915e029dcf36493ed491f23a801861547cb7314 -size 64378 +oid sha256:56e14c49836bd57eec889ac66bf0016da7e0c5bcdc9c51309e680ef77adc12ba +size 64406 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_12,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_12,NEXUS_5,1.0,en].png index 710a494e69..b43b1872c1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_12,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_12,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dc3691993fab8d245c72ab1d3318f73c36f02709f4a7fa3abb664209947bb257 -size 54972 +oid sha256:cb26b5d108b12720d523d2912b4f71a7799322565bda95087fc8cf52a6bfd2b9 +size 55070 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_4,NEXUS_5,1.0,en].png index d51df54093..2a2361797c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:33ae97a6acd31df8419b2066b86d97628151a3aed0464abdec5fbcb4028e3f9d -size 69435 +oid sha256:27d7a635a477aa1b2a4d0ae657333ecf55eafb9a84f29e5494526a64e7c085a0 +size 69525 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_5,NEXUS_5,1.0,en].png index d1f3020e18..8507c48fa6 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:74637c58a18194e1d3af5d3be5755cda81107216732cf8064c49a3dda346c487 -size 82836 +oid sha256:8776d4f031fbb8c934081ac29b6b6bd5746bdd67edac0904e1468b76727ef541 +size 82893 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_8,NEXUS_5,1.0,en].png index a4e5f88942..be7f3f8601 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:354d3112e77e3839dfa894f5baffc68c61795592d3f17a3401595dd47a1c63b7 -size 51648 +oid sha256:60858ea74ed5fe4ef865ccd3f0290edd32bf87ad010f5f7691153491c163c42a +size 51734 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_9,NEXUS_5,1.0,en].png index d997157e7c..d69df0df42 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_9,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_9,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6b988dd6ede4b8e7fd4d488677bf1cb2ab46c2a50f30551268d1573b1466633c -size 63282 +oid sha256:4745bb37c991a9a90996a9ce8975639cf5fcb2d8981d0147d6a3445650d63620 +size 63304 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_0,NEXUS_5,1.0,en].png index 3f327480f0..08734109fb 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4ebcbfc34ae17c122d3372d3cf5676c95d1c82db8c23bec467490b1787e267bc -size 51288 +oid sha256:39b527075df2b3f7afa4f3ecfca1ac93a180855b20d2bd64cb763fb98b0a7b69 +size 51340 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_1,NEXUS_5,1.0,en].png index d8ec14e7c2..60f606fe58 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:83d62d8eb4aadd86e7aa07076df9ea615f2f18b6520086bcaf44e9ae086c870f -size 52540 +oid sha256:81f196dc08f4de31f4257f6ba89c52ea41a97b107e7c5c04261188e6c572d4d0 +size 52594 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png index 44c28c0a3f..6b3be5e81e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:937c9762afb8aa96715acb5239364f42ed0bc2afba764a2f15eadb5782803286 -size 51523 +oid sha256:a648d286a3b0536fc97801c3281bb8df432c7ffa28efff66f67cd6cf4c546c10 +size 51579 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_3,NEXUS_5,1.0,en].png index ee186b8130..57b61342dc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:87770ae87e7d8a74e04842c47d55c3554c348997e2c03fc65b67add3db7980c0 -size 53931 +oid sha256:7225f3510289f07d4c273e3bb179d05df0ac9f1a2ec868f061a2622c6f9d0b84 +size 54030 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_4,NEXUS_5,1.0,en].png index 951de46085..e2266026d1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8737e6006d60b361b5039c0989fd142554b09ce9847dc649139cb7ef9f901d9a -size 50597 +oid sha256:34f9eacfd61965cfde4f420fe6a0fc0d637a21aca0d4b12c6a6f1642bd44556d +size 50586 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_5,NEXUS_5,1.0,en].png index 0f04cd7988..040fa6c12a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1d71dea06589fdd8b62843d6898a74eff256ed0206ed8ad1ddc689f69d145a72 -size 48869 +oid sha256:c336a9cbc803eb314aa9333719d813ae64994a75344aa363b25aee8d52551b21 +size 48928 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_0,NEXUS_5,1.0,en].png index cf1b87bde4..a178b31231 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bda5e19667a7acab4f72ad4dc10fead50f1f3373bd67b6db82eee50c3b53fcdc -size 53096 +oid sha256:5d7148068516b5e3299cce2924ea3cb54c8f1ddd6378e48b0fa746217a547d22 +size 52940 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_1,NEXUS_5,1.0,en].png index a3785ac776..f4a3738cf8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8188739ddc45610d6539592e7aa62a679436f90248b3eaa95ff76b7da808e6e3 -size 54453 +oid sha256:b8aaf2c70473711a24bf587ff524fd71d43c2610ade1c3d4ff2013705d5670b3 +size 54314 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png index 0be5726cab..f40d649d64 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:14d058d0867360a6648876572001087835a06aba20710ed5381bdf393ab5e3df -size 53409 +oid sha256:566d5b197091d4b740e1241eab54017fd31e65f570def4b8c24ade19ea78ccc8 +size 53254 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_3,NEXUS_5,1.0,en].png index 4a53e5dbbc..cd18a11803 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f2485a5713950429ea18c4a7275c2b86a214e45f100116a93c1252b4011aa75a -size 55956 +oid sha256:c9f686208853c864a9aada2c809a43e1de230e422e93af7c6330b8e78dffffec +size 55730 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_4,NEXUS_5,1.0,en].png index 82e1cd0fea..4e0d1ce4bc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cf7a41495ded2f16c86fd293096234ff730dc9bc84814aaec98b01fb9eb56e69 -size 55402 +oid sha256:8353077959916fa85046d3a81d1479d552748635f1286bb8bacc6d922ba30f28 +size 55312 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_5,NEXUS_5,1.0,en].png index becdf3d51c..d2ac508bf8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:87ab35c42a7b42a2625625bc99575ef37d54b84256554ee2e2b5bab80bf4700b -size 50465 +oid sha256:a84dabfdcbaff8de5c30472676dee2cee8dc0f77469f2802dfc796a87bc10dff +size 50328 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png index d590c4eb8e..5fcb6cc260 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:72eee76cc8244eb54f147fc589c7b200dc3a46db4ea7306dbd6757918e4fffde -size 39744 +oid sha256:46bdcc0dcd5dd9ae0740eeb0af0b0587f1989689ec744c2f38cb4813c860bfab +size 39711 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png index a3449da98e..3b7938f529 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8796e5f70cdd09087ed22ede78c3aed985dcd57e073f68d83dd5884e4f29a2c8 -size 39042 +oid sha256:ae44b96af239aee5fc7839df08f9298490add53d76c51f4778d2af4d57aa746b +size 39043 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png index 370689a2fc..f973a24462 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:97250f48dfa0cf2320f837eb87ad90d8a1e73642fbb2d571f326d689c4fc10e0 -size 42373 +oid sha256:66cf5b700fefe4839d6956e83d7590711bc38a659e41d0aff829cf877e7dc209 +size 42351 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png index 6bf7f8fdb0..e400a8de25 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:73f2811197c014d91834d39dad1fe18abdaea9b2510d8deccead39c10a1b5aa8 -size 42473 +oid sha256:9372f8f7e0a173d680fd860fbbe7e4319409b82b02cad8b83eca2059fbf35bba +size 42486 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesDark_0_null_0,NEXUS_5,1.0,en].png index 8bb0a53a37..f7d8135d0b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9048da25ad83e544de8dfa2ec910b7650e34c78a0864e0e1f9644fa18a0ffba8 -size 13144 +oid sha256:964d97909629c1228e96d923ddb478735475839b8540c02142444f9ebd5bf400 +size 13100 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesDark_0_null_1,NEXUS_5,1.0,en].png index 8e68fdc6c1..bff7b81448 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58660c588499291f198046058bf725844bde74a7db4c371d29ee43fba2780e04 +oid sha256:bd8ff4a09babf30be0eb3c336f3cbe6a1508a21696512d0dadbcc9d543e6e34f size 12356 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesLight_0_null_0,NEXUS_5,1.0,en].png index 754ea0cecb..fe1fe39c26 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6d4ee26a608ba57aa6e9eca05d4db22a9135243a73faf767cdc10ff0252079a2 -size 12887 +oid sha256:85530997942e39ce73512513ab0698494778168bc28cfab543b50b721c1807f5 +size 12855 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesLight_0_null_1,NEXUS_5,1.0,en].png index 05e82479e2..23211c9508 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8daffe981e83c5a81b60ec1d00d09a12fb3a67d3bd957bab5b0b924480330bfe -size 12952 +oid sha256:2e0a638be5745c75c2663116877d380c83df093d226d2c969d4f6620e8cee109 +size 12965 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_0,NEXUS_5,1.0,en].png index bf92475b4c..3703690be4 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b9e26aa62cf66b8fc92025cc7cc4cb4f1a8f298edb1b7ccc2597cb8fc16cc876 -size 29888 +oid sha256:48311f503e47fc462a1f4d5afa2ea82c0e0eef99aaddea9cfabf5517af37bcd5 +size 29796 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_1,NEXUS_5,1.0,en].png index 360298acc8..d19b6c9ec9 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d05e01f9c8d0a6173debaf8b6a8491e705b19b3dc0ec2ea133d6f59a210d5388 -size 23442 +oid sha256:1aaa12b291dc1e187835114eb8c5c49bb4eb5bf16d87b039272a6e32e16cc6e2 +size 23369 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_3,NEXUS_5,1.0,en].png index 189dac37b4..46ed873359 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cf8fcba0dff3f86fe7334b829e710f31dce67b5ca207474ac6b1a138568cad9c -size 28824 +oid sha256:82e2cd2caae9b20cb2e3990216b0ecdf0bcfde4478911f00168e4f936c223889 +size 28736 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_4,NEXUS_5,1.0,en].png index fa4f813321..ac9817e2c7 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6485d6e4eb3429140d73f54d99467b2058628681f3588c1462d59390ec7b1bd1 -size 28562 +oid sha256:b2cb829eadcf07760a073af775be6d15e91624a9366d7bde366d7c9cfabe2c9b +size 28456 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_5,NEXUS_5,1.0,en].png index ff4c6d9a78..ade52ae50b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:922a88411d9c53be79d4c755c977e3a0102fb5a91003c57084048b1597ac924b -size 28878 +oid sha256:e142fdf51287c82112267ac8070ff4d6c2fc3f92c14c82c16127aa1822823312 +size 28839 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_6,NEXUS_5,1.0,en].png index 6a122cd7db..abb2875d87 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8911100294fac69ccff4c6d90df5b72e4c45590e369fba3cafca77a0f31b4927 -size 25049 +oid sha256:447fdfc57825e1da34d294b7e212984b088e283810fe961c5b21b66f3c770cbb +size 24971 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_0,NEXUS_5,1.0,en].png index 4bd5c9f12a..9fa729c209 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2ee4fc0d07c55e3729d2cfa81f1304e3553ef9927dc4d7893c9c893b3e888af2 -size 31129 +oid sha256:2b27f3e2719d238b61a8f83264417c9c2d9e561bbaf12eea20f9169366c90489 +size 31076 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_1,NEXUS_5,1.0,en].png index 703e90febf..1408e43788 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6ebeb7f5a99059d2a90acb98f6453ae4b9292ccd57a5b17239a58c6e87d83cdd -size 24410 +oid sha256:b5b4b04d5163e8acec4f156396fd239296b7fe3fc251fc5efa78200f4b6a0e83 +size 24352 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_3,NEXUS_5,1.0,en].png index 17c8b03f44..1dddcbf124 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a90489e5bf9bf1509f17f4f5e36c2b8f72b15e0b9120c29393e6f9d394a58d47 -size 30842 +oid sha256:61b56cbc0193c9081ceb3c8662afc2da8686a7de4a3e8ed12af2f7dadfd0328a +size 30784 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_4,NEXUS_5,1.0,en].png index 2014be77c7..d108a47a92 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:88887436882d7a079ea677bd6a3a947f44c961b1715ceca2ff3955dc178ea675 -size 29767 +oid sha256:f7ff9340f9788a65fe6ec4707cba125196fed08bb57ead4dce8bce2efb70f1f6 +size 29714 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_5,NEXUS_5,1.0,en].png index abf7196fb4..68b91dcaaf 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ed04dcb3e6b3dd792b6500573ee60a64fc08fc6f767e2bb90f54518bcdab385e -size 30862 +oid sha256:3ab65feb9ba77f6a08e52fae42f32133845f169c651049e90c32c3abfbd8cea1 +size 30835 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_6,NEXUS_5,1.0,en].png index 4c4f348533..29f2bfe96a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7470928e4f59c48239d7936805235e3deb04fe5c242d4a5c173649052dff1f5b -size 28255 +oid sha256:bf0735290b594857c52df56f2704b3e9ac7bae00a61a26b956febd5c6679357a +size 28228 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_1,NEXUS_5,1.0,en].png index 56593ba4cd..774ae616b9 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8a07fcc59d425bdbe449537e69448fa4603a69e073c88c2e8b8bc6f1719cd18b -size 28638 +oid sha256:41c029826a7f0d722ff9493a287dc45ed01c4e0f02e1fbdb4f69abd0b762b5ac +size 28592 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_3,NEXUS_5,1.0,en].png index fed3463750..4ace7951a5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8321e14c29391b34ab81e6b85f8e095773dcb00e615329e41032a057f2a0d5ab -size 26574 +oid sha256:5b4898e10aef39b1e7e9d16d9f214fab756dd203403de00e263a6049d4ff8b86 +size 26594 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_5,NEXUS_5,1.0,en].png index 02e6fae1b4..1d6c880873 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:57eb5eac361c61478e9352b7cd92c37212cccad2f1de2c509f06097eb0ef999a -size 45353 +oid sha256:473160d4ce97eecd9bc9ed67011c505e536272ce1acf838516c34f3b992f74a8 +size 45367 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_6,NEXUS_5,1.0,en].png index 7a817b8991..866984d7e3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:783ad0f124f4f385eaa556ad80daa0621fa6251622c16da8be47dca1937c4ce1 -size 38600 +oid sha256:b20115a793c0b021d077d816061b5b221f8e40581a6cf715fb4701941a38c207 +size 38583 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_1,NEXUS_5,1.0,en].png index 9f479f3f6d..36b034bdb4 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b013fa7cba8393ec0defe267dcd64427ed2023ceb7a306ad96b9cb03f63a687e -size 29609 +oid sha256:695041dfecf9415914d4f642c81154c8f90c8460bbd5c2023c9cce91352d2245 +size 29528 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_3,NEXUS_5,1.0,en].png index 7fee50f122..9ac987f959 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a00fde670a39c0cb6e4e12185f9790d3394be743b034fdd1478824d594812f48 -size 27550 +oid sha256:2f8b8e95fc48731162ddf10a3b00bee300ba6fcaa02ea48455a68ce834915b8d +size 27532 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_5,NEXUS_5,1.0,en].png index 7fd2027c56..a7e212f2f3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2dda676216b8f97ef36f02f7bacce4e605bef3c2fa521fbcb59745f27fb36a34 -size 47139 +oid sha256:867deebdc8a7e1844718508501e05d1f2f811f9847c60815fea86113ccb82bbd +size 47057 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_6,NEXUS_5,1.0,en].png index ffb9c0546f..b204cae7f5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dc2746f63bf1f5baf6b0a2595adc67063bdfe958596be405ab5aa2385af0cfd6 -size 40697 +oid sha256:2d99677b0930567cae7f6e356137ed98e701ff9ed2a6bd8aad66f9d12d8a1f27 +size 40726 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_0,NEXUS_5,1.0,en].png index ab649faf22..ba78172dd9 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7cc10ed03f4190d4d66f0ece4a4213db4fc071a7bb7867cee3bb1e17b44451e9 -size 19589 +oid sha256:5ceb363a42cce169fe6458d98f267feb22b87ced5f1bf6d73e5f41a6c2600199 +size 19574 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_1,NEXUS_5,1.0,en].png index 07e172f24b..3a070189ae 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d6234b7193211bb6b27a174d06ff9bf9f73143c7da668c113a2ae3ac6606b8f6 -size 17393 +oid sha256:29fa748333d5bfaebc2877ba66677687a0ac40581c1a4c61bc7cfd67f627f85b +size 17375 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_2,NEXUS_5,1.0,en].png index ac8594070d..2245a0502d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c8b06ea0eeba1a6603bed919934c6869709f948d1dbc6b8333f10be7493a7b97 -size 20005 +oid sha256:dc56b1324ca0206fe25eb83b1bfc0ceb559ec86581227e3db766ed52c4b314e1 +size 19992 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_3,NEXUS_5,1.0,en].png index ab649faf22..ba78172dd9 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7cc10ed03f4190d4d66f0ece4a4213db4fc071a7bb7867cee3bb1e17b44451e9 -size 19589 +oid sha256:5ceb363a42cce169fe6458d98f267feb22b87ced5f1bf6d73e5f41a6c2600199 +size 19574 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_4,NEXUS_5,1.0,en].png index ab649faf22..ba78172dd9 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7cc10ed03f4190d4d66f0ece4a4213db4fc071a7bb7867cee3bb1e17b44451e9 -size 19589 +oid sha256:5ceb363a42cce169fe6458d98f267feb22b87ced5f1bf6d73e5f41a6c2600199 +size 19574 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_5,NEXUS_5,1.0,en].png index 5e20da1ed3..e366ece74c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7d4cc58182afd5e7883e2299e882842e252d9d650ede8d692cc5b55d86f0eaaf -size 20597 +oid sha256:84218b0e445d477223d7dc7aa87e043671b6c4a5ce24f431af4860ba04fc8f02 +size 20591 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_0,NEXUS_5,1.0,en].png index 3a611ff2b3..9aefe59c7c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d06cfa869f95b907f72152ca550536755cde19a9bf14b083ebf4c162208514f1 -size 20037 +oid sha256:9830d6448948fad763093ccf0b8ca8df7cdc60e425d9fab1b1406f893329d620 +size 20054 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_1,NEXUS_5,1.0,en].png index db428f07ef..23ead15fc3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b3c0aba4502aeee24df94fb526fde10f7b8b638dedf6a6330babfcd168845d53 -size 17739 +oid sha256:85bb085789a6c4fa5cfa4379ef19eea470b4e7f276823362cb06f49903c01788 +size 17754 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_2,NEXUS_5,1.0,en].png index b3db394d03..2d1bd42c0e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1217f1e8fbad860bc099746765e7321553338b2e49e55458c55ba331c179dce5 -size 20494 +oid sha256:d21c65c4d5c0070c8a75156cadfa8b7a6f97a4ea8e2ab8b52339792a21638c63 +size 20512 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_3,NEXUS_5,1.0,en].png index 3a611ff2b3..9aefe59c7c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d06cfa869f95b907f72152ca550536755cde19a9bf14b083ebf4c162208514f1 -size 20037 +oid sha256:9830d6448948fad763093ccf0b8ca8df7cdc60e425d9fab1b1406f893329d620 +size 20054 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_4,NEXUS_5,1.0,en].png index 3a611ff2b3..9aefe59c7c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d06cfa869f95b907f72152ca550536755cde19a9bf14b083ebf4c162208514f1 -size 20037 +oid sha256:9830d6448948fad763093ccf0b8ca8df7cdc60e425d9fab1b1406f893329d620 +size 20054 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_5,NEXUS_5,1.0,en].png index ee7132040d..121f05a71c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ce5ba511326e7641dfeb27dcfb94e372a75c6265201248b52d88d977fc8e61f -size 21056 +oid sha256:be5e1b77f5a7d9673f4c498a99e40cb633d536de608408a54dcb78fae7434d45 +size 21068 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListDark_0_null_0,NEXUS_5,1.0,en].png index 8affd2826f..592eb43fad 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3dd75d76dc7e0202e2ee3aa97c81de15f595776402c105cad3dbf55db44720a5 -size 38338 +oid sha256:c59cb5eb1538494a95a4dd531127afc8cae252b08c7812bee79db4b32cce500e +size 38214 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListDark_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListDark_0_null_6,NEXUS_5,1.0,en].png index ac29bf0749..5e988eb0b1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListDark_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListDark_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d002a12bc5821e0cd2838e35d8a74ad9408609acfc8268b002f2066dee143ebe -size 24925 +oid sha256:3535a659e893592ba4010c91049f0595d900d9f0aeea7bc2cb8317484bda58d5 +size 24897 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListLight_0_null_0,NEXUS_5,1.0,en].png index fafd4618fe..8ac709d1b5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:affe57ae0e4a387770f7776ee22be35cdc2bb9fb82281b1c9efdc30e302a64e1 -size 39529 +oid sha256:da07b9156d4e27aaecf0d3860d927660a688f46caa305940f57ae2f783402c8e +size 39429 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListLight_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListLight_0_null_6,NEXUS_5,1.0,en].png index 4dcd4e578f..d8fd92355c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListLight_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListLight_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5c4c30c30dbcbf0da1238096ea9bb152f4a691bcbf02f2aa0ff31720309a8313 -size 25608 +oid sha256:3237f778a1be6d86fcc107942ed8d19d38f4c332c1c307391b70521f9b11c8c8 +size 25600 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png index 77c1b4c04a..0845a2a7be 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8502e633bb26a506693f80ccd438d47280aeb7bc238f25a3834d06a290e7c2ce +oid sha256:2673fa6964ac88be99edaa839a8684bc459b029d210b96fdca698fee569d36f3 size 54613 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png index fbcbc79691..0dc50f37c2 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f82980c426b2374c6c7de0c1d0cabc56d721b34660a0bc2902871a6c4556f7d2 -size 45257 +oid sha256:20e630b0f3bb9fddd5f11e4e9f2a92b5d35c4bbe182662e8d0fde27451297006 +size 45247 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png index f651181262..ca7b6913d5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:15de254bfc9ed30f47d3195a95082af0da1feea68ab703e29ca5c0cdb28533c8 -size 46092 +oid sha256:553b498247e9da02ad037716a67c080a3da2fb07602b0c0c44de8f16a4891eda +size 46086 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png index bb20f8c8c4..57bdb33e14 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9b94c7bc6ff6b3e525507529b73088e8f73c2f094ad1e521c7c1f1d556c6e935 +oid sha256:29aef78fc92caa5283a6c066088d43512c36364ae01709d5d7182f6bf11f52b3 size 48496 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png index bfec221901..570e9977a1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:91062f451f97a21fbf1ca703dc595a093433b02e7ad87651c6b4499cc374143f -size 60188 +oid sha256:20ebfe833d0432d25076c97aaba8007fae940f70ad4e39502e4695e59fdf4c5e +size 60182 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png index e49accd332..b0dc0b4495 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:62925d3679c26248a8a8dd3f71d226cef760e2191ff018d71f482ff302c81980 -size 60411 +oid sha256:c31e8e9d8971b8ef0e4e5a5b7a909baf4e65faa18d50452b38cb109edd193de2 +size 60401 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png index e49accd332..b0dc0b4495 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:62925d3679c26248a8a8dd3f71d226cef760e2191ff018d71f482ff302c81980 -size 60411 +oid sha256:c31e8e9d8971b8ef0e4e5a5b7a909baf4e65faa18d50452b38cb109edd193de2 +size 60401 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png index c5e5b9bd70..c5444af671 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6c444b237d087b863b2ee7279a97433c0e66e80f3561e195453625f508075633 -size 49413 +oid sha256:c159c58e5fa811e63cc8396f0b6910dd62945014c9a645e149b4bc88b0527dee +size 49416 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png index 508dee85bb..8e4244ccad 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d4f35b517edf875a7d9b780e050ff409cef3b1fe15d42571d85256adede78998 -size 54870 +oid sha256:55d72a6ef38f3822131425b56fbb02cad52e836a94cbf878fc654b1f893f9571 +size 54866 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png index b15a56c1e8..90756f11ad 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fc94103988c32e43ea7cf0f350637641b2a3687ced38eb6a5c9deec449cc5b45 -size 56789 +oid sha256:0f1681459983d04b98cfb583679c1c44504e0fb05d9cbcab90c149de04a91ae9 +size 56779 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png index 54f59b053a..852e18b044 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:375b26ca9b248a7d60aed3c3b1c270971e0c944ae281c03aa33fc40d3c151d32 -size 47297 +oid sha256:6f65151d983057ca185c53b4045fb33675f12730fee1b40e3df6d269e2290a05 +size 47290 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png index 22a8280dd8..89ce9d4604 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:19607983cd3005f2d187f40f92ff4fe654ee4fe7d1a579246a5c54af34043210 -size 48370 +oid sha256:de6a5ac50e8b30364b9e630d2edbe49c18cc3684da080e2167f41bd689f17700 +size 48369 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png index c417113267..652fc31f8c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8835bd5edacdbf3db313af13f811f9d5e832cb0d248e29ca19d46f22a2e995f9 -size 49660 +oid sha256:07dc159ecc1cce762240c06902690098a3f84a651272b3d51bf2ebc00951d16c +size 49655 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png index 278b704bbc..5496c8b265 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7654d7ca36112fa73bbb03904cdb93fdbee9507dcd23c7998659a7f0185eccce +oid sha256:44f783fc10ca0aaf56827afb1d2d9a24694e5d192441a8a9f9d1507326d7de94 size 62479 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png index 8a06e354c4..9e791b59b6 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a0adc2b1ae404c4c1cc54fe70326043df9c68ed23029e679461f2294b6df8f3d -size 62518 +oid sha256:b6c8cbb0c5ae7a9e4d4426daaa00c2625731fa93d7fc05bf0cca64d1d7833ec0 +size 62536 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png index 8a06e354c4..9e791b59b6 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a0adc2b1ae404c4c1cc54fe70326043df9c68ed23029e679461f2294b6df8f3d -size 62518 +oid sha256:b6c8cbb0c5ae7a9e4d4426daaa00c2625731fa93d7fc05bf0cca64d1d7833ec0 +size 62536 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png index 2070b2135a..3e8e0372e9 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2790af60ce68930b750508f433cbea718366ee8efc7a310af10719f0f2fe6c25 -size 50726 +oid sha256:210a21565a6b4bf56468125338e9270b9ccc48ce06d24c9eb48f32a027ffc0a4 +size 50720 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png index 3ad38a0cd5..9d9e068cde 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:062d7de096cebe935df18f5daf9b8bcdf93057d6979659f6bd9ed1ab8d7b0c7f -size 57035 +oid sha256:dcf896ec4b058043d5b52065ed3e23549d540d2496e94df3c6c8226d68de5dc4 +size 57033 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarDark_0_null,NEXUS_5,1.0,en].png index a7e8db9f25..72105204f5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:15b339b0c15ecf38f094378e8541fcf417fcab80291db47b061e05f12cf9663a -size 10567 +oid sha256:efe240e29b1e9565edf56390c4ed5cb67a7e342cdfb96361782dd2d5dd28c939 +size 10554 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarLight_0_null,NEXUS_5,1.0,en].png index 438d20a0ba..afcb237bb8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarLight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarLight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da7b416757518cff72cc5bb37b670855fe22119082201871f6fea0bb620a348c -size 10419 +oid sha256:62f986c59715c6f74b0c2bf98afe7ea9df4619b833919183863c2550419e8dc7 +size 10412 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_0,NEXUS_5,1.0,en].png index 045521cfc7..96ad4b73cb 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5586f03088e8571e1f2921721e23aa4415b8254a5785d0fe76a600de57c5fefb -size 12102 +oid sha256:bf5694071227c215dfeee78347b20575aab8456c97ba33129386fa7b156beee0 +size 12089 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_1,NEXUS_5,1.0,en].png index cebcc7ec15..4e2a983e69 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fada88c1a80d3bc00a8dc88ba502744d151dfb9af014d3efea3f3d7500641f83 -size 9376 +oid sha256:9a186c8be46410cd829bcbc46f2e2360816e6d50f6476d1bfa5dbd970d9fe609 +size 9367 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png index abd40193da..fcf7318f4f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0abb3a07dc5283ae1411151caa4b33dfc4f153f70aa0cfe6a9287d47763097de -size 12479 +oid sha256:50826af8c22e844eca956ae277f09ff4c69a262507d32144313bb4638436a186 +size 12465 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png index bece04c505..d4ff97ad67 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cf7e89a8bb33b5f9d17f04c35fc9ac78c362f0576333c82d36aa2929da9e8cdf -size 13376 +oid sha256:dd7d6642bde8e6062a2a87829741b23a18c9a08ecca3f8f1b291ddee9cac8a29 +size 13363 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png index d86cb78f0c..8a1c18bb99 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d16f977abe60656440752e82da244ada6de9dd2ce329679e7c21d4c03df4d306 -size 13710 +oid sha256:bb25fca8bf0a2c4567e1687b37c4eba72cf8d7830cb74555f4bcf72941c66b2b +size 13694 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_6,NEXUS_5,1.0,en].png index 7010d8c333..7d4841a54c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bbc96b4dc345f95d4cee8b2840431ac203e3ad43dc2cf3d8dce688dd4cb28ce6 -size 22111 +oid sha256:3b7fed22743d761141600d8c1f0df0ed9799acc3d2087d693da2fffe53605a30 +size 22092 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_0,NEXUS_5,1.0,en].png index f841f89d1e..0d10b79070 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0a09f04c04925b55b268f16a95ddb9ecadce377ae3bd593bb370488268b230b1 -size 11873 +oid sha256:b0959e717c4964cd8c5acf05fcbbadb2e44bee3217ab451a7b2d77e534be08e3 +size 11868 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_1,NEXUS_5,1.0,en].png index af204846e7..d58e9f7aa0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:63cf90f5dd21d3267bc1aa003861cbd375006176c7ab20285905caddbfb59e9e -size 9228 +oid sha256:17dd1974f121b1bf0c769cb005f0b1cfb57b11e8cfe94f752b4e9d491e554af5 +size 9216 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png index 23e410fcfa..7b034632db 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3ac700080f4b413f4b7ad1fdcefb5c6c7ce2fb0086f76c01e95946d77641f595 -size 12254 +oid sha256:d90d24f83b8ef1d33ddeefe7942728d1b8de914de97b5724f1413fc88acac771 +size 12247 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png index b9cf9a3e68..cf650bfb41 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:145e9daa38533395e411299d9aa2ff09852a8e474e94df20efcb24415934a8bc -size 13215 +oid sha256:193959145770210881785866b3951a5fc9c02f11604d96d2f4dcf9154b69328f +size 13211 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png index da811477a2..07acdce0af 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fa5d7338831e74563c8d93c1627dd1236c511765c1049100370e3d0be2dc6e76 -size 13690 +oid sha256:a439996ea530d83c8f40baf0c4320a8ac21966cff838922e8fab926f7d3af5a4 +size 13683 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_6,NEXUS_5,1.0,en].png index c9f2fe1d4b..5f190faa9e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c8605388c16b1099f10b8bfccde3f5c84669fb252951425d56c2ac5d95ecff5e -size 22492 +oid sha256:9ff4b3f9f077ba9a62878463e3153e89e033bc631c4b627d31324d4f9af511e4 +size 22486 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_ContentTo_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_ContentTo_0_null,NEXUS_5,1.0,en].png index c2f594936c..aebe17e861 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_ContentTo_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_ContentTo_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:519b00c507122ea88d0a43b9774faffba08bf9008208a8cb2e63c7fc4c7c0395 -size 30497 +oid sha256:c0d63e4326bdec31177615bc924c0fbde49842bb895601ae31036813dd7ba669 +size 30482 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_RoomListSearchResultContentDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_RoomListSearchResultContentDark_0_null,NEXUS_5,1.0,en].png index 4d21322aa4..26664565ca 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_RoomListSearchResultContentDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_RoomListSearchResultContentDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ccb53997d492a88ccd952a7b9e4832ef697b78853b5f10c5c21b3d2a3100ec3e -size 29744 +oid sha256:15198a0c45657bcfa1f945349b18106e3239def6e869aa000030e3354ddc03d6 +size 29732 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_RoomListSearchResultContentLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_RoomListSearchResultContentLight_0_null,NEXUS_5,1.0,en].png index c2f594936c..aebe17e861 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_RoomListSearchResultContentLight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_RoomListSearchResultContentLight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:519b00c507122ea88d0a43b9774faffba08bf9008208a8cb2e63c7fc4c7c0395 -size 30497 +oid sha256:c0d63e4326bdec31177615bc924c0fbde49842bb895601ae31036813dd7ba669 +size 30482 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_0,NEXUS_5,1.0,en].png index eba7c38ad3..40e658fe68 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b9ffcde3ac2129ae6bde0cf165b47ec42fb7c436140b5da87ccdfd203076a41 -size 35563 +oid sha256:e045c8686effc435e5d31b7ef034d93bca64a226d2e6ebae941afeb36dbad099 +size 35534 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_1,NEXUS_5,1.0,en].png index 87a72dfed2..8a8da5a453 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b3696cfbb10e89433efbf86d8b3c5dbfa4f3110e4b348811f48b73355aec7ba8 -size 58615 +oid sha256:a62f8d9a50f7d23bc355dfe98be0bc5eeb2b68866e3035b79b51591eae2f781f +size 58626 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_2,NEXUS_5,1.0,en].png index eba7c38ad3..40e658fe68 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b9ffcde3ac2129ae6bde0cf165b47ec42fb7c436140b5da87ccdfd203076a41 -size 35563 +oid sha256:e045c8686effc435e5d31b7ef034d93bca64a226d2e6ebae941afeb36dbad099 +size 35534 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_3,NEXUS_5,1.0,en].png index 034f8eef9d..28ec864478 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:113f877cb441ed9960785eb6b6ff37ed876f50e2a82e232d43130de50e171e90 -size 37464 +oid sha256:76b43763ca93e7bf31e49aa4ba98e9c9cb6d5ee2ab6dba573e69315084884859 +size 37433 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_4,NEXUS_5,1.0,en].png index 9d2b285afe..a26740c566 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:19b85235a764b18aab53b00e75f7513ab357cb8876d77912ba32c73fbeaf2762 -size 36848 +oid sha256:0451e8d5939e9c90ccef22a8384d80e7d83cf8faa8a7df4bcd6032d9f3ef394c +size 36884 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_5,NEXUS_5,1.0,en].png index e5cfd4c10f..e7cb3b98e5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:88afc93c92cf92ac492a82b753c53fde12e34b2e12cee8a67c40570388f33569 -size 37201 +oid sha256:e9220e4a8dca8924d574e9a5511f25f6c41d14163b58cb4d8f622d7fd8fc71ae +size 37238 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_7,NEXUS_5,1.0,en].png index 4d21322aa4..26664565ca 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ccb53997d492a88ccd952a7b9e4832ef697b78853b5f10c5c21b3d2a3100ec3e -size 29744 +oid sha256:15198a0c45657bcfa1f945349b18106e3239def6e869aa000030e3354ddc03d6 +size 29732 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_0,NEXUS_5,1.0,en].png index b936e1b8e4..7f84966744 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b79fdca5780e49319367b0a9d8d965e4d8b290313ac68ae9035ef781bd55a49f -size 38247 +oid sha256:8d24c1170affdcae6f189ba2e6646fb61e01f8eed4d83340297f3f189c2f3470 +size 38225 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_1,NEXUS_5,1.0,en].png index e4b351db01..6a5f613b72 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dd7d4fe0a126ea90cde648ac9f461f1ffb715737330038a7b31f944be3814ccc -size 62183 +oid sha256:1cca9ca327d8a64cb04489cd52c52d3871bd583de9835eb266a1e60db8e53f84 +size 62191 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_2,NEXUS_5,1.0,en].png index b936e1b8e4..7f84966744 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b79fdca5780e49319367b0a9d8d965e4d8b290313ac68ae9035ef781bd55a49f -size 38247 +oid sha256:8d24c1170affdcae6f189ba2e6646fb61e01f8eed4d83340297f3f189c2f3470 +size 38225 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_3,NEXUS_5,1.0,en].png index cb279871dd..7ea53599fb 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:684de1bfd46b540064668dfa54179705f8b3a0ef2ed2b34cdf17c5dafddd510d -size 40281 +oid sha256:fcfec887ae55ce77b049ef49880f1858e7a0a0ea2a7c81140c8c66069a598a14 +size 40265 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_4,NEXUS_5,1.0,en].png index 57dac5e082..dfc6c1155f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0649ff24ba1b1efb8a310202e6bc111db19defcee2d86fedb0c7aa7ee860a8c0 -size 39566 +oid sha256:5716646f8c5d8e9488f79b033ffce5f337133eb78a63328ec616b8eb35d1c70b +size 39534 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_5,NEXUS_5,1.0,en].png index b8bae6649c..d947e91005 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:35e68fda7b2beeab9e716f10fa9a1160af7a427354e8809d7270740047e3f0ae -size 39930 +oid sha256:4a8723f12c2884d20c195a779cf6d48a08191f1caa0acdaa2324e478ecac92b2 +size 39898 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_7,NEXUS_5,1.0,en].png index c2f594936c..aebe17e861 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:519b00c507122ea88d0a43b9774faffba08bf9008208a8cb2e63c7fc4c7c0395 -size 30497 +oid sha256:c0d63e4326bdec31177615bc924c0fbde49842bb895601ae31036813dd7ba669 +size 30482 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_0,NEXUS_5,1.0,en].png index afc4d7c496..dd5e1401fb 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4a33d4b4ed08044b8f539914da03e0228e121c1f82f3b1f0acfe34f22dfd4f47 -size 17915 +oid sha256:3d5e1eec999486b11a48ae992708adb8634a46fc89114de463894fd5730330a8 +size 17895 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_1,NEXUS_5,1.0,en].png index e0079e5e3a..83cf5299d7 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b0712f3a8e86eb5ba2588a03fe79bb4e29e2c6d341f80906d0b39301c694d054 -size 17361 +oid sha256:8a66c143d05cad7db2ca195bcd0d9a3007169c123c96f11fb66dfade6904db1e +size 17359 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_10,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_10,NEXUS_5,1.0,en].png index 97ba3cfdc1..8321f05002 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_10,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_10,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:65aef36778adb865c6320a13e6a2bb297cd8837079adab8524d656266ccc48d1 -size 19095 +oid sha256:8da740d8a43f978b1da59585326848fe18b71b7cbd4cbaecbf520a7219bf5df4 +size 19100 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_12,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_12,NEXUS_5,1.0,en].png index 2083ced12f..7dc547ba61 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_12,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_12,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a2a0967d18a75294f09aafd3b116c270b5c88d9e49a2918f6229a9d6f97cf099 -size 20277 +oid sha256:ae676fe3063c21680f87ba11f7f68d11250c67365a4da0541397c4fb635f939f +size 20231 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_13,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_13,NEXUS_5,1.0,en].png index cf6ea92cff..c0d18e4417 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_13,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_13,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dc3d57b23d0665737f57a2aa6da5133f08410ee12a9fa9112334357960889e3d -size 19021 +oid sha256:2834d0f7335480a35ca041091c8d7062d64501d52855458864505a1eb12453c1 +size 19043 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_15,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_15,NEXUS_5,1.0,en].png index a41f70f1e1..7c3c298a92 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_15,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_15,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1f1f23fc00e55e3ed3f185b931274656e23b5307b238c02188baf5a994d8ef69 -size 22917 +oid sha256:71ea9ad8c4934ee391d94836e57e06f5332963c09ed4c689c125337bb4f66504 +size 22821 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_16,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_16,NEXUS_5,1.0,en].png index 1d8aac11ea..c6c2cca49b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_16,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_16,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3e7a7bc8d46ac765cc79ebb456d789cd919a3b5270d0d682b6964d329525b1f9 -size 20845 +oid sha256:02d3fc1981a83b1635b89cecbfe2ffac65b070060f28050fbafcbb35fa4222b1 +size 20911 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_18,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_18,NEXUS_5,1.0,en].png index 3aea92db8b..0f4969c23d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_18,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_18,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ed96f288c1137cd68c524910fa461336694cd867f2533f92adef228b86738fd7 -size 16680 +oid sha256:34aab6f95f04977d64f97c5a9391806cae363408f011bd57a7a2954f6af6c5a2 +size 16654 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_19,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_19,NEXUS_5,1.0,en].png index 6ec22f322a..b66d0a9445 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_19,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_19,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c5a87ff184c790e5763c6a4249d4f6e3c2a4cd40308c35260578d70b7c6d3db0 +oid sha256:5222d968327e6de88f6f1f2bc02e47da51b6bd2fb2dc109279e5b240762966df size 15899 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_21,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_21,NEXUS_5,1.0,en].png index 9d2ba67cf8..8a9e08a783 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_21,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_21,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9603c41811649cf758e94bd229ed2fbd6eaada6648adf37b7acc4bb0def80665 -size 19586 +oid sha256:677d553d6098e0534d81e7c4218698f8e0b9635225332d484108917332350494 +size 19540 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_22,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_22,NEXUS_5,1.0,en].png index 9c3ef31c21..200d140d83 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_22,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_22,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:84c1d472d23a09383dbeae496c9d2fe54aba37a1ff93e08da0bb4b419242e505 -size 18320 +oid sha256:34e763d9617c7023f3f365ca00e75dcc0d4e80a7a9a2c74bede55456c73f3fea +size 18349 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_24,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_24,NEXUS_5,1.0,en].png index 779efb9dda..12f34d2fe0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_24,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_24,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f8853a6320f11de9e77c115afd576a1fefec9b72086b9c818cf7a83d98bb3902 -size 20512 +oid sha256:7acf87fd6c7da93132c9c89974b6e82728b7aee91f078146ba9a002ed1ae261b +size 20457 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_25,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_25,NEXUS_5,1.0,en].png index 144b992b4d..d6b341d0f2 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_25,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_25,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:00c21652a153330deeb12bbcd95968ef9032cfff38f9d6b325d7d98de6fbb7b4 -size 19256 +oid sha256:a6654898419c10c0fc2f96aa975295ac94a68bf1362c3ac955388e5f9bf8e67c +size 19301 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_27,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_27,NEXUS_5,1.0,en].png index ce9cb0fcae..300f3e1ba0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_27,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_27,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:848bd4e8f7954582d803715d7b04a7dca6888c32c5ac0843e8a6880d1c99bd61 -size 16255 +oid sha256:cba6dc7fb2520afe1553ba63b92195708fd77f8ef852ecae0a1407e65970b31e +size 16263 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_28,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_28,NEXUS_5,1.0,en].png index 9579b215da..a94d27f33c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_28,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_28,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c4f8280513fd8b8f950511389e0cbdd8d1d45a78b5eb5b17592b95ff05b68efe -size 15577 +oid sha256:0271737aee4d0922d0613bce60098a921b1b9f717e9be68d5288f7bef07bd76d +size 15576 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_3,NEXUS_5,1.0,en].png index b4b7bade0a..ae8c04c855 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7f48d8ed65f7b190c5bd0ef69b07da3e8388697a04d2598aa642cf57494d762c -size 23333 +oid sha256:7ea7a72ca0a5e99b0c906342ed34830b7e9ac75cb1e370fc7c9eb33441492aff +size 23247 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_30,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_30,NEXUS_5,1.0,en].png index 23d4f42f4f..203e9e5ca2 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_30,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_30,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:744e8704616c4792d19f4b89b8fdd1ebab7f95c155344edcee839383f87d0297 -size 17063 +oid sha256:c1fbe133ecfff74a27273db57f40991cc3f4676f454a85a18162e0c9bc75b55d +size 17065 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_31,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_31,NEXUS_5,1.0,en].png index a8e354900d..6d763a36c3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_31,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_31,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bec608ddf547a8436f7f2c7e707409d9a5375010a60f97228068b7255c78cc6f -size 16409 +oid sha256:9665e21d61256c77e239a587e45529edd30db85448bb768070d48ccf42a90c32 +size 16407 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_33,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_33,NEXUS_5,1.0,en].png index 9655b03e8e..95df6d421f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_33,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_33,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b84b5f310a6d04511e06208eb638dfc344f0629c6cae50644a1d925e286917b -size 20737 +oid sha256:46ffbd54e3171340f0b6b8d632964b3b91480cfd6d99871c0f1d6bb7b8cfecc6 +size 20738 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_34,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_34,NEXUS_5,1.0,en].png index 2f81f23152..59e8eac7f5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_34,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_34,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:56857d24261e0385855825f310c1e76c4eb244957d6afc48657794231b2041ec +oid sha256:10989322060483d1948f297cf66d7442444f613e9a883fa1377941d73b57be22 size 20096 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_36,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_36,NEXUS_5,1.0,en].png index 3f27b667aa..d455ea4877 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_36,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_36,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ba04160e69b6a05b81f121f64c375809006bf77899be22e3e4fe07a627921b3 -size 18853 +oid sha256:736bd589ada20b9ac5d653fcc78acbedf08d406c0aab7a8159b0bd52db49d8be +size 18774 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_37,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_37,NEXUS_5,1.0,en].png index 42da6e6b20..3a075cd929 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_37,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_37,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b30a0deed825c98ef6be90b0b11485a76547a77959058ed816b133f9190b4f6c -size 17694 +oid sha256:1a494c20b5047c925aa60b8253b4ea1bd90a95013df3d711bded444f1cbb0941 +size 17683 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_39,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_39,NEXUS_5,1.0,en].png index 707c54ca65..9b2e1e6381 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_39,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_39,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e4cc6b4362468eb094d478cf613b272cfe4b55db4be989e33e56d12dd886672 -size 14590 +oid sha256:1fed24563d497b368859de9de4e4c9ae27cb645d89888f7fa7402df64d447471 +size 14589 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_4,NEXUS_5,1.0,en].png index a0d5273229..c479e6007c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e40bf3da586f0ecbfd3794d20fb5b1fc65f4b662aab920fd417a40c17c48326f -size 21308 +oid sha256:bc087aeecec205ff20e45fbe27003409591e9ecada4c2f2b4322537deac6b490 +size 21381 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_40,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_40,NEXUS_5,1.0,en].png index 24b67b4efc..46cc322fde 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_40,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_40,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0971b7af9ec67b0c6ba30dd21a21e9ca780c87862499135afa104ffbbfb70fbd -size 14289 +oid sha256:4ff8361d32597bea90e830056f00846b9e2392685eb6ac000c8c930ba5c981cd +size 14296 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_6,NEXUS_5,1.0,en].png index a957af4444..7165d890d3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7653f42cb5eaaaebcd81d3ccedcfdaebc31d8ea228f7c28d0faf0e288b3d7e1e -size 18762 +oid sha256:6e2070fbae74dff21576afcd623f73ceacd018b934d44247066f469c9690d2f1 +size 18679 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_7,NEXUS_5,1.0,en].png index 0296201a02..92daab450b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bef3f8dabcaf1e4143e3b9f9b965f452d291704dc37b33f0653c1b85c17037af -size 17614 +oid sha256:86660baa06208b38f8201d9155a64fade6fb3ba49689982fa013488f8cbd6f83 +size 17595 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_9,NEXUS_5,1.0,en].png index 60bc9b48ee..3c81ba86b6 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_9,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_9,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3675b41c8caf7069d18e31a5f4a45d0bbb89ec6c468475e39441bd6108cba11b -size 19875 +oid sha256:febcacfbb96dcd0cf8815760409d105847b1fadc65e8254d386d774e41178a38 +size 19849 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_UserAvatar-D_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_UserAvatar-D_0_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..5c14f662d3 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_UserAvatar-D_0_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:85c3b45953da8370bf043b3bfee87304b1c1703e11722c7c796a9e8cf5e84de6 +size 41413 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_UserAvatar-N_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_UserAvatar-N_1_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..acf8d2793c --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_UserAvatar-N_1_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8ab02c533d9866bb6e6ac9b6d732c0d81cfcd080e1321df2834937e6274c9363 +size 40896 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowDark_0_null_0,NEXUS_5,1.0,en].png index d56de11ee3..f6663c9291 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cb0428758e6ef33fc1852566606de812234ca5f01a069fe170002e60739b38cb -size 29257 +oid sha256:775f1249eded2e16bc7e03a827256020504379a6999b7ca3a1eeae2fdbf8415a +size 29227 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowDark_0_null_1,NEXUS_5,1.0,en].png index 9ef8e06a2c..f06a8e0ce6 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9ac5ec83fe207221f064ba9eb4f33ad34c4df69cd10a42c85e7d10982ebb73b3 -size 27535 +oid sha256:12c84950e69b760e32bb59c9d90a01d4ec1e17a28ac3c6ba53bd16c8d561db05 +size 27552 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowLight_0_null_0,NEXUS_5,1.0,en].png index a2649e498b..454bbe5c79 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d91bcfb40c3ba7ab56323c028dae8b6771f9c4a4134e352c67b3981c68b66d14 -size 29638 +oid sha256:f5882ca765a08118f6e23925d0621b882d41eb6ead7f8e62240c3473f3aa029d +size 29599 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowLight_0_null_1,NEXUS_5,1.0,en].png index 96c0c46024..6533078c75 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7f5b9648f35fb2e7e5832d46fd7d5abf93cd3c0cc7a272b27c6fa23f1361da2f -size 29382 +oid sha256:73fc004c07b36c64f08a65a8b9b62352e9a69f634629141dc1da3aa28397d6f1 +size 29347 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableUnresolvedUserRow_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableUnresolvedUserRow_0_null,NEXUS_5,1.0,en].png index e3db6e41f1..a645112020 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableUnresolvedUserRow_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableUnresolvedUserRow_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f1802db5efefe0117383026cfb5310c8b8d391a15013387be6be8f6aa43bf05 -size 116202 +oid sha256:84714adab3d3fc1a8f076589fd49bb35562913d99d353e9a9e318615568fe3a7 +size 116049 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderDark_0_null_0,NEXUS_5,1.0,en].png index 8bb0a53a37..f7d8135d0b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9048da25ad83e544de8dfa2ec910b7650e34c78a0864e0e1f9644fa18a0ffba8 -size 13144 +oid sha256:964d97909629c1228e96d923ddb478735475839b8540c02142444f9ebd5bf400 +size 13100 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderDark_0_null_1,NEXUS_5,1.0,en].png index 8e68fdc6c1..bff7b81448 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58660c588499291f198046058bf725844bde74a7db4c371d29ee43fba2780e04 +oid sha256:bd8ff4a09babf30be0eb3c336f3cbe6a1508a21696512d0dadbcc9d543e6e34f size 12356 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderLight_0_null_0,NEXUS_5,1.0,en].png index 754ea0cecb..fe1fe39c26 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6d4ee26a608ba57aa6e9eca05d4db22a9135243a73faf767cdc10ff0252079a2 -size 12887 +oid sha256:85530997942e39ce73512513ab0698494778168bc28cfab543b50b721c1807f5 +size 12855 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderLight_0_null_1,NEXUS_5,1.0,en].png index 05e82479e2..23211c9508 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8daffe981e83c5a81b60ec1d00d09a12fb3a67d3bd957bab5b0b924480330bfe -size 12952 +oid sha256:2e0a638be5745c75c2663116877d380c83df093d226d2c969d4f6620e8cee109 +size 12965 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowDark_0_null_0,NEXUS_5,1.0,en].png index e333bab625..ad70967875 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd957f1da256db3c598e38d2d6221738ec3feec9124ad00ae6a48ad20e814418 -size 11200 +oid sha256:1acf91a8440717f3467e62a533a6172a7eba01c65b2d8d32b3b3b44d514f52b4 +size 11227 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowDark_0_null_1,NEXUS_5,1.0,en].png index 6bc076c6e2..0563bc9ae3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5b7779aec984398ff8fd44dfaf156fc3af31a43073238faa57cd69e2d6ad67cf -size 10648 +oid sha256:01b6759a944884c2c6c7c0631984dc904da890c3a05ac65f4648729065c4f26c +size 10669 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowLight_0_null_0,NEXUS_5,1.0,en].png index b92144d166..847d11231f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f8d6f64ccc3f43f057f6558340fea61ececbe78655c4ec441f0a4ce3cdbae62e -size 10970 +oid sha256:6c881c08f6501f8a7d2b865360510ec8b2cfc5819d398b477aa1ca970b20fac3 +size 10983 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowLight_0_null_1,NEXUS_5,1.0,en].png index 7cf5f228fc..f133082603 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9ba7e3a152cd236450eb13bd05f4bbb153c38dbc66c4411d2b5e5cfb990d3a2f -size 10997 +oid sha256:ea7db4fd34a741fecff2a084941a55582e167d72a66a4e206102b5cf8d52c806 +size 11014 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedRoomDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedRoomDark_0_null,NEXUS_5,1.0,en].png index 0cbcead563..14155e5999 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedRoomDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedRoomDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:53e540fd5760b5df921fee79d6ee5387e8d4a830a100c21c699d973ff63844f2 -size 9336 +oid sha256:64ca46029a544e74b05f4a1bc84f17082832b5fdaa9d76a1b5dd3aa755241951 +size 9297 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedRoomLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedRoomLight_0_null,NEXUS_5,1.0,en].png index 141d3a059d..0c18e4464d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedRoomLight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedRoomLight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:366b834d60978a9c8fe677660feedcc16dfeb4c725f249d788a8b90740f76e9a -size 9128 +oid sha256:78d437e9257a4e8e0f8478607cb852a18e188f65adc30c2297f1d18ef4fbccf1 +size 9108 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUserDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUserDark_0_null,NEXUS_5,1.0,en].png index 7669bcfbf5..b640b61655 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUserDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUserDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:66ee0c1c8a79faa3067e4fb8c2349c459d9a26db099ed06f9050f6498705d93c -size 9503 +oid sha256:e4f6d3ffbe069775e1110e49d7e95d43cb81919642062953d6d8a7ab3b82987e +size 9464 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUserLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUserLight_0_null,NEXUS_5,1.0,en].png index ebcee9e7cd..6a1f4eaa15 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUserLight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUserLight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d4a756b6fcfa482996055448296f06aed6aaca2849c116692e4a8f2f8c2b455a -size 9173 +oid sha256:c77400352729ec572955725cd8afd6149e7ae86aab18a82dcbd51f4c2cdc0e81 +size 9161 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUsersListDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUsersListDark_0_null,NEXUS_5,1.0,en].png index 425afced51..0d23f92aad 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUsersListDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUsersListDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e71b7329a2f6f4763f2062e0aa4206c62848f566e210eac3fb2787fc53cd08ac -size 74783 +oid sha256:5d3677896ec686f3b9cff36bc947de97bfa3b9274dd19705d6fc79b26bcdcc82 +size 74472 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUsersListLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUsersListLight_0_null,NEXUS_5,1.0,en].png index 637bd77768..bd01feb258 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUsersListLight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUsersListLight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:be62026c5821e47b15b8a2d7f03f9c4ea0fe3dbead9ac12c33d23c72b777f3c4 -size 74045 +oid sha256:d3c61acf6eff591fb7765468aa981b8a87fb6da4054175ea60968f5d81370677 +size 73693 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_UnresolvedUserRow_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_UnresolvedUserRow_0_null,NEXUS_5,1.0,en].png index 7f3f19bea6..c5a2a4a248 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_UnresolvedUserRow_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_UnresolvedUserRow_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ffbc6dae4b06297fbc248d7ac7e0972037492ea3e1d3bae74176b08d1616df1e -size 32171 +oid sha256:9aa050bd40cae65f3a2fbcd396f525238d182d5e99656adc706692e8feeffd42 +size 32134 From 717f632b35c66a8d9d215c8d7ba8fcae1668d1ab Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 5 Sep 2023 16:19:04 +0200 Subject: [PATCH 044/234] Fix system bar color after login on light theme. Actually for the SunsetPage, we need a light status bar. --- changelog.d/1222.bugfix | 1 + .../designsystem/atomic/pages/SunsetPage.kt | 5 ++--- .../android/libraries/theme/ElementTheme.kt | 17 +++++++++++++++-- 3 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 changelog.d/1222.bugfix diff --git a/changelog.d/1222.bugfix b/changelog.d/1222.bugfix new file mode 100644 index 0000000000..325cf6fc4d --- /dev/null +++ b/changelog.d/1222.bugfix @@ -0,0 +1 @@ +Fix system bar color after login on light theme. diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/SunsetPage.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/SunsetPage.kt index 10a6f529af..d4b203d4ae 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/SunsetPage.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/SunsetPage.kt @@ -44,6 +44,7 @@ import io.element.android.libraries.designsystem.text.withColoredPeriod import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.theme.ElementTheme +import io.element.android.libraries.theme.ForcedDarkElementTheme @Composable fun SunsetPage( @@ -53,9 +54,7 @@ fun SunsetPage( modifier: Modifier = Modifier, overallContent: @Composable () -> Unit, ) { - ElementTheme( - darkTheme = true - ) { + ForcedDarkElementTheme(lightStatusBar = true) { Box( modifier = modifier.fillMaxSize() ) { diff --git a/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/ElementTheme.kt b/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/ElementTheme.kt index fa7bd279e7..81780d1c2d 100644 --- a/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/ElementTheme.kt +++ b/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/ElementTheme.kt @@ -92,6 +92,7 @@ internal val LocalCompoundColors = staticCompositionLocalOf { compoundColorsLigh @Composable fun ElementTheme( darkTheme: Boolean = isSystemInDarkTheme(), + lightStatusBar: Boolean = !darkTheme, dynamicColor: Boolean = false, /* true to enable MaterialYou */ compoundColors: SemanticColors = if (darkTheme) compoundColorsDark else compoundColorsLight, materialLightColors: ColorScheme = materialColorSchemeLight, @@ -111,8 +112,19 @@ fun ElementTheme( darkTheme -> materialDarkColors else -> materialLightColors } + val statusBarColorScheme = if (lightStatusBar) { + when { + dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + val context = LocalContext.current + dynamicLightColorScheme(context) + } + else -> materialLightColors + } + } else { + colorScheme + } SideEffect { - systemUiController.applyTheme(colorScheme = colorScheme, darkTheme = darkTheme) + systemUiController.applyTheme(colorScheme = statusBarColorScheme, darkTheme = darkTheme && !lightStatusBar) } CompositionLocalProvider( LocalCompoundColors provides currentCompoundColor, @@ -132,6 +144,7 @@ fun ElementTheme( */ @Composable fun ForcedDarkElementTheme( + lightStatusBar: Boolean = false, content: @Composable () -> Unit, ) { val systemUiController = rememberSystemUiController() @@ -142,7 +155,7 @@ fun ForcedDarkElementTheme( systemUiController.applyTheme(colorScheme, wasDarkTheme) } } - ElementTheme(darkTheme = true, content = content) + ElementTheme(darkTheme = true, lightStatusBar = lightStatusBar, content = content) } private fun SystemUiController.applyTheme( From cfdccc904e994b095497dc369373d6c0934eaf34 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 5 Sep 2023 18:58:05 +0200 Subject: [PATCH 045/234] Replace notification permission dialog with a screen (#1223) * Replace notification permission dialog with a screen --------- Co-authored-by: ElementBot --- appnav/build.gradle.kts | 2 - .../appnav/loggedin/LoggedInPresenter.kt | 16 -- .../android/appnav/loggedin/LoggedInState.kt | 3 - .../appnav/loggedin/LoggedInStateProvider.kt | 2 - .../android/appnav/loggedin/LoggedInView.kt | 9 - .../appnav/loggedin/LoggedInPresenterTest.kt | 9 +- changelog.d/897.feature | 1 + features/ftue/impl/build.gradle.kts | 6 + .../features/ftue/impl/FtueFlowNode.kt | 15 ++ .../notifications/NotificationsOptInEvents.kt | 22 ++ .../notifications/NotificationsOptInNode.kt | 57 +++++ .../NotificationsOptInPresenter.kt | 89 ++++++++ .../notifications/NotificationsOptInState.kt | 24 ++ .../NotificationsOptInStateProvider.kt | 33 +++ .../notifications/NotificationsOptInView.kt | 206 ++++++++++++++++++ .../ftue/impl/state/DefaultFtueState.kt | 25 ++- .../impl/src/main/res/values/localazy.xml | 2 + .../ftue/impl/DefaultFtueStateTests.kt | 62 +++++- .../NotificationsOptInPresenterTests.kt | 140 ++++++++++++ .../components/avatar/AvatarSize.kt | 2 + .../api/PermissionStateProvider.kt | 30 +++ .../permissions/api}/PermissionsStore.kt | 2 +- libraries/permissions/impl/build.gradle.kts | 1 + .../AccompanistPermissionStateProvider.kt | 4 +- .../impl/DefaultPermissionStateProvider.kt | 48 ++++ .../impl/DefaultPermissionsPresenter.kt | 5 +- .../impl/DefaultPermissionsStore.kt | 3 +- .../impl/FakePermissionStateProvider.kt | 53 +++++ .../impl/DefaultPermissionsPresenterTest.kt | 67 ++++-- ... FakeComposablePermissionStateProvider.kt} | 4 +- libraries/permissions/test/build.gradle.kts | 28 +++ .../test/FakePermissionsPresenter.kt | 51 +++++ .../test}/InMemoryPermissionsStore.kt | 6 +- services/toolbox/test/build.gradle.kts | 26 +++ .../sdk/FakeBuildVersionSdkIntProvider.kt | 25 +++ ...OptInView-D-1_2_null_0,NEXUS_5,1.0,en].png | 3 + ...OptInView-N-1_3_null_0,NEXUS_5,1.0,en].png | 3 + ...elcomeView-D-2_3_null,NEXUS_5,1.0,en].png} | 0 ...elcomeView-N-2_4_null,NEXUS_5,1.0,en].png} | 0 ...atars_Avatar_0_null_42,NEXUS_5,1.0,en].png | 3 + ...atars_Avatar_0_null_43,NEXUS_5,1.0,en].png | 3 + ...atars_Avatar_0_null_44,NEXUS_5,1.0,en].png | 3 + tools/localazy/config.json | 3 +- 43 files changed, 1027 insertions(+), 69 deletions(-) create mode 100644 changelog.d/897.feature create mode 100644 features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInEvents.kt create mode 100644 features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInNode.kt create mode 100644 features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenter.kt create mode 100644 features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInState.kt create mode 100644 features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInStateProvider.kt create mode 100644 features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt create mode 100644 features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenterTests.kt create mode 100644 libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionStateProvider.kt rename libraries/permissions/{impl/src/main/kotlin/io/element/android/libraries/permissions/impl => api/src/main/kotlin/io/element/android/libraries/permissions/api}/PermissionsStore.kt (95%) create mode 100644 libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionStateProvider.kt create mode 100644 libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/FakePermissionStateProvider.kt rename libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/{FakePermissionStateProvider.kt => FakeComposablePermissionStateProvider.kt} (95%) create mode 100644 libraries/permissions/test/build.gradle.kts create mode 100644 libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakePermissionsPresenter.kt rename libraries/permissions/{impl/src/test/kotlin/io/element/android/libraries/permissions/impl => test/src/main/kotlin/io/element/android/libraries/permissions/test}/InMemoryPermissionsStore.kt (90%) create mode 100644 services/toolbox/test/build.gradle.kts create mode 100644 services/toolbox/test/src/main/kotlin/io/element/android/services/toolbox/test/sdk/FakeBuildVersionSdkIntProvider.kt create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.notifications_null_NotificationsOptInView-D-1_2_null_0,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.notifications_null_NotificationsOptInView-N-1_3_null_0,NEXUS_5,1.0,en].png rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.ftue.impl.welcome_null_WelcomeView-D-1_2_null,NEXUS_5,1.0,en].png => ui_S_t[f.ftue.impl.welcome_null_WelcomeView-D-2_3_null,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.ftue.impl.welcome_null_WelcomeView-N-1_3_null,NEXUS_5,1.0,en].png => ui_S_t[f.ftue.impl.welcome_null_WelcomeView-N-2_4_null,NEXUS_5,1.0,en].png} (100%) create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_42,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_43,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_44,NEXUS_5,1.0,en].png diff --git a/appnav/build.gradle.kts b/appnav/build.gradle.kts index cffd318fb1..88f0741ebe 100644 --- a/appnav/build.gradle.kts +++ b/appnav/build.gradle.kts @@ -48,8 +48,6 @@ dependencies { implementation(projects.libraries.designsystem) implementation(projects.libraries.matrixui) implementation(projects.libraries.uiStrings) - implementation(projects.libraries.permissions.api) - implementation(projects.libraries.permissions.noop) implementation(libs.coil) 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 6d386a17e5..f2af582c25 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 @@ -16,8 +16,6 @@ package io.element.android.appnav.loggedin -import android.Manifest -import android.os.Build import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState @@ -30,8 +28,6 @@ import io.element.android.features.networkmonitor.api.NetworkStatus import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.roomlist.RoomListService -import io.element.android.libraries.permissions.api.PermissionsPresenter -import io.element.android.libraries.permissions.noop.NoopPermissionsPresenter import io.element.android.libraries.push.api.PushService import kotlinx.coroutines.delay import javax.inject.Inject @@ -40,20 +36,10 @@ private const val DELAY_BEFORE_SHOWING_SYNC_SPINNER_IN_MILLIS = 1500L class LoggedInPresenter @Inject constructor( private val matrixClient: MatrixClient, - private val permissionsPresenterFactory: PermissionsPresenter.Factory, private val networkMonitor: NetworkMonitor, private val pushService: PushService, ) : Presenter { - private val postNotificationPermissionsPresenter by lazy { - // Ask for POST_NOTIFICATION PERMISSION on Android 13+ - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - permissionsPresenterFactory.create(Manifest.permission.POST_NOTIFICATIONS) - } else { - NoopPermissionsPresenter() - } - } - @Composable override fun present(): LoggedInState { LaunchedEffect(Unit) { @@ -66,7 +52,6 @@ class LoggedInPresenter @Inject constructor( val roomListState by matrixClient.roomListService.state.collectAsState() val networkStatus by networkMonitor.connectivity.collectAsState() - val permissionsState = postNotificationPermissionsPresenter.present() var showSyncSpinner by remember { mutableStateOf(false) } @@ -82,7 +67,6 @@ class LoggedInPresenter @Inject constructor( } return LoggedInState( showSyncSpinner = showSyncSpinner, - permissionsState = permissionsState, ) } } diff --git a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInState.kt b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInState.kt index bb06952a50..4196277698 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInState.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInState.kt @@ -16,9 +16,6 @@ package io.element.android.appnav.loggedin -import io.element.android.libraries.permissions.api.PermissionsState - data class LoggedInState( val showSyncSpinner: Boolean, - val permissionsState: PermissionsState, ) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInStateProvider.kt b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInStateProvider.kt index 3cfb03f123..0e8fdef8d8 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInStateProvider.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInStateProvider.kt @@ -17,7 +17,6 @@ package io.element.android.appnav.loggedin import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import io.element.android.libraries.permissions.api.createDummyPostNotificationPermissionsState open class LoggedInStateProvider : PreviewParameterProvider { override val values: Sequence @@ -32,5 +31,4 @@ fun aLoggedInState( showSyncSpinner: Boolean = true, ) = LoggedInState( showSyncSpinner = showSyncSpinner, - permissionsState = createDummyPostNotificationPermissionsState(), ) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt index 0ade93a795..37e6e9591d 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt @@ -23,21 +23,16 @@ import androidx.compose.foundation.layout.systemBarsPadding import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp -import io.element.android.libraries.androidutils.system.openAppSettingsPage import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.ElementPreview -import io.element.android.libraries.permissions.api.PermissionsView @Composable fun LoggedInView( state: LoggedInState, modifier: Modifier = Modifier ) { - val context = LocalContext.current - Box( modifier = modifier .fillMaxSize() @@ -49,10 +44,6 @@ fun LoggedInView( .align(Alignment.TopCenter), isVisible = state.showSyncSpinner, ) - PermissionsView( - state = state.permissionsState, - openSystemSettings = context::openAppSettingsPage - ) } } 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 4abc89e7ee..9ac795f9ab 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 @@ -26,8 +26,6 @@ import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService -import io.element.android.libraries.permissions.api.PermissionsPresenter -import io.element.android.libraries.permissions.noop.NoopPermissionsPresenter import io.element.android.libraries.push.api.PushService import io.element.android.libraries.pushproviders.api.Distributor import io.element.android.libraries.pushproviders.api.PushProvider @@ -43,7 +41,7 @@ class LoggedInPresenterTest { presenter.present() }.test { val initialState = awaitItem() - assertThat(initialState.permissionsState.permission).isEmpty() + assertThat(initialState.showSyncSpinner).isFalse() } } @@ -68,11 +66,6 @@ class LoggedInPresenterTest { ): LoggedInPresenter { return LoggedInPresenter( matrixClient = FakeMatrixClient(roomListService = roomListService), - permissionsPresenterFactory = object : PermissionsPresenter.Factory { - override fun create(permission: String): PermissionsPresenter { - return NoopPermissionsPresenter() - } - }, networkMonitor = FakeNetworkMonitor(networkStatus), pushService = object : PushService { override fun notificationStyleChanged() { diff --git a/changelog.d/897.feature b/changelog.d/897.feature new file mode 100644 index 0000000000..f705f8dee8 --- /dev/null +++ b/changelog.d/897.feature @@ -0,0 +1 @@ +Add a notification permission screen to the initial flow. diff --git a/features/ftue/impl/build.gradle.kts b/features/ftue/impl/build.gradle.kts index 8b12767b20..a4edc8fb7f 100644 --- a/features/ftue/impl/build.gradle.kts +++ b/features/ftue/impl/build.gradle.kts @@ -43,6 +43,10 @@ dependencies { implementation(projects.libraries.testtags) implementation(projects.features.analytics.api) implementation(projects.services.analytics.api) + implementation(projects.libraries.permissions.api) + implementation(projects.libraries.permissions.noop) + implementation(projects.services.toolbox.api) + implementation(projects.services.toolbox.test) testImplementation(libs.test.junit) testImplementation(libs.coroutines.test) @@ -51,6 +55,8 @@ dependencies { testImplementation(libs.test.turbine) testImplementation(projects.libraries.matrix.test) testImplementation(projects.services.analytics.test) + testImplementation(projects.libraries.permissions.impl) + testImplementation(projects.libraries.permissions.test) ksp(libs.showkase.processor) } diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/FtueFlowNode.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/FtueFlowNode.kt index 2b515c18a6..ab6bf94a69 100644 --- a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/FtueFlowNode.kt +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/FtueFlowNode.kt @@ -35,6 +35,7 @@ import io.element.android.anvilannotations.ContributesNode import io.element.android.features.analytics.api.AnalyticsEntryPoint import io.element.android.features.ftue.api.FtueEntryPoint import io.element.android.features.ftue.impl.migration.MigrationScreenNode +import io.element.android.features.ftue.impl.notifications.NotificationsOptInNode import io.element.android.features.ftue.impl.state.DefaultFtueState import io.element.android.features.ftue.impl.state.FtueStep import io.element.android.features.ftue.impl.welcome.WelcomeNode @@ -79,6 +80,9 @@ class FtueFlowNode @AssistedInject constructor( @Parcelize data object WelcomeScreen : NavTarget + @Parcelize + data object NotificationsOptIn : NavTarget + @Parcelize data object AnalyticsOptIn : NavTarget } @@ -124,6 +128,14 @@ class FtueFlowNode @AssistedInject constructor( } createNode(buildContext, listOf(callback)) } + NavTarget.NotificationsOptIn -> { + val callback = object : NotificationsOptInNode.Callback { + override fun onNotificationsOptInFinished() { + lifecycleScope.launch { moveToNextStep() } + } + } + createNode(buildContext, listOf(callback)) + } NavTarget.AnalyticsOptIn -> { analyticsEntryPoint.createNode(this, buildContext) } @@ -138,6 +150,9 @@ class FtueFlowNode @AssistedInject constructor( FtueStep.WelcomeScreen -> { backstack.newRoot(NavTarget.WelcomeScreen) } + FtueStep.NotificationsOptIn -> { + backstack.newRoot(NavTarget.NotificationsOptIn) + } FtueStep.AnalyticsOptIn -> { backstack.replace(NavTarget.AnalyticsOptIn) } diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInEvents.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInEvents.kt new file mode 100644 index 0000000000..55b6748c72 --- /dev/null +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInEvents.kt @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.ftue.impl.notifications + +sealed interface NotificationsOptInEvents { + data object ContinueClicked : NotificationsOptInEvents + data object NotNowClicked : NotificationsOptInEvents +} diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInNode.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInNode.kt new file mode 100644 index 0000000000..00fbb10b1f --- /dev/null +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInNode.kt @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.ftue.impl.notifications + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode +import io.element.android.libraries.architecture.NodeInputs +import io.element.android.libraries.architecture.inputs +import io.element.android.libraries.di.AppScope + +@ContributesNode(AppScope::class) +class NotificationsOptInNode @AssistedInject constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + private val presenterFactory: NotificationsOptInPresenter.Factory, +) : Node(buildContext, plugins = plugins) { + + interface Callback: NodeInputs { + fun onNotificationsOptInFinished() + } + + private val callback = inputs() + + private val presenter: NotificationsOptInPresenter by lazy { + presenterFactory.create(callback) + } + + @Composable + override fun View(modifier: Modifier) { + val state = presenter.present() + NotificationsOptInView( + state = state, + onBack = { callback.onNotificationsOptInFinished() }, + modifier = modifier + ) + } +} diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenter.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenter.kt new file mode 100644 index 0000000000..f7e4b6b26d --- /dev/null +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenter.kt @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.ftue.impl.notifications + +import android.Manifest +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.compose.runtime.Composable +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.permissions.api.PermissionStateProvider +import io.element.android.libraries.permissions.api.PermissionsEvents +import io.element.android.libraries.permissions.api.PermissionsPresenter +import io.element.android.libraries.permissions.noop.NoopPermissionsPresenter +import io.element.android.services.toolbox.api.sdk.BuildVersionSdkIntProvider +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +class NotificationsOptInPresenter @AssistedInject constructor( + private val permissionsPresenterFactory: PermissionsPresenter.Factory, + @Assisted private val callback: NotificationsOptInNode.Callback, + private val appCoroutineScope: CoroutineScope, + private val permissionStateProvider: PermissionStateProvider, + private val buildVersionSdkIntProvider: BuildVersionSdkIntProvider, +) : Presenter { + + @AssistedFactory + interface Factory { + fun create(callback: NotificationsOptInNode.Callback): NotificationsOptInPresenter + } + + private val postNotificationPermissionsPresenter by lazy { + // Ask for POST_NOTIFICATION PERMISSION on Android 13+ + if (buildVersionSdkIntProvider.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { + permissionsPresenterFactory.create(Manifest.permission.POST_NOTIFICATIONS) + } else { + NoopPermissionsPresenter() + } + } + + @Composable + override fun present(): NotificationsOptInState { + val notificationPremissionsState = postNotificationPermissionsPresenter.present() + + fun handleEvents(event: NotificationsOptInEvents) { + when (event) { + NotificationsOptInEvents.ContinueClicked -> { + if (notificationPremissionsState.permissionGranted) { + callback.onNotificationsOptInFinished() + } else { + notificationPremissionsState.eventSink(PermissionsEvents.OpenSystemDialog) + } + } + NotificationsOptInEvents.NotNowClicked -> { + if (buildVersionSdkIntProvider.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { + appCoroutineScope.setPermissionDenied() + } + callback.onNotificationsOptInFinished() + } + } + } + + return NotificationsOptInState( + notificationsPermissionState = notificationPremissionsState, + eventSink = ::handleEvents + ) + } + + @RequiresApi(Build.VERSION_CODES.TIRAMISU) + private fun CoroutineScope.setPermissionDenied() = launch { + permissionStateProvider.setPermissionDenied(Manifest.permission.POST_NOTIFICATIONS, true) + } +} diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInState.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInState.kt new file mode 100644 index 0000000000..a64fb7ad4a --- /dev/null +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInState.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.ftue.impl.notifications + +import io.element.android.libraries.permissions.api.PermissionsState + +data class NotificationsOptInState( + val notificationsPermissionState: PermissionsState, + val eventSink: (NotificationsOptInEvents) -> Unit +) diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInStateProvider.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInStateProvider.kt new file mode 100644 index 0000000000..230e125c1b --- /dev/null +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInStateProvider.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.ftue.impl.notifications + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.permissions.api.aPermissionsState + +open class NotificationsOptInStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + aNotificationsOptInState(), + // Add other states here + ) +} + +fun aNotificationsOptInState() = NotificationsOptInState( + notificationsPermissionState = aPermissionsState(), + eventSink = {} +) diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt new file mode 100644 index 0000000000..73135cafdc --- /dev/null +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.ftue.impl.notifications + +import androidx.activity.compose.BackHandler +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.systemBarsPadding +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Notifications +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.dp +import io.element.android.features.ftue.impl.R +import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule +import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule +import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage +import io.element.android.libraries.designsystem.colors.AvatarColors +import io.element.android.libraries.designsystem.colors.avatarColors +import io.element.android.libraries.designsystem.components.avatar.Avatar +import io.element.android.libraries.designsystem.components.avatar.AvatarData +import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.preview.DayNightPreviews +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.theme.components.Button +import io.element.android.libraries.designsystem.theme.components.Surface +import io.element.android.libraries.designsystem.theme.components.TextButton +import io.element.android.libraries.theme.ElementTheme +import io.element.android.libraries.ui.strings.CommonStrings + +@Composable +fun NotificationsOptInView( + state: NotificationsOptInState, + onBack: () -> Unit, + modifier: Modifier = Modifier, +) { + BackHandler(onBack = onBack) + + if (state.notificationsPermissionState.permissionAlreadyDenied) { + LaunchedEffect(Unit) { + state.eventSink(NotificationsOptInEvents.NotNowClicked) + } + } + + HeaderFooterPage( + modifier = modifier + .systemBarsPadding() + .fillMaxSize(), + header = { NotificationsOptInHeader(modifier = Modifier.padding(top = 60.dp, bottom = 12.dp),) }, + footer = { NotificationsOptInFooter(state) }, + ) { + NotificationsOptInContent(modifier = Modifier.fillMaxWidth()) + } +} + +@Composable +private fun NotificationsOptInHeader( + modifier: Modifier = Modifier, +) { + IconTitleSubtitleMolecule( + modifier = modifier, + title = stringResource(R.string.screen_notification_optin_title), + subTitle = stringResource(R.string.screen_notification_optin_subtitle), + iconImageVector = Icons.Default.Notifications, + ) +} + +@Composable +private fun NotificationsOptInFooter(state: NotificationsOptInState) { + ButtonColumnMolecule { + Button( + modifier = Modifier.fillMaxWidth(), + text = stringResource(CommonStrings.action_ok), + onClick = { + state.eventSink(NotificationsOptInEvents.ContinueClicked) + } + ) + TextButton( + modifier = Modifier.fillMaxWidth(), + text = stringResource(CommonStrings.action_not_now), + onClick = { + state.eventSink(NotificationsOptInEvents.NotNowClicked) + } + ) + } +} + +@Composable +private fun NotificationsOptInContent( + modifier: Modifier = Modifier, +) { + Box(modifier = modifier.fillMaxSize(), contentAlignment = Alignment.Center) { + Column( + verticalArrangement = Arrangement.spacedBy( + 16.dp, + alignment = Alignment.CenterVertically + ) + ) { + NotificationRow( + avatarLetter = "M", + avatarColors = avatarColors("5"), + firstRowPercent = 1f, + secondRowPercent = 0.4f + ) + + NotificationRow( + avatarLetter = "A", + avatarColors = avatarColors("1"), + firstRowPercent = 1f, + secondRowPercent = 1f + ) + + NotificationRow( + avatarLetter = "T", + avatarColors = avatarColors("4"), + firstRowPercent = 0.65f, + secondRowPercent = 0f + ) + } + } +} + +@Composable +private fun NotificationRow( + avatarLetter: String, + avatarColors: AvatarColors, + firstRowPercent: Float, + secondRowPercent: Float, + modifier: Modifier = Modifier +) { + Surface( + modifier = modifier, + color = ElementTheme.colors.bgCanvasDisabled, + shape = RoundedCornerShape(14.dp), + shadowElevation = 2.dp, + ) { + Row( + modifier = Modifier.padding(16.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Avatar( + avatarData = AvatarData(id = "", name = avatarLetter, size = AvatarSize.NotificationsOptIn), + initialAvatarColors = avatarColors, + ) + Column(Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(12.dp)) { + Box( + modifier = Modifier + .clip(CircleShape) + .fillMaxWidth(firstRowPercent) + .height(10.dp) + .background(ElementTheme.colors.borderInteractiveSecondary) + ) + if (secondRowPercent > 0f) { + Box( + modifier = Modifier.clip(CircleShape) + .fillMaxWidth(secondRowPercent) + .height(10.dp) + .background(ElementTheme.colors.borderInteractiveSecondary) + ) + } + } + } + } +} + +@DayNightPreviews +@Composable +internal fun NotificationsOptInViewPreview( + @PreviewParameter(NotificationsOptInStateProvider::class) state: NotificationsOptInState +) { + ElementPreview { + NotificationsOptInView( + onBack = {}, + state = state, + ) + } +} diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/state/DefaultFtueState.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/state/DefaultFtueState.kt index 108072cba9..3247d7faf8 100644 --- a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/state/DefaultFtueState.kt +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/state/DefaultFtueState.kt @@ -16,6 +16,8 @@ package io.element.android.features.ftue.impl.state +import android.Manifest +import android.os.Build import androidx.annotation.VisibleForTesting import com.squareup.anvil.annotations.ContributesBinding import io.element.android.features.ftue.api.state.FtueState @@ -23,7 +25,9 @@ import io.element.android.features.ftue.impl.migration.MigrationScreenStore import io.element.android.features.ftue.impl.welcome.state.WelcomeScreenState import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.permissions.api.PermissionStateProvider import io.element.android.services.analytics.api.AnalyticsService +import io.element.android.services.toolbox.api.sdk.BuildVersionSdkIntProvider import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.first @@ -34,10 +38,12 @@ import javax.inject.Inject @ContributesBinding(SessionScope::class) class DefaultFtueState @Inject constructor( + private val sdkVersionProvider: BuildVersionSdkIntProvider, private val coroutineScope: CoroutineScope, private val analyticsService: AnalyticsService, private val welcomeScreenState: WelcomeScreenState, private val migrationScreenStore: MigrationScreenStore, + private val permissionStateProvider: PermissionStateProvider, private val matrixClient: MatrixClient, ) : FtueState { @@ -47,6 +53,9 @@ class DefaultFtueState @Inject constructor( welcomeScreenState.reset() analyticsService.reset() migrationScreenStore.reset() + if (sdkVersionProvider.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { + permissionStateProvider.resetPermission(Manifest.permission.POST_NOTIFICATIONS) + } } init { @@ -63,7 +72,10 @@ class DefaultFtueState @Inject constructor( FtueStep.MigrationScreen -> if (shouldDisplayWelcomeScreen()) FtueStep.WelcomeScreen else getNextStep( FtueStep.WelcomeScreen ) - FtueStep.WelcomeScreen -> if (needsAnalyticsOptIn()) FtueStep.AnalyticsOptIn else getNextStep( + FtueStep.WelcomeScreen -> if (shouldAskNotificationPermissions()) FtueStep.NotificationsOptIn else getNextStep( + FtueStep.NotificationsOptIn + ) + FtueStep.NotificationsOptIn -> if (needsAnalyticsOptIn()) FtueStep.AnalyticsOptIn else getNextStep( FtueStep.AnalyticsOptIn ) FtueStep.AnalyticsOptIn -> null @@ -73,6 +85,7 @@ class DefaultFtueState @Inject constructor( return listOf( shouldDisplayMigrationScreen(), shouldDisplayWelcomeScreen(), + shouldAskNotificationPermissions(), needsAnalyticsOptIn() ).any { it } } @@ -90,6 +103,15 @@ class DefaultFtueState @Inject constructor( return welcomeScreenState.isWelcomeScreenNeeded() } + private fun shouldAskNotificationPermissions(): Boolean { + return if (sdkVersionProvider.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { + val permission = Manifest.permission.POST_NOTIFICATIONS + val isPermissionDenied = runBlocking { permissionStateProvider.isPermissionDenied(permission).first() } + val isPermissionGranted = permissionStateProvider.isPermissionGranted(permission) + !isPermissionGranted && !isPermissionDenied + } else false + } + fun setWelcomeScreenShown() { welcomeScreenState.setWelcomeScreenShown() updateState() @@ -104,5 +126,6 @@ class DefaultFtueState @Inject constructor( sealed interface FtueStep { data object MigrationScreen : FtueStep data object WelcomeScreen : FtueStep + data object NotificationsOptIn : FtueStep data object AnalyticsOptIn : FtueStep } diff --git a/features/ftue/impl/src/main/res/values/localazy.xml b/features/ftue/impl/src/main/res/values/localazy.xml index aee8470751..b398ba37d0 100644 --- a/features/ftue/impl/src/main/res/values/localazy.xml +++ b/features/ftue/impl/src/main/res/values/localazy.xml @@ -2,6 +2,8 @@ "This is a one time process, thanks for waiting." "Setting up your account." + "You can change your settings later." + "Allow notifications and never miss a message" "Calls, polls, search and more will be added later this year." "Message history for encrypted rooms won’t be available in this update." "We’d love to hear from you, let us know what you think via the settings page." diff --git a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueStateTests.kt b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueStateTests.kt index f93f761994..1388eb8fc1 100644 --- a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueStateTests.kt +++ b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueStateTests.kt @@ -16,6 +16,7 @@ package io.element.android.features.ftue.impl +import android.os.Build import com.google.common.truth.Truth.assertThat import io.element.android.features.ftue.impl.migration.InMemoryMigrationScreenStore import io.element.android.features.ftue.impl.migration.MigrationScreenStore @@ -25,8 +26,10 @@ import io.element.android.features.ftue.impl.welcome.state.FakeWelcomeState import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.libraries.permissions.impl.FakePermissionStateProvider import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.services.toolbox.test.sdk.FakeBuildVersionSdkIntProvider import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel @@ -51,13 +54,21 @@ class DefaultFtueStateTests { val welcomeState = FakeWelcomeState() val analyticsService = FakeAnalyticsService() val migrationScreenStore = InMemoryMigrationScreenStore() + val permissionStateProvider = FakePermissionStateProvider(permissionGranted = true) val coroutineScope = CoroutineScope(coroutineContext + SupervisorJob()) - val state = createState(coroutineScope, welcomeState, analyticsService, migrationScreenStore) + val state = createState( + coroutineScope = coroutineScope, + welcomeState = welcomeState, + analyticsService = analyticsService, + migrationScreenStore = migrationScreenStore, + permissionStateProvider = permissionStateProvider + ) welcomeState.setWelcomeScreenShown() analyticsService.setDidAskUserConsent() migrationScreenStore.setMigrationScreenShown(A_SESSION_ID) + permissionStateProvider.setPermissionGranted() state.updateState() assertThat(state.shouldDisplayFlow.value).isFalse() @@ -71,9 +82,16 @@ class DefaultFtueStateTests { val welcomeState = FakeWelcomeState() val analyticsService = FakeAnalyticsService() val migrationScreenStore = InMemoryMigrationScreenStore() + val permissionStateProvider = FakePermissionStateProvider(permissionGranted = false) val coroutineScope = CoroutineScope(coroutineContext + SupervisorJob()) - val state = createState(coroutineScope, welcomeState, analyticsService, migrationScreenStore) + val state = createState( + coroutineScope = coroutineScope, + welcomeState = welcomeState, + analyticsService = analyticsService, + migrationScreenStore = migrationScreenStore, + permissionStateProvider = permissionStateProvider + ) val steps = mutableListOf() // First step, migration screen @@ -84,7 +102,11 @@ class DefaultFtueStateTests { steps.add(state.getNextStep(steps.lastOrNull())) welcomeState.setWelcomeScreenShown() - // Third step, analytics opt in + // Third step, notifications opt in + steps.add(state.getNextStep(steps.lastOrNull())) + permissionStateProvider.setPermissionGranted() + + // Fourth step, analytics opt in steps.add(state.getNextStep(steps.lastOrNull())) analyticsService.setDidAskUserConsent() @@ -94,6 +116,7 @@ class DefaultFtueStateTests { assertThat(steps).containsExactly( FtueStep.MigrationScreen, FtueStep.WelcomeScreen, + FtueStep.NotificationsOptIn, FtueStep.AnalyticsOptIn, null, // Final state ) @@ -107,8 +130,37 @@ class DefaultFtueStateTests { val coroutineScope = CoroutineScope(coroutineContext + SupervisorJob()) val analyticsService = FakeAnalyticsService() val migrationScreenStore = InMemoryMigrationScreenStore() + val permissionStateProvider = FakePermissionStateProvider(permissionGranted = false) + + val state = createState( + coroutineScope = coroutineScope, + analyticsService = analyticsService, + migrationScreenStore = migrationScreenStore, + permissionStateProvider = permissionStateProvider, + ) + + // Skip first 3 steps + migrationScreenStore.setMigrationScreenShown(A_SESSION_ID) + state.setWelcomeScreenShown() + permissionStateProvider.setPermissionGranted() + + assertThat(state.getNextStep()).isEqualTo(FtueStep.AnalyticsOptIn) + + analyticsService.setDidAskUserConsent() + assertThat(state.getNextStep(FtueStep.WelcomeScreen)).isNull() + + // Cleanup + coroutineScope.cancel() + } + + @Test + fun `if version is older than 13 we don't display the notification opt in screen`() = runTest { + val coroutineScope = CoroutineScope(coroutineContext + SupervisorJob()) + val analyticsService = FakeAnalyticsService() + val migrationScreenStore = InMemoryMigrationScreenStore() val state = createState( + sdkIntVersion = Build.VERSION_CODES.M, coroutineScope = coroutineScope, analyticsService = analyticsService, migrationScreenStore = migrationScreenStore, @@ -132,12 +184,16 @@ class DefaultFtueStateTests { welcomeState: FakeWelcomeState = FakeWelcomeState(), analyticsService: AnalyticsService = FakeAnalyticsService(), migrationScreenStore: MigrationScreenStore = InMemoryMigrationScreenStore(), + permissionStateProvider: FakePermissionStateProvider = FakePermissionStateProvider(permissionGranted = false), matrixClient: MatrixClient = FakeMatrixClient(), + sdkIntVersion: Int = Build.VERSION_CODES.TIRAMISU, // First version where notification permission is required ) = DefaultFtueState( + sdkVersionProvider = FakeBuildVersionSdkIntProvider(sdkIntVersion), coroutineScope = coroutineScope, analyticsService = analyticsService, welcomeScreenState = welcomeState, migrationScreenStore = migrationScreenStore, + permissionStateProvider = permissionStateProvider, matrixClient = matrixClient, ) } diff --git a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenterTests.kt b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenterTests.kt new file mode 100644 index 0000000000..fa1ab39007 --- /dev/null +++ b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenterTests.kt @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.ftue.impl.notifications + +import android.os.Build +import app.cash.molecule.RecompositionMode +import app.cash.molecule.moleculeFlow +import app.cash.turbine.test +import com.google.common.truth.Truth +import io.element.android.libraries.permissions.api.PermissionStateProvider +import io.element.android.libraries.permissions.api.PermissionsPresenter +import io.element.android.libraries.permissions.impl.FakePermissionStateProvider +import io.element.android.libraries.permissions.test.FakePermissionsPresenter +import io.element.android.services.toolbox.test.sdk.FakeBuildVersionSdkIntProvider +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class NotificationsOptInPresenterTests { + + private var isFinished = false + + @Test + fun `initial state`() = runTest { + val presenter = createPresenter() + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + Truth.assertThat(initialState.notificationsPermissionState.showDialog).isFalse() + } + } + + @Test + fun `show dialog on continue clicked`() = runTest { + val permissionPresenter = FakePermissionsPresenter() + val presenter = createPresenter(permissionPresenter) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink(NotificationsOptInEvents.ContinueClicked) + Truth.assertThat(awaitItem().notificationsPermissionState.showDialog).isTrue() + } + } + + @Test + fun `finish flow on continue clicked with permission already granted`() = runTest { + val permissionPresenter = FakePermissionsPresenter().apply { + setPermissionGranted() + } + val presenter = createPresenter(permissionPresenter) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink(NotificationsOptInEvents.ContinueClicked) + Truth.assertThat(isFinished).isTrue() + } + } + + @Test + fun `finish flow on not now clicked`() = runTest { + val permissionPresenter = FakePermissionsPresenter() + val presenter = createPresenter( + permissionsPresenter = permissionPresenter, + sdkIntVersion = Build.VERSION_CODES.M + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink(NotificationsOptInEvents.NotNowClicked) + Truth.assertThat(isFinished).isTrue() + } + } + + @Test + fun `set permission denied on not now clicked in API 33`() = runTest(StandardTestDispatcher()) { + val permissionPresenter = FakePermissionsPresenter() + val permissionStateProvider = FakePermissionStateProvider() + val presenter = createPresenter( + permissionsPresenter = permissionPresenter, + permissionStateProvider = permissionStateProvider, + sdkIntVersion = Build.VERSION_CODES.TIRAMISU + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink(NotificationsOptInEvents.NotNowClicked) + + // Allow background coroutines to run + runCurrent() + + val isPermissionDenied = runBlocking { + permissionStateProvider.isPermissionDenied("notifications").first() + } + Truth.assertThat(isPermissionDenied).isTrue() + } + } + + private fun TestScope.createPresenter( + permissionsPresenter: PermissionsPresenter = FakePermissionsPresenter(), + permissionStateProvider: PermissionStateProvider = FakePermissionStateProvider(), + sdkIntVersion: Int = Build.VERSION_CODES.TIRAMISU, + ) = NotificationsOptInPresenter( + permissionsPresenterFactory = object : PermissionsPresenter.Factory { + override fun create(permission: String): PermissionsPresenter { + return permissionsPresenter + } + }, + callback = object : NotificationsOptInNode.Callback { + override fun onNotificationsOptInFinished() { + isFinished = true + } + }, + appCoroutineScope = this, + permissionStateProvider = permissionStateProvider, + buildVersionSdkIntProvider = FakeBuildVersionSdkIntProvider(sdkIntVersion), + ) +} 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 2438e5f017..372aecea32 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 @@ -42,4 +42,6 @@ enum class AvatarSize(val dp: Dp) { RoomInviteItem(52.dp), InviteSender(16.dp), + + NotificationsOptIn(32.dp), } diff --git a/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionStateProvider.kt b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionStateProvider.kt new file mode 100644 index 0000000000..8ea50b4ada --- /dev/null +++ b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionStateProvider.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.permissions.api + +import kotlinx.coroutines.flow.Flow + +interface PermissionStateProvider { + fun isPermissionGranted(permission: String): Boolean + suspend fun setPermissionDenied(permission: String, value: Boolean) + fun isPermissionDenied(permission: String): Flow + + suspend fun setPermissionAsked(permission: String, value: Boolean) + fun isPermissionAsked(permission: String): Flow + + suspend fun resetPermission(permission: String) +} diff --git a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/PermissionsStore.kt b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsStore.kt similarity index 95% rename from libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/PermissionsStore.kt rename to libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsStore.kt index 25b41e2a71..be16dc74e5 100644 --- a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/PermissionsStore.kt +++ b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsStore.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.libraries.permissions.impl +package io.element.android.libraries.permissions.api import kotlinx.coroutines.flow.Flow diff --git a/libraries/permissions/impl/build.gradle.kts b/libraries/permissions/impl/build.gradle.kts index 9808986f8f..4ae9fc9fcc 100644 --- a/libraries/permissions/impl/build.gradle.kts +++ b/libraries/permissions/impl/build.gradle.kts @@ -56,6 +56,7 @@ dependencies { testImplementation(libs.test.truth) testImplementation(libs.test.turbine) testImplementation(projects.libraries.matrix.test) + testImplementation(projects.libraries.permissions.test) ksp(libs.showkase.processor) } diff --git a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/AccompanistPermissionStateProvider.kt b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/AccompanistPermissionStateProvider.kt index 15acd868f2..02b4dd535c 100644 --- a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/AccompanistPermissionStateProvider.kt +++ b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/AccompanistPermissionStateProvider.kt @@ -26,13 +26,13 @@ import com.squareup.anvil.annotations.ContributesBinding import io.element.android.libraries.di.AppScope import javax.inject.Inject -interface PermissionStateProvider { +interface ComposablePermissionStateProvider { @Composable fun provide(permission: String, onPermissionResult: (Boolean) -> Unit): PermissionState } @ContributesBinding(AppScope::class) -class AccompanistPermissionStateProvider @Inject constructor() : PermissionStateProvider { +class AccompanistPermissionStateProvider @Inject constructor() : ComposablePermissionStateProvider { @Composable override fun provide(permission: String, onPermissionResult: (Boolean) -> Unit): PermissionState { return rememberPermissionState( diff --git a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionStateProvider.kt b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionStateProvider.kt new file mode 100644 index 0000000000..86cc646982 --- /dev/null +++ b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionStateProvider.kt @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.permissions.impl + +import android.content.Context +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.libraries.di.AppScope +import io.element.android.libraries.di.ApplicationContext +import io.element.android.libraries.di.SingleIn +import io.element.android.libraries.permissions.api.PermissionStateProvider +import io.element.android.libraries.permissions.api.PermissionsStore +import kotlinx.coroutines.flow.Flow +import javax.inject.Inject + +@SingleIn(AppScope::class) +@ContributesBinding(AppScope::class) +class DefaultPermissionStateProvider @Inject constructor( + @ApplicationContext private val context: Context, + private val permissionsStore: PermissionsStore, +): PermissionStateProvider { + override fun isPermissionGranted(permission: String): Boolean { + return context.checkSelfPermission(permission) == android.content.pm.PackageManager.PERMISSION_GRANTED + } + + override suspend fun setPermissionDenied(permission: String, value: Boolean) = permissionsStore.setPermissionDenied(permission, value) + + override fun isPermissionDenied(permission: String): Flow = permissionsStore.isPermissionDenied(permission) + + override suspend fun setPermissionAsked(permission: String, value: Boolean) = permissionsStore.setPermissionAsked(permission, value) + + override fun isPermissionAsked(permission: String): Flow = permissionsStore.isPermissionAsked(permission) + + override suspend fun resetPermission(permission: String) = permissionsStore.resetPermission(permission) +} diff --git a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenter.kt b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenter.kt index f98ab1fb9d..ddd45f865f 100644 --- a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenter.kt +++ b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenter.kt @@ -38,6 +38,7 @@ import io.element.android.libraries.di.AppScope import io.element.android.libraries.permissions.api.PermissionsEvents import io.element.android.libraries.permissions.api.PermissionsPresenter import io.element.android.libraries.permissions.api.PermissionsState +import io.element.android.libraries.permissions.api.PermissionsStore import kotlinx.coroutines.launch import timber.log.Timber @@ -46,7 +47,7 @@ private val loggerTag = LoggerTag("DefaultPermissionsPresenter") class DefaultPermissionsPresenter @AssistedInject constructor( @Assisted val permission: String, private val permissionsStore: PermissionsStore, - private val permissionStateProvider: PermissionStateProvider, + private val composablePermissionStateProvider: ComposablePermissionStateProvider, ) : PermissionsPresenter { @AssistedFactory @@ -90,7 +91,7 @@ class DefaultPermissionsPresenter @AssistedInject constructor( } } - permissionState = permissionStateProvider.provide( + permissionState = composablePermissionStateProvider.provide( permission = permission, onPermissionResult = ::onPermissionResult ) diff --git a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsStore.kt b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsStore.kt index 9ee29b7a61..49528da329 100644 --- a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsStore.kt +++ b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsStore.kt @@ -26,6 +26,7 @@ import com.squareup.anvil.annotations.ContributesBinding import io.element.android.libraries.core.bool.orFalse import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.ApplicationContext +import io.element.android.libraries.permissions.api.PermissionsStore import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import javax.inject.Inject @@ -34,7 +35,7 @@ private val Context.dataStore: DataStore by preferencesDataStore(na @ContributesBinding(AppScope::class) class DefaultPermissionsStore @Inject constructor( - @ApplicationContext context: Context, + @ApplicationContext private val context: Context, ) : PermissionsStore { private val store = context.dataStore diff --git a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/FakePermissionStateProvider.kt b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/FakePermissionStateProvider.kt new file mode 100644 index 0000000000..364f8072a1 --- /dev/null +++ b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/FakePermissionStateProvider.kt @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.permissions.impl + +import io.element.android.libraries.permissions.api.PermissionStateProvider +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow + +class FakePermissionStateProvider( + private var permissionGranted: Boolean = true, + permissionDenied: Boolean = false, + permissionAsked: Boolean = false, +): PermissionStateProvider { + private val permissionDeniedFlow = MutableStateFlow(permissionDenied) + private val permissionAskedFlow = MutableStateFlow(permissionAsked) + + fun setPermissionGranted() { + permissionGranted = true + } + + override fun isPermissionGranted(permission: String): Boolean = permissionGranted + + override suspend fun setPermissionDenied(permission: String, value: Boolean) { + permissionDeniedFlow.value = value + } + + override fun isPermissionDenied(permission: String): Flow = permissionDeniedFlow + + override suspend fun setPermissionAsked(permission: String, value: Boolean) { + permissionAskedFlow.value = value + } + + override fun isPermissionAsked(permission: String): Flow = permissionAskedFlow + + override suspend fun resetPermission(permission: String) { + setPermissionAsked(permission, false) + setPermissionDenied(permission, false) + } +} diff --git a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt index f501bcee8a..d435e4b89d 100644 --- a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt +++ b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt @@ -25,6 +25,7 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.PermissionStatus import com.google.common.truth.Truth.assertThat import io.element.android.libraries.permissions.api.PermissionsEvents +import io.element.android.libraries.permissions.test.InMemoryPermissionsStore import kotlinx.coroutines.test.runTest import org.junit.Test @@ -34,8 +35,14 @@ class DefaultPermissionsPresenterTest { @Test fun `present - initial state`() = runTest { val permissionsStore = InMemoryPermissionsStore() - val permissionState = FakePermissionState(A_PERMISSION, PermissionStatus.Granted) - val permissionStateProvider = FakePermissionStateProvider(permissionState) + val permissionState = FakePermissionState( + A_PERMISSION, + PermissionStatus.Granted + ) + val permissionStateProvider = + FakeComposablePermissionStateProvider( + permissionState + ) val presenter = DefaultPermissionsPresenter( A_PERMISSION, permissionsStore, @@ -57,8 +64,14 @@ class DefaultPermissionsPresenterTest { @Test fun `present - user closes dialog`() = runTest { val permissionsStore = InMemoryPermissionsStore() - val permissionState = FakePermissionState(A_PERMISSION, PermissionStatus.Denied(shouldShowRationale = false)) - val permissionStateProvider = FakePermissionStateProvider(permissionState) + val permissionState = FakePermissionState( + A_PERMISSION, + PermissionStatus.Denied(shouldShowRationale = false) + ) + val permissionStateProvider = + FakeComposablePermissionStateProvider( + permissionState + ) val presenter = DefaultPermissionsPresenter( A_PERMISSION, permissionsStore, @@ -77,8 +90,14 @@ class DefaultPermissionsPresenterTest { @Test fun `present - user does not grant permission`() = runTest { val permissionsStore = InMemoryPermissionsStore() - val permissionState = FakePermissionState(A_PERMISSION, PermissionStatus.Denied(shouldShowRationale = false)) - val permissionStateProvider = FakePermissionStateProvider(permissionState) + val permissionState = FakePermissionState( + A_PERMISSION, + PermissionStatus.Denied(shouldShowRationale = false) + ) + val permissionStateProvider = + FakeComposablePermissionStateProvider( + permissionState + ) val presenter = DefaultPermissionsPresenter( A_PERMISSION, permissionsStore, @@ -106,8 +125,14 @@ class DefaultPermissionsPresenterTest { @Test fun `present - user does not grant permission second time`() = runTest { val permissionsStore = InMemoryPermissionsStore() - val permissionState = FakePermissionState(A_PERMISSION, PermissionStatus.Denied(shouldShowRationale = true)) - val permissionStateProvider = FakePermissionStateProvider(permissionState) + val permissionState = FakePermissionState( + A_PERMISSION, + PermissionStatus.Denied(shouldShowRationale = true) + ) + val permissionStateProvider = + FakeComposablePermissionStateProvider( + permissionState + ) val presenter = DefaultPermissionsPresenter( A_PERMISSION, permissionsStore, @@ -134,9 +159,19 @@ class DefaultPermissionsPresenterTest { @Test fun `present - user does not grant permission third time`() = runTest { - val permissionsStore = InMemoryPermissionsStore(permissionDenied = true, permissionAsked = true) - val permissionState = FakePermissionState(A_PERMISSION, PermissionStatus.Denied(shouldShowRationale = false)) - val permissionStateProvider = FakePermissionStateProvider(permissionState) + val permissionsStore = + InMemoryPermissionsStore( + permissionDenied = true, + permissionAsked = true + ) + val permissionState = FakePermissionState( + A_PERMISSION, + PermissionStatus.Denied(shouldShowRationale = false) + ) + val permissionStateProvider = + FakeComposablePermissionStateProvider( + permissionState + ) val presenter = DefaultPermissionsPresenter( A_PERMISSION, permissionsStore, @@ -157,8 +192,14 @@ class DefaultPermissionsPresenterTest { @Test fun `present - user grants permission`() = runTest { val permissionsStore = InMemoryPermissionsStore() - val permissionState = FakePermissionState(A_PERMISSION, PermissionStatus.Denied(shouldShowRationale = false)) - val permissionStateProvider = FakePermissionStateProvider(permissionState) + val permissionState = FakePermissionState( + A_PERMISSION, + PermissionStatus.Denied(shouldShowRationale = false) + ) + val permissionStateProvider = + FakeComposablePermissionStateProvider( + permissionState + ) val presenter = DefaultPermissionsPresenter( A_PERMISSION, permissionsStore, diff --git a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/FakePermissionStateProvider.kt b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/FakeComposablePermissionStateProvider.kt similarity index 95% rename from libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/FakePermissionStateProvider.kt rename to libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/FakeComposablePermissionStateProvider.kt index c204ff5fc6..900d9ccc69 100644 --- a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/FakePermissionStateProvider.kt +++ b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/FakeComposablePermissionStateProvider.kt @@ -27,9 +27,9 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.PermissionState import com.google.accompanist.permissions.PermissionStatus -class FakePermissionStateProvider constructor( +class FakeComposablePermissionStateProvider constructor( private val permissionState: FakePermissionState -) : PermissionStateProvider { +) : ComposablePermissionStateProvider { private lateinit var onPermissionResult: (Boolean) -> Unit @OptIn(ExperimentalPermissionsApi::class) diff --git a/libraries/permissions/test/build.gradle.kts b/libraries/permissions/test/build.gradle.kts new file mode 100644 index 0000000000..6ed6a89677 --- /dev/null +++ b/libraries/permissions/test/build.gradle.kts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + id("io.element.android-compose-library") +} + +android { + namespace = "io.element.android.libraries.permissions.test" +} + +dependencies { + implementation(projects.libraries.architecture) + api(projects.libraries.permissions.api) +} diff --git a/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakePermissionsPresenter.kt b/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakePermissionsPresenter.kt new file mode 100644 index 0000000000..f26f268860 --- /dev/null +++ b/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakePermissionsPresenter.kt @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.permissions.test + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import io.element.android.libraries.permissions.api.PermissionsEvents +import io.element.android.libraries.permissions.api.PermissionsPresenter +import io.element.android.libraries.permissions.api.PermissionsState +import io.element.android.libraries.permissions.api.aPermissionsState + +class FakePermissionsPresenter( + private val initialState: PermissionsState = aPermissionsState().copy(showDialog = false), +) : PermissionsPresenter { + + private fun eventSink(events: PermissionsEvents) { + when (events) { + PermissionsEvents.OpenSystemDialog -> state.value = state.value.copy(showDialog = true, permissionAlreadyAsked = true) + PermissionsEvents.CloseDialog -> state.value = state.value.copy(showDialog = false) + } + } + + private val state = mutableStateOf(initialState.copy(eventSink = ::eventSink)) + + fun setPermissionGranted() { + state.value = state.value.copy(permissionGranted = true) + } + + fun setPermissionDenied() { + state.value = state.value.copy(permissionAlreadyDenied = true) + } + + @Composable + override fun present(): PermissionsState { + return state.value + } +} diff --git a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/InMemoryPermissionsStore.kt b/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/InMemoryPermissionsStore.kt similarity index 90% rename from libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/InMemoryPermissionsStore.kt rename to libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/InMemoryPermissionsStore.kt index 3f5d925ccd..abb357ab98 100644 --- a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/InMemoryPermissionsStore.kt +++ b/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/InMemoryPermissionsStore.kt @@ -14,8 +14,9 @@ * limitations under the License. */ -package io.element.android.libraries.permissions.impl +package io.element.android.libraries.permissions.test +import io.element.android.libraries.permissions.api.PermissionsStore import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow @@ -43,6 +44,5 @@ class InMemoryPermissionsStore( setPermissionDenied(permission, false) } - override suspend fun resetStore() { - } + override suspend fun resetStore() = Unit } diff --git a/services/toolbox/test/build.gradle.kts b/services/toolbox/test/build.gradle.kts new file mode 100644 index 0000000000..cb8857ceaa --- /dev/null +++ b/services/toolbox/test/build.gradle.kts @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +plugins { + id("io.element.android-library") +} + +android { + namespace = "io.element.android.services.toolbox.test" +} + +dependencies { + api(projects.services.toolbox.api) +} diff --git a/services/toolbox/test/src/main/kotlin/io/element/android/services/toolbox/test/sdk/FakeBuildVersionSdkIntProvider.kt b/services/toolbox/test/src/main/kotlin/io/element/android/services/toolbox/test/sdk/FakeBuildVersionSdkIntProvider.kt new file mode 100644 index 0000000000..072afeca77 --- /dev/null +++ b/services/toolbox/test/src/main/kotlin/io/element/android/services/toolbox/test/sdk/FakeBuildVersionSdkIntProvider.kt @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.toolbox.test.sdk + +import io.element.android.services.toolbox.api.sdk.BuildVersionSdkIntProvider + +class FakeBuildVersionSdkIntProvider( + private val sdkInt: Int +) : BuildVersionSdkIntProvider { + override fun get(): Int = sdkInt +} diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.notifications_null_NotificationsOptInView-D-1_2_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.notifications_null_NotificationsOptInView-D-1_2_null_0,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..aa866c7812 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.notifications_null_NotificationsOptInView-D-1_2_null_0,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2a47f94d02280f2122c0743fadc2d53824555f2e57e2c595b07dc32836f80586 +size 37142 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.notifications_null_NotificationsOptInView-N-1_3_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.notifications_null_NotificationsOptInView-N-1_3_null_0,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..49c3a7bafb --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.notifications_null_NotificationsOptInView-N-1_3_null_0,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f9028f6a5a6f67954385bcbcc098535071c096f37d12428c32af94a3e898bf6a +size 33685 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.welcome_null_WelcomeView-D-1_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.welcome_null_WelcomeView-D-2_3_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.welcome_null_WelcomeView-D-1_2_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.welcome_null_WelcomeView-D-2_3_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.welcome_null_WelcomeView-N-1_3_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.welcome_null_WelcomeView-N-2_4_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.welcome_null_WelcomeView-N-1_3_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.ftue.impl.welcome_null_WelcomeView-N-2_4_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_42,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_42,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..1483a5ea12 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_42,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5c50d9aee05b3e8b8be0b403a0621bc949c08dbca46695f6c70666002d5101d2 +size 18355 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_43,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_43,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..868cdd8e71 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_43,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d56abddf692484f8e2f3795c6cd3c62e8497a2d03042ef770fb75e8863921d40 +size 17689 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_44,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_44,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..a475b2e7d1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_44,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f0cb196c59e3bbd845f0e110150ac358ca78c9c08c212e184423ead5d841f67c +size 20219 diff --git a/tools/localazy/config.json b/tools/localazy/config.json index 4be78689de..05d1ced2c6 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -118,7 +118,8 @@ "name": ":features:ftue:impl", "includeRegex": [ "screen_welcome_.*", - "screen_migration_.*" + "screen_migration_.*", + "screen_notification_optin_.*" ] }, { From 7f8e54662f1a1c257e9d2f4b863f7e515bc505d7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 19:02:09 +0000 Subject: [PATCH 046/234] Update dependency me.saket.telephoto:zoomable-image-coil to v0.6.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 841e53b75d..7a722301fd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -45,7 +45,7 @@ dependencycheck = "8.4.0" dependencyanalysis = "1.21.0" stem = "2.3.0" sqldelight = "1.5.5" -telephoto = "0.6.0-SNAPSHOT" +telephoto = "0.6.0" # DI dagger = "2.48" From ffff48b66e2858512272b1a743ec118b8644a6b4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 Sep 2023 08:58:32 +0200 Subject: [PATCH 047/234] Fix R8 error, due to exclusion of analytics group done in #1221. --- libraries/pushproviders/firebase/build.gradle.kts | 7 +++++++ .../pushproviders/firebase/consumer-proguard-rules.pro | 4 ++++ 2 files changed, 11 insertions(+) create mode 100644 libraries/pushproviders/firebase/consumer-proguard-rules.pro diff --git a/libraries/pushproviders/firebase/build.gradle.kts b/libraries/pushproviders/firebase/build.gradle.kts index cdb55b1119..186ab121fd 100644 --- a/libraries/pushproviders/firebase/build.gradle.kts +++ b/libraries/pushproviders/firebase/build.gradle.kts @@ -20,6 +20,13 @@ plugins { android { namespace = "io.element.android.libraries.pushproviders.firebase" + + buildTypes { + release { + isMinifyEnabled = true + consumerProguardFiles("consumer-proguard-rules.pro") + } + } } anvil { diff --git a/libraries/pushproviders/firebase/consumer-proguard-rules.pro b/libraries/pushproviders/firebase/consumer-proguard-rules.pro new file mode 100644 index 0000000000..0bc7b604bf --- /dev/null +++ b/libraries/pushproviders/firebase/consumer-proguard-rules.pro @@ -0,0 +1,4 @@ +# Fix this error: +# ERROR: Missing classes detected while running R8. Please add the missing classes or apply additional keep rules that are generated in /Users/bmarty/workspaces/element-x-android/app/build/outputs/mapping/nightly/missing_rules.txt. +# ERROR: R8: Missing class com.google.firebase.analytics.connector.AnalyticsConnector (referenced from: void com.google.firebase.messaging.MessagingAnalytics.logToScion(java.lang.String, android.os.Bundle) and 1 other context) +-dontwarn com.google.firebase.analytics.connector.AnalyticsConnector From ce12b7f3f7588f19c455726659adbbc301638495 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 Sep 2023 09:23:22 +0200 Subject: [PATCH 048/234] Draft a documentation about the continuous integration --- docs/continuous_integration.md | 69 ++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 docs/continuous_integration.md diff --git a/docs/continuous_integration.md b/docs/continuous_integration.md new file mode 100644 index 0000000000..4ff0ebb983 --- /dev/null +++ b/docs/continuous_integration.md @@ -0,0 +1,69 @@ +# Continuous integration strategy + + + +* [Introduction](#introduction) +* [CI tools](#ci-tools) +* [Rules](#rules) +* [What is the CI checking](#what-is-the-ci-checking) +* [What is the CI reporting](#what-is-the-ci-reporting) +* [Current choices](#current-choices) + * [R8 task](#r8-task) + * [Android test (connected test)](#android-test-connected-test) + + + +## Introduction + +This document gives some information about how we take advantage of the continuous integration (CI). + +## CI tools + +We use GitHub Actions to configure and perform the CI. + +## Rules + +We want: + +1. The CI to detect as soon as possible any issue in the code +2. The CI to be fast - it's run on all the Pull Requests, and developers do not like to wait too long +3. The CI to be reliable - it should not fail randomly +4. The CI to generate artifacts which can be used by the team and the community +5. The CI to generate useful logs and reports, not too verbose, not too short +6. The developer to be able to run the CI locally - to help with this we have [a script](../tools/check/check_code_quality.sh) the can be run locally and which does more checks that just building and deploying the app. +7. The CI to be used as a common environment for the team: generate the screenshots image for the screenshot test, build the release build (unsigned) +8. The CI to run repeated tasks, like building the nightly builds, integrating data from external tools (translations, etc.) +9. The CI to upgrade our dependencies (Renovate) +10. The CI to do some issue triaging + +## What is the CI checking + +The CI checks that: + +1. The code is compiling, without any warnings, for all the app build types and variants and for the minimal app +2. The tests are passing +3. The code quality is good (detekt, ktlint, lint) +4. The code is running and smoke tests are passing (maestro) +5. The PullRequest itself is good (with danger) +6. Files that must be added with git-lfs are added with git-lfs + +## What is the CI reporting + +The CI reports: + +1. Code coverage reports +2. Sonar reports + +## Current choices + +### R8 task + +The CI does not run R8 because it's too slow, and it breaks rule 2. + +The drawback is that the nightly build can fail, as well as the release build. + +Since the nightly build is failing, the team can detect the failure quite fast and react to it. + +### Android test (connected test) + +We limit the number of connected tests (tests under folder `androidTest`), because it often break rule 2 and 3. From 64030fa0a383c05a884de4c2dece8ef9c65803d5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 07:56:49 +0000 Subject: [PATCH 049/234] Update dependency io.sentry:sentry-android to v6.29.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 841e53b75d..3d5d605118 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -163,7 +163,7 @@ maplibre_annotation = "org.maplibre.gl:android-plugin-annotation-v9:2.0.1" # Analytics posthog = "com.posthog.android:posthog:2.0.3" -sentry = "io.sentry:sentry-android:6.28.0" +sentry = "io.sentry:sentry-android:6.29.0" matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:42b2faa417c1e95f430bf8f6e379adba25ad5ef8" # Emojibase From 128c4a7b09f77e54eec2cb1342ab4dc8af1f7e5d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 Sep 2023 11:33:36 +0200 Subject: [PATCH 050/234] SDK 0.1.49: notification decryption is now fully handled by the Rust SDK. (#1231) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Revert "Ensure the sync is started when receiving a Push, to ensure that the encryption loop is running." This reverts commit 82f6f358a7987e46a38189e78f96455b94f2b6ad. * Integrate SDK from https://github.com/matrix-org/matrix-rust-sdk/pull/2505 * Enable retryDecryption() on the NotificationClient. * SDK 0.1.49 - Encryption Sync is enabled by default now, and retryDecryption is the default too. * Remove feature flag `UseEncryptionSync` * Fix sample project build * Exclude `DeveloperSettingsPresenter` from kover verification. * Add changelog --------- Co-authored-by: Jorge Martín --- .../android/appnav/LoggedInFlowNode.kt | 5 +-- build.gradle.kts | 2 + changelog.d/+sdk_bump.feature | 1 + .../developer/DeveloperSettingsPresenter.kt | 6 +-- gradle/libs.versions.toml | 2 +- .../libraries/featureflag/api/FeatureFlags.kt | 6 --- .../impl/BuildtimeFeatureFlagProvider.kt | 1 - .../matrix/api/sync/StartSyncReason.kt | 25 ------------ .../libraries/matrix/api/sync/SyncService.kt | 4 +- .../libraries/matrix/impl/RustMatrixClient.kt | 13 ++++-- .../matrix/impl/RustMatrixClientFactory.kt | 9 +---- .../impl/roomlist/RustRoomListService.kt | 1 + .../matrix/impl/sync/RustSyncService.kt | 40 +++++-------------- .../matrix/test/sync/FakeSyncService.kt | 5 +-- .../notifications/NotifiableEventResolver.kt | 12 ------ .../android/samples/minimal/MainActivity.kt | 2 - .../android/samples/minimal/RoomListScreen.kt | 5 +-- 17 files changed, 35 insertions(+), 104 deletions(-) create mode 100644 changelog.d/+sdk_bump.feature delete mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/sync/StartSyncReason.kt diff --git a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt index c3a79acb81..5006218bda 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt @@ -60,7 +60,6 @@ import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.MAIN_SPACE import io.element.android.libraries.matrix.api.core.RoomId -import io.element.android.libraries.matrix.api.sync.StartSyncReason import io.element.android.libraries.matrix.api.sync.SyncState import io.element.android.libraries.push.api.notifications.NotificationDrawerManager import io.element.android.services.appnavstate.api.AppNavigationStateService @@ -125,7 +124,7 @@ class LoggedInFlowNode @AssistedInject constructor( onStop = { //Counterpart startSync is done in observeSyncStateAndNetworkStatus method. coroutineScope.launch { - syncService.stopSync(StartSyncReason.AppInForeground) + syncService.stopSync() } }, onDestroy = { @@ -151,7 +150,7 @@ class LoggedInFlowNode @AssistedInject constructor( .collect { (syncState, networkStatus) -> Timber.d("Sync state: $syncState, network status: $networkStatus") if (syncState != SyncState.Running && networkStatus == NetworkStatus.Online) { - syncService.startSync(StartSyncReason.AppInForeground) + syncService.startSync() } } } diff --git a/build.gradle.kts b/build.gradle.kts index b48ef70ce7..69f5676e72 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -261,6 +261,8 @@ koverMerged { includes += "*Presenter" excludes += "*Fake*Presenter" excludes += "io.element.android.appnav.loggedin.LoggedInPresenter$*" + // Some options can't be tested at the moment + excludes += "io.element.android.features.preferences.impl.developer.DeveloperSettingsPresenter$*" } bound { minValue = 85 diff --git a/changelog.d/+sdk_bump.feature b/changelog.d/+sdk_bump.feature new file mode 100644 index 0000000000..4f92120f84 --- /dev/null +++ b/changelog.d/+sdk_bump.feature @@ -0,0 +1 @@ +Bump Rust SDK to `v0.1.49` \ No newline at end of file diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenter.kt index 5f50fde309..ebcd44b4db 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenter.kt @@ -124,16 +124,12 @@ class DeveloperSettingsPresenter @Inject constructor( enabledFeatures: SnapshotStateMap, featureUiModel: FeatureUiModel, enabled: Boolean, - triggerClearCache: () -> Unit, + @Suppress("UNUSED_PARAMETER") triggerClearCache: () -> Unit, ) = launch { val feature = features[featureUiModel.key] ?: return@launch if (featureFlagService.setFeatureEnabled(feature, enabled)) { enabledFeatures[featureUiModel.key] = enabled } - - if (featureUiModel.key == FeatureFlags.UseEncryptionSync.key) { - triggerClearCache() - } } private fun CoroutineScope.computeCacheSize(cacheSize: MutableState>) = launch { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7a722301fd..f42532ac1b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -146,7 +146,7 @@ jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" } appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = { module = "app.cash.molecule:molecule-runtime", version.ref = "molecule" } timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.48" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.49" sqldelight-driver-android = { module = "com.squareup.sqldelight:android-driver", version.ref = "sqldelight" } sqldelight-driver-jvm = { module = "com.squareup.sqldelight:sqlite-driver", version.ref = "sqldelight" } sqldelight-coroutines = { module = "com.squareup.sqldelight:coroutines-extensions", version.ref = "sqldelight" } diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt index 312745a4df..c28dc28144 100644 --- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt +++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt @@ -31,10 +31,4 @@ enum class FeatureFlags( title = "Polls", description = "Create poll and render poll events in the timeline", ), - UseEncryptionSync( - key = "feature.useencryptionsync", - title = "Use encryption sync", - description = "Use the encryption sync API for decrypting notifications.", - defaultValue = true, - ) } diff --git a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/BuildtimeFeatureFlagProvider.kt b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/BuildtimeFeatureFlagProvider.kt index 5640d108a6..83913cbac5 100644 --- a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/BuildtimeFeatureFlagProvider.kt +++ b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/BuildtimeFeatureFlagProvider.kt @@ -31,7 +31,6 @@ class BuildtimeFeatureFlagProvider @Inject constructor() : when (feature) { FeatureFlags.LocationSharing -> true FeatureFlags.Polls -> false - FeatureFlags.UseEncryptionSync -> true } } else { false diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/sync/StartSyncReason.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/sync/StartSyncReason.kt deleted file mode 100644 index 4a6b44949e..0000000000 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/sync/StartSyncReason.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2023 New Vector Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.element.android.libraries.matrix.api.sync - -import io.element.android.libraries.matrix.api.core.EventId -import io.element.android.libraries.matrix.api.core.RoomId - -sealed interface StartSyncReason { - data object AppInForeground : StartSyncReason - data class Notification(val roomId: RoomId, val eventId: EventId) : StartSyncReason -} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/sync/SyncService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/sync/SyncService.kt index 03a8402b32..994b35edc4 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/sync/SyncService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/sync/SyncService.kt @@ -22,12 +22,12 @@ interface SyncService { /** * Tries to start the sync. If already syncing it has no effect. */ - suspend fun startSync(reason: StartSyncReason): Result + suspend fun startSync(): Result /** * Tries to stop the sync. If service is not syncing it has no effect. */ - suspend fun stopSync(reason: StartSyncReason): Result + suspend fun stopSync(): Result /** * Flow of [SyncState]. Will be updated as soon as the current [SyncState] changes. diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index 4b0afb0b4f..54641f785b 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -65,6 +65,7 @@ import kotlinx.coroutines.withContext import kotlinx.coroutines.withTimeout import org.matrix.rustcomponents.sdk.Client import org.matrix.rustcomponents.sdk.ClientDelegate +import org.matrix.rustcomponents.sdk.NotificationProcessSetup import org.matrix.rustcomponents.sdk.Room import org.matrix.rustcomponents.sdk.RoomListItem import org.matrix.rustcomponents.sdk.use @@ -98,9 +99,13 @@ class RustMatrixClient constructor( client = client, dispatchers = dispatchers, ) - private val notificationClient = client.notificationClient().use { builder -> - builder.filterByPushRules().finish() - } + private val notificationProcessSetup = NotificationProcessSetup.SingleProcess(syncService) + private val notificationClient = client.notificationClient(notificationProcessSetup) + .use { builder -> + builder + .filterByPushRules() + .finish() + } private val notificationService = RustNotificationService(sessionId, notificationClient, dispatchers, clock) @@ -279,6 +284,7 @@ class RustMatrixClient constructor( syncService.destroy() innerRoomListService.destroy() notificationClient.destroy() + notificationProcessSetup.destroy() client.destroy() } @@ -316,6 +322,7 @@ class RustMatrixClient constructor( client.accountUrl() } } + override suspend fun loadUserDisplayName(): Result = withContext(sessionDispatcher) { runCatching { client.displayName() diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt index 3615115bb4..b37266342e 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt @@ -19,8 +19,6 @@ package io.element.android.libraries.matrix.impl import android.content.Context import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.di.ApplicationContext -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.network.useragent.UserAgentProvider import io.element.android.libraries.sessionstorage.api.SessionData import io.element.android.libraries.sessionstorage.api.SessionStore @@ -41,7 +39,6 @@ class RustMatrixClientFactory @Inject constructor( private val sessionStore: SessionStore, private val userAgentProvider: UserAgentProvider, private val clock: SystemClock, - private val featureFlagsService: FeatureFlagService, ) { suspend fun create(sessionData: SessionData): RustMatrixClient = withContext(coroutineDispatchers.io) { @@ -56,11 +53,7 @@ class RustMatrixClientFactory @Inject constructor( client.restoreSession(sessionData.toSession()) - val syncService = client.syncService().apply { - if (featureFlagsService.isFeatureEnabled(FeatureFlags.UseEncryptionSync)) { - withEncryptionSync(withCrossProcessLock = false, appIdentifier = null) - } - } + val syncService = client.syncService() .finish() RustMatrixClient( diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt index f56e55d759..655c634502 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt @@ -126,6 +126,7 @@ private fun RoomListLoadingState.toLoadingState(): RoomList.LoadingState { private fun RoomListServiceState.toRoomListState(): RoomListService.State { return when (this) { RoomListServiceState.INITIAL, + RoomListServiceState.RECOVERING, RoomListServiceState.SETTING_UP -> RoomListService.State.Idle RoomListServiceState.RUNNING -> RoomListService.State.Running RoomListServiceState.ERROR -> RoomListService.State.Error diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/RustSyncService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/RustSyncService.kt index b0a9fb31ec..932da42afb 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/RustSyncService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/RustSyncService.kt @@ -16,7 +16,6 @@ package io.element.android.libraries.matrix.impl.sync -import io.element.android.libraries.matrix.api.sync.StartSyncReason import io.element.android.libraries.matrix.api.sync.SyncService import io.element.android.libraries.matrix.api.sync.SyncState import kotlinx.coroutines.CoroutineScope @@ -26,8 +25,6 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock import org.matrix.rustcomponents.sdk.SyncServiceInterface import org.matrix.rustcomponents.sdk.SyncServiceState import timber.log.Timber @@ -36,36 +33,19 @@ class RustSyncService( private val innerSyncService: SyncServiceInterface, sessionCoroutineScope: CoroutineScope ) : SyncService { - private val mutex = Mutex() - private val startSyncReasonSet = mutableSetOf() - override suspend fun startSync(reason: StartSyncReason): Result { - return mutex.withLock { - startSyncReasonSet.add(reason) - runCatching { - Timber.d("Start sync") - innerSyncService.start() - }.onFailure { - Timber.e("Start sync failed: $it") - } - } + override suspend fun startSync() = runCatching { + Timber.i("Start sync") + innerSyncService.start() + }.onFailure { + Timber.d("Start sync failed: $it") } - override suspend fun stopSync(reason: StartSyncReason): Result { - return mutex.withLock { - startSyncReasonSet.remove(reason) - if (startSyncReasonSet.isEmpty()) { - runCatching { - Timber.d("Stop sync") - innerSyncService.stop() - }.onFailure { - Timber.e("Stop sync failed: $it") - } - } else { - Timber.d("Stop sync skipped, still $startSyncReasonSet") - Result.success(Unit) - } - } + override suspend fun stopSync() = runCatching { + Timber.i("Stop sync") + innerSyncService.stop() + }.onFailure { + Timber.d("Stop sync failed: $it") } override val syncState: StateFlow = diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/sync/FakeSyncService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/sync/FakeSyncService.kt index 87a54a2571..4e618deb9a 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/sync/FakeSyncService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/sync/FakeSyncService.kt @@ -16,7 +16,6 @@ package io.element.android.libraries.matrix.test.sync -import io.element.android.libraries.matrix.api.sync.StartSyncReason import io.element.android.libraries.matrix.api.sync.SyncService import io.element.android.libraries.matrix.api.sync.SyncState import kotlinx.coroutines.flow.MutableStateFlow @@ -30,12 +29,12 @@ class FakeSyncService : SyncService { syncStateFlow.value = SyncState.Error } - override suspend fun startSync(reason: StartSyncReason): Result { + override suspend fun startSync(): Result { syncStateFlow.value = SyncState.Running return Result.success(Unit) } - override suspend fun stopSync(reason: StartSyncReason): Result { + override suspend fun stopSync(): Result { syncStateFlow.value = SyncState.Terminated return Result.success(Unit) } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventResolver.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventResolver.kt index ce3d09f013..e5af7785db 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventResolver.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventResolver.kt @@ -26,7 +26,6 @@ import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.notification.NotificationContent import io.element.android.libraries.matrix.api.notification.NotificationData import io.element.android.libraries.matrix.api.room.RoomMembershipState -import io.element.android.libraries.matrix.api.sync.StartSyncReason import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType import io.element.android.libraries.matrix.api.timeline.item.event.EmoteMessageType import io.element.android.libraries.matrix.api.timeline.item.event.FileMessageType @@ -45,7 +44,6 @@ import io.element.android.libraries.push.impl.notifications.model.NotifiableMess import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.services.toolbox.api.strings.StringProvider import io.element.android.services.toolbox.api.systemclock.SystemClock -import kotlinx.coroutines.delay import timber.log.Timber import javax.inject.Inject @@ -67,14 +65,6 @@ class NotifiableEventResolver @Inject constructor( // Restore session val client = matrixClientProvider.getOrRestore(sessionId).getOrNull() ?: return null val notificationService = client.notificationService() - - // Restart the sync service to ensure that the crypto sync handle the toDevice Events. - client.syncService().startSync(StartSyncReason.Notification(roomId, eventId)) - // Wait for toDevice Event to be processed - // FIXME This delay can be removed when the Rust SDK will handle internal retry to get - // clear notification content. - delay(300) - val notificationData = notificationService.getNotification( userId = sessionId, roomId = roomId, @@ -83,8 +73,6 @@ class NotifiableEventResolver @Inject constructor( Timber.tag(loggerTag.value).e(it, "Unable to resolve event: $eventId.") }.getOrNull() - client.syncService().stopSync(StartSyncReason.Notification(roomId, eventId)) - // TODO this notificationData is not always valid at the moment, sometimes the Rust SDK can't fetch the matching event return notificationData?.asNotifiableEvent(sessionId) } diff --git a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt index 94cd28f021..d0309ebec7 100644 --- a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt +++ b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt @@ -26,7 +26,6 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.core.view.WindowCompat -import io.element.android.libraries.featureflag.impl.DefaultFeatureFlagService import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.impl.RustMatrixClientFactory import io.element.android.libraries.matrix.impl.auth.RustMatrixAuthenticationService @@ -56,7 +55,6 @@ class MainActivity : ComponentActivity() { sessionStore = sessionStore, userAgentProvider = userAgentProvider, clock = DefaultSystemClock(), - featureFlagsService = DefaultFeatureFlagService(emptySet()) ) ) } diff --git a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt index bb90425a48..faaccc9b8e 100644 --- a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt +++ b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt @@ -39,7 +39,6 @@ import io.element.android.libraries.eventformatter.impl.StateContentFormatter import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.RoomMembershipObserver -import io.element.android.libraries.matrix.api.sync.StartSyncReason import io.element.android.services.toolbox.impl.strings.AndroidStringProvider import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking @@ -110,12 +109,12 @@ class RoomListScreen( DisposableEffect(Unit) { Timber.w("Start sync!") runBlocking { - matrixClient.syncService().startSync(StartSyncReason.AppInForeground) + matrixClient.syncService().startSync() } onDispose { Timber.w("Stop sync!") runBlocking { - matrixClient.syncService().stopSync(StartSyncReason.AppInForeground) + matrixClient.syncService().stopSync() } } } From 9e5b46200bd31d5213e59af58fcbaaed723f8504 Mon Sep 17 00:00:00 2001 From: jonnyandrew Date: Wed, 6 Sep 2023 11:08:21 +0100 Subject: [PATCH 051/234] Reduce test flakiness by warming up molecule tests (#1226) --- .../android/appnav/RootPresenterTest.kt | 6 +++ .../appnav/loggedin/LoggedInPresenterTest.kt | 7 +++ features/analytics/impl/build.gradle.kts | 1 + .../impl/AnalyticsOptInPresenterTest.kt | 7 +++ .../AnalyticsPreferencesPresenterTest.kt | 7 +++ features/createroom/impl/build.gradle.kts | 1 + .../impl/addpeople/AddPeoplePresenterTests.kt | 6 +++ .../ConfigureRoomPresenterTests.kt | 6 +++ .../impl/root/CreateRoomRootPresenterTests.kt | 6 +++ .../userlist/DefaultUserListPresenterTests.kt | 6 +++ features/ftue/impl/build.gradle.kts | 1 + .../migration/MigrationScreenPresenterTest.kt | 7 +++ .../NotificationsOptInPresenterTests.kt | 6 +++ features/invitelist/impl/build.gradle.kts | 1 + .../impl/InviteListPresenterTests.kt | 5 ++ .../impl/LeaveRoomPresenterImplTest.kt | 6 +++ features/location/impl/build.gradle.kts | 1 + .../impl/send/SendLocationPresenterTest.kt | 6 +++ .../impl/show/ShowLocationPresenterTest.kt | 6 +++ .../changeserver/ChangeServerPresenterTest.kt | 7 +++ .../impl/oidc/webview/OidcPresenterTest.kt | 7 +++ .../ChangeAccountProviderPresenterTest.kt | 7 +++ .../ConfirmAccountProviderPresenterTest.kt | 7 +++ .../LoginPasswordPresenterTest.kt | 7 +++ .../SearchAccountProviderPresenterTest.kt | 7 +++ .../waitlistscreen/WaitListPresenterTest.kt | 7 +++ features/logout/impl/build.gradle.kts | 1 + .../impl/LogoutPreferencePresenterTest.kt | 7 +++ .../messages/MessagesPresenterTest.kt | 6 +++ .../actionlist/ActionListPresenterTest.kt | 7 +++ .../AttachmentsPreviewPresenterTest.kt | 6 +++ .../forward/ForwardMessagesPresenterTests.kt | 7 +++ .../media/viewer/MediaViewerPresenterTest.kt | 7 +++ .../report/ReportMessagePresenterTests.kt | 6 +++ .../MessageComposerPresenterTest.kt | 6 +++ .../timeline/TimelinePresenterTest.kt | 7 +++ .../CustomReactionPresenterTests.kt | 6 +++ .../ReactionSummaryPresenterTests.kt | 7 +++ .../RetrySendMenuPresenterTests.kt | 6 +++ features/onboarding/impl/build.gradle.kts | 1 + .../impl/OnBoardingPresenterTest.kt | 7 +++ features/poll/impl/build.gradle.kts | 1 + .../impl/create/CreatePollPresenterTest.kt | 6 +++ .../impl/about/AboutPresenterTest.kt | 7 +++ .../AnalyticsSettingsPresenterTest.kt | 7 +++ .../DeveloperSettingsPresenterTest.kt | 7 +++ .../tracing/ConfigureTracingPresenterTest.kt | 6 +++ .../impl/root/PreferencesRootPresenterTest.kt | 7 +++ features/rageshake/impl/build.gradle.kts | 1 + .../impl/bugreport/BugReportPresenterTest.kt | 7 +++ .../crash/ui/CrashDetectionPresenterTest.kt | 7 +++ .../RageshakeDetectionPresenterTest.kt | 6 +++ .../RageshakePreferencesPresenterTest.kt | 7 +++ .../roomdetails/RoomDetailsPresenterTests.kt | 6 +++ .../edit/RoomDetailsEditPresenterTest.kt | 6 +++ .../invite/RoomInviteMembersPresenterTest.kt | 6 +++ .../members/RoomMemberListPresenterTests.kt | 6 +++ .../RoomMemberDetailsPresenterTests.kt | 6 +++ .../roomlist/impl/RoomListPresenterTests.kt | 6 +++ features/verifysession/impl/build.gradle.kts | 1 + .../impl/VerifySelfSessionPresenterTests.kt | 6 +++ libraries/permissions/impl/build.gradle.kts | 1 + .../impl/DefaultPermissionsPresenterTest.kt | 7 +++ libraries/permissions/noop/build.gradle.kts | 1 + .../noop/NoopPermissionsPresenterTest.kt | 7 +++ tests/testutils/build.gradle.kts | 3 +- .../android/tests/testutils/WarmUpRule.kt | 48 +++++++++++++++++++ 67 files changed, 406 insertions(+), 1 deletion(-) create mode 100644 tests/testutils/src/main/kotlin/io/element/android/tests/testutils/WarmUpRule.kt diff --git a/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt b/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt index dad9365921..703e59c7f1 100644 --- a/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt +++ b/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt @@ -31,10 +31,16 @@ import io.element.android.features.rageshake.test.screenshot.FakeScreenshotHolde import io.element.android.services.apperror.api.AppErrorState import io.element.android.services.apperror.api.AppErrorStateService import io.element.android.services.apperror.impl.DefaultAppErrorStateService +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class RootPresenterTest { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial state`() = runTest { val presenter = createPresenter() 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 9ac795f9ab..f0a9642f4f 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 @@ -29,11 +29,18 @@ import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService import io.element.android.libraries.push.api.PushService import io.element.android.libraries.pushproviders.api.Distributor import io.element.android.libraries.pushproviders.api.PushProvider +import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.consumeItemsUntilPredicate import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class LoggedInPresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial state`() = runTest { val presenter = createPresenter() diff --git a/features/analytics/impl/build.gradle.kts b/features/analytics/impl/build.gradle.kts index 3ce2bab507..3deb202ebc 100644 --- a/features/analytics/impl/build.gradle.kts +++ b/features/analytics/impl/build.gradle.kts @@ -51,4 +51,5 @@ dependencies { testImplementation(libs.test.mockk) testImplementation(projects.libraries.matrix.test) testImplementation(projects.services.analytics.test) + testImplementation(projects.tests.testutils) } diff --git a/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInPresenterTest.kt b/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInPresenterTest.kt index b9cb4d95ff..aad9973282 100644 --- a/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInPresenterTest.kt +++ b/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInPresenterTest.kt @@ -23,11 +23,18 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.analytics.api.AnalyticsOptInEvents import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.flow.first import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class AnalyticsOptInPresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - enable`() = runTest { val analyticsService = FakeAnalyticsService(isEnabled = false) diff --git a/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/preferences/AnalyticsPreferencesPresenterTest.kt b/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/preferences/AnalyticsPreferencesPresenterTest.kt index 29c4579d8f..3a2812b72e 100644 --- a/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/preferences/AnalyticsPreferencesPresenterTest.kt +++ b/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/preferences/AnalyticsPreferencesPresenterTest.kt @@ -23,10 +23,17 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.analytics.api.AnalyticsOptInEvents import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class AnalyticsPreferencesPresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial state available`() = runTest { val presenter = DefaultAnalyticsPreferencesPresenter( diff --git a/features/createroom/impl/build.gradle.kts b/features/createroom/impl/build.gradle.kts index 0ef46a57ec..3ea54ca4ea 100644 --- a/features/createroom/impl/build.gradle.kts +++ b/features/createroom/impl/build.gradle.kts @@ -65,6 +65,7 @@ dependencies { testImplementation(projects.libraries.mediapickers.test) testImplementation(projects.libraries.mediaupload.test) testImplementation(projects.libraries.usersearch.test) + testImplementation(projects.tests.testutils) ksp(libs.showkase.processor) } diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeoplePresenterTests.kt b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeoplePresenterTests.kt index 43cf6cff4d..af68f0dd57 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeoplePresenterTests.kt +++ b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeoplePresenterTests.kt @@ -24,12 +24,18 @@ import io.element.android.features.createroom.impl.CreateRoomDataStore import io.element.android.features.createroom.impl.userlist.FakeUserListPresenterFactory import io.element.android.features.createroom.impl.userlist.UserListDataStore import io.element.android.libraries.usersearch.test.FakeUserRepository +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest import org.junit.Before +import org.junit.Rule import org.junit.Test class AddPeoplePresenterTests { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + private lateinit var presenter: AddPeoplePresenter @Before diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenterTests.kt b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenterTests.kt index 864d85423d..bc5bafa843 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenterTests.kt +++ b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenterTests.kt @@ -38,6 +38,7 @@ import io.element.android.libraries.mediapickers.test.FakePickerProvider import io.element.android.libraries.mediaupload.api.MediaUploadInfo import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.WarmUpRule import io.mockk.every import io.mockk.mockk import io.mockk.mockkStatic @@ -47,6 +48,7 @@ import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.test.runTest import org.junit.After import org.junit.Before +import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner @@ -58,6 +60,10 @@ private const val AN_URI_FROM_GALLERY = "content://uri_from_gallery" @RunWith(RobolectricTestRunner::class) class ConfigureRoomPresenterTests { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + private lateinit var presenter: ConfigureRoomPresenter private lateinit var userListDataStore: UserListDataStore private lateinit var createRoomDataStore: CreateRoomDataStore diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenterTests.kt b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenterTests.kt index 0f88280c84..1809df135b 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenterTests.kt +++ b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenterTests.kt @@ -35,13 +35,19 @@ import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.libraries.usersearch.test.FakeUserRepository import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.WarmUpRule import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.test.runTest import org.junit.Before +import org.junit.Rule import org.junit.Test class CreateRoomRootPresenterTests { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + private lateinit var userRepository: FakeUserRepository private lateinit var presenter: CreateRoomRootPresenter private lateinit var fakeUserListPresenter: FakeUserListPresenter diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/userlist/DefaultUserListPresenterTests.kt b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/userlist/DefaultUserListPresenterTests.kt index 3561387dcf..12e9f2fc90 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/userlist/DefaultUserListPresenterTests.kt +++ b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/userlist/DefaultUserListPresenterTests.kt @@ -25,12 +25,18 @@ import io.element.android.libraries.matrix.ui.components.aMatrixUser import io.element.android.libraries.matrix.ui.components.aMatrixUserList import io.element.android.libraries.usersearch.api.UserSearchResult import io.element.android.libraries.usersearch.test.FakeUserRepository +import io.element.android.tests.testutils.WarmUpRule import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class DefaultUserListPresenterTests { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + private val userRepository = FakeUserRepository() @Test diff --git a/features/ftue/impl/build.gradle.kts b/features/ftue/impl/build.gradle.kts index a4edc8fb7f..42fe8dade5 100644 --- a/features/ftue/impl/build.gradle.kts +++ b/features/ftue/impl/build.gradle.kts @@ -57,6 +57,7 @@ dependencies { testImplementation(projects.services.analytics.test) testImplementation(projects.libraries.permissions.impl) testImplementation(projects.libraries.permissions.test) + testImplementation(projects.tests.testutils) ksp(libs.showkase.processor) } diff --git a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/migration/MigrationScreenPresenterTest.kt b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/migration/MigrationScreenPresenterTest.kt index 6e19879b86..1a9a33130d 100644 --- a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/migration/MigrationScreenPresenterTest.kt +++ b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/migration/MigrationScreenPresenterTest.kt @@ -25,10 +25,17 @@ import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class MigrationScreenPresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial`() = runTest { val presenter = createPresenter() diff --git a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenterTests.kt b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenterTests.kt index fa1ab39007..0c55992367 100644 --- a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenterTests.kt +++ b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenterTests.kt @@ -26,16 +26,22 @@ import io.element.android.libraries.permissions.api.PermissionsPresenter import io.element.android.libraries.permissions.impl.FakePermissionStateProvider import io.element.android.libraries.permissions.test.FakePermissionsPresenter import io.element.android.services.toolbox.test.sdk.FakeBuildVersionSdkIntProvider +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.flow.first import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class NotificationsOptInPresenterTests { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + private var isFinished = false @Test diff --git a/features/invitelist/impl/build.gradle.kts b/features/invitelist/impl/build.gradle.kts index cd008472b5..d8fb25585f 100644 --- a/features/invitelist/impl/build.gradle.kts +++ b/features/invitelist/impl/build.gradle.kts @@ -54,6 +54,7 @@ dependencies { testImplementation(projects.libraries.push.test) testImplementation(projects.features.invitelist.test) testImplementation(projects.services.analytics.test) + testImplementation(projects.tests.testutils) ksp(libs.showkase.processor) } diff --git a/features/invitelist/impl/src/test/kotlin/io/element/android/features/invitelist/impl/InviteListPresenterTests.kt b/features/invitelist/impl/src/test/kotlin/io/element/android/features/invitelist/impl/InviteListPresenterTests.kt index adb2042b62..9ba26b5e2d 100644 --- a/features/invitelist/impl/src/test/kotlin/io/element/android/features/invitelist/impl/InviteListPresenterTests.kt +++ b/features/invitelist/impl/src/test/kotlin/io/element/android/features/invitelist/impl/InviteListPresenterTests.kt @@ -44,10 +44,15 @@ import io.element.android.libraries.push.api.notifications.NotificationDrawerMan import io.element.android.libraries.push.test.notifications.FakeNotificationDrawerManager import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class InviteListPresenterTests { + @Rule + @JvmField + val warmUpRule = WarmUpRule() @Test fun `present - starts empty, adds invites when received`() = runTest { diff --git a/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt b/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt index 3075d3c686..7bbab71a8d 100644 --- a/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt +++ b/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt @@ -29,14 +29,20 @@ import io.element.android.libraries.matrix.api.timeline.item.event.MembershipCha import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.coroutines.flow.first import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class LeaveRoomPresenterImplTest { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial state hides all dialogs`() = runTest { val presenter = createPresenter() diff --git a/features/location/impl/build.gradle.kts b/features/location/impl/build.gradle.kts index 325003b110..dd265ee7f0 100644 --- a/features/location/impl/build.gradle.kts +++ b/features/location/impl/build.gradle.kts @@ -57,4 +57,5 @@ dependencies { testImplementation(projects.libraries.matrix.test) testImplementation(projects.services.analytics.test) testImplementation(projects.features.messages.test) + testImplementation(projects.tests.testutils) } diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/SendLocationPresenterTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/SendLocationPresenterTest.kt index 21766a2cf0..15afa48b26 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/SendLocationPresenterTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/SendLocationPresenterTest.kt @@ -34,12 +34,18 @@ import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.libraries.matrix.test.room.SendLocationInvocation import io.element.android.libraries.textcomposer.MessageComposerMode import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.delay import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class SendLocationPresenterTest { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + private val permissionsPresenterFake = PermissionsPresenterFake() private val fakeMatrixRoom = FakeMatrixRoom() private val fakeAnalyticsService = FakeAnalyticsService() diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt index 12ccdc16a5..ebb146ca57 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt @@ -27,12 +27,18 @@ import io.element.android.features.location.impl.common.permissions.PermissionsP import io.element.android.features.location.impl.common.permissions.PermissionsPresenterFake import io.element.android.features.location.impl.common.permissions.PermissionsState import io.element.android.libraries.matrix.test.core.aBuildMeta +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.delay import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class ShowLocationPresenterTest { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + private val permissionsPresenterFake = PermissionsPresenterFake() private val fakeLocationActions = FakeLocationActions() private val fakeBuildMeta = aBuildMeta(applicationName = "app name") diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt index 009ab31dcd..4a2fcc397c 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt @@ -26,10 +26,17 @@ import io.element.android.libraries.architecture.Async import io.element.android.libraries.matrix.test.A_HOMESERVER import io.element.android.libraries.matrix.test.A_HOMESERVER_URL import io.element.android.libraries.matrix.test.auth.FakeAuthenticationService +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class ChangeServerPresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial state`() = runTest { val presenter = ChangeServerPresenter( diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/oidc/webview/OidcPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/oidc/webview/OidcPresenterTest.kt index 32d1c6918a..60cc1285e3 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/oidc/webview/OidcPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/oidc/webview/OidcPresenterTest.kt @@ -27,11 +27,18 @@ import io.element.android.libraries.architecture.Async import io.element.android.libraries.matrix.test.A_THROWABLE import io.element.android.libraries.matrix.test.auth.A_OIDC_DATA import io.element.android.libraries.matrix.test.auth.FakeAuthenticationService +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class OidcPresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial state`() = runTest { val presenter = OidcPresenter( diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderPresenterTest.kt index f807355cb1..6fe3248ec3 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderPresenterTest.kt @@ -24,10 +24,17 @@ import io.element.android.features.login.impl.accountprovider.AccountProvider import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource import io.element.android.features.login.impl.changeserver.ChangeServerPresenter import io.element.android.libraries.matrix.test.auth.FakeAuthenticationService +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class ChangeAccountProviderPresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial state`() = runTest { val changeServerPresenter = ChangeServerPresenter( diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt index 95cd9bf053..0ec396694b 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt @@ -31,11 +31,18 @@ import io.element.android.libraries.matrix.test.A_HOMESERVER import io.element.android.libraries.matrix.test.A_HOMESERVER_OIDC import io.element.android.libraries.matrix.test.A_THROWABLE import io.element.android.libraries.matrix.test.auth.FakeAuthenticationService +import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.waitForPredicate import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class ConfirmAccountProviderPresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial test`() = runTest { val presenter = createConfirmAccountProviderPresenter() diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenterTest.kt index 421eb869b0..1848940966 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenterTest.kt @@ -31,10 +31,17 @@ import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.A_THROWABLE import io.element.android.libraries.matrix.test.A_USER_NAME import io.element.android.libraries.matrix.test.auth.FakeAuthenticationService +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class LoginPasswordPresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial state`() = runTest { val authenticationService = FakeAuthenticationService() diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderPresenterTest.kt index ae6ae4d344..89d1a22b0c 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderPresenterTest.kt @@ -30,11 +30,18 @@ import io.element.android.features.login.impl.resolver.network.WellKnownSlidingS import io.element.android.libraries.architecture.Async import io.element.android.libraries.matrix.test.A_HOMESERVER_URL import io.element.android.libraries.matrix.test.auth.FakeAuthenticationService +import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class SearchAccountProviderPresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial state`() = runTest { val fakeWellknownRequest = FakeWellknownRequest() diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/waitlistscreen/WaitListPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/waitlistscreen/WaitListPresenterTest.kt index 507e8cec8b..dadcbe186a 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/waitlistscreen/WaitListPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/waitlistscreen/WaitListPresenterTest.kt @@ -30,10 +30,17 @@ import io.element.android.libraries.matrix.test.A_THROWABLE import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.auth.FakeAuthenticationService import io.element.android.libraries.matrix.test.core.aBuildMeta +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class WaitListPresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial state`() = runTest { val authenticationService = FakeAuthenticationService().apply { diff --git a/features/logout/impl/build.gradle.kts b/features/logout/impl/build.gradle.kts index 464695e169..52a9f76b41 100644 --- a/features/logout/impl/build.gradle.kts +++ b/features/logout/impl/build.gradle.kts @@ -48,4 +48,5 @@ dependencies { testImplementation(libs.test.truth) testImplementation(libs.test.turbine) testImplementation(projects.libraries.matrix.test) + testImplementation(projects.tests.testutils) } diff --git a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPreferencePresenterTest.kt b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPreferencePresenterTest.kt index 29df521cb1..9527012e28 100644 --- a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPreferencePresenterTest.kt +++ b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPreferencePresenterTest.kt @@ -25,10 +25,17 @@ import io.element.android.features.logout.api.LogoutPreferenceState import io.element.android.libraries.architecture.Async import io.element.android.libraries.matrix.test.A_THROWABLE import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class LogoutPreferencePresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial state`() = runTest { val presenter = DefaultLogoutPreferencePresenter( diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt index 992ea60869..3d98f665b6 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt @@ -70,6 +70,7 @@ import io.element.android.libraries.mediaupload.api.MediaSender import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor import io.element.android.libraries.textcomposer.MessageComposerMode 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.consumeItemsUntilTimeout import io.element.android.tests.testutils.testCoroutineDispatchers @@ -77,10 +78,15 @@ import io.element.android.tests.testutils.waitForPredicate import io.mockk.mockk import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class MessagesPresenterTest { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + private val mockMediaUrl: Uri = mockk("localMediaUri") @Test diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt index a4ff484ff3..3f3114dff3 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt @@ -33,11 +33,18 @@ import io.element.android.features.messages.impl.timeline.model.event.aTimelineI import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemStateEventContent import io.element.android.libraries.matrix.test.A_MESSAGE import io.element.android.libraries.matrix.test.core.aBuildMeta +import io.element.android.tests.testutils.WarmUpRule import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class ActionListPresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial state`() = runTest { val presenter = anActionListPresenter(isBuildDebuggable = true) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/attachments/AttachmentsPreviewPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/attachments/AttachmentsPreviewPresenterTest.kt index 3608d9e80e..5a66fe13b8 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/attachments/AttachmentsPreviewPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/attachments/AttachmentsPreviewPresenterTest.kt @@ -34,13 +34,19 @@ import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.libraries.mediaupload.api.MediaPreProcessor import io.element.android.libraries.mediaupload.api.MediaSender import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor +import io.element.android.tests.testutils.WarmUpRule import io.mockk.mockk import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class AttachmentsPreviewPresenterTest { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + private val mediaPreProcessor = FakeMediaPreProcessor() private val mockMediaUrl: Uri = mockk("localMediaUri") diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/forward/ForwardMessagesPresenterTests.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/forward/ForwardMessagesPresenterTests.kt index 983b251df7..7b6f48403f 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/forward/ForwardMessagesPresenterTests.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/forward/ForwardMessagesPresenterTests.kt @@ -30,13 +30,20 @@ import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.libraries.matrix.test.room.aRoomSummaryDetail import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService +import io.element.android.tests.testutils.WarmUpRule import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class ForwardMessagesPresenterTests { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + + @Test fun `present - initial state`() = runTest { val presenter = aPresenter() diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/media/viewer/MediaViewerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/media/viewer/MediaViewerPresenterTest.kt index 3c31fa49d3..97ee81bcb6 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/media/viewer/MediaViewerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/media/viewer/MediaViewerPresenterTest.kt @@ -33,15 +33,22 @@ import io.element.android.libraries.architecture.Async import io.element.android.libraries.designsystem.utils.SnackbarDispatcher import io.element.android.libraries.matrix.test.media.FakeMediaLoader import io.element.android.libraries.matrix.test.media.aMediaSource +import io.element.android.tests.testutils.WarmUpRule import io.mockk.mockk import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test private val TESTED_MEDIA_INFO = aFileInfo() class MediaViewerPresenterTest { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + + private val mockMediaUri: Uri = mockk("localMediaUri") private val localMediaFactory = FakeLocalMediaFactory(mockMediaUri) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/report/ReportMessagePresenterTests.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/report/ReportMessagePresenterTests.kt index e6b0dee0c9..97b0227def 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/report/ReportMessagePresenterTests.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/report/ReportMessagePresenterTests.kt @@ -28,11 +28,17 @@ import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class ReportMessagePresenterTests { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `presenter - initial state`() = runTest { val presenter = aPresenter() diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt index 799db7f274..d89a0392ad 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt @@ -55,15 +55,21 @@ import io.element.android.libraries.mediaupload.api.MediaUploadInfo import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor import io.element.android.libraries.textcomposer.MessageComposerMode import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.WarmUpRule import io.mockk.mockk import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test import java.io.File class MessageComposerPresenterTest { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + private val pickerProvider = FakePickerProvider().apply { givenResult(mockk()) // Uri is not available in JVM, so the only way to have a non-null Uri is using Mockk } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/TimelinePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/TimelinePresenterTest.kt index 860f8def37..4e8ab07d95 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/TimelinePresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/TimelinePresenterTest.kt @@ -37,15 +37,22 @@ import io.element.android.libraries.matrix.test.room.aMessageContent import io.element.android.libraries.matrix.test.room.anEventTimelineItem import io.element.android.libraries.matrix.test.timeline.FakeMatrixTimeline import io.element.android.libraries.matrix.ui.components.aMatrixUserList +import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.awaitWithLatch import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test import java.util.Date class TimelinePresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial state`() = runTest { val presenter = createTimelinePresenter() diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/customreaction/CustomReactionPresenterTests.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/customreaction/CustomReactionPresenterTests.kt index bb77605132..9f9b7358d8 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/customreaction/CustomReactionPresenterTests.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/customreaction/CustomReactionPresenterTests.kt @@ -26,11 +26,17 @@ import io.element.android.features.messages.impl.timeline.components.customreact import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionPresenter import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionState import io.element.android.libraries.matrix.test.AN_EVENT_ID +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class CustomReactionPresenterTests { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + private val presenter = CustomReactionPresenter(emojibaseProvider = FakeEmojibaseProvider()) @Test diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/reactionsummary/ReactionSummaryPresenterTests.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/reactionsummary/ReactionSummaryPresenterTests.kt index 0170878cb5..c2a415ea44 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/reactionsummary/ReactionSummaryPresenterTests.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/reactionsummary/ReactionSummaryPresenterTests.kt @@ -30,10 +30,17 @@ import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.A_USER_NAME import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.libraries.matrix.test.room.aRoomMember +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class ReactionSummaryPresenterTests { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + private val aggregatedReaction = anAggregatedReaction(userId = A_USER_ID, key = "👍", isHighlighted = true) private val roomMember = aRoomMember(userId = A_USER_ID, avatarUrl = AN_AVATAR_URL, displayName = A_USER_NAME) private val summaryEvent = ReactionSummaryEvents.ShowReactionSummary(AN_EVENT_ID, listOf(aggregatedReaction), aggregatedReaction.key) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/retrysendmenu/RetrySendMenuPresenterTests.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/retrysendmenu/RetrySendMenuPresenterTests.kt index 4f4f0a0ee4..5a23eba6da 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/retrysendmenu/RetrySendMenuPresenterTests.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/retrysendmenu/RetrySendMenuPresenterTests.kt @@ -25,11 +25,17 @@ import io.element.android.features.messages.impl.timeline.components.retrysendme import io.element.android.features.messages.impl.timeline.components.retrysendmenu.RetrySendMenuPresenter import io.element.android.libraries.matrix.test.A_TRANSACTION_ID import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class RetrySendMenuPresenterTests { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + private val room = FakeMatrixRoom() private val presenter = RetrySendMenuPresenter(room) diff --git a/features/onboarding/impl/build.gradle.kts b/features/onboarding/impl/build.gradle.kts index 0f97a0ffeb..9994eacf81 100644 --- a/features/onboarding/impl/build.gradle.kts +++ b/features/onboarding/impl/build.gradle.kts @@ -48,4 +48,5 @@ dependencies { testImplementation(libs.test.truth) testImplementation(libs.test.turbine) testImplementation(projects.libraries.matrix.test) + testImplementation(projects.tests.testutils) } diff --git a/features/onboarding/impl/src/test/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenterTest.kt b/features/onboarding/impl/src/test/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenterTest.kt index d336e5b466..c2db28631c 100644 --- a/features/onboarding/impl/src/test/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenterTest.kt +++ b/features/onboarding/impl/src/test/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenterTest.kt @@ -20,10 +20,17 @@ import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class OnBoardingPresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial state`() = runTest { val presenter = OnBoardingPresenter() diff --git a/features/poll/impl/build.gradle.kts b/features/poll/impl/build.gradle.kts index 4e8d36966a..e2139424e1 100644 --- a/features/poll/impl/build.gradle.kts +++ b/features/poll/impl/build.gradle.kts @@ -48,6 +48,7 @@ dependencies { testImplementation(libs.test.turbine) testImplementation(projects.libraries.matrix.test) testImplementation(projects.services.analytics.test) + testImplementation(projects.tests.testutils) ksp(libs.showkase.processor) } diff --git a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenterTest.kt b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenterTest.kt index 9dacc6062d..c54972e9d1 100644 --- a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenterTest.kt +++ b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenterTest.kt @@ -23,12 +23,18 @@ import com.google.common.truth.Truth import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.matrix.test.room.CreatePollInvocation import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.delay import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class CreatePollPresenterTest { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + private var navUpInvocationsCount = 0 private val fakeMatrixRoom = FakeMatrixRoom() // private val fakeAnalyticsService = FakeAnalyticsService() // TODO Polls: add analytics diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/about/AboutPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/about/AboutPresenterTest.kt index 4b025c10ad..ad98756992 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/about/AboutPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/about/AboutPresenterTest.kt @@ -20,10 +20,17 @@ import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class AboutPresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial state`() = runTest { val presenter = AboutPresenter() diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/analytics/AnalyticsSettingsPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/analytics/AnalyticsSettingsPresenterTest.kt index 2a7fdba258..775ad1b183 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/analytics/AnalyticsSettingsPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/analytics/AnalyticsSettingsPresenterTest.kt @@ -23,10 +23,17 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.analytics.impl.preferences.DefaultAnalyticsPreferencesPresenter import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class AnalyticsSettingsPresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial state`() = runTest { val analyticsPresenter = DefaultAnalyticsPreferencesPresenter(FakeAnalyticsService(), aBuildMeta()) diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenterTest.kt index 9b1bda3631..17ffa2fe73 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenterTest.kt @@ -28,10 +28,17 @@ import io.element.android.features.rageshake.test.rageshake.FakeRageshakeDataSto import io.element.android.libraries.architecture.Async import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.test.FakeFeatureFlagService +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class DeveloperSettingsPresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - ensures initial state is correct`() = runTest { val rageshakePresenter = DefaultRageshakePreferencesPresenter(FakeRageShake(), FakeRageshakeDataStore()) diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/tracing/ConfigureTracingPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/tracing/ConfigureTracingPresenterTest.kt index 979713427e..5388e97e9e 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/tracing/ConfigureTracingPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/tracing/ConfigureTracingPresenterTest.kt @@ -22,11 +22,17 @@ import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.tracing.LogLevel import io.element.android.libraries.matrix.api.tracing.Target +import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.waitForPredicate import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class ConfigureTracingPresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() @Test fun `present - initial state`() = runTest { val store = InMemoryTracingConfigurationStore() 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 9ad5db3d1b..5217519071 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 @@ -30,10 +30,17 @@ 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.verification.FakeSessionVerificationService import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class PreferencesRootPresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial state`() = runTest { val matrixClient = FakeMatrixClient() diff --git a/features/rageshake/impl/build.gradle.kts b/features/rageshake/impl/build.gradle.kts index 464d521689..eced5c78b8 100644 --- a/features/rageshake/impl/build.gradle.kts +++ b/features/rageshake/impl/build.gradle.kts @@ -57,4 +57,5 @@ dependencies { testImplementation(libs.test.mockk) testImplementation(projects.libraries.matrix.test) testImplementation(projects.features.rageshake.test) + testImplementation(projects.tests.testutils) } diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt index c0418783dd..204cd4aea1 100644 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt @@ -26,13 +26,20 @@ import io.element.android.features.rageshake.test.screenshot.A_SCREENSHOT_URI import io.element.android.features.rageshake.test.screenshot.FakeScreenshotHolder import io.element.android.libraries.architecture.Async import io.element.android.libraries.matrix.test.A_FAILURE_REASON +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test const val A_SHORT_DESCRIPTION = "bug!" const val A_LONG_DESCRIPTION = "I have seen a bug!" class BugReportPresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial state`() = runTest { val presenter = BugReportPresenter( diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/crash/ui/CrashDetectionPresenterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/crash/ui/CrashDetectionPresenterTest.kt index b8b8c4b6d0..e77c1fd7e2 100644 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/crash/ui/CrashDetectionPresenterTest.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/crash/ui/CrashDetectionPresenterTest.kt @@ -24,10 +24,17 @@ import io.element.android.features.rageshake.api.crash.CrashDetectionEvents import io.element.android.features.rageshake.impl.crash.DefaultCrashDetectionPresenter import io.element.android.features.rageshake.test.crash.A_CRASH_DATA import io.element.android.features.rageshake.test.crash.FakeCrashDataStore +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class CrashDetectionPresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial state no crash`() = runTest { val presenter = DefaultCrashDetectionPresenter( diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/detection/RageshakeDetectionPresenterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/detection/RageshakeDetectionPresenterTest.kt index 02a0fc0794..d1d09131ad 100644 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/detection/RageshakeDetectionPresenterTest.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/detection/RageshakeDetectionPresenterTest.kt @@ -28,14 +28,20 @@ import io.element.android.features.rageshake.test.rageshake.FakeRageShake import io.element.android.features.rageshake.test.rageshake.FakeRageshakeDataStore import io.element.android.features.rageshake.test.screenshot.FakeScreenshotHolder import io.element.android.libraries.matrix.test.AN_EXCEPTION +import io.element.android.tests.testutils.WarmUpRule import io.mockk.mockk import kotlinx.coroutines.flow.first import kotlinx.coroutines.test.runTest import org.junit.BeforeClass +import org.junit.Rule import org.junit.Test class RageshakeDetectionPresenterTest { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + companion object { private lateinit var aBitmap: Bitmap diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/preferences/RageshakePreferencesPresenterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/preferences/RageshakePreferencesPresenterTest.kt index 56759c360c..74cd1906a9 100644 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/preferences/RageshakePreferencesPresenterTest.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/preferences/RageshakePreferencesPresenterTest.kt @@ -24,10 +24,17 @@ import io.element.android.features.rageshake.api.preferences.RageshakePreference import io.element.android.features.rageshake.test.rageshake.A_SENSITIVITY import io.element.android.features.rageshake.test.rageshake.FakeRageShake import io.element.android.features.rageshake.test.rageshake.FakeRageshakeDataStore +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class RageshakePreferencesPresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial state available`() = runTest { val presenter = DefaultRageshakePreferencesPresenter( diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt index 08d6a58535..275b4888d1 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt @@ -40,13 +40,19 @@ import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.A_USER_ID_2 import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test @ExperimentalCoroutinesApi class RoomDetailsPresenterTests { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + private fun aRoomDetailsPresenter(room: MatrixRoom, leaveRoomPresenter: LeaveRoomPresenter = LeaveRoomPresenterFake()): RoomDetailsPresenter { val roomMemberDetailsPresenterFactory = object : RoomMemberDetailsPresenter.Factory { override fun create(roomMemberId: UserId): RoomMemberDetailsPresenter { diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/edit/RoomDetailsEditPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/edit/RoomDetailsEditPresenterTest.kt index e43703e235..587cc34429 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/edit/RoomDetailsEditPresenterTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/edit/RoomDetailsEditPresenterTest.kt @@ -32,6 +32,7 @@ import io.element.android.libraries.matrix.ui.media.AvatarAction import io.element.android.libraries.mediapickers.test.FakePickerProvider import io.element.android.libraries.mediaupload.api.MediaUploadInfo import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor +import io.element.android.tests.testutils.WarmUpRule import io.mockk.every import io.mockk.mockk import io.mockk.mockkStatic @@ -40,12 +41,17 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest import org.junit.After import org.junit.Before +import org.junit.Rule import org.junit.Test import java.io.File @ExperimentalCoroutinesApi class RoomDetailsEditPresenterTest { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + private lateinit var fakePickerProvider: FakePickerProvider private lateinit var fakeMediaPreProcessor: FakeMediaPreProcessor diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersPresenterTest.kt index ede7342882..175e4ec48c 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersPresenterTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersPresenterTest.kt @@ -36,14 +36,20 @@ import io.element.android.libraries.matrix.ui.components.aMatrixUser import io.element.android.libraries.matrix.ui.components.aMatrixUserList import io.element.android.libraries.usersearch.api.UserSearchResult import io.element.android.libraries.usersearch.test.FakeUserRepository +import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.collections.immutable.ImmutableList import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test internal class RoomInviteMembersPresenterTest { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial state has no results and no search`() = runTest { val presenter = RoomInviteMembersPresenter( diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/RoomMemberListPresenterTests.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/RoomMemberListPresenterTests.kt index 9de035d017..6dd8e5bf56 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/RoomMemberListPresenterTests.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/RoomMemberListPresenterTests.kt @@ -32,15 +32,21 @@ import io.element.android.libraries.designsystem.theme.components.SearchBarResul import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test @ExperimentalCoroutinesApi class RoomMemberListPresenterTests { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `search is done automatically on start, but is async`() = runTest { val presenter = createPresenter() diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/details/RoomMemberDetailsPresenterTests.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/details/RoomMemberDetailsPresenterTests.kt index 71df3ad633..2fd240237f 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/details/RoomMemberDetailsPresenterTests.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/details/RoomMemberDetailsPresenterTests.kt @@ -29,13 +29,19 @@ import io.element.android.libraries.architecture.Async import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState import io.element.android.libraries.matrix.test.A_THROWABLE import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test @ExperimentalCoroutinesApi class RoomMemberDetailsPresenterTests { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - returns the room member's data, then updates it if needed`() = runTest { val roomMember = aRoomMember(displayName = "Alice") diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt index d8524d5834..1a2f32e54d 100644 --- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt @@ -50,15 +50,21 @@ import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.room.aRoomSummaryFilled import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService +import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.consumeItemsUntilPredicate import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class RoomListPresenterTests { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - should start with no user and then load user with success`() = runTest { val presenter = createRoomListPresenter() diff --git a/features/verifysession/impl/build.gradle.kts b/features/verifysession/impl/build.gradle.kts index cba9f2890e..a85d714d1e 100644 --- a/features/verifysession/impl/build.gradle.kts +++ b/features/verifysession/impl/build.gradle.kts @@ -47,6 +47,7 @@ dependencies { testImplementation(libs.test.truth) testImplementation(libs.test.turbine) testImplementation(projects.libraries.matrix.test) + testImplementation(projects.tests.testutils) ksp(libs.showkase.processor) } diff --git a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenterTests.kt b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenterTests.kt index 82664f0e03..ced2c48e9b 100644 --- a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenterTests.kt +++ b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenterTests.kt @@ -26,13 +26,19 @@ import io.element.android.libraries.architecture.Async import io.element.android.libraries.matrix.api.verification.VerificationEmoji import io.element.android.libraries.matrix.api.verification.VerificationFlowState import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test @ExperimentalCoroutinesApi class VerifySelfSessionPresenterTests { + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - Initial state is received`() = runTest { val presenter = createPresenter() diff --git a/libraries/permissions/impl/build.gradle.kts b/libraries/permissions/impl/build.gradle.kts index 4ae9fc9fcc..7d05d9a1d7 100644 --- a/libraries/permissions/impl/build.gradle.kts +++ b/libraries/permissions/impl/build.gradle.kts @@ -57,6 +57,7 @@ dependencies { testImplementation(libs.test.turbine) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.permissions.test) + testImplementation(projects.tests.testutils) ksp(libs.showkase.processor) } diff --git a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt index d435e4b89d..c25e8072e7 100644 --- a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt +++ b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt @@ -26,12 +26,19 @@ import com.google.accompanist.permissions.PermissionStatus import com.google.common.truth.Truth.assertThat import io.element.android.libraries.permissions.api.PermissionsEvents import io.element.android.libraries.permissions.test.InMemoryPermissionsStore +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test const val A_PERMISSION = "A_PERMISSION" class DefaultPermissionsPresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial state`() = runTest { val permissionsStore = InMemoryPermissionsStore() diff --git a/libraries/permissions/noop/build.gradle.kts b/libraries/permissions/noop/build.gradle.kts index e4b8963c89..9282d796bf 100644 --- a/libraries/permissions/noop/build.gradle.kts +++ b/libraries/permissions/noop/build.gradle.kts @@ -31,4 +31,5 @@ dependencies { testImplementation(libs.molecule.runtime) testImplementation(libs.test.truth) testImplementation(libs.test.turbine) + testImplementation(projects.tests.testutils) } diff --git a/libraries/permissions/noop/src/test/kotlin/io/element/android/libraries/permissions/noop/NoopPermissionsPresenterTest.kt b/libraries/permissions/noop/src/test/kotlin/io/element/android/libraries/permissions/noop/NoopPermissionsPresenterTest.kt index 912edd9294..f837529515 100644 --- a/libraries/permissions/noop/src/test/kotlin/io/element/android/libraries/permissions/noop/NoopPermissionsPresenterTest.kt +++ b/libraries/permissions/noop/src/test/kotlin/io/element/android/libraries/permissions/noop/NoopPermissionsPresenterTest.kt @@ -20,10 +20,17 @@ import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat +import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest +import org.junit.Rule import org.junit.Test class NoopPermissionsPresenterTest { + + @Rule + @JvmField + val warmUpRule = WarmUpRule() + @Test fun `present - initial state`() = runTest { val presenter = NoopPermissionsPresenter() diff --git a/tests/testutils/build.gradle.kts b/tests/testutils/build.gradle.kts index 184bbc418a..8275c975d2 100644 --- a/tests/testutils/build.gradle.kts +++ b/tests/testutils/build.gradle.kts @@ -14,7 +14,7 @@ * limitations under the License. */ plugins { - id("io.element.android-library") + id("io.element.android-compose-library") alias(libs.plugins.ksp) } @@ -31,4 +31,5 @@ dependencies { implementation(libs.coroutines.test) implementation(projects.libraries.core) implementation(libs.test.turbine) + implementation(libs.molecule.runtime) } diff --git a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/WarmUpRule.kt b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/WarmUpRule.kt new file mode 100644 index 0000000000..a192cfbd63 --- /dev/null +++ b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/WarmUpRule.kt @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.tests.testutils + +import app.cash.molecule.RecompositionMode +import app.cash.molecule.moleculeFlow +import app.cash.turbine.test +import kotlinx.coroutines.test.runTest +import org.junit.rules.TestRule +import org.junit.runner.Description +import org.junit.runners.model.Statement +import kotlin.time.Duration.Companion.seconds + +/** + * moleculeFlow can take time to initialise during the first test of any given + * test class. + * + * Applying this test rule ensures that the slow initialisation is not done + * inside runTest which has a short default timeout. + */ +class WarmUpRule: TestRule { + override fun apply(base: Statement, description: Description): Statement = object: Statement() { + override fun evaluate() { + runTest(timeout = 60.seconds) { + moleculeFlow(RecompositionMode.Immediate) { + // Do nothing + }.test { + awaitItem() // Await a Unit composition + } + } + base.evaluate() + } + } +} From 1a1a0f4503788e4e0df205873866ce7e64555658 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 Sep 2023 15:25:08 +0200 Subject: [PATCH 052/234] Make links in room topic clickable (#612) --- changelog.d/612.bugfix | 1 + .../features/roomdetails/impl/RoomDetailsView.kt | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 changelog.d/612.bugfix diff --git a/changelog.d/612.bugfix b/changelog.d/612.bugfix new file mode 100644 index 0000000000..390329afa1 --- /dev/null +++ b/changelog.d/612.bugfix @@ -0,0 +1 @@ +Make links in room topic clickable diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt index 51754ca6de..735ed8491a 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt @@ -16,6 +16,7 @@ package io.element.android.features.roomdetails.impl +import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi @@ -55,6 +56,7 @@ import io.element.android.features.roomdetails.impl.blockuser.BlockUserDialogs import io.element.android.features.roomdetails.impl.blockuser.BlockUserSection import io.element.android.features.roomdetails.impl.members.details.RoomMemberHeaderSection import io.element.android.features.roomdetails.impl.members.details.RoomMemberMainActionsSection +import io.element.android.libraries.designsystem.components.ClickableLinkText import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize @@ -266,11 +268,13 @@ internal fun TopicSection( onClick = { onActionClicked(RoomDetailsAction.AddTopic) }, ) } else if (roomTopic is RoomTopicState.ExistingTopic) { - Text( - roomTopic.topic, + ClickableLinkText( + text = roomTopic.topic, modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 12.dp), - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.tertiary + interactionSource = remember { MutableInteractionSource() }, + style = MaterialTheme.typography.bodyMedium.copy( + color = MaterialTheme.colorScheme.tertiary, + ), ) } } From 8504092b1ff3399c14db4d53acf4a60a73162c03 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 6 Sep 2023 13:33:54 +0000 Subject: [PATCH 053/234] Update screenshots --- ....impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png | 4 ++-- 14 files changed, 28 insertions(+), 28 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png index 0845a2a7be..9ef89a09c3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2673fa6964ac88be99edaa839a8684bc459b029d210b96fdca698fee569d36f3 -size 54613 +oid sha256:6edcc452c76049a978ceb97b46776446790dbdbe30eef1693fafda089cdc3ee7 +size 55527 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png index 57bdb33e14..9610377f28 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:29aef78fc92caa5283a6c066088d43512c36364ae01709d5d7182f6bf11f52b3 -size 48496 +oid sha256:d91c291503dc745092b132fec62208e73dcd031822ca21a66a7fb1f48ecfa6e1 +size 49316 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png index 570e9977a1..1fe7df1eaa 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:20ebfe833d0432d25076c97aaba8007fae940f70ad4e39502e4695e59fdf4c5e -size 60182 +oid sha256:efda43a25fdc2a21a4ad3767b14b4c7a308003f9bcb9e67d64520db13c83f0fd +size 61061 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png index b0dc0b4495..761666b2e3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c31e8e9d8971b8ef0e4e5a5b7a909baf4e65faa18d50452b38cb109edd193de2 -size 60401 +oid sha256:31f2d59ad03a4d9ba8efd5f146668162f3c2095ac90e16dd3634d3e817f7263d +size 61238 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png index b0dc0b4495..761666b2e3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c31e8e9d8971b8ef0e4e5a5b7a909baf4e65faa18d50452b38cb109edd193de2 -size 60401 +oid sha256:31f2d59ad03a4d9ba8efd5f146668162f3c2095ac90e16dd3634d3e817f7263d +size 61238 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png index c5444af671..f7d782f1b8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c159c58e5fa811e63cc8396f0b6910dd62945014c9a645e149b4bc88b0527dee -size 49416 +oid sha256:fba2e76faa5915acf1e9d2ede6b58e1ab73e287aefa6e5ffc643be527350d987 +size 50147 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png index 8e4244ccad..572f6d76e1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:55d72a6ef38f3822131425b56fbb02cad52e836a94cbf878fc654b1f893f9571 -size 54866 +oid sha256:1089845cd143d07e0d6a363a9dc490ab6f5ae4711fc99843c01e4f074dbdeb98 +size 55780 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png index 90756f11ad..6620f9dc9f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0f1681459983d04b98cfb583679c1c44504e0fb05d9cbcab90c149de04a91ae9 -size 56779 +oid sha256:59054f5692d41c0d6fe65c6f1bc9d0c4e1e3149aedd987e9335fabff7b46d85f +size 57237 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png index 652fc31f8c..95f7e24521 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:07dc159ecc1cce762240c06902690098a3f84a651272b3d51bf2ebc00951d16c -size 49655 +oid sha256:edcf03466e38ce3906583f2701f45d2a9538a6fd7e9d1c9d4822a037b833a512 +size 50185 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png index 5496c8b265..2f17f119fc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:44f783fc10ca0aaf56827afb1d2d9a24694e5d192441a8a9f9d1507326d7de94 -size 62479 +oid sha256:670f05e0c2861234708c7dee4d919a977bbd3aec3e965db631505957871f19fa +size 62904 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png index 9e791b59b6..d0c76cd680 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b6c8cbb0c5ae7a9e4d4426daaa00c2625731fa93d7fc05bf0cca64d1d7833ec0 -size 62536 +oid sha256:9553c9ef84cd1f2e890290e093cb0006f03d1a2f36de5e2b7d104d0eb102b2e2 +size 63045 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png index 9e791b59b6..d0c76cd680 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b6c8cbb0c5ae7a9e4d4426daaa00c2625731fa93d7fc05bf0cca64d1d7833ec0 -size 62536 +oid sha256:9553c9ef84cd1f2e890290e093cb0006f03d1a2f36de5e2b7d104d0eb102b2e2 +size 63045 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png index 3e8e0372e9..0e72199eb0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:210a21565a6b4bf56468125338e9270b9ccc48ce06d24c9eb48f32a027ffc0a4 -size 50720 +oid sha256:7ab533a35fbbba8b45d94bcfb0637d0f021ee2ef71230754ed418702ee18f11d +size 51182 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png index 9d9e068cde..159c179d5c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dcf896ec4b058043d5b52065ed3e23549d540d2496e94df3c6c8226d68de5dc4 -size 57033 +oid sha256:9ec34df75877b7050ad874905926f5d35fee29d1f8324437b502d7152ef87cdc +size 57494 From 5b5d2b824a7bd2418e38b1b3f6ff9fb7b37a094d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 21:13:29 +0000 Subject: [PATCH 054/234] Update lifecycle to v2.6.2 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f42532ac1b..32a14d1a9c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ datastore = "1.0.0" constraintlayout = "2.1.4" constraintlayout_compose = "1.0.1" recyclerview = "1.3.1" -lifecycle = "2.6.1" +lifecycle = "2.6.2" activity = "1.7.2" startup = "1.1.1" media3 = "1.1.1" From aed598783b357828e3e946eaf758a9bdeaf6b538 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 7 Sep 2023 01:43:49 +0000 Subject: [PATCH 055/234] Update dependency androidx.compose:compose-bom to v2023.09.00 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f42532ac1b..1ce7a09e72 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,7 +22,7 @@ media3 = "1.1.1" browser = "1.6.0" # Compose -compose_bom = "2023.08.00" +compose_bom = "2023.09.00" composecompiler = "1.5.3" # Coroutines From 4a5a01d7100a209314df84eeeb9bc84a2712c45f Mon Sep 17 00:00:00 2001 From: Yoan Pintas Date: Thu, 7 Sep 2023 08:24:34 +0000 Subject: [PATCH 056/234] Add room notification settings (#807) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add room notification settings --------- Co-authored-by: ElementBot Co-authored-by: Jorge Martín Co-authored-by: Benoit Marty Co-authored-by: David Langley --- changelog.d/506.feature | 2 + .../messages/impl/MessagesPresenter.kt | 13 +- .../messages/MessagesPresenterTest.kt | 12 +- features/roomdetails/impl/build.gradle.kts | 2 + .../roomdetails/impl/RoomDetailsEvent.kt | 2 + .../roomdetails/impl/RoomDetailsFlowNode.kt | 12 ++ .../roomdetails/impl/RoomDetailsNode.kt | 6 + .../roomdetails/impl/RoomDetailsPresenter.kt | 46 ++++- .../roomdetails/impl/RoomDetailsState.kt | 3 + .../impl/RoomDetailsStateProvider.kt | 4 + .../roomdetails/impl/RoomDetailsView.kt | 53 +++++- .../RoomNotificationSettingsEvents.kt | 24 +++ .../RoomNotificationSettingsItem.kt | 52 ++++++ .../RoomNotificationSettingsNode.kt | 57 +++++++ .../RoomNotificationSettingsOption.kt | 97 +++++++++++ .../RoomNotificationSettingsPresenter.kt | 108 ++++++++++++ .../RoomNotificationSettingsState.kt | 26 +++ .../RoomNotificationSettingsStateProvider.kt | 34 ++++ .../RoomNotificationSettingsView.kt | 161 ++++++++++++++++++ .../src/main/res/values-fr/translations.xml | 10 ++ .../src/main/res/values-ru/translations.xml | 11 ++ .../src/main/res/values-sk/translations.xml | 11 ++ .../main/res/values-zh-rTW/translations.xml | 6 + .../impl/src/main/res/values/localazy.xml | 11 ++ .../roomdetails/RoomDetailsPresenterTests.kt | 127 ++++++++++++-- .../RoomNotificationSettingsPresenterTests.kt | 83 +++++++++ .../components/preferences/PreferenceText.kt | 19 ++- .../libraries/featureflag/api/FeatureFlags.kt | 6 + .../impl/BuildtimeFeatureFlagProvider.kt | 1 + .../libraries/matrix/api/MatrixClient.kt | 2 + .../NotificationSettingsService.kt | 36 ++++ .../libraries/matrix/api/room/MatrixRoom.kt | 4 + .../MatrixRoomNotificationSettingsState.kt | 33 ++++ .../api/room/RoomNotificationSettings.kt | 26 +++ .../libraries/matrix/impl/RustMatrixClient.kt | 10 ++ .../matrix/impl/di/SessionMatrixModule.kt | 6 + .../RoomNotificationSettingsMapper.kt | 44 +++++ .../RustNotificationSettingsService.kt | 86 ++++++++++ .../matrix/impl/room/RustMatrixRoom.kt | 24 +++ .../libraries/matrix/test/FakeMatrixClient.kt | 4 + .../android/libraries/matrix/test/TestData.kt | 4 + .../FakeNotificationSettingsService.kt | 64 +++++++ .../matrix/test/room/FakeMatrixRoom.kt | 13 ++ .../src/main/res/values/localazy.xml | 5 + ...nSettingsDark_0_null_0,NEXUS_5,1.0,en].png | 3 + ...SettingsLight_0_null_0,NEXUS_5,1.0,en].png | 3 + ...OptionLight-D-0_1_null,NEXUS_5,1.0,en].png | 3 + ...OptionLight-N-0_2_null,NEXUS_5,1.0,en].png | 3 + ...etailsDark--1_1_null_0,NEXUS_5,1.0,en].png | 4 +- ...etailsDark--1_1_null_1,NEXUS_5,1.0,en].png | 4 +- ...etailsDark--1_1_null_2,NEXUS_5,1.0,en].png | 4 +- ...etailsDark--1_1_null_3,NEXUS_5,1.0,en].png | 4 +- ...etailsDark--1_1_null_4,NEXUS_5,1.0,en].png | 4 +- ...etailsDark--1_1_null_5,NEXUS_5,1.0,en].png | 4 +- ...etailsDark--1_1_null_6,NEXUS_5,1.0,en].png | 4 +- ...etailsDark--1_1_null_7,NEXUS_5,1.0,en].png | 4 +- ...etailsDark--1_1_null_8,NEXUS_5,1.0,en].png | 4 +- ...tailsLight--0_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...tailsLight--0_0_null_1,NEXUS_5,1.0,en].png | 4 +- ...tailsLight--0_0_null_2,NEXUS_5,1.0,en].png | 4 +- ...tailsLight--0_0_null_3,NEXUS_5,1.0,en].png | 4 +- ...tailsLight--0_0_null_4,NEXUS_5,1.0,en].png | 4 +- ...tailsLight--0_0_null_5,NEXUS_5,1.0,en].png | 4 +- ...tailsLight--0_0_null_6,NEXUS_5,1.0,en].png | 4 +- ...tailsLight--0_0_null_7,NEXUS_5,1.0,en].png | 4 +- ...tailsLight--0_0_null_8,NEXUS_5,1.0,en].png | 4 +- ..._PreferenceText_0_null,NEXUS_5,1.0,en].png | 4 +- tools/localazy/config.json | 3 +- 68 files changed, 1381 insertions(+), 70 deletions(-) create mode 100644 changelog.d/506.feature create mode 100644 features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsEvents.kt create mode 100644 features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsItem.kt create mode 100644 features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsNode.kt create mode 100644 features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt create mode 100644 features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt create mode 100644 features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsState.kt create mode 100644 features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsStateProvider.kt create mode 100644 features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt create mode 100644 features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/notificationsettings/RoomNotificationSettingsPresenterTests.kt create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomNotificationSettingsState.kt create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomNotificationSettings.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RoomNotificationSettingsMapper.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt create mode 100644 libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomNotificationSettingsDark_0_null_0,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomNotificationSettingsLight_0_null_0,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomPrivacyOptionLight-D-0_1_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomPrivacyOptionLight-N-0_2_null,NEXUS_5,1.0,en].png diff --git a/changelog.d/506.feature b/changelog.d/506.feature new file mode 100644 index 0000000000..1b4d7c50cc --- /dev/null +++ b/changelog.d/506.feature @@ -0,0 +1,2 @@ + Add a "Mute" shortcut icon and a "Notifications" section in the room details screen + \ No newline at end of file diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index 5f67fd1f7c..dc6f3304b1 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -59,7 +59,6 @@ import io.element.android.features.networkmonitor.api.NetworkStatus import io.element.android.libraries.androidutils.clipboard.ClipboardHelper import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.architecture.runCatchingUpdatingState import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize @@ -215,7 +214,8 @@ class MessagesPresenter @AssistedInject constructor( } private fun CoroutineScope.reinviteOtherUser(inviteProgress: MutableState>) = launch(dispatchers.io) { - suspend { + inviteProgress.value = Async.Loading() + runCatching { room.updateMembers() val memberList = when (val memberState = room.membersStateFlow.value) { @@ -228,7 +228,14 @@ class MessagesPresenter @AssistedInject constructor( room.inviteUserById(member.userId).onFailure { t -> Timber.e(t, "Failed to reinvite DM partner") }.getOrThrow() - }.runCatchingUpdatingState(inviteProgress) + }.fold( + onSuccess = { + inviteProgress.value = Async.Success(Unit) + }, + onFailure = { + inviteProgress.value = Async.Failure(it) + } + ) } private suspend fun handleActionRedact(event: TimelineItem.Event) { diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt index 3d98f665b6..48a8480915 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt @@ -51,6 +51,7 @@ import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.utils.SnackbarDispatcher +import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.room.MatrixRoom @@ -80,6 +81,7 @@ import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test +import kotlin.time.Duration.Companion.milliseconds class MessagesPresenterTest { @@ -380,13 +382,13 @@ class MessagesPresenterTest { assertThat(initialState.showReinvitePrompt).isFalse() // When the input field is focused we show the alert initialState.composerState.eventSink(MessageComposerEvents.FocusChanged(true)) - val focusedState = consumeItemsUntilPredicate { state -> + val focusedState = consumeItemsUntilPredicate(timeout = 250.milliseconds) { state -> state.showReinvitePrompt }.last() assertThat(focusedState.showReinvitePrompt).isTrue() // If it's dismissed then we stop showing the alert initialState.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Cancel)) - val dismissedState = consumeItemsUntilPredicate { state -> + val dismissedState = consumeItemsUntilPredicate(timeout = 250.milliseconds) { state -> !state.showReinvitePrompt }.last() assertThat(dismissedState.showReinvitePrompt).isFalse() @@ -470,7 +472,9 @@ class MessagesPresenterTest { val initialState = consumeItemsUntilTimeout().last() initialState.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Invite)) skipItems(1) - val loadingState = awaitItem() + val loadingState = consumeItemsUntilPredicate { state -> + state.inviteProgress.isLoading() + }.last() assertThat(loadingState.inviteProgress.isLoading()).isTrue() val newState = awaitItem() assertThat(newState.inviteProgress.isSuccess()).isTrue() @@ -595,7 +599,7 @@ class MessagesPresenterTest { appCoroutineScope = this, room = matrixRoom, mediaPickerProvider = FakePickerProvider(), - featureFlagService = FakeFeatureFlagService(), + featureFlagService = FakeFeatureFlagService(mapOf(FeatureFlags.NotificationSettings.key to true)), localMediaFactory = FakeLocalMediaFactory(mockMediaUrl), mediaSender = MediaSender(FakeMediaPreProcessor(), matrixRoom), snackbarDispatcher = SnackbarDispatcher(), diff --git a/features/roomdetails/impl/build.gradle.kts b/features/roomdetails/impl/build.gradle.kts index 0965cf484a..2137b1401d 100644 --- a/features/roomdetails/impl/build.gradle.kts +++ b/features/roomdetails/impl/build.gradle.kts @@ -42,6 +42,7 @@ dependencies { implementation(projects.libraries.androidutils) implementation(projects.libraries.mediapickers.api) implementation(projects.libraries.mediaupload.api) + implementation(projects.libraries.featureflag.api) api(projects.features.roomdetails.api) api(projects.libraries.usersearch.api) api(projects.services.apperror.api) @@ -59,6 +60,7 @@ dependencies { testImplementation(projects.libraries.mediaupload.test) testImplementation(projects.libraries.mediapickers.test) testImplementation(projects.libraries.usersearch.test) + testImplementation(projects.libraries.featureflag.test) testImplementation(projects.tests.testutils) testImplementation(projects.features.leaveroom.fake) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsEvent.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsEvent.kt index 7b18d398df..fdad01d83c 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsEvent.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsEvent.kt @@ -18,4 +18,6 @@ package io.element.android.features.roomdetails.impl sealed interface RoomDetailsEvent { data object LeaveRoom : RoomDetailsEvent + data object MuteNotification : RoomDetailsEvent + data object UnmuteNotification : RoomDetailsEvent } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt index b456df9f02..675ef7de60 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt @@ -33,6 +33,7 @@ import io.element.android.features.roomdetails.impl.edit.RoomDetailsEditNode import io.element.android.features.roomdetails.impl.invite.RoomInviteMembersNode import io.element.android.features.roomdetails.impl.members.RoomMemberListNode import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsNode +import io.element.android.features.roomdetails.impl.notificationsettings.RoomNotificationSettingsNode import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.createNode @@ -66,6 +67,9 @@ class RoomDetailsFlowNode @AssistedInject constructor( @Parcelize data object InviteMembers : NavTarget + @Parcelize + object RoomNotificationSettings : NavTarget + @Parcelize data class RoomMemberDetails(val roomMemberId: UserId) : NavTarget } @@ -85,6 +89,10 @@ class RoomDetailsFlowNode @AssistedInject constructor( override fun openInviteMembers() { backstack.push(NavTarget.InviteMembers) } + + override fun openRoomNotificationSettings() { + backstack.push(NavTarget.RoomNotificationSettings) + } } createNode(buildContext, listOf(roomDetailsCallback)) } @@ -110,6 +118,10 @@ class RoomDetailsFlowNode @AssistedInject constructor( createNode(buildContext) } + NavTarget.RoomNotificationSettings -> { + createNode(buildContext) + } + is NavTarget.RoomMemberDetails -> { val plugins = listOf(RoomMemberDetailsNode.RoomMemberDetailsInput(navTarget.roomMemberId)) createNode(buildContext, plugins) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt index b74cf7aaf1..65c2ed0f89 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt @@ -51,6 +51,7 @@ class RoomDetailsNode @AssistedInject constructor( fun openRoomMemberList() fun openInviteMembers() fun editRoomDetails() + fun openRoomNotificationSettings() } private val callbacks = plugins() @@ -67,6 +68,10 @@ class RoomDetailsNode @AssistedInject constructor( callbacks.forEach { it.openRoomMemberList() } } + private fun openRoomNotificationSettings() { + callbacks.forEach { it.openRoomNotificationSettings() } + } + private fun invitePeople() { callbacks.forEach { it.openInviteMembers() } } @@ -133,6 +138,7 @@ class RoomDetailsNode @AssistedInject constructor( onShareRoom = ::onShareRoom, onShareMember = ::onShareMember, openRoomMemberList = ::openRoomMemberList, + openRoomNotificationSettings = ::openRoomNotificationSettings, invitePeople = ::invitePeople, ) } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt index 2612c24365..b12d4710a0 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt @@ -22,31 +22,55 @@ import androidx.compose.runtime.State import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.produceState import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import io.element.android.features.leaveroom.api.LeaveRoomEvent import io.element.android.features.leaveroom.api.LeaveRoomPresenter import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsPresenter import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.core.coroutine.CoroutineDispatchers +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags +import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.powerlevels.canInvite import io.element.android.libraries.matrix.api.room.powerlevels.canSendState +import io.element.android.libraries.matrix.api.room.roomNotificationSettings import io.element.android.libraries.matrix.ui.room.getDirectRoomMember +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch import javax.inject.Inject class RoomDetailsPresenter @Inject constructor( + private val client: MatrixClient, private val room: MatrixRoom, + private val featureFlagService: FeatureFlagService, + private val notificationSettingsService: NotificationSettingsService, private val roomMembersDetailsPresenterFactory: RoomMemberDetailsPresenter.Factory, private val leaveRoomPresenter: LeaveRoomPresenter, + private val dispatchers: CoroutineDispatchers, ) : Presenter { @Composable override fun present(): RoomDetailsState { + val scope = rememberCoroutineScope() val leaveRoomState = leaveRoomPresenter.present() + val canShowNotificationSettings = remember { mutableStateOf(false) } + LaunchedEffect(Unit) { + canShowNotificationSettings.value = featureFlagService.isFeatureEnabled(FeatureFlags.NotificationSettings) + if (canShowNotificationSettings.value) { + room.updateRoomNotificationSettings() + observeNotificationSettings() + } room.updateMembers() } @@ -69,10 +93,22 @@ class RoomDetailsPresenter @Inject constructor( } } + val roomNotificationSettingsState by room.roomNotificationSettingsStateFlow.collectAsState() + fun handleEvents(event: RoomDetailsEvent) { when (event) { - is RoomDetailsEvent.LeaveRoom -> + RoomDetailsEvent.LeaveRoom -> leaveRoomState.eventSink(LeaveRoomEvent.ShowConfirmation(room.roomId)) + RoomDetailsEvent.MuteNotification -> { + scope.launch(dispatchers.io) { + client.notificationSettingsService().muteRoom(room.roomId) + } + } + RoomDetailsEvent.UnmuteNotification -> { + scope.launch(dispatchers.io) { + client.notificationSettingsService().unmuteRoom(room.roomId, room.isEncrypted, room.activeMemberCount) + } + } } } @@ -88,9 +124,11 @@ class RoomDetailsPresenter @Inject constructor( isEncrypted = room.isEncrypted, canInvite = canInvite, canEdit = (canEditAvatar || canEditName || canEditTopic) && roomType == RoomDetailsType.Room, + canShowNotificationSettings = canShowNotificationSettings.value, roomType = roomType, roomMemberDetailsState = roomMemberDetailsState, leaveRoomState = leaveRoomState, + roomNotificationSettings = roomNotificationSettingsState.roomNotificationSettings(), eventSink = ::handleEvents, ) } @@ -122,4 +160,10 @@ class RoomDetailsPresenter @Inject constructor( private fun getCanSendState(membersState: MatrixRoomMembersState, type: StateEventType) = produceState(false, membersState) { value = room.canSendState(type).getOrElse { false } } + + private fun CoroutineScope.observeNotificationSettings() { + notificationSettingsService.notificationSettingsChangeFlow.onEach { + room.updateRoomNotificationSettings() + }.launchIn(this) + } } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt index 49aa7f6ce0..8dc6f81bf1 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt @@ -19,6 +19,7 @@ package io.element.android.features.roomdetails.impl import io.element.android.features.leaveroom.api.LeaveRoomState import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsState import io.element.android.libraries.matrix.api.room.RoomMember +import io.element.android.libraries.matrix.api.room.RoomNotificationSettings data class RoomDetailsState( val roomId: String, @@ -32,7 +33,9 @@ data class RoomDetailsState( val roomMemberDetailsState: RoomMemberDetailsState?, val canEdit: Boolean, val canInvite: Boolean, + val canShowNotificationSettings: Boolean, val leaveRoomState: LeaveRoomState, + val roomNotificationSettings: RoomNotificationSettings?, val eventSink: (RoomDetailsEvent) -> Unit ) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt index cc4c4a6b1b..c580e6d677 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt @@ -22,6 +22,8 @@ import io.element.android.features.roomdetails.impl.members.details.aRoomMemberD import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMembershipState +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.api.room.RoomNotificationSettings open class RoomDetailsStateProvider : PreviewParameterProvider { override val values: Sequence @@ -75,9 +77,11 @@ fun aRoomDetailsState() = RoomDetailsState( isEncrypted = true, canInvite = false, canEdit = false, + canShowNotificationSettings = true, roomType = RoomDetailsType.Room, roomMemberDetailsState = null, leaveRoomState = LeaveRoomState(), + roomNotificationSettings = RoomNotificationSettings(mode = RoomNotificationMode.MUTE, isDefault = false), eventSink = {} ) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt index 735ed8491a..19aeb7ba0f 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt @@ -27,12 +27,15 @@ 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.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material.icons.outlined.Add import androidx.compose.material.icons.outlined.Lock +import androidx.compose.material.icons.outlined.Notifications +import androidx.compose.material.icons.outlined.NotificationsOff import androidx.compose.material.icons.outlined.Person import androidx.compose.material.icons.outlined.PersonAddAlt import androidx.compose.material.icons.outlined.Share @@ -75,6 +78,7 @@ import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.matrix.api.room.RoomMember +import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.ui.strings.CommonStrings @@ -87,6 +91,7 @@ fun RoomDetailsView( onShareRoom: () -> Unit, onShareMember: (RoomMember) -> Unit, openRoomMemberList: () -> Unit, + openRoomNotificationSettings: () -> Unit, invitePeople: () -> Unit, modifier: Modifier = Modifier, ) { @@ -120,7 +125,10 @@ fun RoomDetailsView( roomName = state.roomName, roomAlias = state.roomAlias ) - MainActionsSection(onShareRoom = onShareRoom) + MainActionsSection( + state = state, + onShareRoom = onShareRoom + ) } is RoomDetailsType.Dm -> { @@ -142,6 +150,12 @@ fun RoomDetailsView( ) } + if (state.canShowNotificationSettings && state.roomNotificationSettings != null) { + NotificationSection( + isDefaultMode = state.roomNotificationSettings.isDefault, + openRoomNotificationSettings = openRoomNotificationSettings) + } + if (state.roomType is RoomDetailsType.Room) { MembersSection( memberCount = state.memberCount, @@ -211,8 +225,21 @@ internal fun RoomDetailsTopBar( } @Composable -internal fun MainActionsSection(onShareRoom: () -> Unit, modifier: Modifier = Modifier) { +internal fun MainActionsSection(state: RoomDetailsState, onShareRoom: () -> Unit, modifier: Modifier = Modifier) { Row(modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) { + val roomNotificationSettings = state.roomNotificationSettings + if (state.canShowNotificationSettings && roomNotificationSettings != null) { + if (roomNotificationSettings.mode == RoomNotificationMode.MUTE) { + MainActionButton(title = stringResource(CommonStrings.common_unmute), icon = Icons.Outlined.NotificationsOff, onClick = { + state.eventSink(RoomDetailsEvent.UnmuteNotification) + }) + } else { + MainActionButton(title = stringResource(CommonStrings.common_mute), icon = Icons.Outlined.Notifications, onClick = { + state.eventSink(RoomDetailsEvent.MuteNotification) + }) + } + } + Spacer(modifier = Modifier.width(20.dp)) MainActionButton(title = stringResource(R.string.screen_room_details_share_room_title), icon = Icons.Outlined.Share, onClick = onShareRoom) } } @@ -280,6 +307,27 @@ internal fun TopicSection( } } +@Composable +internal fun NotificationSection( + isDefaultMode: Boolean, + openRoomNotificationSettings: () -> Unit, + modifier: Modifier = Modifier +) { + val subtitle = if (isDefaultMode) { + stringResource(R.string.screen_room_details_notification_mode_default) + } else { + stringResource(R.string.screen_room_details_notification_mode_custom) + } + PreferenceCategory(modifier = modifier) { + PreferenceText( + title = stringResource(R.string.screen_room_details_notification_title), + subtitle = subtitle, + icon = Icons.Outlined.Notifications, + onClick = openRoomNotificationSettings, + ) + } +} + @Composable internal fun MembersSection( memberCount: Long, @@ -352,6 +400,7 @@ private fun ContentToPreview(state: RoomDetailsState) { onShareRoom = {}, onShareMember = {}, openRoomMemberList = {}, + openRoomNotificationSettings = {}, invitePeople = {}, ) } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsEvents.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsEvents.kt new file mode 100644 index 0000000000..bbe756b154 --- /dev/null +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsEvents.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomdetails.impl.notificationsettings + +import io.element.android.libraries.matrix.api.room.RoomNotificationMode + +sealed interface RoomNotificationSettingsEvents { + data class RoomNotificationModeChanged(val mode: RoomNotificationMode) : RoomNotificationSettingsEvents + data class SetNotificationMode(val isDefault: Boolean): RoomNotificationSettingsEvents +} diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsItem.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsItem.kt new file mode 100644 index 0000000000..182944c70e --- /dev/null +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsItem.kt @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomdetails.impl.notificationsettings + +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import io.element.android.features.roomdetails.impl.R +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.ui.strings.CommonStrings +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.toImmutableList + +data class RoomNotificationSettingsItem( + val mode: RoomNotificationMode, + val title: String, +) + +@Composable +fun roomNotificationSettingsItems(): ImmutableList { + return RoomNotificationMode.values() + .map { + when (it) { + RoomNotificationMode.ALL_MESSAGES -> RoomNotificationSettingsItem( + mode = it, + title = stringResource(R.string.screen_room_notification_settings_mode_all_messages), + ) + RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> RoomNotificationSettingsItem( + mode = it, + title = stringResource(R.string.screen_room_notification_settings_mode_mentions_and_keywords), + ) + RoomNotificationMode.MUTE -> RoomNotificationSettingsItem( + mode = it, + title = stringResource(CommonStrings.common_mute), + ) + } + } + .toImmutableList() +} diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsNode.kt new file mode 100644 index 0000000000..224f850e28 --- /dev/null +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsNode.kt @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomdetails.impl.notificationsettings + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.bumble.appyx.core.lifecycle.subscribe +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import im.vector.app.features.analytics.plan.MobileScreen +import io.element.android.anvilannotations.ContributesNode +import io.element.android.libraries.di.RoomScope +import io.element.android.services.analytics.api.AnalyticsService + +@ContributesNode(RoomScope::class) +class RoomNotificationSettingsNode @AssistedInject constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + private val presenter: RoomNotificationSettingsPresenter, + private val analyticsService: AnalyticsService, +) : Node(buildContext, plugins = plugins) { + + init { + lifecycle.subscribe( + onResume = { + analyticsService.screen(MobileScreen(screenName = MobileScreen.ScreenName.RoomNotifications)) + } + ) + } + + @Composable + override fun View(modifier: Modifier) { + val state = presenter.present() + RoomNotificationSettingsView( + state = state, + modifier = modifier, + onBackPressed = this::navigateUp, + ) + } +} diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt new file mode 100644 index 0000000000..28592b3b7e --- /dev/null +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomdetails.impl.notificationsettings + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.selection.selectable +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.unit.dp +import io.element.android.libraries.designsystem.preview.DayNightPreviews +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.theme.components.RadioButton +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.toEnabledColor +import io.element.android.libraries.theme.ElementTheme + +@Composable +fun RoomNotificationSettingsOption( + roomNotificationSettingsItem: RoomNotificationSettingsItem, + modifier: Modifier = Modifier, + enabled: Boolean = true, + isSelected: Boolean = false, + onOptionSelected: (RoomNotificationSettingsItem) -> Unit = {}, +) { + Row( + modifier + .fillMaxWidth() + .selectable( + selected = isSelected, + enabled = enabled, + onClick = { onOptionSelected(roomNotificationSettingsItem) }, + role = Role.RadioButton, + ) + .padding(8.dp), + ) { + Column( + Modifier + .weight(1f) + .padding(horizontal = 8.dp) + .align(Alignment.CenterVertically) + ) { + Text( + text = roomNotificationSettingsItem.title, + style = ElementTheme.typography.fontBodyLgRegular, + color = enabled.toEnabledColor(), + ) + } + + RadioButton( + modifier = Modifier + .align(Alignment.CenterVertically) + .size(48.dp), + selected = isSelected, + enabled = enabled, + onClick = null // null recommended for accessibility with screenreaders + ) + } +} + +@DayNightPreviews +@Composable +internal fun RoomPrivacyOptionLightPreview() = ElementPreview { ContentToPreview() } + +@Composable +private fun ContentToPreview() { + Column { + RoomNotificationSettingsOption( + roomNotificationSettingsItem = roomNotificationSettingsItems().first(), + isSelected = true, + ) + RoomNotificationSettingsOption( + roomNotificationSettingsItem = roomNotificationSettingsItems().last(), + isSelected = false, + enabled = false, + ) + } +} diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt new file mode 100644 index 0000000000..fd9f0bc930 --- /dev/null +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomdetails.impl.notificationsettings + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.saveable.rememberSaveable +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService +import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.api.room.roomNotificationSettings +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.FlowPreview +import kotlinx.coroutines.flow.debounce +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch +import javax.inject.Inject +import kotlin.time.Duration.Companion.seconds + +class RoomNotificationSettingsPresenter @Inject constructor( + private val room: MatrixRoom, + private val notificationSettingsService: NotificationSettingsService, +) : Presenter { + + @Composable + override fun present(): RoomNotificationSettingsState { + val defaultRoomNotificationMode: MutableState = rememberSaveable { + mutableStateOf(null) + } + val localCoroutineScope = rememberCoroutineScope() + + LaunchedEffect(Unit) { + getDefaultRoomNotificationMode(defaultRoomNotificationMode) + observeNotificationSettings() + } + + val roomNotificationSettingsState by room.roomNotificationSettingsStateFlow.collectAsState() + + fun handleEvents(event: RoomNotificationSettingsEvents) { + when (event) { + is RoomNotificationSettingsEvents.RoomNotificationModeChanged -> { + localCoroutineScope.setRoomNotificationMode(event.mode) + } + is RoomNotificationSettingsEvents.SetNotificationMode -> { + if (event.isDefault) { + localCoroutineScope.restoreDefaultRoomNotificationMode() + } else { + defaultRoomNotificationMode.value?.let { + localCoroutineScope.setRoomNotificationMode(it) + } + } + } + } + } + + return RoomNotificationSettingsState( + roomNotificationSettings = roomNotificationSettingsState.roomNotificationSettings(), + defaultRoomNotificationMode = defaultRoomNotificationMode.value, + eventSink = ::handleEvents, + ) + } + + @OptIn(FlowPreview::class) + private fun CoroutineScope.observeNotificationSettings() { + notificationSettingsService.notificationSettingsChangeFlow + .debounce(0.5.seconds) + .onEach { + room.updateRoomNotificationSettings() + } + .launchIn(this) + } + + private fun CoroutineScope.getDefaultRoomNotificationMode(defaultRoomNotificationMode: MutableState) = launch { + defaultRoomNotificationMode.value = notificationSettingsService.getDefaultRoomNotificationMode( + room.isEncrypted, + room.activeMemberCount + ).getOrThrow() + } + + private fun CoroutineScope.setRoomNotificationMode(mode: RoomNotificationMode) = launch { + notificationSettingsService.setRoomNotificationMode(room.roomId, mode) + } + + private fun CoroutineScope.restoreDefaultRoomNotificationMode() = launch { + notificationSettingsService.restoreDefaultRoomNotificationMode(room.roomId) + } +} diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsState.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsState.kt new file mode 100644 index 0000000000..04742781b5 --- /dev/null +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsState.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomdetails.impl.notificationsettings + +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.api.room.RoomNotificationSettings + +data class RoomNotificationSettingsState( + val roomNotificationSettings: RoomNotificationSettings?, + val defaultRoomNotificationMode: RoomNotificationMode?, + val eventSink: (RoomNotificationSettingsEvents) -> Unit +) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsStateProvider.kt new file mode 100644 index 0000000000..df1dd7977b --- /dev/null +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsStateProvider.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomdetails.impl.notificationsettings + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.api.room.RoomNotificationSettings + +internal class RoomNotificationSettingsStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + RoomNotificationSettingsState( + RoomNotificationSettings( + mode = RoomNotificationMode.MUTE, + isDefault = true), + RoomNotificationMode.ALL_MESSAGES, + eventSink = { }, + ), + ) +} diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt new file mode 100644 index 0000000000..3709280477 --- /dev/null +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomdetails.impl.notificationsettings + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.consumeWindowInsets +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.selection.selectableGroup +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.dp +import io.element.android.features.roomdetails.impl.R +import io.element.android.libraries.core.bool.orTrue +import io.element.android.libraries.designsystem.components.button.BackButton +import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory +import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch +import io.element.android.libraries.designsystem.components.preferences.PreferenceText +import io.element.android.libraries.designsystem.preview.ElementPreviewDark +import io.element.android.libraries.designsystem.preview.ElementPreviewLight +import io.element.android.libraries.designsystem.theme.aliasScreenTitle +import io.element.android.libraries.designsystem.theme.components.Scaffold +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.components.TopAppBar +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.theme.ElementTheme +import io.element.android.libraries.ui.strings.CommonStrings + +@OptIn(ExperimentalLayoutApi::class) +@Composable +fun RoomNotificationSettingsView( + state: RoomNotificationSettingsState, + modifier: Modifier = Modifier, + onBackPressed: () -> Unit = {}, +) { + Scaffold( + modifier = modifier, + topBar = { + RoomNotificationSettingsTopBar( + onBackPressed = { onBackPressed() } + ) + } + ) { padding -> + Column( + modifier = Modifier + .fillMaxWidth() + .padding(padding) + .consumeWindowInsets(padding), + verticalArrangement = Arrangement.spacedBy(16.dp), + ) { + val subtitle = when(state.defaultRoomNotificationMode) { + RoomNotificationMode.ALL_MESSAGES -> stringResource(id = R.string.screen_room_notification_settings_mode_all_messages) + RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> stringResource(id = R.string.screen_room_notification_settings_mode_mentions_and_keywords) + RoomNotificationMode.MUTE -> stringResource(id = CommonStrings.common_mute) + null -> "" + } + + + PreferenceCategory(title = stringResource(id = R.string.screen_room_notification_settings_custom_settings_title)) { + PreferenceSwitch( + isChecked = state.roomNotificationSettings?.isDefault.orTrue(), + onCheckedChange = { + state.eventSink(RoomNotificationSettingsEvents.SetNotificationMode(it)) + }, + title = "Match default setting", + subtitle = subtitle, + enabled = state.roomNotificationSettings != null + ) + + PreferenceText( + title = stringResource(id = R.string.screen_room_notification_settings_allow_custom), + subtitle = stringResource(id = R.string.screen_room_notification_settings_allow_custom_footnote), + enabled = state.roomNotificationSettings != null && !state.roomNotificationSettings.isDefault, + ) + + if (state.roomNotificationSettings != null) { + RoomNotificationSettingsOptions( + selected = state.roomNotificationSettings.mode, + enabled = !state.roomNotificationSettings.isDefault, + onOptionSelected = { + state.eventSink(RoomNotificationSettingsEvents.RoomNotificationModeChanged(it.mode)) + }, + ) + } + } + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun RoomNotificationSettingsTopBar( + modifier: Modifier = Modifier, + onBackPressed: () -> Unit = {}, +) { + TopAppBar( + modifier = modifier, + title = { + Text( + text = stringResource(R.string.screen_room_details_notification_title), + style = ElementTheme.typography.aliasScreenTitle, + ) + }, + navigationIcon = { BackButton(onClick = onBackPressed) }, + ) +} + +@Composable +fun RoomNotificationSettingsOptions( + selected: RoomNotificationMode?, + enabled: Boolean, + modifier: Modifier = Modifier, + onOptionSelected: (RoomNotificationSettingsItem) -> Unit = {}, +) { + val items = roomNotificationSettingsItems() + Column(modifier = modifier.selectableGroup()) { + items.forEach { item -> + RoomNotificationSettingsOption( + roomNotificationSettingsItem = item, + isSelected = selected == item.mode, + onOptionSelected = onOptionSelected, + enabled = enabled + ) + } + } +} + +@Preview +@Composable +internal fun RoomNotificationSettingsLightPreview(@PreviewParameter(RoomNotificationSettingsStateProvider::class) state: RoomNotificationSettingsState) = + ElementPreviewLight { ContentToPreview(state) } + +@Preview +@Composable +internal fun RoomNotificationSettingsDarkPreview(@PreviewParameter(RoomNotificationSettingsStateProvider::class) state: RoomNotificationSettingsState) = + ElementPreviewDark { ContentToPreview(state) } + +@Composable +private fun ContentToPreview(state: RoomNotificationSettingsState) { + RoomNotificationSettingsView(state) +} diff --git a/features/roomdetails/impl/src/main/res/values-fr/translations.xml b/features/roomdetails/impl/src/main/res/values-fr/translations.xml index 2696cc99ea..34fae4fea9 100644 --- a/features/roomdetails/impl/src/main/res/values-fr/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-fr/translations.xml @@ -23,6 +23,16 @@ "Partager le salon" "Mise à jour du salon…" "En attente" + "Autoriser les paramètres personnalisés" + "Activer cette option remplacera votre paramètre par défaut" + "Me notifier dans ce chat pour" + "paramètres généraux" + "Paramètre par défaut" + "Une erreur s’est produite lors du chargement des paramètres de notification." + "Impossible de restaurer le mode par défaut, veuillez réessayer." + "Impossible de régler le mode, veuillez réessayer." + "Tous les messages" + "Mentions et mots-clés uniquement" "Bloquer" "Les utilisateurs bloqués ne pourront pas vous envoyer de messages et tous leurs messages seront masqués. Vous pouvez les débloquer à tout moment." "Bloquer l\'utilisateur" diff --git a/features/roomdetails/impl/src/main/res/values-ru/translations.xml b/features/roomdetails/impl/src/main/res/values-ru/translations.xml index 4d2664ab30..4154f041ff 100644 --- a/features/roomdetails/impl/src/main/res/values-ru/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ru/translations.xml @@ -25,6 +25,17 @@ "Обновление комнаты…" "В ожидании" "Участники комнаты" + "Разрешить пользовательские настройки" + "Включение этого параметра отменяет настройки по умолчанию" + "Уведомить меня в этом чате" + "Вы можете изменить его в своем %1$s." + "Основные Настройки" + "Настройка по умолчанию" + "Произошла ошибка при загрузке настроек уведомлений." + "Не удалось восстановить режим по умолчанию, попробуйте еще раз." + "Не удалось настроить режим, попробуйте еще раз." + "Все сообщения" + "Только упоминания и ключевые слова" "Заблокировать" "Заблокированные пользователи не смогут отправлять вам сообщения, а все их сообщения будут скрыты. Вы можете разблокировать их в любое время." "Заблокировать пользователя" diff --git a/features/roomdetails/impl/src/main/res/values-sk/translations.xml b/features/roomdetails/impl/src/main/res/values-sk/translations.xml index 1d744fba30..687c495ce7 100644 --- a/features/roomdetails/impl/src/main/res/values-sk/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-sk/translations.xml @@ -25,6 +25,17 @@ "Aktualizácia miestnosti…" "Čaká sa" "Členovia miestnosti" + "Povoliť vlastné nastavenie" + "Zapnutím tohto nastavenia sa prepíše vaše predvolené nastavenie" + "Upozorniť ma v tejto konverzácii na" + "Môžete to zmeniť vo svojich %1$s." + "všeobecných nastaveniach" + "Predvolené nastavenie" + "Pri načítavaní nastavení oznámení došlo k chybe." + "Nepodarilo sa obnoviť predvolený režim, skúste to prosím znova." + "Nepodarilo sa nastaviť režim, skúste to prosím znova." + "Všetky správy" + "Iba zmienky a kľúčové slová" "Zablokovať" "Blokovaní používatelia vám nebudú môcť posielať správy a všetky ich správy budú skryté. Môžete ich kedykoľvek odblokovať." "Zablokovať používateľa" diff --git a/features/roomdetails/impl/src/main/res/values-zh-rTW/translations.xml b/features/roomdetails/impl/src/main/res/values-zh-rTW/translations.xml index fb7872844a..7b4eb895ea 100644 --- a/features/roomdetails/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-zh-rTW/translations.xml @@ -18,6 +18,12 @@ "正在更新聊天室…" "待定" "聊天室成員" + "全域設定" + "預設" + "無法重設為預設模式,請再試一次。" + "無法設定模式,請再試一次。" + "所有訊息" + "只限提及與關鍵字" "封鎖" "封鎖使用者" "解除封鎖" diff --git a/features/roomdetails/impl/src/main/res/values/localazy.xml b/features/roomdetails/impl/src/main/res/values/localazy.xml index b1f67dab1e..717f503e22 100644 --- a/features/roomdetails/impl/src/main/res/values/localazy.xml +++ b/features/roomdetails/impl/src/main/res/values/localazy.xml @@ -24,6 +24,17 @@ "Updating room…" "Pending" "Room members" + "Allow custom setting" + "Turning this on will override your default setting" + "Notify me in this chat for" + "You can change it in your %1$s." + "global settings" + "Default setting" + "An error occurred while loading notification settings." + "Failed restoring the default mode, please try again." + "Failed setting the mode, please try again." + "All messages" + "Mentions and Keywords only" "Block" "Blocked users won\'t be able to send you messages and all their messages will be hidden. You can unblock them anytime." "Block user" diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt index 275b4888d1..71695094b3 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt @@ -29,22 +29,30 @@ import io.element.android.features.roomdetails.impl.RoomDetailsType import io.element.android.features.roomdetails.impl.RoomTopicState import io.element.android.features.roomdetails.impl.members.aRoomMember import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsPresenter +import io.element.android.libraries.core.coroutine.CoroutineDispatchers +import io.element.android.libraries.featureflag.api.FeatureFlags +import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState +import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_NAME import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.A_USER_ID_2 import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +import io.element.android.tests.testutils.consumeItemsUntilPredicate +import io.element.android.tests.testutils.testCoroutineDispatchers import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test +import kotlin.time.Duration.Companion.milliseconds @ExperimentalCoroutinesApi class RoomDetailsPresenterTests { @@ -52,20 +60,37 @@ class RoomDetailsPresenterTests { @Rule @JvmField val warmUpRule = WarmUpRule() + private fun aRoomDetailsPresenter( + room: MatrixRoom, + leaveRoomPresenter: LeaveRoomPresenter = LeaveRoomPresenterFake(), + dispatchers: CoroutineDispatchers, + notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService() + ): RoomDetailsPresenter { + val matrixClient = FakeMatrixClient(notificationSettingsService = notificationSettingsService) - private fun aRoomDetailsPresenter(room: MatrixRoom, leaveRoomPresenter: LeaveRoomPresenter = LeaveRoomPresenterFake()): RoomDetailsPresenter { val roomMemberDetailsPresenterFactory = object : RoomMemberDetailsPresenter.Factory { override fun create(roomMemberId: UserId): RoomMemberDetailsPresenter { - return RoomMemberDetailsPresenter(FakeMatrixClient(), room, roomMemberId) + return RoomMemberDetailsPresenter(matrixClient, room, roomMemberId) } } - return RoomDetailsPresenter(room, roomMemberDetailsPresenterFactory, leaveRoomPresenter) + val featureFlagService = FakeFeatureFlagService( + mapOf(FeatureFlags.NotificationSettings.key to true) + ) + return RoomDetailsPresenter( + matrixClient, + room, + featureFlagService, + matrixClient.notificationSettingsService(), + roomMemberDetailsPresenterFactory, + leaveRoomPresenter, + dispatchers + ) } @Test fun `present - initial state is created from room info`() = runTest { val room = aMatrixRoom() - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -84,7 +109,7 @@ class RoomDetailsPresenterTests { @Test fun `present - initial state with no room name`() = runTest { val room = aMatrixRoom(name = null) - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -106,7 +131,7 @@ class RoomDetailsPresenterTests { val roomMembers = listOf(myRoomMember, otherRoomMember) givenRoomMembersState(MatrixRoomMembersState.Ready(roomMembers)) } - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -122,7 +147,7 @@ class RoomDetailsPresenterTests { val room = aMatrixRoom().apply { givenCanInviteResult(Result.success(true)) } - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -140,11 +165,13 @@ class RoomDetailsPresenterTests { val room = aMatrixRoom().apply { givenCanInviteResult(Result.success(false)) } - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { assertThat(awaitItem().canInvite).isFalse() + + cancelAndIgnoreRemainingEvents() } } @@ -153,11 +180,13 @@ class RoomDetailsPresenterTests { val room = aMatrixRoom().apply { givenCanInviteResult(Result.failure(Throwable("Whoops"))) } - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { assertThat(awaitItem().canInvite).isFalse() + + cancelAndIgnoreRemainingEvents() } } @@ -169,7 +198,7 @@ class RoomDetailsPresenterTests { givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.failure(Throwable("Whelp"))) givenCanInviteResult(Result.success(false)) } - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -198,7 +227,7 @@ class RoomDetailsPresenterTests { givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(true)) givenCanInviteResult(Result.success(false)) } - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -227,7 +256,7 @@ class RoomDetailsPresenterTests { givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.success(true)) } - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -248,7 +277,7 @@ class RoomDetailsPresenterTests { givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(true)) givenCanInviteResult(Result.success(false)) } - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -269,12 +298,14 @@ class RoomDetailsPresenterTests { givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(false)) givenCanInviteResult(Result.success(false)) } - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { // Initially false, and no further events assertThat(awaitItem().canEdit).isFalse() + + cancelAndIgnoreRemainingEvents() } } @@ -285,12 +316,14 @@ class RoomDetailsPresenterTests { givenCanInviteResult(Result.success(false)) } - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { // The initial state is "hidden" and no further state changes happen assertThat(awaitItem().roomTopic).isEqualTo(RoomTopicState.Hidden) + + cancelAndIgnoreRemainingEvents() } } @@ -301,7 +334,7 @@ class RoomDetailsPresenterTests { givenCanInviteResult(Result.success(false)) } - val presenter = aRoomDetailsPresenter(room) + val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -319,7 +352,7 @@ class RoomDetailsPresenterTests { fun `present - leave room event is passed on to leave room presenter`() = runTest { val leaveRoomPresenter = LeaveRoomPresenterFake() val room = aMatrixRoom() - val presenter = aRoomDetailsPresenter(room, leaveRoomPresenter) + val presenter = aRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -330,6 +363,64 @@ class RoomDetailsPresenterTests { cancelAndIgnoreRemainingEvents() } } + + @Test + fun `present - notification mode changes`() = runTest { + val leaveRoomPresenter = LeaveRoomPresenterFake() + val notificationSettingsService = FakeNotificationSettingsService() + val room = aMatrixRoom(notificationSettingsService = notificationSettingsService) + val presenter = aRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers(), notificationSettingsService) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + + notificationSettingsService.setRoomNotificationMode(room.roomId, RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY) + val updatedState = consumeItemsUntilPredicate { + it.roomNotificationSettings?.mode == RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY + }.last() + assertThat(updatedState.roomNotificationSettings?.mode).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY) + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - mute room notifications`() = runTest { + val leaveRoomPresenter = LeaveRoomPresenterFake() + val notificationSettingsService = FakeNotificationSettingsService(initialMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY) + val room = aMatrixRoom(notificationSettingsService = notificationSettingsService) + val presenter = aRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers(), notificationSettingsService) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem().eventSink(RoomDetailsEvent.MuteNotification) + val updatedState = consumeItemsUntilPredicate(timeout = 250.milliseconds) { + it.roomNotificationSettings?.mode == RoomNotificationMode.MUTE + }.last() + assertThat(updatedState.roomNotificationSettings?.mode).isEqualTo(RoomNotificationMode.MUTE) + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - unmute room notifications`() = runTest { + val leaveRoomPresenter = LeaveRoomPresenterFake() + val notificationSettingsService = FakeNotificationSettingsService( + initialMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY, + initialDefaultMode = RoomNotificationMode.ALL_MESSAGES + ) + val room = aMatrixRoom(notificationSettingsService = notificationSettingsService) + val presenter = aRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers(), notificationSettingsService) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem().eventSink(RoomDetailsEvent.UnmuteNotification) + val updatedState = consumeItemsUntilPredicate { + it.roomNotificationSettings?.mode == RoomNotificationMode.ALL_MESSAGES + }.last() + assertThat(updatedState.roomNotificationSettings?.mode).isEqualTo(RoomNotificationMode.ALL_MESSAGES) + cancelAndIgnoreRemainingEvents() + } + } } fun aMatrixRoom( @@ -341,6 +432,7 @@ fun aMatrixRoom( isEncrypted: Boolean = true, isPublic: Boolean = true, isDirect: Boolean = false, + notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService() ) = FakeMatrixRoom( roomId = roomId, name = name, @@ -350,5 +442,6 @@ fun aMatrixRoom( isEncrypted = isEncrypted, isPublic = isPublic, isDirect = isDirect, + notificationSettingsService = notificationSettingsService ) diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/notificationsettings/RoomNotificationSettingsPresenterTests.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/notificationsettings/RoomNotificationSettingsPresenterTests.kt new file mode 100644 index 0000000000..29bec7f622 --- /dev/null +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/notificationsettings/RoomNotificationSettingsPresenterTests.kt @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomdetails.notificationsettings + +import app.cash.molecule.RecompositionMode +import app.cash.molecule.moleculeFlow +import app.cash.turbine.test +import com.google.common.truth.Truth +import io.element.android.features.roomdetails.aMatrixRoom +import io.element.android.features.roomdetails.impl.notificationsettings.RoomNotificationSettingsEvents +import io.element.android.features.roomdetails.impl.notificationsettings.RoomNotificationSettingsPresenter +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.test.A_ROOM_NOTIFICATION_MODE +import io.element.android.tests.testutils.consumeItemsUntilPredicate +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class RoomNotificationSettingsPresenterTests { + @Test + fun `present - initial state is created from room info`() = runTest { + val presenter = aNotificationPresenter + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + Truth.assertThat(initialState.roomNotificationSettings).isNull() + Truth.assertThat(initialState.defaultRoomNotificationMode).isNull() + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - notification mode changed`() = runTest { + val presenter = aNotificationPresenter + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem().eventSink(RoomNotificationSettingsEvents.RoomNotificationModeChanged(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)) + val updatedState = consumeItemsUntilPredicate { + it.roomNotificationSettings?.mode == RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY + }.last() + Truth.assertThat(updatedState.roomNotificationSettings?.mode).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY) + } + } + + @Test + fun `present - notification settings restore default`() = runTest { + val presenter = aNotificationPresenter + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink(RoomNotificationSettingsEvents.RoomNotificationModeChanged(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)) + initialState.eventSink(RoomNotificationSettingsEvents.SetNotificationMode(true)) + val defaultState = consumeItemsUntilPredicate { + it.roomNotificationSettings?.mode == A_ROOM_NOTIFICATION_MODE + }.last() + Truth.assertThat(defaultState.roomNotificationSettings?.mode).isEqualTo(A_ROOM_NOTIFICATION_MODE) + } + } + + private val aNotificationPresenter: RoomNotificationSettingsPresenter get() { + val room = aMatrixRoom() + return RoomNotificationSettingsPresenter( + room = room, + notificationSettingsService = room.notificationSettingsService + ) + } +} diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceText.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceText.kt index 3f204ee847..9a5f6b9a41 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceText.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceText.kt @@ -39,6 +39,8 @@ import io.element.android.libraries.designsystem.preview.ElementThemedPreview import io.element.android.libraries.designsystem.preview.PreviewGroup import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.toEnabledColor +import io.element.android.libraries.designsystem.toSecondaryEnabledColor import io.element.android.libraries.theme.ElementTheme /** @@ -48,6 +50,7 @@ import io.element.android.libraries.theme.ElementTheme fun PreferenceText( title: String, modifier: Modifier = Modifier, + enabled: Boolean = true, subtitle: String? = null, currentValue: String? = null, loadingCurrentValue: Boolean = false, @@ -68,8 +71,9 @@ fun PreferenceText( ) { PreferenceIcon( icon = icon, + enabled = enabled, isVisible = showIconAreaIfNoIcon, - tintColor = tintColor ?: ElementTheme.materialColors.secondary + tintColor = tintColor ?: enabled.toSecondaryEnabledColor(), ) Column( modifier = Modifier @@ -79,13 +83,13 @@ fun PreferenceText( Text( style = ElementTheme.typography.fontBodyLgRegular, text = title, - color = tintColor ?: ElementTheme.materialColors.primary, + color = tintColor ?: enabled.toEnabledColor(), ) if (subtitle != null) { Text( style = ElementTheme.typography.fontBodyMdRegular, text = subtitle, - color = tintColor ?: ElementTheme.materialColors.secondary, + color = tintColor ?: enabled.toSecondaryEnabledColor(), ) } } @@ -96,7 +100,7 @@ fun PreferenceText( .padding(start = 16.dp, end = 8.dp), text = currentValue, style = ElementTheme.typography.fontBodyXsMedium, - color = ElementTheme.materialColors.secondary, + color = enabled.toSecondaryEnabledColor(), ) } else if (loadingCurrentValue) { CircularProgressIndicator( @@ -135,6 +139,13 @@ private fun ContentToPreview() { icon = Icons.Default.BugReport, currentValue = "123", ) + PreferenceText( + title = "Title", + subtitle = "Some content", + icon = Icons.Default.BugReport, + currentValue = "123", + enabled = false, + ) PreferenceText( title = "Title", subtitle = "Some content", diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt index c28dc28144..6490b4e357 100644 --- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt +++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt @@ -30,5 +30,11 @@ enum class FeatureFlags( key = "feature.polls", title = "Polls", description = "Create poll and render poll events in the timeline", + defaultValue = false, + ), + NotificationSettings( + key = "feature.notificationsettings", + title = "Show notification settings", + defaultValue = false, ), } diff --git a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/BuildtimeFeatureFlagProvider.kt b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/BuildtimeFeatureFlagProvider.kt index 83913cbac5..0117a4aa22 100644 --- a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/BuildtimeFeatureFlagProvider.kt +++ b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/BuildtimeFeatureFlagProvider.kt @@ -31,6 +31,7 @@ class BuildtimeFeatureFlagProvider @Inject constructor() : when (feature) { FeatureFlags.LocationSharing -> true FeatureFlags.Polls -> false + FeatureFlags.NotificationSettings -> false } } else { false diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt index 2ca4420145..63093064b6 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt @@ -23,6 +23,7 @@ import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters import io.element.android.libraries.matrix.api.media.MatrixMediaLoader import io.element.android.libraries.matrix.api.notification.NotificationService +import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.pusher.PushersService import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.RoomMembershipObserver @@ -49,6 +50,7 @@ interface MatrixClient : Closeable { fun sessionVerificationService(): SessionVerificationService fun pushersService(): PushersService fun notificationService(): NotificationService + fun notificationSettingsService(): NotificationSettingsService suspend fun getCacheSize(): Long /** diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt new file mode 100644 index 0000000000..0f82604aba --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.api.notificationsettings + +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.room.MatrixRoomNotificationSettingsState +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.api.room.RoomNotificationSettings +import kotlinx.coroutines.flow.SharedFlow + +interface NotificationSettingsService { + /** + * State of the current room notification settings flow ([MatrixRoomNotificationSettingsState.Unknown] if not started). + */ + val notificationSettingsChangeFlow : SharedFlow + suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, membersCount: Long): Result + suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, membersCount: Long): Result + suspend fun setRoomNotificationMode(roomId: RoomId, mode: RoomNotificationMode): Result + suspend fun restoreDefaultRoomNotificationMode(roomId: RoomId): Result + suspend fun muteRoom(roomId: RoomId): Result + suspend fun unmuteRoom(roomId: RoomId, isEncrypted: Boolean, membersCount: Long): Result +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt index 41f105df8e..60c8b1ddd5 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt @@ -56,11 +56,15 @@ interface MatrixRoom : Closeable { */ val membersStateFlow: StateFlow + val roomNotificationSettingsStateFlow: StateFlow + /** * Try to load the room members and update the membersFlow. */ suspend fun updateMembers(): Result + suspend fun updateRoomNotificationSettings(): Result + val syncUpdateFlow: StateFlow val timeline: MatrixTimeline diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomNotificationSettingsState.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomNotificationSettingsState.kt new file mode 100644 index 0000000000..d98a3a83d2 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomNotificationSettingsState.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.api.room + +sealed interface MatrixRoomNotificationSettingsState { + object Unknown : MatrixRoomNotificationSettingsState + data class Pending(val prevRoomNotificationSettings: RoomNotificationSettings? = null) : MatrixRoomNotificationSettingsState + data class Error(val failure: Throwable, val prevRoomNotificationSettings: RoomNotificationSettings? = null) : MatrixRoomNotificationSettingsState + data class Ready(val roomNotificationSettings: RoomNotificationSettings) : MatrixRoomNotificationSettingsState +} + +fun MatrixRoomNotificationSettingsState.roomNotificationSettings(): RoomNotificationSettings? { + return when (this) { + is MatrixRoomNotificationSettingsState.Ready -> roomNotificationSettings + is MatrixRoomNotificationSettingsState.Pending -> prevRoomNotificationSettings + is MatrixRoomNotificationSettingsState.Error -> prevRoomNotificationSettings + else -> null + } +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomNotificationSettings.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomNotificationSettings.kt new file mode 100644 index 0000000000..23f2b41797 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomNotificationSettings.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.api.room + +data class RoomNotificationSettings( + val mode: RoomNotificationMode, + val isDefault: Boolean, +) + +enum class RoomNotificationMode { + ALL_MESSAGES, MENTIONS_AND_KEYWORDS_ONLY, MUTE +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index 54641f785b..22f1e9af3f 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -29,6 +29,7 @@ import io.element.android.libraries.matrix.api.createroom.RoomPreset import io.element.android.libraries.matrix.api.createroom.RoomVisibility import io.element.android.libraries.matrix.api.media.MatrixMediaLoader import io.element.android.libraries.matrix.api.notification.NotificationService +import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.pusher.PushersService import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.RoomMembershipObserver @@ -42,6 +43,7 @@ import io.element.android.libraries.matrix.impl.core.toProgressWatcher import io.element.android.libraries.matrix.impl.mapper.toSessionData import io.element.android.libraries.matrix.impl.media.RustMediaLoader import io.element.android.libraries.matrix.impl.notification.RustNotificationService +import io.element.android.libraries.matrix.impl.notificationsettings.RustNotificationSettingsService import io.element.android.libraries.matrix.impl.pushers.RustPushersService import io.element.android.libraries.matrix.impl.room.RoomContentForwarder import io.element.android.libraries.matrix.impl.room.RustMatrixRoom @@ -99,6 +101,7 @@ class RustMatrixClient constructor( client = client, dispatchers = dispatchers, ) + private val notificationProcessSetup = NotificationProcessSetup.SingleProcess(syncService) private val notificationClient = client.notificationClient(notificationProcessSetup) .use { builder -> @@ -106,8 +109,10 @@ class RustMatrixClient constructor( .filterByPushRules() .finish() } + private val notificationSettings = client.getNotificationSettings() private val notificationService = RustNotificationService(sessionId, notificationClient, dispatchers, clock) + private val notificationSettingsService = RustNotificationSettingsService(notificationSettings, dispatchers) private val isLoggingOut = AtomicBoolean(false) @@ -173,6 +178,7 @@ class RustMatrixClient constructor( sessionId = sessionId, roomListItem = roomListItem, innerRoom = fullRoom, + roomNotificationSettingsService = notificationSettingsService, sessionCoroutineScope = sessionCoroutineScope, coroutineDispatchers = dispatchers, systemClock = clock, @@ -277,9 +283,13 @@ class RustMatrixClient constructor( override fun notificationService(): NotificationService = notificationService + override fun notificationSettingsService(): NotificationSettingsService = notificationSettingsService + override fun close() { sessionCoroutineScope.cancel() client.setDelegate(null) + notificationSettings.setDelegate(null) + notificationSettings.destroy() verificationService.destroy() syncService.destroy() innerRoomListService.destroy() diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/di/SessionMatrixModule.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/di/SessionMatrixModule.kt index dba1dbd0a3..1159f668e6 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/di/SessionMatrixModule.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/di/SessionMatrixModule.kt @@ -22,6 +22,7 @@ import dagger.Provides import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.media.MatrixMediaLoader +import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.api.verification.SessionVerificationService @@ -34,6 +35,11 @@ object SessionMatrixModule { return matrixClient.sessionVerificationService() } + @Provides + fun providesNotificationSettingsService(matrixClient: MatrixClient): NotificationSettingsService { + return matrixClient.notificationSettingsService() + } + @Provides fun provideRoomMembershipObserver(matrixClient: MatrixClient): RoomMembershipObserver { return matrixClient.roomMembershipObserver() diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RoomNotificationSettingsMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RoomNotificationSettingsMapper.kt new file mode 100644 index 0000000000..084a6f973e --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RoomNotificationSettingsMapper.kt @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.impl.notificationsettings + +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.api.room.RoomNotificationSettings +import org.matrix.rustcomponents.sdk.RoomNotificationMode as RustRoomNotificationMode +import org.matrix.rustcomponents.sdk.RoomNotificationSettings as RustRoomNotificationSettings + +object RoomNotificationSettingsMapper { + fun map(roomNotificationSettings: RustRoomNotificationSettings): RoomNotificationSettings = + RoomNotificationSettings( + mode = mapMode(roomNotificationSettings.mode), + isDefault = roomNotificationSettings.isDefault + ) + + fun mapMode(mode: RustRoomNotificationMode): RoomNotificationMode = + when (mode) { + RustRoomNotificationMode.ALL_MESSAGES -> RoomNotificationMode.ALL_MESSAGES + RustRoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY + RustRoomNotificationMode.MUTE -> RoomNotificationMode.MUTE + } + + fun mapMode(mode: RoomNotificationMode): RustRoomNotificationMode = + when (mode) { + RoomNotificationMode.ALL_MESSAGES -> RustRoomNotificationMode.ALL_MESSAGES + RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> RustRoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY + RoomNotificationMode.MUTE -> RustRoomNotificationMode.MUTE + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt new file mode 100644 index 0000000000..1b1d51214f --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.impl.notificationsettings + +import io.element.android.libraries.core.coroutine.CoroutineDispatchers +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.api.room.RoomNotificationSettings +import kotlinx.coroutines.channels.BufferOverflow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.withContext +import org.matrix.rustcomponents.sdk.NotificationSettings +import org.matrix.rustcomponents.sdk.NotificationSettingsDelegate + +class RustNotificationSettingsService( + private val notificationSettings: NotificationSettings, + private val dispatchers: CoroutineDispatchers, +) : NotificationSettingsService { + + private val _notificationSettingsChangeFlow = MutableSharedFlow(extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST) + override val notificationSettingsChangeFlow: SharedFlow = _notificationSettingsChangeFlow.asSharedFlow() + + private var notificationSettingsDelegate = object : NotificationSettingsDelegate { + override fun settingsDidChange() { + _notificationSettingsChangeFlow.tryEmit(Unit) + } + } + + init { + notificationSettings.setDelegate(notificationSettingsDelegate) + } + + override suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, membersCount: Long): Result = + runCatching { + notificationSettings.getRoomNotificationSettings(roomId.value, isEncrypted, isOneToOne(membersCount)).let(RoomNotificationSettingsMapper::map) + } + + override suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, membersCount: Long): Result = + runCatching { + notificationSettings.getDefaultRoomNotificationMode(isEncrypted, isOneToOne(membersCount)).let(RoomNotificationSettingsMapper::mapMode) + } + + override suspend fun setRoomNotificationMode(roomId: RoomId, mode: RoomNotificationMode): Result = withContext(dispatchers.io) { + runCatching { + notificationSettings.setRoomNotificationMode(roomId.value, mode.let(RoomNotificationSettingsMapper::mapMode)) + } + } + + override suspend fun restoreDefaultRoomNotificationMode(roomId: RoomId): Result = withContext(dispatchers.io) { + runCatching { + notificationSettings.restoreDefaultRoomNotificationMode(roomId.value) + } + } + + override suspend fun muteRoom(roomId: RoomId): Result = setRoomNotificationMode(roomId, RoomNotificationMode.MUTE) + + override suspend fun unmuteRoom(roomId: RoomId, isEncrypted: Boolean, membersCount: Long) = withContext(dispatchers.io) { + runCatching { + notificationSettings.unmuteRoom(roomId.value, isEncrypted, isOneToOne(membersCount)) + } + } + + /** + * A one-to-one is a room with exactly 2 members. + * See [the Matrix spec](https://spec.matrix.org/latest/client-server-api/#default-underride-rules). + * @param membersCount The active members count in a room + */ + private fun isOneToOne(membersCount: Long) = membersCount == 2L +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt index 71caed8f19..461e43931e 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt @@ -33,16 +33,19 @@ import io.element.android.libraries.matrix.api.media.VideoInfo import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState +import io.element.android.libraries.matrix.api.room.MatrixRoomNotificationSettingsState import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.room.roomMembers +import io.element.android.libraries.matrix.api.room.roomNotificationSettings import io.element.android.libraries.matrix.api.timeline.MatrixTimeline import io.element.android.libraries.matrix.api.timeline.item.event.EventType import io.element.android.libraries.matrix.impl.core.toProgressWatcher import io.element.android.libraries.matrix.impl.media.MediaUploadHandlerImpl import io.element.android.libraries.matrix.impl.media.map import io.element.android.libraries.matrix.impl.poll.toInner +import io.element.android.libraries.matrix.impl.notificationsettings.RustNotificationSettingsService import io.element.android.libraries.matrix.impl.room.location.toInner import io.element.android.libraries.matrix.impl.timeline.RustMatrixTimeline import io.element.android.libraries.matrix.impl.util.destroyAll @@ -72,6 +75,7 @@ class RustMatrixRoom( override val sessionId: SessionId, private val roomListItem: RoomListItem, private val innerRoom: Room, + private val roomNotificationSettingsService: RustNotificationSettingsService, sessionCoroutineScope: CoroutineScope, private val coroutineDispatchers: CoroutineDispatchers, private val systemClock: SystemClock, @@ -90,6 +94,10 @@ class RustMatrixRoom( private val roomCoroutineScope = sessionCoroutineScope.childScope(coroutineDispatchers.main, "RoomScope-$roomId") private val _membersStateFlow = MutableStateFlow(MatrixRoomMembersState.Unknown) private val _syncUpdateFlow = MutableStateFlow(0L) + + private val _roomNotificationSettingsStateFlow = MutableStateFlow(MatrixRoomNotificationSettingsState.Unknown) + override val roomNotificationSettingsStateFlow: StateFlow = _roomNotificationSettingsStateFlow + private val _timeline by lazy { RustMatrixTimeline( matrixRoom = this, @@ -197,6 +205,22 @@ class RustMatrixRoom( } } + override suspend fun updateRoomNotificationSettings(): Result = withContext(coroutineDispatchers.io) { + val currentState = _roomNotificationSettingsStateFlow.value + val currentRoomNotificationSettings = currentState.roomNotificationSettings() + _roomNotificationSettingsStateFlow.value = MatrixRoomNotificationSettingsState.Pending(prevRoomNotificationSettings = currentRoomNotificationSettings) + runCatching { + roomNotificationSettingsService.getRoomNotificationSettings(roomId, isEncrypted, activeMemberCount).getOrThrow() + }.map { + _roomNotificationSettingsStateFlow.value = MatrixRoomNotificationSettingsState.Ready(it) + }.onFailure { + _roomNotificationSettingsStateFlow.value = MatrixRoomNotificationSettingsState.Error( + prevRoomNotificationSettings = currentRoomNotificationSettings, + failure = it + ) + } + } + override suspend fun userAvatarUrl(userId: UserId): Result = withContext(roomDispatcher) { runCatching { innerRoom.memberAvatarUrl(userId.value) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt index 83f7f3ad79..9ef50ecda5 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt @@ -24,6 +24,7 @@ import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters import io.element.android.libraries.matrix.api.media.MatrixMediaLoader import io.element.android.libraries.matrix.api.notification.NotificationService +import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.pusher.PushersService import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.RoomMembershipObserver @@ -33,6 +34,7 @@ import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.verification.SessionVerificationService import io.element.android.libraries.matrix.test.media.FakeMediaLoader import io.element.android.libraries.matrix.test.notification.FakeNotificationService +import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService import io.element.android.libraries.matrix.test.pushers.FakePushersService import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService @@ -50,6 +52,7 @@ class FakeMatrixClient( private val sessionVerificationService: FakeSessionVerificationService = FakeSessionVerificationService(), private val pushersService: FakePushersService = FakePushersService(), private val notificationService: FakeNotificationService = FakeNotificationService(), + private val notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(), private val syncService: FakeSyncService = FakeSyncService(), private val accountManagementUrlString: Result = Result.success(null), ) : MatrixClient { @@ -142,6 +145,7 @@ class FakeMatrixClient( override fun pushersService(): PushersService = pushersService override fun notificationService(): NotificationService = notificationService + override fun notificationSettingsService(): NotificationSettingsService = notificationSettingsService override fun roomMembershipObserver(): RoomMembershipObserver { return RoomMembershipObserver() diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt index f6b6e1645f..cae5df4dc4 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt @@ -24,6 +24,8 @@ import io.element.android.libraries.matrix.api.core.SpaceId import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.core.TransactionId import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.api.room.RoomNotificationSettings const val A_USER_NAME = "alice" const val A_PASSWORD = "password" @@ -59,6 +61,8 @@ const val A_HOMESERVER_URL_2 = "matrix-client.org" val A_HOMESERVER = MatrixHomeServerDetails(A_HOMESERVER_URL, supportsPasswordLogin = true, supportsOidcLogin = false) val A_HOMESERVER_OIDC = MatrixHomeServerDetails(A_HOMESERVER_URL, supportsPasswordLogin = false, supportsOidcLogin = true) +val A_ROOM_NOTIFICATION_MODE = RoomNotificationMode.MUTE +val A_ROOM_NOTIFICATION_SETTINGS = RoomNotificationSettings(mode = A_ROOM_NOTIFICATION_MODE, isDefault = false) const val AN_AVATAR_URL = "mxc://data" diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt new file mode 100644 index 0000000000..852496e0b3 --- /dev/null +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.test.notificationsettings + +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.api.room.RoomNotificationSettings +import io.element.android.libraries.matrix.test.A_ROOM_NOTIFICATION_MODE +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharedFlow + +class FakeNotificationSettingsService( + initialMode: RoomNotificationMode = A_ROOM_NOTIFICATION_MODE, + initialDefaultMode: RoomNotificationMode = A_ROOM_NOTIFICATION_MODE +) : NotificationSettingsService { + private var _roomNotificationSettingsStateFlow = MutableStateFlow(Unit) + private var defaultRoomNotificationMode: RoomNotificationMode = initialDefaultMode + private var roomNotificationMode: RoomNotificationMode = initialMode + override val notificationSettingsChangeFlow: SharedFlow + get() = _roomNotificationSettingsStateFlow + + override suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, membersCount: Long): Result { + return Result.success(RoomNotificationSettings(mode = roomNotificationMode, isDefault = roomNotificationMode == defaultRoomNotificationMode)) + } + + override suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, membersCount: Long): Result { + return Result.success(defaultRoomNotificationMode) + } + + override suspend fun setRoomNotificationMode(roomId: RoomId, mode: RoomNotificationMode): Result { + roomNotificationMode = mode + _roomNotificationSettingsStateFlow.emit(Unit) + return Result.success(Unit) + } + + override suspend fun restoreDefaultRoomNotificationMode(roomId: RoomId): Result { + roomNotificationMode = defaultRoomNotificationMode + _roomNotificationSettingsStateFlow.emit(Unit) + return Result.success(Unit) + } + + override suspend fun muteRoom(roomId: RoomId): Result { + return setRoomNotificationMode(roomId, RoomNotificationMode.MUTE) + } + + override suspend fun unmuteRoom(roomId: RoomId, isEncrypted: Boolean, membersCount: Long): Result { + return restoreDefaultRoomNotificationMode(roomId) + } +} diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index 7bffb985bb..761e479816 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -27,16 +27,19 @@ import io.element.android.libraries.matrix.api.media.FileInfo import io.element.android.libraries.matrix.api.media.ImageInfo import io.element.android.libraries.matrix.api.media.MediaUploadHandler import io.element.android.libraries.matrix.api.media.VideoInfo +import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState import io.element.android.libraries.matrix.api.room.MessageEventType +import io.element.android.libraries.matrix.api.room.MatrixRoomNotificationSettingsState import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.timeline.MatrixTimeline import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.media.FakeMediaUploadHandler +import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService import io.element.android.libraries.matrix.test.timeline.FakeMatrixTimeline import io.element.android.tests.testutils.simulateLongTask import kotlinx.coroutines.delay @@ -58,6 +61,7 @@ class FakeMatrixRoom( override val isDirect: Boolean = false, override val joinedMemberCount: Long = 123L, override val activeMemberCount: Long = 234L, + val notificationSettingsService: NotificationSettingsService = FakeNotificationSettingsService(), private val matrixTimeline: MatrixTimeline = FakeMatrixTimeline(), canRedact: Boolean = false, ) : MatrixRoom { @@ -136,10 +140,19 @@ class FakeMatrixRoom( override val membersStateFlow: MutableStateFlow = MutableStateFlow(MatrixRoomMembersState.Unknown) + override val roomNotificationSettingsStateFlow: MutableStateFlow = + MutableStateFlow(MatrixRoomNotificationSettingsState.Unknown) + override suspend fun updateMembers(): Result = simulateLongTask { updateMembersResult } + override suspend fun updateRoomNotificationSettings(): Result = simulateLongTask { + val notificationSettings = notificationSettingsService.getRoomNotificationSettings(roomId, isEncrypted, activeMemberCount).getOrThrow() + roomNotificationSettingsStateFlow.value = MatrixRoomNotificationSettingsState.Ready(notificationSettings) + return Result.success(Unit) + } + override val syncUpdateFlow: StateFlow = MutableStateFlow(0L) override val timeline: MatrixTimeline = matrixTimeline diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 8a9f1cee2f..d6f9f2cbaf 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -1,5 +1,6 @@ + "Use an identity server to invite by email. ""Use the default (%(defaultIdentityServerName)s)"" or manage in ""Settings""." "Hide password" "Mentions only" "Muted" @@ -161,6 +162,10 @@ "Are you sure that you want to leave this room? This room is not public and you won\'t be able to rejoin without an invite." "Are you sure that you want to leave the room?" "%1$s Android" + + "%(count)s room" + "%(count)s rooms" + "%1$d member" "%1$d members" diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomNotificationSettingsDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomNotificationSettingsDark_0_null_0,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..352d1a95e1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomNotificationSettingsDark_0_null_0,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7d1c7b862db8afe25dd958c9011de82e1439d298a95ec15a86dfbae0457f7937 +size 36436 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomNotificationSettingsLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomNotificationSettingsLight_0_null_0,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..4dc3771f2f --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomNotificationSettingsLight_0_null_0,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c1900985fb6b9d25eee44af5cdc0c6fcdee994ffc3da8dae5a6e742c3d0b7127 +size 40016 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomPrivacyOptionLight-D-0_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomPrivacyOptionLight-D-0_1_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..38c517ea47 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomPrivacyOptionLight-D-0_1_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:62418ebe7afa2c1c7eda2b1251fb189a75527aa7a4289a9478c531fac7dee8bd +size 10666 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomPrivacyOptionLight-N-0_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomPrivacyOptionLight-N-0_2_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..cecfc09f64 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.notificationsettings_null_RoomPrivacyOptionLight-N-0_2_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e5a32b1baaaad0bf266e190084a64b3d382a2d6d472a55b1c3653ee948e100c9 +size 9756 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png index 9ef89a09c3..211bbf07bc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6edcc452c76049a978ceb97b46776446790dbdbe30eef1693fafda089cdc3ee7 -size 55527 +oid sha256:49bd51a32dbd3615364a6039163a36c08d0096a8c511a7084e21b7c1780131db +size 52810 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png index 0dc50f37c2..19f56b887f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:20e630b0f3bb9fddd5f11e4e9f2a92b5d35c4bbe182662e8d0fde27451297006 -size 45247 +oid sha256:2c61e5d0eabb1f9cae83c3df0f73f14545e0c61bd7393d6e2862e0f48b9e3d7a +size 51272 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png index ca7b6913d5..ec15315140 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:553b498247e9da02ad037716a67c080a3da2fb07602b0c0c44de8f16a4891eda -size 46086 +oid sha256:adf48ade91c22ce7f98bf2773ec4e14ce0c290f7ba25e8c76d9f722677c46277 +size 44388 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png index 9610377f28..d72802868e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d91c291503dc745092b132fec62208e73dcd031822ca21a66a7fb1f48ecfa6e1 -size 49316 +oid sha256:262ba970549c3c137ab90ffc607279479dfc4fbf86468e18b08ea6c5ef5b0710 +size 53634 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png index 1fe7df1eaa..04edeb3284 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:efda43a25fdc2a21a4ad3767b14b4c7a308003f9bcb9e67d64520db13c83f0fd -size 61061 +oid sha256:49d92579bffadd59f89e79217b5e6148bbfeda0c5750a06ad7aa36f8125d6d29 +size 50616 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png index 761666b2e3..2150b91f12 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:31f2d59ad03a4d9ba8efd5f146668162f3c2095ac90e16dd3634d3e817f7263d -size 61238 +oid sha256:b742f507ba11be8bdf733e5e751fc5d9fe1c0cc2eb070abf9abcffb605783ab3 +size 52151 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png index 761666b2e3..2150b91f12 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:31f2d59ad03a4d9ba8efd5f146668162f3c2095ac90e16dd3634d3e817f7263d -size 61238 +oid sha256:b742f507ba11be8bdf733e5e751fc5d9fe1c0cc2eb070abf9abcffb605783ab3 +size 52151 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png index f7d782f1b8..f94aa99b7b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fba2e76faa5915acf1e9d2ede6b58e1ab73e287aefa6e5ffc643be527350d987 -size 50147 +oid sha256:467ca1b17857b053881cb9999c3d6b099949c6b4279188da57383fdb9083041f +size 53946 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png index 572f6d76e1..dbddc54999 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1089845cd143d07e0d6a363a9dc490ab6f5ae4711fc99843c01e4f074dbdeb98 -size 55780 +oid sha256:d8e1ede8c0ea34595e90b2031c9607b99e72c3d7d1e9a778bbfbece98eb23875 +size 53035 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png index 6620f9dc9f..ca3e37d42a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:59054f5692d41c0d6fe65c6f1bc9d0c4e1e3149aedd987e9335fabff7b46d85f -size 57237 +oid sha256:a9f1d200ef2c93d557a67a29700918bd70439c7d7d8d247d60473b26f0c44eb3 +size 53851 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png index 852e18b044..c27ccdc333 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6f65151d983057ca185c53b4045fb33675f12730fee1b40e3df6d269e2290a05 -size 47290 +oid sha256:b06e1652745ceff912734b9bf74543c95f4d420eaf3aec4b388dd101ea1428f8 +size 53838 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png index 89ce9d4604..087bd78cc4 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:de6a5ac50e8b30364b9e630d2edbe49c18cc3684da080e2167f41bd689f17700 -size 48369 +oid sha256:5d4a381a3c99a7f04a11a2e93cd7c4145fa0bd33a1f7461038b3918c5cd94571 +size 46676 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png index 95f7e24521..0ebb4bdfc9 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:edcf03466e38ce3906583f2701f45d2a9538a6fd7e9d1c9d4822a037b833a512 -size 50185 +oid sha256:61add95d28096c65f94764df109d253c7b589058cea324d908616312e7dffc3e +size 54723 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png index 2f17f119fc..8a3a6dddf4 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:670f05e0c2861234708c7dee4d919a977bbd3aec3e965db631505957871f19fa -size 62904 +oid sha256:3197e871e4b4c39dc714610b54e351c4061149bfc0b5511f78a0c73e8ec2236b +size 51824 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png index d0c76cd680..6547257b66 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9553c9ef84cd1f2e890290e093cb0006f03d1a2f36de5e2b7d104d0eb102b2e2 -size 63045 +oid sha256:a0cf7d5d0c91aa7946586e5258077b07b329f387f46b0df0a29c49cc211ed584 +size 54021 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png index d0c76cd680..6547257b66 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9553c9ef84cd1f2e890290e093cb0006f03d1a2f36de5e2b7d104d0eb102b2e2 -size 63045 +oid sha256:a0cf7d5d0c91aa7946586e5258077b07b329f387f46b0df0a29c49cc211ed584 +size 54021 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png index 0e72199eb0..6879d4dfb5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ab533a35fbbba8b45d94bcfb0637d0f021ee2ef71230754ed418702ee18f11d -size 51182 +oid sha256:cd4be4f49a78aba83c4b5f9c350f8b64cfe96d50890df16154cd7b0e20546d25 +size 55020 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png index 159c179d5c..92a37ad86d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9ec34df75877b7050ad874905926f5d35fee29d1f8324437b502d7152ef87cdc -size 57494 +oid sha256:da79bef2bd54301f2724269719d93d1d9212fd17b9dc0d2a7ba935693c6170ac +size 54107 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.preferences_null_Preferences_PreferenceText_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.preferences_null_Preferences_PreferenceText_0_null,NEXUS_5,1.0,en].png index 15e7b55fa2..f757da3a86 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.preferences_null_Preferences_PreferenceText_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.preferences_null_Preferences_PreferenceText_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:08af9a706d579b4632c70265b6f1529008bd483cb4924c341e3a9f0172cc8cd4 -size 39251 +oid sha256:bd05144d4b3527a44e1c9f3fb92d227ccc38fd7afce5436f32b59f14f0b54e27 +size 39028 diff --git a/tools/localazy/config.json b/tools/localazy/config.json index 05d1ced2c6..cf29033d88 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -92,7 +92,8 @@ "includeRegex": [ "screen_room_details_.*", "screen_room_member_list_.*", - "screen_dm_details_.*" + "screen_dm_details_.*", + "screen_room_notification_settings_.*" ] }, { From c16c875e68cd7650b8285276a3d1c9e2faaf937f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 7 Sep 2023 10:29:10 +0200 Subject: [PATCH 057/234] Rework the feature flag module. Fix typo, rename class and interface, add doc, do small refacto, to improve code clarity. --- .../featureflag/api/FeatureFlagService.kt | 3 ++- .../impl/DefaultFeatureFlagService.kt | 2 +- ...ovider.kt => MutableFeatureFlagProvider.kt} | 2 +- .../impl/PreferencesFeatureFlagProvider.kt | 9 +++++---- ...rovider.kt => StaticFeatureFlagProvider.kt} | 9 ++++++--- .../featureflag/impl/di/FeatureFlagModule.kt | 18 +++++++++++------- .../impl/DefaultFeatureFlagServiceTest.kt | 14 +++++++------- ...er.kt => FakeMutableFeatureFlagProvider.kt} | 2 +- 8 files changed, 34 insertions(+), 25 deletions(-) rename libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/{RuntimeFeatureFlagProvider.kt => MutableFeatureFlagProvider.kt} (92%) rename libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/{BuildtimeFeatureFlagProvider.kt => StaticFeatureFlagProvider.kt} (84%) rename libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/{FakeRuntimeFeatureFlagProvider.kt => FakeMutableFeatureFlagProvider.kt} (92%) diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlagService.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlagService.kt index 59e224a1ae..8089c837ff 100644 --- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlagService.kt +++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlagService.kt @@ -28,7 +28,8 @@ interface FeatureFlagService { * @param feature the feature to enable or disable * @param enabled true to enable the feature * - * @return true if the method succeeds, ie if a RuntimeFeatureFlagProvider is registered + * @return true if the method succeeds, ie if a [io.element.android.libraries.featureflag.impl.MutableFeatureFlagProvider] + * is registered */ suspend fun setFeatureEnabled(feature: Feature, enabled: Boolean): Boolean } diff --git a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagService.kt b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagService.kt index 7298929aea..b445599693 100644 --- a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagService.kt +++ b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagService.kt @@ -38,7 +38,7 @@ class DefaultFeatureFlagService @Inject constructor( } override suspend fun setFeatureEnabled(feature: Feature, enabled: Boolean): Boolean { - return providers.filterIsInstance(RuntimeFeatureFlagProvider::class.java) + return providers.filterIsInstance(MutableFeatureFlagProvider::class.java) .sortedBy(FeatureFlagProvider::priority) .firstOrNull() ?.setFeatureEnabled(feature, enabled) diff --git a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/RuntimeFeatureFlagProvider.kt b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/MutableFeatureFlagProvider.kt similarity index 92% rename from libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/RuntimeFeatureFlagProvider.kt rename to libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/MutableFeatureFlagProvider.kt index 1238ad354c..7e2da181b6 100644 --- a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/RuntimeFeatureFlagProvider.kt +++ b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/MutableFeatureFlagProvider.kt @@ -18,6 +18,6 @@ package io.element.android.libraries.featureflag.impl import io.element.android.libraries.featureflag.api.Feature -interface RuntimeFeatureFlagProvider : FeatureFlagProvider { +interface MutableFeatureFlagProvider : FeatureFlagProvider { suspend fun setFeatureEnabled(feature: Feature, enabled: Boolean) } diff --git a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/PreferencesFeatureFlagProvider.kt b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/PreferencesFeatureFlagProvider.kt index 15ab08b338..ddffdebd34 100644 --- a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/PreferencesFeatureFlagProvider.kt +++ b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/PreferencesFeatureFlagProvider.kt @@ -30,12 +30,13 @@ import javax.inject.Inject private val Context.dataStore: DataStore by preferencesDataStore(name = "elementx_featureflag") -class PreferencesFeatureFlagProvider @Inject constructor(@ApplicationContext context: Context) : RuntimeFeatureFlagProvider { - +/** + * Note: this will be used only in the nightly and in the debug build. + */ +class PreferencesFeatureFlagProvider @Inject constructor(@ApplicationContext context: Context) : MutableFeatureFlagProvider { private val store = context.dataStore - override val priority: Int - get() = MEDIUM_PRIORITY + override val priority = MEDIUM_PRIORITY override suspend fun setFeatureEnabled(feature: Feature, enabled: Boolean) { store.edit { prefs -> diff --git a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/BuildtimeFeatureFlagProvider.kt b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/StaticFeatureFlagProvider.kt similarity index 84% rename from libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/BuildtimeFeatureFlagProvider.kt rename to libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/StaticFeatureFlagProvider.kt index 0117a4aa22..2d66d3be21 100644 --- a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/BuildtimeFeatureFlagProvider.kt +++ b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/StaticFeatureFlagProvider.kt @@ -20,11 +20,14 @@ import io.element.android.libraries.featureflag.api.Feature import io.element.android.libraries.featureflag.api.FeatureFlags import javax.inject.Inject -class BuildtimeFeatureFlagProvider @Inject constructor() : +/** + * This provider is used for release build. + * Change the value return by [isFeatureEnabled] to enable/disable features. + */ +class StaticFeatureFlagProvider @Inject constructor() : FeatureFlagProvider { - override val priority: Int - get() = LOW_PRIORITY + override val priority = LOW_PRIORITY override suspend fun isFeatureEnabled(feature: Feature): Boolean { return if (feature is FeatureFlags) { diff --git a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/di/FeatureFlagModule.kt b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/di/FeatureFlagModule.kt index 07ee53ceee..b2f0a4106d 100644 --- a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/di/FeatureFlagModule.kt +++ b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/di/FeatureFlagModule.kt @@ -22,7 +22,7 @@ import dagger.Provides import dagger.multibindings.ElementsIntoSet import io.element.android.libraries.core.meta.BuildType import io.element.android.libraries.di.AppScope -import io.element.android.libraries.featureflag.impl.BuildtimeFeatureFlagProvider +import io.element.android.libraries.featureflag.impl.StaticFeatureFlagProvider import io.element.android.libraries.featureflag.impl.FeatureFlagProvider import io.element.android.libraries.featureflag.impl.PreferencesFeatureFlagProvider @@ -35,14 +35,18 @@ object FeatureFlagModule { @ElementsIntoSet fun providesFeatureFlagProvider( buildType: BuildType, - runtimeFeatureFlagProvider: PreferencesFeatureFlagProvider, - buildtimeFeatureFlagProvider: BuildtimeFeatureFlagProvider, + mutableFeatureFlagProvider: PreferencesFeatureFlagProvider, + staticFeatureFlagProvider: StaticFeatureFlagProvider, ): Set { val providers = HashSet() - if (buildType == BuildType.RELEASE) { - providers.add(buildtimeFeatureFlagProvider) - } else { - providers.add(runtimeFeatureFlagProvider) + when (buildType) { + BuildType.RELEASE -> { + providers.add(staticFeatureFlagProvider) + } + BuildType.NIGHTLY, + BuildType.DEBUG -> { + providers.add(mutableFeatureFlagProvider) + } } return providers } diff --git a/libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagServiceTest.kt b/libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagServiceTest.kt index ea9b03acdf..890959639f 100644 --- a/libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagServiceTest.kt +++ b/libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagServiceTest.kt @@ -39,7 +39,7 @@ class DefaultFeatureFlagServiceTest { @Test fun `given service with a runtime provider when set enabled feature is called then it returns true`() = runTest { - val featureFlagProvider = FakeRuntimeFeatureFlagProvider(0) + val featureFlagProvider = FakeMutableFeatureFlagProvider(0) val featureFlagService = DefaultFeatureFlagService(setOf(featureFlagProvider)) val result = featureFlagService.setFeatureEnabled(FeatureFlags.LocationSharing, true) assertThat(result).isEqualTo(true) @@ -47,7 +47,7 @@ class DefaultFeatureFlagServiceTest { @Test fun `given service with a runtime provider and feature enabled when feature is checked then it returns the correct value`() = runTest { - val featureFlagProvider = FakeRuntimeFeatureFlagProvider(0) + val featureFlagProvider = FakeMutableFeatureFlagProvider(0) val featureFlagService = DefaultFeatureFlagService(setOf(featureFlagProvider)) featureFlagService.setFeatureEnabled(FeatureFlags.LocationSharing, true) assertThat(featureFlagService.isFeatureEnabled(FeatureFlags.LocationSharing)).isEqualTo(true) @@ -57,11 +57,11 @@ class DefaultFeatureFlagServiceTest { @Test fun `given service with 2 runtime providers when feature is checked then it uses the priority correctly`() = runTest { - val lowPriorityfeatureFlagProvider = FakeRuntimeFeatureFlagProvider(LOW_PRIORITY) - val highPriorityfeatureFlagProvider = FakeRuntimeFeatureFlagProvider(HIGH_PRIORITY) - val featureFlagService = DefaultFeatureFlagService(setOf(lowPriorityfeatureFlagProvider, highPriorityfeatureFlagProvider)) - lowPriorityfeatureFlagProvider.setFeatureEnabled(FeatureFlags.LocationSharing, false) - highPriorityfeatureFlagProvider.setFeatureEnabled(FeatureFlags.LocationSharing, true) + val lowPriorityFeatureFlagProvider = FakeMutableFeatureFlagProvider(LOW_PRIORITY) + val highPriorityFeatureFlagProvider = FakeMutableFeatureFlagProvider(HIGH_PRIORITY) + val featureFlagService = DefaultFeatureFlagService(setOf(lowPriorityFeatureFlagProvider, highPriorityFeatureFlagProvider)) + lowPriorityFeatureFlagProvider.setFeatureEnabled(FeatureFlags.LocationSharing, false) + highPriorityFeatureFlagProvider.setFeatureEnabled(FeatureFlags.LocationSharing, true) assertThat(featureFlagService.isFeatureEnabled(FeatureFlags.LocationSharing)).isEqualTo(true) } } diff --git a/libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/FakeRuntimeFeatureFlagProvider.kt b/libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/FakeMutableFeatureFlagProvider.kt similarity index 92% rename from libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/FakeRuntimeFeatureFlagProvider.kt rename to libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/FakeMutableFeatureFlagProvider.kt index 5ff5cf932f..f1d075ace2 100644 --- a/libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/FakeRuntimeFeatureFlagProvider.kt +++ b/libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/FakeMutableFeatureFlagProvider.kt @@ -18,7 +18,7 @@ package io.element.android.libraries.featureflag.impl import io.element.android.libraries.featureflag.api.Feature -class FakeRuntimeFeatureFlagProvider(override val priority: Int) : RuntimeFeatureFlagProvider { +class FakeMutableFeatureFlagProvider(override val priority: Int) : MutableFeatureFlagProvider { private val enabledFeatures = HashMap() From aacfa0d83a3983d09dba457c047f72e8ca08b7b1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 7 Sep 2023 10:44:32 +0200 Subject: [PATCH 058/234] To avoid mistake, FeatureFlags does not have `defaultValue` set to true, and `StaticFeatureFlagProvider` return the default value. This fixes #1241. --- changelog.d/1241.bugfix | 1 + .../android/libraries/featureflag/api/FeatureFlags.kt | 9 +++++++-- .../featureflag/impl/StaticFeatureFlagProvider.kt | 8 ++------ 3 files changed, 10 insertions(+), 8 deletions(-) create mode 100644 changelog.d/1241.bugfix diff --git a/changelog.d/1241.bugfix b/changelog.d/1241.bugfix new file mode 100644 index 0000000000..d2339b3158 --- /dev/null +++ b/changelog.d/1241.bugfix @@ -0,0 +1 @@ +Enable polls in release build. diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt index 6490b4e357..36113389a4 100644 --- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt +++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt @@ -16,21 +16,26 @@ package io.element.android.libraries.featureflag.api +/** + * To enable or disable a FeatureFlags, change the `defaultValue` value. + * It will impact all the build types. + */ enum class FeatureFlags( override val key: String, override val title: String, override val description: String? = null, - override val defaultValue: Boolean = true + override val defaultValue: Boolean ) : Feature { LocationSharing( key = "feature.locationsharing", title = "Allow user to share location", + defaultValue = true, ), Polls( key = "feature.polls", title = "Polls", description = "Create poll and render poll events in the timeline", - defaultValue = false, + defaultValue = true, ), NotificationSettings( key = "feature.notificationsettings", diff --git a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/StaticFeatureFlagProvider.kt b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/StaticFeatureFlagProvider.kt index 2d66d3be21..50a1ac4dd5 100644 --- a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/StaticFeatureFlagProvider.kt +++ b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/StaticFeatureFlagProvider.kt @@ -22,7 +22,7 @@ import javax.inject.Inject /** * This provider is used for release build. - * Change the value return by [isFeatureEnabled] to enable/disable features. + * [isFeatureEnabled] just returns the default value of the FeatureFlags. */ class StaticFeatureFlagProvider @Inject constructor() : FeatureFlagProvider { @@ -31,11 +31,7 @@ class StaticFeatureFlagProvider @Inject constructor() : override suspend fun isFeatureEnabled(feature: Feature): Boolean { return if (feature is FeatureFlags) { - when (feature) { - FeatureFlags.LocationSharing -> true - FeatureFlags.Polls -> false - FeatureFlags.NotificationSettings -> false - } + feature.defaultValue } else { false } From 762a03259b9d24f65e7cff8eadad98532691776e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 7 Sep 2023 12:32:21 +0200 Subject: [PATCH 059/234] Make a diff between `FeatureFlags.defaultValue` and value returned by `StaticFeatureFlagProvider.isFeatureEnabled()`. Iterate after Ganfra's review. --- .../android/libraries/featureflag/api/FeatureFlags.kt | 4 +++- .../featureflag/impl/StaticFeatureFlagProvider.kt | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt index 36113389a4..fc13a8a1cc 100644 --- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt +++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt @@ -18,7 +18,8 @@ package io.element.android.libraries.featureflag.api /** * To enable or disable a FeatureFlags, change the `defaultValue` value. - * It will impact all the build types. + * Warning: to enable a flog for the release app, you MUST update the file + * [io.element.android.libraries.featureflag.impl.StaticFeatureFlagProvider] */ enum class FeatureFlags( override val key: String, @@ -40,6 +41,7 @@ enum class FeatureFlags( NotificationSettings( key = "feature.notificationsettings", title = "Show notification settings", + // Do not forget to edit StaticFeatureFlagProvider when enabling the feature. defaultValue = false, ), } diff --git a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/StaticFeatureFlagProvider.kt b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/StaticFeatureFlagProvider.kt index 50a1ac4dd5..50efdb9fc3 100644 --- a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/StaticFeatureFlagProvider.kt +++ b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/StaticFeatureFlagProvider.kt @@ -22,7 +22,7 @@ import javax.inject.Inject /** * This provider is used for release build. - * [isFeatureEnabled] just returns the default value of the FeatureFlags. + * This is the place to enable or disable feature for the release build. */ class StaticFeatureFlagProvider @Inject constructor() : FeatureFlagProvider { @@ -31,7 +31,11 @@ class StaticFeatureFlagProvider @Inject constructor() : override suspend fun isFeatureEnabled(feature: Feature): Boolean { return if (feature is FeatureFlags) { - feature.defaultValue + when(feature) { + FeatureFlags.LocationSharing -> true + FeatureFlags.Polls -> true + FeatureFlags.NotificationSettings -> false + } } else { false } From e19b27badf965c46b676f13be7a5cfb5d95c82ca Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Thu, 7 Sep 2023 13:19:13 +0200 Subject: [PATCH 060/234] De-duplicate sonar job in the CI (#1238) * De-duplicate sonar job in the CI * Remove workaround for `src/*/kotlin` folders * Downgrade the sonarqube plugin version * Try increasing workers for this job, since it's quite slow * Warn about regression in latest sonarqube release * Forbid backups to prevent cryptographic issues --- .github/workflows/quality.yml | 6 ------ .github/workflows/sonar.yml | 12 +++--------- app/src/main/AndroidManifest.xml | 2 +- app/src/main/res/xml/backup_rules.xml | 11 ++--------- app/src/main/res/xml/data_extraction_rules.xml | 16 ++++------------ build.gradle.kts | 16 ---------------- gradle/libs.versions.toml | 5 ++++- 7 files changed, 14 insertions(+), 54 deletions(-) diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 9c0aac7aef..37648a5403 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -52,12 +52,6 @@ jobs: name: linting-report path: | */build/reports/**/*.* - - name: 🔊 Publish results to Sonar - env: - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - ORG_GRADLE_PROJECT_SONAR_LOGIN: ${{ secrets.SONAR_TOKEN }} - if: ${{ always() && env.SONAR_TOKEN != '' && env.ORG_GRADLE_PROJECT_SONAR_LOGIN != '' }} - run: ./gradlew sonar $CI_GRADLE_ARG_PROPERTIES - name: Prepare Danger if: always() run: | diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index 42846c2cd5..e8efe99d28 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -1,4 +1,4 @@ -name: Code Quality Checks +name: Sonar on: workflow_dispatch: @@ -10,11 +10,11 @@ on: # Enrich gradle.properties for CI/CD env: GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -XX:MaxMetaspaceSize=512m -Dkotlin.daemon.jvm.options="-Xmx2g" -Dkotlin.incremental=false - CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon --warn + CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 4 --no-daemon --warn jobs: sonar: - name: Project Check Suite + name: Sonar Quality Checks runs-on: ubuntu-latest # Allow all jobs on main and develop. Just one per PR. concurrency: @@ -41,9 +41,3 @@ jobs: ORG_GRADLE_PROJECT_SONAR_LOGIN: ${{ secrets.SONAR_TOKEN }} if: ${{ always() && env.SONAR_TOKEN != '' && env.ORG_GRADLE_PROJECT_SONAR_LOGIN != '' }} run: ./gradlew sonar $CI_GRADLE_ARG_PROPERTIES - - name: Prepare Danger - if: always() - run: | - npm install --save-dev @babel/core - npm install --save-dev @babel/plugin-transform-flow-strip-types - yarn add danger-plugin-lint-report --dev diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ffd0265584..7d1c45b1b1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -22,7 +22,7 @@ - + diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/app/src/main/res/xml/data_extraction_rules.xml index a6ecda4638..9b4bbfff1c 100644 --- a/app/src/main/res/xml/data_extraction_rules.xml +++ b/app/src/main/res/xml/data_extraction_rules.xml @@ -1,5 +1,5 @@ - + - diff --git a/build.gradle.kts b/build.gradle.kts index 69f5676e72..bd0f84177a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -143,22 +143,6 @@ sonar { } } -allprojects { - val projectDir = projectDir.toString() - sonar { - properties { - // Note: folders `kotlin` are not supported (yet), I asked on their side: https://community.sonarsource.com/t/82824 - // As a workaround provide the path in `sonar.sources` property. - if (File("$projectDir/src/main/kotlin").exists()) { - property("sonar.sources", "src/main/kotlin") - } - if (File("$projectDir/src/test/kotlin").exists()) { - property("sonar.tests", "src/test/kotlin") - } - } - } -} - allprojects { tasks.withType { maxParallelForks = (Runtime.getRuntime().availableProcessors() / 2).coerceAtLeast(1) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1ce7a09e72..b1e068613d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -203,6 +203,9 @@ dependencygraph = { id = "com.savvasdalkitsis.module-dependency-graph", version. dependencycheck = { id = "org.owasp.dependencycheck", version.ref = "dependencycheck" } dependencyanalysis = { id = "com.autonomousapps.dependency-analysis", version.ref = "dependencyanalysis" } paparazzi = "app.cash.paparazzi:1.3.1" -sonarqube = "org.sonarqube:4.3.1.3277" kover = "org.jetbrains.kotlinx.kover:0.6.1" sqldelight = { id = "com.squareup.sqldelight", version.ref = "sqldelight" } + +# Version '4.3.1.3277' introduced some regressions in CI time (more than 2x slower), so make sure +# this is no longer the case before upgrading. +sonarqube = "org.sonarqube:4.2.1.3168" From c44b7eb81c060b0de3a7869f7219b72b7a7a1bb2 Mon Sep 17 00:00:00 2001 From: jonnyandrew Date: Thu, 7 Sep 2023 14:05:11 +0100 Subject: [PATCH 061/234] Fix crash in error tracking (#1248) --- changelog.d/1248.bugfix | 1 + .../analyticsproviders/posthog/PosthogAnalyticsProvider.kt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelog.d/1248.bugfix diff --git a/changelog.d/1248.bugfix b/changelog.d/1248.bugfix new file mode 100644 index 0000000000..c36862df63 --- /dev/null +++ b/changelog.d/1248.bugfix @@ -0,0 +1 @@ +Fix crash in error tracking \ No newline at end of file diff --git a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogAnalyticsProvider.kt b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogAnalyticsProvider.kt index fb2e341e1e..1f21c0beb5 100644 --- a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogAnalyticsProvider.kt +++ b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogAnalyticsProvider.kt @@ -71,7 +71,7 @@ class PosthogAnalyticsProvider @Inject constructor( } override fun trackError(throwable: Throwable) { - TODO("Not yet implemented") + // Not implemented } private fun createPosthog(): PostHog = postHogFactory.createPosthog() From b9896bab8034d7450eb248d30d85bd7f117a0311 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 7 Sep 2023 15:10:10 +0200 Subject: [PATCH 062/234] Use CircleShape by default on FAB, for coherency with other platforms. --- .../designsystem/theme/components/FloatingActionButton.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/FloatingActionButton.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/FloatingActionButton.kt index e126a429d8..16af6203ca 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/FloatingActionButton.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/FloatingActionButton.kt @@ -19,6 +19,7 @@ package io.element.android.libraries.designsystem.theme.components import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Close import androidx.compose.material3.FloatingActionButtonDefaults @@ -38,7 +39,7 @@ import io.element.android.libraries.designsystem.preview.PreviewGroup fun FloatingActionButton( onClick: () -> Unit, modifier: Modifier = Modifier, - shape: Shape = FloatingActionButtonDefaults.shape, + shape: Shape = CircleShape, // FloatingActionButtonDefaults.shape, containerColor: Color = FloatingActionButtonDefaults.containerColor, contentColor: Color = contentColorFor(containerColor), elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(), From 33dd0b202065976229cbd5525f576ad31b682e97 Mon Sep 17 00:00:00 2001 From: jonnyandrew Date: Thu, 7 Sep 2023 14:30:55 +0100 Subject: [PATCH 063/234] Remove changelog (#1249) --- changelog.d/1248.bugfix | 1 - 1 file changed, 1 deletion(-) delete mode 100644 changelog.d/1248.bugfix diff --git a/changelog.d/1248.bugfix b/changelog.d/1248.bugfix deleted file mode 100644 index c36862df63..0000000000 --- a/changelog.d/1248.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix crash in error tracking \ No newline at end of file From 3d6b5976e3d8d245fff5701405c8735d71f8509d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 7 Sep 2023 15:49:51 +0200 Subject: [PATCH 064/234] Iterate on icon in Fab in the room list. --- .../features/roomlist/impl/RoomListView.kt | 3 +-- .../src/main/res/drawable/ic_edit_square.xml | 17 +++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt index 176962ca2a..f7eb5aa4eb 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt @@ -219,8 +219,7 @@ fun RoomListContent( onClick = onCreateRoomClicked ) { Icon( - // Correct icon alignment for better rendering. - modifier = Modifier.padding(start = 1.dp, bottom = 1.dp), + // Note cannot use Icons.Outlined.EditSquare, it does not exist :/ resourceId = DrawableR.drawable.ic_edit_square, contentDescription = stringResource(id = R.string.screen_roomlist_a11y_create_message) ) diff --git a/libraries/designsystem/src/main/res/drawable/ic_edit_square.xml b/libraries/designsystem/src/main/res/drawable/ic_edit_square.xml index 73b092ea47..121486a4a2 100644 --- a/libraries/designsystem/src/main/res/drawable/ic_edit_square.xml +++ b/libraries/designsystem/src/main/res/drawable/ic_edit_square.xml @@ -15,12 +15,13 @@ --> - + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + + From d0a36b5e64d9ec74e487e8516c086b6cec3adf4c Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 7 Sep 2023 13:59:56 +0000 Subject: [PATCH 065/234] Update screenshots --- ...end_null_SendLocationView-D-0_1_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...end_null_SendLocationView-D-0_1_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...end_null_SendLocationView-D-0_1_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...end_null_SendLocationView-D-0_1_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...end_null_SendLocationView-D-0_1_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...end_null_SendLocationView-N-0_2_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...end_null_SendLocationView-N-0_2_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...end_null_SendLocationView-N-0_2_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...end_null_SendLocationView-N-0_2_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...end_null_SendLocationView-N-0_2_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...how_null_ShowLocationViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...how_null_ShowLocationViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...how_null_ShowLocationViewDark_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...how_null_ShowLocationViewDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...how_null_ShowLocationViewDark_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...how_null_ShowLocationViewDark_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...how_null_ShowLocationViewDark_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...how_null_ShowLocationViewDark_0_null_7,NEXUS_5,1.0,en].png | 4 ++-- ...ow_null_ShowLocationViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ow_null_ShowLocationViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...ow_null_ShowLocationViewLight_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...ow_null_ShowLocationViewLight_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...ow_null_ShowLocationViewLight_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...ow_null_ShowLocationViewLight_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...ow_null_ShowLocationViewLight_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...ow_null_ShowLocationViewLight_0_null_7,NEXUS_5,1.0,en].png | 4 ++-- ...st.impl_null_RoomListViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...st.impl_null_RoomListViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...st.impl_null_RoomListViewDark_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...st.impl_null_RoomListViewDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...st.impl_null_RoomListViewDark_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...st.impl_null_RoomListViewDark_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...t.impl_null_RoomListViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...t.impl_null_RoomListViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...t.impl_null_RoomListViewLight_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...t.impl_null_RoomListViewLight_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...t.impl_null_RoomListViewLight_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...t.impl_null_RoomListViewLight_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...ionButtons_FloatingActionButton_0_null,NEXUS_5,1.0,en].png | 4 ++-- 39 files changed, 78 insertions(+), 78 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-D-0_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-D-0_1_null_0,NEXUS_5,1.0,en].png index 8e5282128a..8d2683d552 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-D-0_1_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-D-0_1_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1625b6184c01ab75efcfe4c8d1594af1ffb84f0416219580adce5a9371fabe7d -size 21292 +oid sha256:ad8519086ae725ac7b1aeae9cd628237afeb489c6000c814b4d8e3f644592e58 +size 22278 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-D-0_1_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-D-0_1_null_1,NEXUS_5,1.0,en].png index 135577ac2f..173cc88678 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-D-0_1_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-D-0_1_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:91d1b5d5c58a4f2cbf048ad20b3a9742c209ea19703eafaf6d3e6f542caf2111 -size 40640 +oid sha256:f4cc5cd0ba741aa217ee000749ec4041186c2c83d13f6c87023d16f16689a9ed +size 41359 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-D-0_1_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-D-0_1_null_2,NEXUS_5,1.0,en].png index 8f41e9cece..153b681988 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-D-0_1_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-D-0_1_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fe37eb6328241c70b4219c9fde9118593b1354fe99628e106af828868f9cc4c6 -size 39178 +oid sha256:1ff04ca56c00e2bbf4858bcf6f8faed596e2c538937ec26d61abac7922cda2e1 +size 39890 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-D-0_1_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-D-0_1_null_3,NEXUS_5,1.0,en].png index 8e5282128a..8d2683d552 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-D-0_1_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-D-0_1_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1625b6184c01ab75efcfe4c8d1594af1ffb84f0416219580adce5a9371fabe7d -size 21292 +oid sha256:ad8519086ae725ac7b1aeae9cd628237afeb489c6000c814b4d8e3f644592e58 +size 22278 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-D-0_1_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-D-0_1_null_4,NEXUS_5,1.0,en].png index 6c7b3227a0..95dff5613b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-D-0_1_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-D-0_1_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c94b320a8a6e1bbf2824eaa66d80476a293405b6bd0e7c2c96ce3b016be8f291 -size 21430 +oid sha256:b461bb08151c6efb41b0c4d7a40c33b3710dc5a1d0a32cb707ba90f0ef1ee2d1 +size 22419 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-N-0_2_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-N-0_2_null_0,NEXUS_5,1.0,en].png index 34ad716b56..ba420c0094 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-N-0_2_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-N-0_2_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eba27416d7da08fbd8c47a172f3b54a603c893e1d07faff443417e4949fbc985 -size 19849 +oid sha256:0a59281bb44aea2e220f48f1229afd6b4d2d0551dc0a7dd6e19b7a6ff3984f09 +size 20742 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-N-0_2_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-N-0_2_null_1,NEXUS_5,1.0,en].png index 685b83696c..ed4299da45 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-N-0_2_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-N-0_2_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:40184d796909922b4316ee027e4500fa183d275bc73d7f69e51801e3f956333b -size 37569 +oid sha256:ac124e959b3c2303ecabe6eeba7c4faf7de55929757c0b69ceb4c0021cc1a390 +size 38197 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-N-0_2_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-N-0_2_null_2,NEXUS_5,1.0,en].png index 7d313adf76..29f176bdf8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-N-0_2_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-N-0_2_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5647bd3d7605f49358a4e1a76bf5fa86ab9a3ad32d180a134ea5e5271d8d8093 -size 36026 +oid sha256:7e064103aa27ef0b2765962bb5d21f24387ac215d27691570991a75dd85f8725 +size 36633 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-N-0_2_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-N-0_2_null_3,NEXUS_5,1.0,en].png index 34ad716b56..ba420c0094 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-N-0_2_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-N-0_2_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eba27416d7da08fbd8c47a172f3b54a603c893e1d07faff443417e4949fbc985 -size 19849 +oid sha256:0a59281bb44aea2e220f48f1229afd6b4d2d0551dc0a7dd6e19b7a6ff3984f09 +size 20742 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-N-0_2_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-N-0_2_null_4,NEXUS_5,1.0,en].png index b418af4d4e..4a37a3011c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-N-0_2_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.send_null_SendLocationView-N-0_2_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:434170541079e63b9c606e592407168f8e7e1e695f5f3e188428570ec364e2c6 -size 20047 +oid sha256:5b7db80ee7f9c4a4d74b0665803c1cf85a391b6af0643f7cc823de5e8897ba6e +size 20904 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_0,NEXUS_5,1.0,en].png index fe9329c1ed..f2ece2ce45 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d502b465f6f70ead5b9bc373b443d548053bc1d0867b4cbfb52d84e59fa253f1 -size 11596 +oid sha256:905d574bc64f14e309072a508732281c87dd00f8fa756bbd20b6d59c9b50eee6 +size 12428 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_1,NEXUS_5,1.0,en].png index 5d205c3650..cc035b2513 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:81c29f9bb336e74a97189d8361490a3a29c4f4678d80f62c2e384396cb90a871 -size 32465 +oid sha256:1cb7669bfe98a30d0658c4444f08c11de6b8589a8a81163cb9a83366343c3aea +size 33113 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_2,NEXUS_5,1.0,en].png index 24894be572..b5ee476b1e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:daf1ab743402e503ff6a5d0ec5f7a599b531c23fcbd9767570527828530bf5b3 -size 30817 +oid sha256:520a4053273d7d72a7339fdc609355ffbca183cbf151a24c701b9674e806306d +size 31453 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_3,NEXUS_5,1.0,en].png index fe9329c1ed..f2ece2ce45 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d502b465f6f70ead5b9bc373b443d548053bc1d0867b4cbfb52d84e59fa253f1 -size 11596 +oid sha256:905d574bc64f14e309072a508732281c87dd00f8fa756bbd20b6d59c9b50eee6 +size 12428 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_4,NEXUS_5,1.0,en].png index cdb697c87c..535f1e9742 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:03769782960e9fc1abf6c609a318ca90debb03484d7b8d61d0703ef1374a0b55 -size 11786 +oid sha256:71e4415423627091abedfccd7a03e20afa27fc9f599de70dd82be1571c4131a0 +size 12616 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_5,NEXUS_5,1.0,en].png index 2cad2a5615..7d9397fdf7 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e0c113e7eb9d495ab2fa3d03a945fd6fac35810af2df4571703a8a3f2b55a079 -size 15018 +oid sha256:ca76be1bf0a76e93614c5bca704269932d690f6133f53d09275e2f08d3d27200 +size 15843 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_6,NEXUS_5,1.0,en].png index 36cf496a43..a30c830e66 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:92da6c43ebe2da8ad035e0f03ddd5261491e846212396240aee8287d4f4d9a10 -size 22631 +oid sha256:4d0e5e459ed40f12fa3d2897a53928bc6808903bc8a36938e7954be41eab80b2 +size 23415 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_7,NEXUS_5,1.0,en].png index aa84f464a9..7186047697 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewDark_0_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c23fded123579979a9b6acf41def9a864ff99de6adbf224014c6d77a552fb2fe -size 24754 +oid sha256:adb557b5ccc00a8bbb5b605e372c892f6c0b7d194ed3e6e352f05b975e2e0eab +size 25525 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_0,NEXUS_5,1.0,en].png index a4889e3b27..2c284aec09 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6519ea26cb85aa1cecdab38d9f3cd54f3e986d33a9d411c576714fb070835d6f -size 12503 +oid sha256:c581e4cf30caec4e5039f11091417780ab0decf779ec7b31112a94fec0a596e1 +size 13524 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_1,NEXUS_5,1.0,en].png index 1cae9d483f..09e3c2f716 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1cdb9c379d685e7664c76f4ae7c712665de8dc8ad1f65441121dde4475a92f57 -size 35269 +oid sha256:e82b0029ac4e23aacfde992e36267eec369108d6ef9021138510d4b421017bd3 +size 36033 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_2,NEXUS_5,1.0,en].png index b0da61c4b7..b346f9e4a7 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0c5285cb82229e84a7cf2c1f2ce375060ec4f99577c88a9840b6db3b8d0966cb -size 33736 +oid sha256:9229d55e1a109abacfa82f066a48fa60606a0d0ed0d155634b4c31fb2c7be98c +size 34501 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_3,NEXUS_5,1.0,en].png index a4889e3b27..2c284aec09 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6519ea26cb85aa1cecdab38d9f3cd54f3e986d33a9d411c576714fb070835d6f -size 12503 +oid sha256:c581e4cf30caec4e5039f11091417780ab0decf779ec7b31112a94fec0a596e1 +size 13524 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_4,NEXUS_5,1.0,en].png index cb89527934..60d4ccb3c9 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d33eeef612e03599f835991ad70c5f128c51e0ac49e67fff445b2e98ed3b71ef -size 12706 +oid sha256:9703d279e6401268fd066984d4cc91403c7f8f8e2c248c6ba2ea4c242694170f +size 13729 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_5,NEXUS_5,1.0,en].png index aafeea9a40..ca5503a3e0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b47af4d036f0cf1275773fb8b81d3cae847626b49f5197e2249df1d9d9be2cbb -size 16501 +oid sha256:11a6fd8151812c8733bab26904f53754899db2caeaa0f4f24ea010dd2d54b538 +size 17522 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_6,NEXUS_5,1.0,en].png index c1de14e11e..81bf0e3914 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1aca2f20b99dbbdbd70ca437c06949b634d10c30701f7634cfebaf78593c34d8 -size 25515 +oid sha256:0083578f572e51de0a0464caf90ec68e8a82930b97e0217d20a550ce269f7519 +size 26504 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_7,NEXUS_5,1.0,en].png index 0833282d1f..050b78e680 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.location.impl.show_null_ShowLocationViewLight_0_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f612c17dedc33b8c4089828673dd58d6f1b51faa0c6df3edb1a0f3398c4c55e2 -size 27885 +oid sha256:1a5e11eed79ab3f92c130c3055e70e5cf0df2b22200e8e73e2180c0114ff5b04 +size 28881 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_0,NEXUS_5,1.0,en].png index 40e658fe68..50d588999b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e045c8686effc435e5d31b7ef034d93bca64a226d2e6ebae941afeb36dbad099 -size 35534 +oid sha256:4482b15d928567822dc984a1f19c698f6a9d981d907b70635b3054795292306a +size 36543 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_1,NEXUS_5,1.0,en].png index 8a8da5a453..9ffc58dd11 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a62f8d9a50f7d23bc355dfe98be0bc5eeb2b68866e3035b79b51591eae2f781f -size 58626 +oid sha256:8b22df92cc4ec3e9622f23f6fb7e800e17afbe3a12f9f3d4121b1981ac0350f8 +size 59635 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_2,NEXUS_5,1.0,en].png index 40e658fe68..50d588999b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e045c8686effc435e5d31b7ef034d93bca64a226d2e6ebae941afeb36dbad099 -size 35534 +oid sha256:4482b15d928567822dc984a1f19c698f6a9d981d907b70635b3054795292306a +size 36543 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_3,NEXUS_5,1.0,en].png index 28ec864478..58940cb17b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:76b43763ca93e7bf31e49aa4ba98e9c9cb6d5ee2ab6dba573e69315084884859 -size 37433 +oid sha256:c78072a5ab2e95aaf7abb085db0d66761eb987b22c0e1dcd6da901f3fbe2a3d7 +size 38438 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_4,NEXUS_5,1.0,en].png index a26740c566..98f9563247 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0451e8d5939e9c90ccef22a8384d80e7d83cf8faa8a7df4bcd6032d9f3ef394c -size 36884 +oid sha256:2cbf0a4e9ca5d3471d361890737d5aa9636abe3143f5de9218e0568951d59bf5 +size 37887 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_5,NEXUS_5,1.0,en].png index e7cb3b98e5..3db493ae46 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e9220e4a8dca8924d574e9a5511f25f6c41d14163b58cb4d8f622d7fd8fc71ae -size 37238 +oid sha256:12cac3731fd61b4cbfec09b0f439b2744a5374b6d9ee2b79880507af2224b969 +size 38241 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_0,NEXUS_5,1.0,en].png index 7f84966744..7b757a00fd 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d24c1170affdcae6f189ba2e6646fb61e01f8eed4d83340297f3f189c2f3470 -size 38225 +oid sha256:b03c0240edcc58f64bd1dc7e9ef619081f4019c5825c6e4133f3aab4b7cf9b7a +size 39711 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_1,NEXUS_5,1.0,en].png index 6a5f613b72..b624add247 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1cca9ca327d8a64cb04489cd52c52d3871bd583de9835eb266a1e60db8e53f84 -size 62191 +oid sha256:f2ca4bee47e6beaf4b79c0417dbfe132f6e92974c33484bb0440929a35ada794 +size 63618 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_2,NEXUS_5,1.0,en].png index 7f84966744..7b757a00fd 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d24c1170affdcae6f189ba2e6646fb61e01f8eed4d83340297f3f189c2f3470 -size 38225 +oid sha256:b03c0240edcc58f64bd1dc7e9ef619081f4019c5825c6e4133f3aab4b7cf9b7a +size 39711 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_3,NEXUS_5,1.0,en].png index 7ea53599fb..d046533d4d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fcfec887ae55ce77b049ef49880f1858e7a0a0ea2a7c81140c8c66069a598a14 -size 40265 +oid sha256:19e78d44954b0cde8ea83873f40e6b0a5cf53a02b4bd523e8b8710a483471e32 +size 41698 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_4,NEXUS_5,1.0,en].png index dfc6c1155f..479929ff78 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5716646f8c5d8e9488f79b033ffce5f337133eb78a63328ec616b8eb35d1c70b -size 39534 +oid sha256:6ff479b11d48f3bdf5adc02d466b6427cbf778b2d2184d6e88d7abe8c12043c5 +size 40960 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_5,NEXUS_5,1.0,en].png index d947e91005..7d8cdf7415 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4a8723f12c2884d20c195a779cf6d48a08191f1caa0acdaa2324e478ecac92b2 -size 39898 +oid sha256:1f9e4cc9f63f4414fbe1f82e82b9eca7b5071e26aa057b1137daa75cecccf150 +size 41329 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_FloatingActionButtons_FloatingActionButton_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_FloatingActionButtons_FloatingActionButton_0_null,NEXUS_5,1.0,en].png index 9d9156d829..a09bf2aa83 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_FloatingActionButtons_FloatingActionButton_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_FloatingActionButtons_FloatingActionButton_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e5931cf1a6098e1b3011d81e544b65b6612a603ec3f5fc46de55b73a115ed5f8 -size 9692 +oid sha256:63f00a1f3ec151b25e481f9ac389944d457e08b2c5ed21912dbcdbb2b47a579d +size 11510 From 1dbecaac7975d88b9a8215c9bd25948bfcb71e19 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 7 Sep 2023 17:02:45 +0200 Subject: [PATCH 066/234] Fix typo --- .../element/android/libraries/featureflag/api/FeatureFlags.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt index fc13a8a1cc..c7744f486d 100644 --- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt +++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt @@ -18,7 +18,7 @@ package io.element.android.libraries.featureflag.api /** * To enable or disable a FeatureFlags, change the `defaultValue` value. - * Warning: to enable a flog for the release app, you MUST update the file + * Warning: to enable a flag for the release app, you MUST update the file * [io.element.android.libraries.featureflag.impl.StaticFeatureFlagProvider] */ enum class FeatureFlags( From 6f86fca2c2256630cdade2197572b339cca34112 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 7 Sep 2023 17:03:52 +0200 Subject: [PATCH 067/234] Sync: use the new SyncIndicator api --- .../appnav/loggedin/LoggedInPresenter.kt | 20 +++++-------------- .../matrix/api/roomlist/RoomListService.kt | 10 ++++++++++ .../impl/roomlist/RoomListExtensions.kt | 14 +++++++++++++ .../impl/roomlist/RustRoomListService.kt | 17 ++++++++++++++++ .../test/roomlist/FakeRoomListService.kt | 3 +++ 5 files changed, 49 insertions(+), 15 deletions(-) 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 f2af582c25..49253edc99 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 @@ -19,17 +19,15 @@ package io.element.android.appnav.loggedin import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import io.element.android.features.networkmonitor.api.NetworkMonitor import io.element.android.features.networkmonitor.api.NetworkStatus import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.push.api.PushService -import kotlinx.coroutines.delay import javax.inject.Inject private const val DELAY_BEFORE_SHOWING_SYNC_SPINNER_IN_MILLIS = 1500L @@ -50,19 +48,11 @@ class LoggedInPresenter @Inject constructor( pushService.registerWith(matrixClient, pushProvider, distributor) } - val roomListState by matrixClient.roomListService.state.collectAsState() + val syncIndicator by matrixClient.roomListService.syncIndicator.collectAsState() val networkStatus by networkMonitor.connectivity.collectAsState() - var showSyncSpinner by remember { - mutableStateOf(false) - } - LaunchedEffect(roomListState, networkStatus) { - showSyncSpinner = when { - networkStatus == NetworkStatus.Offline -> false - roomListState == RoomListService.State.Running -> false - else -> { - delay(DELAY_BEFORE_SHOWING_SYNC_SPINNER_IN_MILLIS) - true - } + val showSyncSpinner by remember { + derivedStateOf { + networkStatus == NetworkStatus.Online && syncIndicator == RoomListService.SyncIndicator.Show } } return LoggedInState( diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt index 9ae6c22e7d..de7f1f3918 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt @@ -32,6 +32,11 @@ interface RoomListService { data object Terminated : State() } + sealed class SyncIndicator { + data object Show : SyncIndicator() + data object Hide : SyncIndicator() + } + /** * returns a [RoomList] object of all rooms we want to display. * This will exclude some rooms like the invites, or spaces. @@ -49,6 +54,11 @@ interface RoomListService { */ fun updateAllRoomsVisibleRange(range: IntRange) + /** + * The sync indicator as a flow. + */ + val syncIndicator: StateFlow + /** * The state of the service as a flow. */ diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListExtensions.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListExtensions.kt index 8d96990a9e..ea932be896 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListExtensions.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListExtensions.kt @@ -33,6 +33,8 @@ import org.matrix.rustcomponents.sdk.RoomListLoadingStateListener import org.matrix.rustcomponents.sdk.RoomListService import org.matrix.rustcomponents.sdk.RoomListServiceState import org.matrix.rustcomponents.sdk.RoomListServiceStateListener +import org.matrix.rustcomponents.sdk.RoomListServiceSyncIndicator +import org.matrix.rustcomponents.sdk.RoomListServiceSyncIndicatorListener import timber.log.Timber fun RoomList.loadingStateFlow(): Flow = @@ -83,6 +85,18 @@ fun RoomListService.stateFlow(): Flow = } }.buffer(Channel.UNLIMITED) +fun RoomListService.syncIndicator(): Flow = + mxCallbackFlow { + val listener = object : RoomListServiceSyncIndicatorListener { + override fun onUpdate(indicator: RoomListServiceSyncIndicator) { + trySendBlocking(indicator) + } + } + tryOrNull { + syncIndicator(listener) + } + }.buffer(Channel.UNLIMITED) + fun RoomListService.roomOrNull(roomId: String): RoomListItem? { return try { room(roomId) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt index 655c634502..0a828affd4 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt @@ -38,6 +38,7 @@ import org.matrix.rustcomponents.sdk.RoomListInput import org.matrix.rustcomponents.sdk.RoomListLoadingState import org.matrix.rustcomponents.sdk.RoomListRange import org.matrix.rustcomponents.sdk.RoomListServiceState +import org.matrix.rustcomponents.sdk.RoomListServiceSyncIndicator import timber.log.Timber import org.matrix.rustcomponents.sdk.RoomListService as InnerRustRoomListService @@ -106,6 +107,15 @@ class RustRoomListService( } } + override val syncIndicator: StateFlow = + innerRoomListService.syncIndicator() + .map { it.toSyncIndicator() } + .onEach { syncIndicator -> + Timber.d("SyncIndicator = $syncIndicator") + } + .distinctUntilChanged() + .stateIn(sessionCoroutineScope, SharingStarted.Eagerly, RoomListService.SyncIndicator.Hide) + override val state: StateFlow = innerRoomListService.stateFlow() .map { it.toRoomListState() } @@ -134,6 +144,13 @@ private fun RoomListServiceState.toRoomListState(): RoomListService.State { } } +private fun RoomListServiceSyncIndicator.toSyncIndicator(): RoomListService.SyncIndicator { + return when (this) { + RoomListServiceSyncIndicator.SHOW -> RoomListService.SyncIndicator.Show + RoomListServiceSyncIndicator.HIDE -> RoomListService.SyncIndicator.Hide + } +} + private fun org.matrix.rustcomponents.sdk.RoomList.observeEntriesWithProcessor(processor: RoomSummaryListProcessor): Flow> { return entriesFlow { roomListEntries -> processor.postEntries(roomListEntries) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/FakeRoomListService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/FakeRoomListService.kt index fa2e347e3b..7e0f3e8891 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/FakeRoomListService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/FakeRoomListService.kt @@ -29,6 +29,7 @@ class FakeRoomListService : RoomListService { private val allRoomsLoadingStateFlow = MutableStateFlow(RoomList.LoadingState.NotLoaded) private val inviteRoomsLoadingStateFlow = MutableStateFlow(RoomList.LoadingState.NotLoaded) private val roomListStateFlow = MutableStateFlow(RoomListService.State.Idle) + private val syncIndicatorStateFlow = MutableStateFlow(RoomListService.SyncIndicator.Hide) suspend fun postAllRooms(roomSummaries: List) { allRoomSummariesFlow.emit(roomSummaries) @@ -72,4 +73,6 @@ class FakeRoomListService : RoomListService { } override val state: StateFlow = roomListStateFlow + + override val syncIndicator: StateFlow = syncIndicatorStateFlow } From f214493c9da729145a60767124ac3ca7360eadef Mon Sep 17 00:00:00 2001 From: jonnyandrew Date: Thu, 7 Sep 2023 16:21:29 +0100 Subject: [PATCH 068/234] [Rich text editor] Integrate rich text editor library (#1172) * Integrate rich text editor * Also increase swapfile size in test CI Fixes issue where screenshot tests are terminated due to lack of CI resources. See https://github.com/actions/runner-images/discussions/7188#discussioncomment-6750749 --------- Co-authored-by: ElementBot --- .github/workflows/tests.yml | 10 + changelog.d/1172.feature | 2 + features/messages/api/build.gradle.kts | 2 +- features/messages/impl/build.gradle.kts | 3 +- .../messages/impl/MessagesPresenter.kt | 6 +- .../messages/impl/MessagesStateProvider.kt | 5 +- .../impl/actionlist/ActionListPresenter.kt | 2 +- .../messagecomposer/MessageComposerEvents.kt | 6 +- .../MessageComposerPresenter.kt | 43 ++-- .../messagecomposer/MessageComposerState.kt | 9 +- .../MessageComposerStateProvider.kt | 8 +- .../messagecomposer/MessageComposerView.kt | 19 +- .../RichTextEditorStateFactory.kt | 38 ++++ .../impl/timeline/TimelinePresenter.kt | 5 +- .../customreaction/CustomReactionPresenter.kt | 2 +- .../ReactionSummaryPresenter.kt | 2 +- .../retrysendmenu/RetrySendMenuPresenter.kt | 2 +- .../event/TimelineItemTextBasedContent.kt | 2 + .../messages/MessagesPresenterTest.kt | 11 +- .../MessageComposerPresenterTest.kt | 124 ++++++----- .../TestRichTextEditorStateFactory.kt | 29 +++ gradle/libs.versions.toml | 3 + .../libraries/matrix/api/room/MatrixRoom.kt | 6 +- .../matrix/impl/room/RustMatrixRoom.kt | 31 +-- .../matrix/test/room/FakeMatrixRoom.kt | 14 +- .../impl/DefaultPermissionsPresenter.kt | 2 +- .../textcomposer/{ => impl}/build.gradle.kts | 6 +- .../android/libraries/textcomposer/Message.kt | 22 ++ .../textcomposer/MessageComposerMode.kt | 0 .../libraries/textcomposer/TextComposer.kt | 210 ++++++++---------- .../main/res/drawable/ic_add_attachment.xml | 0 .../src/main/res/drawable/ic_send.xml | 0 .../src/main/res/drawable/ic_tick.xml | 0 .../src/main/res/values-cs/translations.xml | 0 .../src/main/res/values-de/translations.xml | 0 .../src/main/res/values-ro/translations.xml | 0 .../src/main/res/values-ru/translations.xml | 0 .../src/main/res/values-sk/translations.xml | 0 .../main/res/values-zh-rTW/translations.xml | 0 .../src/main/res/values/localazy.xml | 0 libraries/textcomposer/test/build.gradle.kts | 28 +++ .../kotlin/extension/DependencyHandleScope.kt | 2 +- .../analytics/test/FakeAnalyticsService.kt | 2 + ...poserViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...oserViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...sagesViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...sagesViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 +- ...sagesViewDark_0_null_2,NEXUS_5,1.0,en].png | 4 +- ...sagesViewDark_0_null_4,NEXUS_5,1.0,en].png | 4 +- ...sagesViewDark_0_null_5,NEXUS_5,1.0,en].png | 4 +- ...agesViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...agesViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 +- ...agesViewLight_0_null_2,NEXUS_5,1.0,en].png | 4 +- ...agesViewLight_0_null_4,NEXUS_5,1.0,en].png | 4 +- ...agesViewLight_0_null_5,NEXUS_5,1.0,en].png | 4 +- ...omposerEdit-D-1_2_null,NEXUS_5,1.0,en].png | 4 +- ...omposerEdit-N-1_3_null,NEXUS_5,1.0,en].png | 4 +- ...mposerReply-D-2_3_null,NEXUS_5,1.0,en].png | 4 +- ...mposerReply-N-2_4_null,NEXUS_5,1.0,en].png | 4 +- ...poserSimple-D-0_1_null,NEXUS_5,1.0,en].png | 4 +- ...poserSimple-N-0_2_null,NEXUS_5,1.0,en].png | 4 +- tools/localazy/config.json | 2 +- 62 files changed, 441 insertions(+), 289 deletions(-) create mode 100644 changelog.d/1172.feature create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/RichTextEditorStateFactory.kt create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/TestRichTextEditorStateFactory.kt rename libraries/textcomposer/{ => impl}/build.gradle.kts (89%) create mode 100644 libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/Message.kt rename libraries/textcomposer/{ => impl}/src/main/kotlin/io/element/android/libraries/textcomposer/MessageComposerMode.kt (100%) rename libraries/textcomposer/{ => impl}/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt (74%) rename libraries/textcomposer/{ => impl}/src/main/res/drawable/ic_add_attachment.xml (100%) rename libraries/textcomposer/{ => impl}/src/main/res/drawable/ic_send.xml (100%) rename libraries/textcomposer/{ => impl}/src/main/res/drawable/ic_tick.xml (100%) rename libraries/textcomposer/{ => impl}/src/main/res/values-cs/translations.xml (100%) rename libraries/textcomposer/{ => impl}/src/main/res/values-de/translations.xml (100%) rename libraries/textcomposer/{ => impl}/src/main/res/values-ro/translations.xml (100%) rename libraries/textcomposer/{ => impl}/src/main/res/values-ru/translations.xml (100%) rename libraries/textcomposer/{ => impl}/src/main/res/values-sk/translations.xml (100%) rename libraries/textcomposer/{ => impl}/src/main/res/values-zh-rTW/translations.xml (100%) rename libraries/textcomposer/{ => impl}/src/main/res/values/localazy.xml (100%) create mode 100644 libraries/textcomposer/test/build.gradle.kts diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 460e57b4e3..f662e5352d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -22,6 +22,16 @@ jobs: group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-{0}', github.sha) || format('unit-tests-{0}', github.ref) }} cancel-in-progress: true steps: + # Increase swapfile size to prevent screenshot tests getting terminated + # https://github.com/actions/runner-images/discussions/7188#discussioncomment-6750749 + - name: 💽 Increase swapfile size + run: | + sudo swapoff -a + sudo fallocate -l 8G /mnt/swapfile + sudo chmod 600 /mnt/swapfile + sudo mkswap /mnt/swapfile + sudo swapon /mnt/swapfile + sudo swapon --show - name: ⏬ Checkout with LFS uses: nschloe/action-cached-lfs-checkout@v1.2.2 with: diff --git a/changelog.d/1172.feature b/changelog.d/1172.feature new file mode 100644 index 0000000000..ea03101f0c --- /dev/null +++ b/changelog.d/1172.feature @@ -0,0 +1,2 @@ +[Rich text editor] Integrate rich text editor library. Note that markdown is now not supported and further formatting support will be introduced through the rich text editor. + diff --git a/features/messages/api/build.gradle.kts b/features/messages/api/build.gradle.kts index 756014e97d..9e890265ec 100644 --- a/features/messages/api/build.gradle.kts +++ b/features/messages/api/build.gradle.kts @@ -25,5 +25,5 @@ android { dependencies { implementation(projects.libraries.architecture) implementation(projects.libraries.matrix.api) - api(projects.libraries.textcomposer) + api(projects.libraries.textcomposer.impl) } diff --git a/features/messages/impl/build.gradle.kts b/features/messages/impl/build.gradle.kts index 1a61a2d8b6..00d65eba6a 100644 --- a/features/messages/impl/build.gradle.kts +++ b/features/messages/impl/build.gradle.kts @@ -41,7 +41,7 @@ dependencies { implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrixui) implementation(projects.libraries.designsystem) - implementation(projects.libraries.textcomposer) + implementation(projects.libraries.textcomposer.impl) implementation(projects.libraries.uiStrings) implementation(projects.libraries.dateformatter.api) implementation(projects.libraries.eventformatter.api) @@ -76,6 +76,7 @@ dependencies { testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.mediaupload.test) testImplementation(projects.libraries.mediapickers.test) + testImplementation(projects.libraries.textcomposer.test) testImplementation(libs.test.mockk) ksp(libs.showkase.processor) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index dc6f3304b1..b0ff403984 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -175,7 +175,7 @@ class MessagesPresenter @AssistedInject constructor( snackbarMessage = snackbarMessage, showReinvitePrompt = showReinvitePrompt, inviteProgress = inviteProgress.value, - eventSink = ::handleEvents + eventSink = { handleEvents(it) } ) } @@ -250,7 +250,9 @@ class MessagesPresenter @AssistedInject constructor( private fun handleActionEdit(targetEvent: TimelineItem.Event, composerState: MessageComposerState) { val composerMode = MessageComposerMode.Edit( targetEvent.eventId, - (targetEvent.content as? TimelineItemTextBasedContent)?.body.orEmpty(), + (targetEvent.content as? TimelineItemTextBasedContent)?.let { + it.htmlBody ?: it.body + }.orEmpty(), targetEvent.transactionId, ) composerState.eventSink( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt index 7eb1a0984e..6ca799dc84 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt @@ -30,6 +30,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.textcomposer.MessageComposerMode +import io.element.android.wysiwyg.compose.RichTextEditorState import kotlinx.collections.immutable.persistentSetOf open class MessagesStateProvider : PreviewParameterProvider { @@ -54,7 +55,9 @@ fun aMessagesState() = MessagesState( userHasPermissionToSendMessage = true, userHasPermissionToRedact = false, composerState = aMessageComposerState().copy( - text = "Hello", + richTextEditorState = RichTextEditorState("Hello", fake = true).apply { + requestFocus() + }, isFullScreen = false, mode = MessageComposerMode.Normal("Hello"), ), diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt index f5e28818c9..d0fa46175a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt @@ -70,7 +70,7 @@ class ActionListPresenter @Inject constructor( return ActionListState( target = target.value, displayEmojiReactions = displayEmojiReactions, - eventSink = ::handleEvents + eventSink = { handleEvents(it) } ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerEvents.kt index d99eb3c158..4bfd290a77 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerEvents.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerEvents.kt @@ -17,16 +17,15 @@ package io.element.android.features.messages.impl.messagecomposer import androidx.compose.runtime.Immutable +import io.element.android.libraries.textcomposer.Message import io.element.android.libraries.textcomposer.MessageComposerMode @Immutable sealed interface MessageComposerEvents { data object ToggleFullScreenState : MessageComposerEvents - data class FocusChanged(val hasFocus: Boolean) : MessageComposerEvents - data class SendMessage(val message: String) : MessageComposerEvents + data class SendMessage(val message: Message) : MessageComposerEvents data object CloseSpecialMode : MessageComposerEvents data class SetMode(val composerMode: MessageComposerMode) : MessageComposerEvents - data class UpdateText(val text: String) : MessageComposerEvents data object AddAttachment : MessageComposerEvents data object DismissAttachmentMenu : MessageComposerEvents sealed interface PickAttachmentSource : MessageComposerEvents { @@ -38,4 +37,5 @@ sealed interface MessageComposerEvents { data object Poll : PickAttachmentSource } data object CancelSendAttachment : MessageComposerEvents + data class Error(val error: Throwable) : MessageComposerEvents } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt index cc735dc008..687e951933 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt @@ -44,8 +44,10 @@ import io.element.android.libraries.matrix.api.core.ProgressCallback import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.mediapickers.api.PickerProvider import io.element.android.libraries.mediaupload.api.MediaSender +import io.element.android.libraries.textcomposer.Message import io.element.android.libraries.textcomposer.MessageComposerMode import io.element.android.services.analytics.api.AnalyticsService +import io.element.android.wysiwyg.compose.RichTextEditorState import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope @@ -67,6 +69,7 @@ class MessageComposerPresenter @Inject constructor( private val snackbarDispatcher: SnackbarDispatcher, private val analyticsService: AnalyticsService, private val messageComposerContext: MessageComposerContextImpl, + private val richTextEditorStateFactory: RichTextEditorStateFactory, ) : Presenter { @SuppressLint("UnsafeOptInUsageError") @@ -103,19 +106,15 @@ class MessageComposerPresenter @Inject constructor( val isFullScreen = rememberSaveable { mutableStateOf(false) } - val hasFocus = remember { - mutableStateOf(false) - } - val text: MutableState = rememberSaveable { - mutableStateOf("") - } + val richTextEditorState = richTextEditorStateFactory.create() val ongoingSendAttachmentJob = remember { mutableStateOf(null) } var showAttachmentSourcePicker: Boolean by remember { mutableStateOf(false) } LaunchedEffect(messageComposerContext.composerMode) { when (val modeValue = messageComposerContext.composerMode) { - is MessageComposerMode.Edit -> text.value = modeValue.defaultContent + is MessageComposerMode.Edit -> + richTextEditorState.setHtml(modeValue.defaultContent) else -> Unit } } @@ -136,18 +135,15 @@ class MessageComposerPresenter @Inject constructor( when (event) { MessageComposerEvents.ToggleFullScreenState -> isFullScreen.value = !isFullScreen.value - is MessageComposerEvents.FocusChanged -> hasFocus.value = event.hasFocus - - is MessageComposerEvents.UpdateText -> text.value = event.text MessageComposerEvents.CloseSpecialMode -> { - text.value = "" + richTextEditorState.setHtml("") messageComposerContext.composerMode = MessageComposerMode.Normal("") } is MessageComposerEvents.SendMessage -> appCoroutineScope.sendMessage( - text = event.message, + message = event.message, updateComposerMode = { messageComposerContext.composerMode = it }, - textState = text + richTextEditorState = richTextEditorState, ) is MessageComposerEvents.SetMode -> { messageComposerContext.composerMode = event.composerMode @@ -194,43 +190,46 @@ class MessageComposerPresenter @Inject constructor( ongoingSendAttachmentJob.value == null } } + is MessageComposerEvents.Error -> { + analyticsService.trackError(event.error) + } } } return MessageComposerState( - text = text.value, + richTextEditorState = richTextEditorState, isFullScreen = isFullScreen.value, - hasFocus = hasFocus.value, mode = messageComposerContext.composerMode, showAttachmentSourcePicker = showAttachmentSourcePicker, canShareLocation = canShareLocation.value, canCreatePoll = canCreatePoll.value, attachmentsState = attachmentsState.value, - eventSink = ::handleEvents + eventSink = { handleEvents(it) } ) } private fun CoroutineScope.sendMessage( - text: String, + message: Message, updateComposerMode: (newComposerMode: MessageComposerMode) -> Unit, - textState: MutableState + richTextEditorState: RichTextEditorState, ) = launch { val capturedMode = messageComposerContext.composerMode // Reset composer right away - textState.value = "" + richTextEditorState.setHtml("") updateComposerMode(MessageComposerMode.Normal("")) when (capturedMode) { - is MessageComposerMode.Normal -> room.sendMessage(text) + is MessageComposerMode.Normal -> room.sendMessage(body = message.markdown, htmlBody = message.html) is MessageComposerMode.Edit -> { val eventId = capturedMode.eventId val transactionId = capturedMode.transactionId - room.editMessage(eventId, transactionId, text) + room.editMessage(eventId, transactionId, message.markdown, message.html) } is MessageComposerMode.Quote -> TODO() is MessageComposerMode.Reply -> room.replyMessage( capturedMode.eventId, - text + message.markdown, + message.html, ) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt index dbbc62ca47..bdff621521 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt @@ -19,21 +19,22 @@ package io.element.android.features.messages.impl.messagecomposer import androidx.compose.runtime.Immutable import io.element.android.features.messages.impl.attachments.Attachment import io.element.android.libraries.textcomposer.MessageComposerMode +import io.element.android.wysiwyg.compose.RichTextEditorState import kotlinx.collections.immutable.ImmutableList @Immutable data class MessageComposerState( - val text: String?, + val richTextEditorState: RichTextEditorState, val isFullScreen: Boolean, - val hasFocus: Boolean, val mode: MessageComposerMode, val showAttachmentSourcePicker: Boolean, val canShareLocation: Boolean, val canCreatePoll: Boolean, val attachmentsState: AttachmentsState, - val eventSink: (MessageComposerEvents) -> Unit + val eventSink: (MessageComposerEvents) -> Unit, ) { - val isSendButtonVisible: Boolean = text.isNullOrEmpty().not() + val canSendMessage: Boolean = richTextEditorState.messageHtml.isNotEmpty() + val hasFocus: Boolean = richTextEditorState.hasFocus } @Immutable diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt index 2217b574b4..ab15d8ccd8 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt @@ -18,6 +18,7 @@ package io.element.android.features.messages.impl.messagecomposer import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.textcomposer.MessageComposerMode +import io.element.android.wysiwyg.compose.RichTextEditorState open class MessageComposerStateProvider : PreviewParameterProvider { override val values: Sequence @@ -27,18 +28,17 @@ open class MessageComposerStateProvider : PreviewParameterProvider(null) } val timelineItems by timelineItemsFactory.collectItemsAsState() @@ -119,7 +120,7 @@ class TimelinePresenter @Inject constructor( paginationState = paginationState, timelineItems = timelineItems, hasNewItems = hasNewItems.value, - eventSink = ::handleEvents + eventSink = { handleEvents(it) } ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt index b048383b1f..8bbd6cbff7 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt @@ -63,7 +63,7 @@ class CustomReactionPresenter @Inject constructor( return CustomReactionState( target = target.value, selectedEmoji = selectedEmoji, - eventSink = ::handleEvents + eventSink = { handleEvents(it) } ) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenter.kt index 456ac5f548..e75e49c1e3 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryPresenter.kt @@ -61,7 +61,7 @@ class ReactionSummaryPresenter @Inject constructor( } return ReactionSummaryState( target = targetWithAvatars.value, - eventSink = ::handleEvents + eventSink = { handleEvents(it) } ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMenuPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMenuPresenter.kt index 237dc5683d..c9ebd9be8c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMenuPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMenuPresenter.kt @@ -66,7 +66,7 @@ class RetrySendMenuPresenter @Inject constructor( return RetrySendMenuState( selectedEvent = selectedEvent, - eventSink = ::handleEvent, + eventSink = { handleEvent(it) }, ) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemTextBasedContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemTextBasedContent.kt index ec6ee16675..10fca53261 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemTextBasedContent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemTextBasedContent.kt @@ -22,4 +22,6 @@ sealed interface TimelineItemTextBasedContent : TimelineItemEventContent { val body: String val htmlDocument: Document? val isEdited: Boolean + val htmlBody: String? + get() = htmlDocument?.body()?.html() } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt index 48a8480915..ed7c4a8064 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt @@ -30,7 +30,6 @@ import io.element.android.features.messages.impl.actionlist.ActionListPresenter import io.element.android.features.messages.impl.actionlist.ActionListState import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.messagecomposer.MessageComposerContextImpl -import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents import io.element.android.features.messages.impl.messagecomposer.MessageComposerPresenter import io.element.android.features.messages.impl.timeline.TimelinePresenter import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionPresenter @@ -41,6 +40,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent import io.element.android.features.messages.media.FakeLocalMediaFactory +import io.element.android.features.messages.textcomposer.TestRichTextEditorStateFactory import io.element.android.features.messages.timeline.components.customreaction.FakeEmojibaseProvider import io.element.android.features.messages.utils.messagesummary.FakeMessageSummaryFormatter import io.element.android.features.networkmonitor.test.FakeNetworkMonitor @@ -325,6 +325,7 @@ class MessagesPresenterTest { initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Redact, aMessageEvent())) assertThat(matrixRoom.redactEventEventIdParam).isEqualTo(AN_EVENT_ID) assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None) + skipItems(1) // back paginating } } @@ -381,7 +382,7 @@ class MessagesPresenterTest { // Initially the composer doesn't have focus, so we don't show the alert assertThat(initialState.showReinvitePrompt).isFalse() // When the input field is focused we show the alert - initialState.composerState.eventSink(MessageComposerEvents.FocusChanged(true)) + initialState.composerState.richTextEditorState.requestFocus() val focusedState = consumeItemsUntilPredicate(timeout = 250.milliseconds) { state -> state.showReinvitePrompt }.last() @@ -405,7 +406,7 @@ class MessagesPresenterTest { skipItems(1) val initialState = awaitItem() assertThat(initialState.showReinvitePrompt).isFalse() - initialState.composerState.eventSink(MessageComposerEvents.FocusChanged(true)) + initialState.composerState.richTextEditorState.requestFocus() val focusedState = awaitItem() assertThat(focusedState.showReinvitePrompt).isFalse() } @@ -421,7 +422,7 @@ class MessagesPresenterTest { skipItems(1) val initialState = awaitItem() assertThat(initialState.showReinvitePrompt).isFalse() - initialState.composerState.eventSink(MessageComposerEvents.FocusChanged(true)) + initialState.composerState.richTextEditorState.requestFocus() val focusedState = awaitItem() assertThat(focusedState.showReinvitePrompt).isFalse() } @@ -605,6 +606,8 @@ class MessagesPresenterTest { snackbarDispatcher = SnackbarDispatcher(), analyticsService = FakeAnalyticsService(), messageComposerContext = MessageComposerContextImpl(), + richTextEditorStateFactory = TestRichTextEditorStateFactory(), + ) val timelinePresenter = TimelinePresenter( timelineItemsFactory = aTimelineItemsFactory(), diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt index d89a0392ad..7284fb3b7e 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt @@ -53,6 +53,7 @@ import io.element.android.libraries.mediaupload.api.MediaPreProcessor import io.element.android.libraries.mediaupload.api.MediaSender import io.element.android.libraries.mediaupload.api.MediaUploadInfo import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor +import io.element.android.libraries.textcomposer.Message import io.element.android.libraries.textcomposer.MessageComposerMode import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.WarmUpRule @@ -80,6 +81,7 @@ class MessageComposerPresenterTest { private val snackbarDispatcher = SnackbarDispatcher() private val mockMediaUrl: Uri = mockk("localMediaUri") private val localMediaFactory = FakeLocalMediaFactory(mockMediaUrl) + private val analyticsService = FakeAnalyticsService() @Test fun `present - initial state`() = runTest { @@ -90,12 +92,12 @@ class MessageComposerPresenterTest { skipItems(1) val initialState = awaitItem() assertThat(initialState.isFullScreen).isFalse() - assertThat(initialState.text).isEqualTo("") + assertThat(initialState.richTextEditorState.messageHtml).isEqualTo("") assertThat(initialState.mode).isEqualTo(MessageComposerMode.Normal("")) assertThat(initialState.showAttachmentSourcePicker).isFalse() assertThat(initialState.canShareLocation).isTrue() assertThat(initialState.attachmentsState).isEqualTo(AttachmentsState.None) - assertThat(initialState.isSendButtonVisible).isFalse() + assertThat(initialState.canSendMessage).isFalse() } } @@ -124,14 +126,14 @@ class MessageComposerPresenterTest { }.test { skipItems(1) val initialState = awaitItem() - initialState.eventSink.invoke(MessageComposerEvents.UpdateText(A_MESSAGE)) + initialState.richTextEditorState.setHtml(A_MESSAGE) val withMessageState = awaitItem() - assertThat(withMessageState.text).isEqualTo(A_MESSAGE) - assertThat(withMessageState.isSendButtonVisible).isTrue() - withMessageState.eventSink.invoke(MessageComposerEvents.UpdateText("")) + assertThat(withMessageState.richTextEditorState.messageHtml).isEqualTo(A_MESSAGE) + assertThat(withMessageState.canSendMessage).isTrue() + withMessageState.richTextEditorState.setHtml("") val withEmptyMessageState = awaitItem() - assertThat(withEmptyMessageState.text).isEqualTo("") - assertThat(withEmptyMessageState.isSendButtonVisible).isFalse() + assertThat(withEmptyMessageState.richTextEditorState.messageHtml).isEqualTo("") + assertThat(withEmptyMessageState.canSendMessage).isFalse() } } @@ -148,8 +150,8 @@ class MessageComposerPresenterTest { state = awaitItem() assertThat(state.mode).isEqualTo(mode) state = awaitItem() - assertThat(state.text).isEqualTo(A_MESSAGE) - assertThat(state.isSendButtonVisible).isTrue() + assertThat(state.richTextEditorState.messageHtml).isEqualTo(A_MESSAGE) + assertThat(state.canSendMessage).isTrue() backToNormalMode(state, skipCount = 1) } } @@ -166,8 +168,8 @@ class MessageComposerPresenterTest { state.eventSink.invoke(MessageComposerEvents.SetMode(mode)) state = awaitItem() assertThat(state.mode).isEqualTo(mode) - assertThat(state.text).isEqualTo("") - assertThat(state.isSendButtonVisible).isFalse() + assertThat(state.richTextEditorState.messageHtml).isEqualTo("") + assertThat(state.canSendMessage).isFalse() backToNormalMode(state) } } @@ -184,8 +186,8 @@ class MessageComposerPresenterTest { state.eventSink.invoke(MessageComposerEvents.SetMode(mode)) state = awaitItem() assertThat(state.mode).isEqualTo(mode) - assertThat(state.text).isEqualTo("") - assertThat(state.isSendButtonVisible).isFalse() + assertThat(state.richTextEditorState.messageHtml).isEqualTo("") + assertThat(state.canSendMessage).isFalse() backToNormalMode(state) } } @@ -198,14 +200,14 @@ class MessageComposerPresenterTest { }.test { skipItems(1) val initialState = awaitItem() - initialState.eventSink.invoke(MessageComposerEvents.UpdateText(A_MESSAGE)) + initialState.richTextEditorState.setHtml(A_MESSAGE) val withMessageState = awaitItem() - assertThat(withMessageState.text).isEqualTo(A_MESSAGE) - assertThat(withMessageState.isSendButtonVisible).isTrue() - withMessageState.eventSink.invoke(MessageComposerEvents.SendMessage(A_MESSAGE)) + assertThat(withMessageState.richTextEditorState.messageHtml).isEqualTo(A_MESSAGE) + assertThat(withMessageState.canSendMessage).isTrue() + withMessageState.eventSink.invoke(MessageComposerEvents.SendMessage(A_MESSAGE.toMessage())) val messageSentState = awaitItem() - assertThat(messageSentState.text).isEqualTo("") - assertThat(messageSentState.isSendButtonVisible).isFalse() + assertThat(messageSentState.richTextEditorState.messageHtml).isEqualTo("") + assertThat(messageSentState.canSendMessage).isFalse() } } @@ -221,23 +223,23 @@ class MessageComposerPresenterTest { }.test { skipItems(1) val initialState = awaitItem() - assertThat(initialState.text).isEqualTo("") + assertThat(initialState.richTextEditorState.messageHtml).isEqualTo("") val mode = anEditMode() initialState.eventSink.invoke(MessageComposerEvents.SetMode(mode)) skipItems(1) val withMessageState = awaitItem() assertThat(withMessageState.mode).isEqualTo(mode) - assertThat(withMessageState.text).isEqualTo(A_MESSAGE) - assertThat(withMessageState.isSendButtonVisible).isTrue() - withMessageState.eventSink.invoke(MessageComposerEvents.UpdateText(ANOTHER_MESSAGE)) + assertThat(withMessageState.richTextEditorState.messageHtml).isEqualTo(A_MESSAGE) + assertThat(withMessageState.canSendMessage).isTrue() + withMessageState.richTextEditorState.setHtml(ANOTHER_MESSAGE) val withEditedMessageState = awaitItem() - assertThat(withEditedMessageState.text).isEqualTo(ANOTHER_MESSAGE) - withEditedMessageState.eventSink.invoke(MessageComposerEvents.SendMessage(ANOTHER_MESSAGE)) + assertThat(withEditedMessageState.richTextEditorState.messageHtml).isEqualTo(ANOTHER_MESSAGE) + withEditedMessageState.eventSink.invoke(MessageComposerEvents.SendMessage(ANOTHER_MESSAGE.toMessage())) skipItems(1) val messageSentState = awaitItem() - assertThat(messageSentState.text).isEqualTo("") - assertThat(messageSentState.isSendButtonVisible).isFalse() - assertThat(fakeMatrixRoom.editMessageCalls.first()).isEqualTo(ANOTHER_MESSAGE) + assertThat(messageSentState.richTextEditorState.messageHtml).isEqualTo("") + assertThat(messageSentState.canSendMessage).isFalse() + assertThat(fakeMatrixRoom.editMessageCalls.first()).isEqualTo(ANOTHER_MESSAGE to ANOTHER_MESSAGE) } } @@ -253,23 +255,23 @@ class MessageComposerPresenterTest { }.test { skipItems(1) val initialState = awaitItem() - assertThat(initialState.text).isEqualTo("") + assertThat(initialState.richTextEditorState.messageHtml).isEqualTo("") val mode = anEditMode(eventId = null, transactionId = A_TRANSACTION_ID) initialState.eventSink.invoke(MessageComposerEvents.SetMode(mode)) skipItems(1) val withMessageState = awaitItem() assertThat(withMessageState.mode).isEqualTo(mode) - assertThat(withMessageState.text).isEqualTo(A_MESSAGE) - assertThat(withMessageState.isSendButtonVisible).isTrue() - withMessageState.eventSink.invoke(MessageComposerEvents.UpdateText(ANOTHER_MESSAGE)) + assertThat(withMessageState.richTextEditorState.messageHtml).isEqualTo(A_MESSAGE) + assertThat(withMessageState.canSendMessage).isTrue() + withMessageState.richTextEditorState.setHtml(ANOTHER_MESSAGE) val withEditedMessageState = awaitItem() - assertThat(withEditedMessageState.text).isEqualTo(ANOTHER_MESSAGE) - withEditedMessageState.eventSink.invoke(MessageComposerEvents.SendMessage(ANOTHER_MESSAGE)) + assertThat(withEditedMessageState.richTextEditorState.messageHtml).isEqualTo(ANOTHER_MESSAGE) + withEditedMessageState.eventSink.invoke(MessageComposerEvents.SendMessage(ANOTHER_MESSAGE.toMessage())) skipItems(1) val messageSentState = awaitItem() - assertThat(messageSentState.text).isEqualTo("") - assertThat(messageSentState.isSendButtonVisible).isFalse() - assertThat(fakeMatrixRoom.editMessageCalls.first()).isEqualTo(ANOTHER_MESSAGE) + assertThat(messageSentState.richTextEditorState.messageHtml).isEqualTo("") + assertThat(messageSentState.canSendMessage).isFalse() + assertThat(fakeMatrixRoom.editMessageCalls.first()).isEqualTo(ANOTHER_MESSAGE to ANOTHER_MESSAGE) } } @@ -285,23 +287,23 @@ class MessageComposerPresenterTest { }.test { skipItems(1) val initialState = awaitItem() - assertThat(initialState.text).isEqualTo("") + assertThat(initialState.richTextEditorState.messageHtml).isEqualTo("") val mode = aReplyMode() initialState.eventSink.invoke(MessageComposerEvents.SetMode(mode)) val state = awaitItem() assertThat(state.mode).isEqualTo(mode) - assertThat(state.text).isEqualTo("") - assertThat(state.isSendButtonVisible).isFalse() - initialState.eventSink.invoke(MessageComposerEvents.UpdateText(A_REPLY)) + assertThat(state.richTextEditorState.messageHtml).isEqualTo("") + assertThat(state.canSendMessage).isFalse() + state.richTextEditorState.setHtml(A_REPLY) val withMessageState = awaitItem() - assertThat(withMessageState.text).isEqualTo(A_REPLY) - assertThat(withMessageState.isSendButtonVisible).isTrue() - withMessageState.eventSink.invoke(MessageComposerEvents.SendMessage(A_REPLY)) + assertThat(withMessageState.richTextEditorState.messageHtml).isEqualTo(A_REPLY) + assertThat(withMessageState.canSendMessage).isTrue() + withMessageState.eventSink.invoke(MessageComposerEvents.SendMessage(A_REPLY.toMessage())) skipItems(1) val messageSentState = awaitItem() - assertThat(messageSentState.text).isEqualTo("") - assertThat(messageSentState.isSendButtonVisible).isFalse() - assertThat(fakeMatrixRoom.replyMessageParameter).isEqualTo(A_REPLY) + assertThat(messageSentState.richTextEditorState.messageHtml).isEqualTo("") + assertThat(messageSentState.canSendMessage).isFalse() + assertThat(fakeMatrixRoom.replyMessageParameter).isEqualTo(A_REPLY to A_REPLY) } } @@ -523,13 +525,27 @@ class MessageComposerPresenterTest { } } + @Test + fun `present - errors are tracked`() = runTest { + val testException = Exception("Test error") + val presenter = createPresenter(this) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + skipItems(1) + val initialState = awaitItem() + initialState.eventSink(MessageComposerEvents.Error(testException)) + assertThat(analyticsService.trackedErrors).containsExactly(testException) + } + } + private suspend fun ReceiveTurbine.backToNormalMode(state: MessageComposerState, skipCount: Int = 0) { state.eventSink.invoke(MessageComposerEvents.CloseSpecialMode) skipItems(skipCount) val normalState = awaitItem() assertThat(normalState.mode).isEqualTo(MessageComposerMode.Normal("")) - assertThat(normalState.text).isEqualTo("") - assertThat(normalState.isSendButtonVisible).isFalse() + assertThat(normalState.richTextEditorState.messageHtml).isEqualTo("") + assertThat(normalState.canSendMessage).isFalse() } private fun createPresenter( @@ -547,8 +563,9 @@ class MessageComposerPresenterTest { localMediaFactory, MediaSender(mediaPreProcessor, room), snackbarDispatcher, - FakeAnalyticsService(), + analyticsService, MessageComposerContextImpl(), + TestRichTextEditorStateFactory(), ) } @@ -560,3 +577,8 @@ fun anEditMode( fun aReplyMode() = MessageComposerMode.Reply(A_USER_NAME, null, AN_EVENT_ID, A_MESSAGE) fun aQuoteMode() = MessageComposerMode.Quote(AN_EVENT_ID, A_MESSAGE) + +private fun String.toMessage() = Message( + html = this, + markdown = this, +) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/TestRichTextEditorStateFactory.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/TestRichTextEditorStateFactory.kt new file mode 100644 index 0000000000..762d144cd6 --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/TestRichTextEditorStateFactory.kt @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.messages.textcomposer + +import androidx.compose.runtime.Composable +import io.element.android.features.messages.impl.messagecomposer.RichTextEditorStateFactory +import io.element.android.wysiwyg.compose.RichTextEditorState +import io.element.android.wysiwyg.compose.rememberRichTextEditorState + +class TestRichTextEditorStateFactory : RichTextEditorStateFactory { + @Composable + override fun create(): RichTextEditorState { + return rememberRichTextEditorState("", fake = true) + } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 877dd7955f..ebbc937bfa 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -46,6 +46,7 @@ dependencyanalysis = "1.21.0" stem = "2.3.0" sqldelight = "1.5.5" telephoto = "0.6.0" +wysiwyg = "2.9.0" # DI dagger = "2.48" @@ -147,6 +148,8 @@ appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = { module = "app.cash.molecule:molecule-runtime", version.ref = "molecule" } timber = "com.jakewharton.timber:timber:5.0.1" matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.49" +matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } +matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "com.squareup.sqldelight:android-driver", version.ref = "sqldelight" } sqldelight-driver-jvm = { module = "com.squareup.sqldelight:sqlite-driver", version.ref = "sqldelight" } sqldelight-coroutines = { module = "com.squareup.sqldelight:coroutines-extensions", version.ref = "sqldelight" } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt index 60c8b1ddd5..169381f25e 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt @@ -79,11 +79,11 @@ interface MatrixRoom : Closeable { suspend fun userAvatarUrl(userId: UserId): Result - suspend fun sendMessage(message: String): Result + suspend fun sendMessage(body: String, htmlBody: String): Result - suspend fun editMessage(originalEventId: EventId?, transactionId: TransactionId?, message: String): Result + suspend fun editMessage(originalEventId: EventId?, transactionId: TransactionId?, body: String, htmlBody: String): Result - suspend fun replyMessage(eventId: EventId, message: String): Result + suspend fun replyMessage(eventId: EventId, body: String, htmlBody: String): Result suspend fun redactEvent(eventId: EventId, reason: String? = null): Result diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt index 461e43931e..9e75d10aad 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt @@ -66,7 +66,7 @@ import org.matrix.rustcomponents.sdk.RoomMember import org.matrix.rustcomponents.sdk.RoomSubscription import org.matrix.rustcomponents.sdk.SendAttachmentJoinHandle import org.matrix.rustcomponents.sdk.genTransactionId -import org.matrix.rustcomponents.sdk.messageEventContentFromMarkdown +import org.matrix.rustcomponents.sdk.messageEventContentFromHtml import timber.log.Timber import java.io.File @@ -227,31 +227,32 @@ class RustMatrixRoom( } } - override suspend fun sendMessage(message: String): Result = withContext(roomDispatcher) { + override suspend fun sendMessage(body: String, htmlBody: String): Result = withContext(roomDispatcher) { val transactionId = genTransactionId() - messageEventContentFromMarkdown(message).use { content -> + messageEventContentFromHtml(body, htmlBody).use { content -> runCatching { innerRoom.send(content, transactionId) } } } - override suspend fun editMessage(originalEventId: EventId?, transactionId: TransactionId?, message: String): Result = withContext(roomDispatcher) { - if (originalEventId != null) { - runCatching { - innerRoom.edit(messageEventContentFromMarkdown(message), originalEventId.value, transactionId?.value) - } - } else { - runCatching { - transactionId?.let { cancelSend(it) } - innerRoom.send(messageEventContentFromMarkdown(message), genTransactionId()) + override suspend fun editMessage(originalEventId: EventId?, transactionId: TransactionId?, body: String, htmlBody: String): Result = + withContext(roomDispatcher) { + if (originalEventId != null) { + runCatching { + innerRoom.edit(messageEventContentFromHtml(body, htmlBody), originalEventId.value, transactionId?.value) + } + } else { + runCatching { + transactionId?.let { cancelSend(it) } + innerRoom.send(messageEventContentFromHtml(body, htmlBody), genTransactionId()) + } } } - } - override suspend fun replyMessage(eventId: EventId, message: String): Result = withContext(roomDispatcher) { + override suspend fun replyMessage(eventId: EventId, body: String, htmlBody: String): Result = withContext(roomDispatcher) { runCatching { - innerRoom.sendReply(messageEventContentFromMarkdown(message), eventId.value, genTransactionId()) + innerRoom.sendReply(messageEventContentFromHtml(body, htmlBody), eventId.value, genTransactionId()) } } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index 761e479816..24f0e68d10 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -92,7 +92,7 @@ class FakeMatrixRoom( private var sendPollResponseResult = Result.success(Unit) private var endPollResult = Result.success(Unit) private var progressCallbackValues = emptyList>() - val editMessageCalls = mutableListOf() + val editMessageCalls = mutableListOf>() var sendMediaCount = 0 private set @@ -171,7 +171,7 @@ class FakeMatrixRoom( userAvatarUrlResult } - override suspend fun sendMessage(message: String): Result = simulateLongTask { + override suspend fun sendMessage(body: String, htmlBody: String) = simulateLongTask { Result.success(Unit) } @@ -200,16 +200,16 @@ class FakeMatrixRoom( return cancelSendResult } - override suspend fun editMessage(originalEventId: EventId?, transactionId: TransactionId?, message: String): Result { - editMessageCalls += message + override suspend fun editMessage(originalEventId: EventId?, transactionId: TransactionId?, body: String, htmlBody: String): Result { + editMessageCalls += body to htmlBody return Result.success(Unit) } - var replyMessageParameter: String? = null + var replyMessageParameter: Pair? = null private set - override suspend fun replyMessage(eventId: EventId, message: String): Result { - replyMessageParameter = message + override suspend fun replyMessage(eventId: EventId, body: String, htmlBody: String): Result { + replyMessageParameter = body to htmlBody return Result.success(Unit) } diff --git a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenter.kt b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenter.kt index ddd45f865f..1684833d70 100644 --- a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenter.kt +++ b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenter.kt @@ -124,7 +124,7 @@ class DefaultPermissionsPresenter @AssistedInject constructor( showDialog = showDialog.value, permissionAlreadyAsked = isAlreadyAsked, permissionAlreadyDenied = isAlreadyDenied, - eventSink = ::handleEvents + eventSink = { handleEvents(it) } ) } diff --git a/libraries/textcomposer/build.gradle.kts b/libraries/textcomposer/impl/build.gradle.kts similarity index 89% rename from libraries/textcomposer/build.gradle.kts rename to libraries/textcomposer/impl/build.gradle.kts index 76d7d00a03..3aaae7ca6e 100644 --- a/libraries/textcomposer/build.gradle.kts +++ b/libraries/textcomposer/impl/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 New Vector Ltd + * Copyright (c) 2023 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,5 +31,9 @@ dependencies { implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrixui) implementation(projects.libraries.designsystem) + + implementation(libs.matrix.richtexteditor) + api(libs.matrix.richtexteditor.compose) + ksp(libs.showkase.processor) } diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/Message.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/Message.kt new file mode 100644 index 0000000000..0f3a213427 --- /dev/null +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/Message.kt @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.textcomposer + +data class Message( + val html: String, + val markdown: String, +) diff --git a/libraries/textcomposer/src/main/kotlin/io/element/android/libraries/textcomposer/MessageComposerMode.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/MessageComposerMode.kt similarity index 100% rename from libraries/textcomposer/src/main/kotlin/io/element/android/libraries/textcomposer/MessageComposerMode.kt rename to libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/MessageComposerMode.kt diff --git a/libraries/textcomposer/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt similarity index 74% rename from libraries/textcomposer/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt rename to libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt index 3c0e0fa723..04fa08c9ce 100644 --- a/libraries/textcomposer/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt @@ -37,38 +37,25 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.text.BasicTextField -import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Close import androidx.compose.material.ripple.rememberRipple -import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableIntStateOf -import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment -import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.focus.FocusRequester -import androidx.compose.ui.focus.focusRequester -import androidx.compose.ui.focus.onFocusEvent import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter -import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.input.KeyboardCapitalization -import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp @@ -88,23 +75,23 @@ import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.ui.strings.CommonStrings +import io.element.android.wysiwyg.compose.RichTextEditor +import io.element.android.wysiwyg.compose.RichTextEditorDefaults +import io.element.android.wysiwyg.compose.RichTextEditorState import kotlinx.coroutines.android.awaitFrame -@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class) @Composable fun TextComposer( - composerText: String?, + state: RichTextEditorState, composerMode: MessageComposerMode, - composerCanSendMessage: Boolean, + canSendMessage: Boolean, modifier: Modifier = Modifier, - focusRequester: FocusRequester = FocusRequester(), - onSendMessage: (String) -> Unit = {}, + onRequestFocus: () -> Unit = {}, + onSendMessage: (Message) -> Unit = {}, onResetComposerMode: () -> Unit = {}, - onComposerTextChange: (String) -> Unit = {}, onAddAttachment: () -> Unit = {}, - onFocusChanged: (Boolean) -> Unit = {}, + onError: (Throwable) -> Unit = {}, ) { - val text = composerText.orEmpty() Row( modifier.padding( horizontal = 12.dp, @@ -115,10 +102,9 @@ fun TextComposer( Spacer(modifier = Modifier.width(12.dp)) val roundCornerSmall = 20.dp.applyScaleUp() val roundCornerLarge = 28.dp.applyScaleUp() - var lineCount by remember { mutableIntStateOf(0) } - val roundedCornerSize = remember(lineCount, composerMode) { - if (lineCount > 1 || composerMode is MessageComposerMode.Special) { + val roundedCornerSize = remember(state.lineCount, composerMode) { + if (state.lineCount > 1 || composerMode is MessageComposerMode.Special) { roundCornerSmall } else { roundCornerLarge @@ -132,10 +118,15 @@ fun TextComposer( ) val roundedCorners = RoundedCornerShape(roundedCornerSizeState.value) val minHeight = 42.dp.applyScaleUp() - val bgColor = ElementTheme.colors.bgSubtleSecondary - // Change border color depending on focus - var hasFocus by remember { mutableStateOf(false) } - val borderColor = if (hasFocus) ElementTheme.colors.borderDisabled else bgColor + val colors = ElementTheme.colors + val bgColor = colors.bgSubtleSecondary + + val borderColor by remember(state.hasFocus, colors) { + derivedStateOf { + if (state.hasFocus) colors.borderDisabled else bgColor + } + } + Column( modifier = Modifier .fillMaxWidth() @@ -147,66 +138,56 @@ fun TextComposer( ComposerModeView(composerMode = composerMode, onResetComposerMode = onResetComposerMode) } val defaultTypography = ElementTheme.typography.fontBodyLgRegular + Box { - BasicTextField( + Box( modifier = Modifier - .fillMaxWidth() .heightIn(min = minHeight) - .focusRequester(focusRequester) - .onFocusEvent { - hasFocus = it.hasFocus - onFocusChanged(it.hasFocus) - }, - value = text, - onValueChange = { onComposerTextChange(it) }, - onTextLayout = { - lineCount = it.lineCount - }, - keyboardOptions = KeyboardOptions( - capitalization = KeyboardCapitalization.Sentences, - ), - textStyle = defaultTypography.copy(color = MaterialTheme.colorScheme.primary), - cursorBrush = SolidColor(ElementTheme.colors.iconAccentTertiary), - decorationBox = { innerTextField -> - TextFieldDefaults.DecorationBox( - value = text, - innerTextField = innerTextField, - enabled = true, - singleLine = false, - visualTransformation = VisualTransformation.None, - shape = roundedCorners, - contentPadding = PaddingValues( - top = 10.dp.applyScaleUp(), - bottom = 10.dp.applyScaleUp(), + .background(color = bgColor, shape = roundedCorners) + .padding( + PaddingValues( + top = 4.dp.applyScaleUp(), + bottom = 4.dp.applyScaleUp(), start = 12.dp.applyScaleUp(), - end = 42.dp.applyScaleUp(), - ), - interactionSource = remember { MutableInteractionSource() }, - placeholder = { - Text(stringResource(CommonStrings.common_message), style = defaultTypography) - }, - colors = TextFieldDefaults.colors( - unfocusedTextColor = MaterialTheme.colorScheme.secondary, - focusedTextColor = MaterialTheme.colorScheme.primary, - unfocusedPlaceholderColor = ElementTheme.colors.textDisabled, - focusedPlaceholderColor = ElementTheme.colors.textDisabled, - unfocusedIndicatorColor = Color.Transparent, - focusedIndicatorColor = Color.Transparent, - disabledIndicatorColor = Color.Transparent, - errorIndicatorColor = Color.Transparent, - unfocusedContainerColor = bgColor, - focusedContainerColor = bgColor, - errorContainerColor = bgColor, - disabledContainerColor = bgColor, + end = 42.dp.applyScaleUp() ) + ), + contentAlignment = Alignment.CenterStart, + ) { + + // Placeholder + if (state.messageHtml.isEmpty()) { + Text( + stringResource(CommonStrings.common_message), + style = defaultTypography.copy( + color = ElementTheme.colors.textDisabled, + ), ) } - ) + + RichTextEditor( + state = state, + modifier = Modifier + .fillMaxWidth(), + style = RichTextEditorDefaults.style( + text = RichTextEditorDefaults.textStyle( + color = if (state.hasFocus) { + MaterialTheme.colorScheme.primary + } else { + MaterialTheme.colorScheme.secondary + } + ), + cursor = RichTextEditorDefaults.cursorStyle( + color = ElementTheme.colors.iconAccentTertiary, + ) + ), + onError = onError + ) + } SendButton( - text = text, - canSendMessage = composerCanSendMessage, - onSendMessage = onSendMessage, + canSendMessage = canSendMessage, + onClick = { onSendMessage(Message(html = state.messageHtml, markdown = state.messageMarkdown)) }, composerMode = composerMode, modifier = Modifier.padding(end = 6.dp.applyScaleUp(), bottom = 6.dp.applyScaleUp()) ) @@ -218,7 +199,7 @@ fun TextComposer( val keyboard = LocalSoftwareKeyboardController.current LaunchedEffect(composerMode) { if (composerMode is MessageComposerMode.Special) { - focusRequester.requestFocus() + onRequestFocus() keyboard?.let { awaitFrame() it.show() @@ -241,7 +222,7 @@ private fun ComposerModeView( ReplyToModeView( modifier = modifier.padding(8.dp), senderName = composerMode.senderName, - text = composerMode.defaultContent.toString(), + text = composerMode.defaultContent, attachmentThumbnailInfo = composerMode.attachmentThumbnailInfo, onResetComposerMode = onResetComposerMode, ) @@ -385,9 +366,8 @@ private fun AttachmentButton( @Composable private fun BoxScope.SendButton( - text: String, canSendMessage: Boolean, - onSendMessage: (String) -> Unit, + onClick: () -> Unit, composerMode: MessageComposerMode, modifier: Modifier = Modifier, ) { @@ -405,9 +385,8 @@ private fun BoxScope.SendButton( enabled = canSendMessage, interactionSource = interactionSource, indication = rememberRipple(bounded = false), - onClick = { - onSendMessage(text) - }), + onClick = onClick, + ), contentAlignment = Alignment.Center, ) { val iconId = when (composerMode) { @@ -433,28 +412,37 @@ private fun BoxScope.SendButton( internal fun TextComposerSimplePreview() = ElementPreview { Column { TextComposer( + RichTextEditorState("", fake = true).apply { requestFocus() }, + canSendMessage = false, + onSendMessage = {}, + composerMode = MessageComposerMode.Normal(""), + onResetComposerMode = {}, + ) + TextComposer( + RichTextEditorState("A message", fake = true).apply { requestFocus() }, + canSendMessage = true, onSendMessage = {}, - onComposerTextChange = {}, composerMode = MessageComposerMode.Normal(""), onResetComposerMode = {}, - composerCanSendMessage = false, - composerText = "", ) TextComposer( + RichTextEditorState( + "A message\nWith several lines\nTo preview larger textfields and long lines with overflow", + fake = true + ).apply { + requestFocus() + }, + canSendMessage = true, onSendMessage = {}, - onComposerTextChange = {}, composerMode = MessageComposerMode.Normal(""), onResetComposerMode = {}, - composerCanSendMessage = true, - composerText = "A message", ) TextComposer( + RichTextEditorState("A message without focus", fake = true), + canSendMessage = true, onSendMessage = {}, - onComposerTextChange = {}, composerMode = MessageComposerMode.Normal(""), onResetComposerMode = {}, - composerCanSendMessage = true, - composerText = "A message\nWith several lines\nTo preview larger textfields and long lines with overflow", ) } } @@ -463,12 +451,11 @@ internal fun TextComposerSimplePreview() = ElementPreview { @Composable internal fun TextComposerEditPreview() = ElementPreview { TextComposer( + RichTextEditorState("A message", fake = true).apply { requestFocus() }, + canSendMessage = true, onSendMessage = {}, - onComposerTextChange = {}, composerMode = MessageComposerMode.Edit(EventId("$1234"), "Some text", TransactionId("1234")), onResetComposerMode = {}, - composerCanSendMessage = true, - composerText = "A message", ) } @@ -477,8 +464,9 @@ internal fun TextComposerEditPreview() = ElementPreview { internal fun TextComposerReplyPreview() = ElementPreview { Column { TextComposer( + RichTextEditorState("", fake = true), + canSendMessage = false, onSendMessage = {}, - onComposerTextChange = {}, composerMode = MessageComposerMode.Reply( senderName = "Alice", eventId = EventId("$1234"), @@ -488,12 +476,11 @@ internal fun TextComposerReplyPreview() = ElementPreview { "To preview larger textfields and long lines with overflow" ), onResetComposerMode = {}, - composerCanSendMessage = true, - composerText = "A message", ) TextComposer( + RichTextEditorState("A message", fake = true), + canSendMessage = true, onSendMessage = {}, - onComposerTextChange = {}, composerMode = MessageComposerMode.Reply( senderName = "Alice", eventId = EventId("$1234"), @@ -506,12 +493,11 @@ internal fun TextComposerReplyPreview() = ElementPreview { defaultContent = "image.jpg" ), onResetComposerMode = {}, - composerCanSendMessage = true, - composerText = "A message", ) TextComposer( + RichTextEditorState("A message", fake = true), + canSendMessage = true, onSendMessage = {}, - onComposerTextChange = {}, composerMode = MessageComposerMode.Reply( senderName = "Alice", eventId = EventId("$1234"), @@ -524,12 +510,11 @@ internal fun TextComposerReplyPreview() = ElementPreview { defaultContent = "video.mp4" ), onResetComposerMode = {}, - composerCanSendMessage = true, - composerText = "A message", ) TextComposer( + RichTextEditorState("A message", fake = true), + canSendMessage = true, onSendMessage = {}, - onComposerTextChange = {}, composerMode = MessageComposerMode.Reply( senderName = "Alice", eventId = EventId("$1234"), @@ -542,12 +527,11 @@ internal fun TextComposerReplyPreview() = ElementPreview { defaultContent = "logs.txt" ), onResetComposerMode = {}, - composerCanSendMessage = true, - composerText = "A message", ) TextComposer( + RichTextEditorState("A message", fake = true).apply { requestFocus() }, + canSendMessage = true, onSendMessage = {}, - onComposerTextChange = {}, composerMode = MessageComposerMode.Reply( senderName = "Alice", eventId = EventId("$1234"), @@ -560,8 +544,6 @@ internal fun TextComposerReplyPreview() = ElementPreview { defaultContent = "Shared location" ), onResetComposerMode = {}, - composerCanSendMessage = true, - composerText = "A message", ) } } diff --git a/libraries/textcomposer/src/main/res/drawable/ic_add_attachment.xml b/libraries/textcomposer/impl/src/main/res/drawable/ic_add_attachment.xml similarity index 100% rename from libraries/textcomposer/src/main/res/drawable/ic_add_attachment.xml rename to libraries/textcomposer/impl/src/main/res/drawable/ic_add_attachment.xml diff --git a/libraries/textcomposer/src/main/res/drawable/ic_send.xml b/libraries/textcomposer/impl/src/main/res/drawable/ic_send.xml similarity index 100% rename from libraries/textcomposer/src/main/res/drawable/ic_send.xml rename to libraries/textcomposer/impl/src/main/res/drawable/ic_send.xml diff --git a/libraries/textcomposer/src/main/res/drawable/ic_tick.xml b/libraries/textcomposer/impl/src/main/res/drawable/ic_tick.xml similarity index 100% rename from libraries/textcomposer/src/main/res/drawable/ic_tick.xml rename to libraries/textcomposer/impl/src/main/res/drawable/ic_tick.xml diff --git a/libraries/textcomposer/src/main/res/values-cs/translations.xml b/libraries/textcomposer/impl/src/main/res/values-cs/translations.xml similarity index 100% rename from libraries/textcomposer/src/main/res/values-cs/translations.xml rename to libraries/textcomposer/impl/src/main/res/values-cs/translations.xml diff --git a/libraries/textcomposer/src/main/res/values-de/translations.xml b/libraries/textcomposer/impl/src/main/res/values-de/translations.xml similarity index 100% rename from libraries/textcomposer/src/main/res/values-de/translations.xml rename to libraries/textcomposer/impl/src/main/res/values-de/translations.xml diff --git a/libraries/textcomposer/src/main/res/values-ro/translations.xml b/libraries/textcomposer/impl/src/main/res/values-ro/translations.xml similarity index 100% rename from libraries/textcomposer/src/main/res/values-ro/translations.xml rename to libraries/textcomposer/impl/src/main/res/values-ro/translations.xml diff --git a/libraries/textcomposer/src/main/res/values-ru/translations.xml b/libraries/textcomposer/impl/src/main/res/values-ru/translations.xml similarity index 100% rename from libraries/textcomposer/src/main/res/values-ru/translations.xml rename to libraries/textcomposer/impl/src/main/res/values-ru/translations.xml diff --git a/libraries/textcomposer/src/main/res/values-sk/translations.xml b/libraries/textcomposer/impl/src/main/res/values-sk/translations.xml similarity index 100% rename from libraries/textcomposer/src/main/res/values-sk/translations.xml rename to libraries/textcomposer/impl/src/main/res/values-sk/translations.xml diff --git a/libraries/textcomposer/src/main/res/values-zh-rTW/translations.xml b/libraries/textcomposer/impl/src/main/res/values-zh-rTW/translations.xml similarity index 100% rename from libraries/textcomposer/src/main/res/values-zh-rTW/translations.xml rename to libraries/textcomposer/impl/src/main/res/values-zh-rTW/translations.xml diff --git a/libraries/textcomposer/src/main/res/values/localazy.xml b/libraries/textcomposer/impl/src/main/res/values/localazy.xml similarity index 100% rename from libraries/textcomposer/src/main/res/values/localazy.xml rename to libraries/textcomposer/impl/src/main/res/values/localazy.xml diff --git a/libraries/textcomposer/test/build.gradle.kts b/libraries/textcomposer/test/build.gradle.kts new file mode 100644 index 0000000000..04e36e337d --- /dev/null +++ b/libraries/textcomposer/test/build.gradle.kts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + id("io.element.android-compose-library") +} + +android { + namespace = "io.element.android.libraries.textcomposer.test" +} + +dependencies { + api(projects.libraries.textcomposer.impl) + implementation(projects.tests.testutils) +} diff --git a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt index fb082e27a7..592cf3c52a 100644 --- a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt +++ b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt @@ -99,7 +99,7 @@ fun DependencyHandlerScope.allLibrariesImpl() { implementation(project(":libraries:mediapickers:impl")) implementation(project(":libraries:mediaupload:impl")) implementation(project(":libraries:usersearch:impl")) - implementation(project(":libraries:textcomposer")) + implementation(project(":libraries:textcomposer:impl")) } fun DependencyHandlerScope.allServicesImpl() { diff --git a/services/analytics/test/src/main/kotlin/io/element/android/services/analytics/test/FakeAnalyticsService.kt b/services/analytics/test/src/main/kotlin/io/element/android/services/analytics/test/FakeAnalyticsService.kt index f3b3a7fab2..c52f66ef2d 100644 --- a/services/analytics/test/src/main/kotlin/io/element/android/services/analytics/test/FakeAnalyticsService.kt +++ b/services/analytics/test/src/main/kotlin/io/element/android/services/analytics/test/FakeAnalyticsService.kt @@ -32,6 +32,7 @@ class FakeAnalyticsService( private val isEnabledFlow = MutableStateFlow(isEnabled) private val didAskUserConsentFlow = MutableStateFlow(didAskUserConsent) val capturedEvents = mutableListOf() + val trackedErrors = mutableListOf() override fun getAvailableAnalyticsProviders(): Set = emptySet() @@ -66,6 +67,7 @@ class FakeAnalyticsService( } override fun trackError(throwable: Throwable) { + trackedErrors += throwable } override suspend fun reset() { diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewDark_0_null_0,NEXUS_5,1.0,en].png index f11cec4281..fa68f3bd24 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:906c643393af8d290f0635d7560eaa54339fc0498744f9ab8139932986d73a8c -size 9740 +oid sha256:4013454094701004f3c132df1ea1c3db2aa56a025b9edea80417fdd16fe55b19 +size 10422 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewLight_0_null_0,NEXUS_5,1.0,en].png index eb5a63601c..f6040d0e1a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bd57f885f161316550712dcb471ed213537a395539ed5b9975e17465310803b7 -size 9823 +oid sha256:db74b1655e377e4fd8c35aa18c22ef5f5641586b64d5e582ab2079afeac4b8c3 +size 10775 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_0,NEXUS_5,1.0,en].png index 08734109fb..2a10272dac 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:39b527075df2b3f7afa4f3ecfca1ac93a180855b20d2bd64cb763fb98b0a7b69 -size 51340 +oid sha256:cfc6f54988e4fab08ff443f0c2ea285d47e3d030a8e6c92a1294ee0f85dc1269 +size 51967 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_1,NEXUS_5,1.0,en].png index 60f606fe58..5cf07497cd 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:81f196dc08f4de31f4257f6ba89c52ea41a97b107e7c5c04261188e6c572d4d0 -size 52594 +oid sha256:d2ffd4fc93e7da38836fd860ce5e505c5f0c25fdd6558efef480aaeb05d00dd5 +size 53327 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png index 6b3be5e81e..41f0170682 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a648d286a3b0536fc97801c3281bb8df432c7ffa28efff66f67cd6cf4c546c10 -size 51579 +oid sha256:96864552336c65b464251c262f330856fc82c69a5f92f89b1357a185d654fccd +size 52252 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_4,NEXUS_5,1.0,en].png index e2266026d1..a022fb7675 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:34f9eacfd61965cfde4f420fe6a0fc0d637a21aca0d4b12c6a6f1642bd44556d -size 50586 +oid sha256:2411212e87f95415e0b4ed6732387922faed891cde5e78fa9f0691a185873129 +size 51026 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_5,NEXUS_5,1.0,en].png index 040fa6c12a..5fe74737cf 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c336a9cbc803eb314aa9333719d813ae64994a75344aa363b25aee8d52551b21 -size 48928 +oid sha256:255560f478c093f4ca7d021646f4cf9064c16b420d5eeec7cbce97d26c751d92 +size 49540 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_0,NEXUS_5,1.0,en].png index a178b31231..caf6d5a3da 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d7148068516b5e3299cce2924ea3cb54c8f1ddd6378e48b0fa746217a547d22 -size 52940 +oid sha256:a384aa84ae514aa4989d4b4a5ef8048cb8810f1f37056137c77fd0ee798a0bab +size 53941 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_1,NEXUS_5,1.0,en].png index f4a3738cf8..93163a476e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b8aaf2c70473711a24bf587ff524fd71d43c2610ade1c3d4ff2013705d5670b3 -size 54314 +oid sha256:a48badf15c59ab5c42fc7cc200971f00cefa7838461ad0cb59537c2b4065bfff +size 55409 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png index f40d649d64..1ff65d3301 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:566d5b197091d4b740e1241eab54017fd31e65f570def4b8c24ade19ea78ccc8 -size 53254 +oid sha256:88a498b9070653513b3e27aa2b597367ee85c8526c6e4c3712a4cb0c06e5313b +size 54353 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_4,NEXUS_5,1.0,en].png index 4e0d1ce4bc..be91f54717 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8353077959916fa85046d3a81d1479d552748635f1286bb8bacc6d922ba30f28 -size 55312 +oid sha256:bf493a9cb7325b4f68924abd86864b37c72226afcf1c4179a06c17e923cfd0ae +size 55837 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_5,NEXUS_5,1.0,en].png index d2ac508bf8..432e114fd5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a84dabfdcbaff8de5c30472676dee2cee8dc0f77469f2802dfc796a87bc10dff -size 50328 +oid sha256:8ac3dbf36380fa273d82ebe8836c525bbeee004d6348822d965b216f9bcdb920 +size 51335 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-D-1_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-D-1_2_null,NEXUS_5,1.0,en].png index 4e97d85b18..b1144213da 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-D-1_2_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-D-1_2_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b8c4dfcbfb6c97b9bb8a33df6fd1ef57ef436b2c7e7e9bfa5d6a59fcae2515be -size 14140 +oid sha256:ce08e8c81d5494d2d803da43612a137df881e359646878b1d38cdfe77e0857ff +size 13829 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-N-1_3_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-N-1_3_null,NEXUS_5,1.0,en].png index 4fe86c030b..62264fcf27 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-N-1_3_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-N-1_3_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4fd3c3f554bd668552863a6f7cd3b43cd15cf4a29b2fd67265e3a9a8a05d4258 -size 13216 +oid sha256:3c2ba0ac13c81c707f0d00e3ff69737163dfc450a3d21aa468dd0b34deeeb7e1 +size 12916 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-2_3_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-2_3_null,NEXUS_5,1.0,en].png index 26c038b0a4..3e872eda82 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-2_3_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-2_3_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:049d237aa3e2ba18df462caca17d059fa47e25de9bee8f1fbfd310106a1de07c -size 81319 +oid sha256:f15bc37e2a3d052e8d79e663f2c03223c27ddff3c02cd69f95a140c33fc6952c +size 79320 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-2_4_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-2_4_null,NEXUS_5,1.0,en].png index 0e609116be..8bd9e09c69 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-2_4_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-2_4_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d45e4a53b9280b295b731ac1287ea31a8c2b653e0ae5dedd82fd2c0a6c2078ba -size 78323 +oid sha256:6aa9b8849a2bbd7b487de6fee7fd355300091bc14d647973c4beea02e6009ac4 +size 76465 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-D-0_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-D-0_1_null,NEXUS_5,1.0,en].png index ef4d9ab56c..8afc6fc94a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-D-0_1_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-D-0_1_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a817f9c6e2d9823dc7f4d20669c80a3cf8f39e6a4468d7dde7159cb7920f20fd -size 35134 +oid sha256:501734b297cec566a008d3492690cf75b46ab68e662d2835a0b195fd0740c13f +size 42912 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-N-0_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-N-0_2_null,NEXUS_5,1.0,en].png index 9b3ff03b0b..de57e08951 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-N-0_2_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-N-0_2_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a67d75e43fff35eaa3fff9c17245738b16cb7687f6915c1857a2ba85a61037bf -size 33576 +oid sha256:ff69ed7056380df3279a39b7544bc1887d2e455b43fb069b547e32cf5c92dc0f +size 40229 diff --git a/tools/localazy/config.json b/tools/localazy/config.json index cf29033d88..b92e02f670 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -45,7 +45,7 @@ ] }, { - "name": ":libraries:textcomposer", + "name": ":libraries:textcomposer:impl", "includeRegex": [ "rich_text_editor_.*" ] From 54968f98ed5ef9f4c4bfd0b7c1c3700ff0bcb93b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 7 Sep 2023 17:25:50 +0200 Subject: [PATCH 069/234] Add a last Spacer item to ensure that the FAB does not hide the last room item --- .../android/features/roomlist/impl/RoomListView.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt index f7eb5aa4eb..f7f712fbc3 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt @@ -20,8 +20,10 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed @@ -52,8 +54,8 @@ import io.element.android.features.roomlist.impl.model.RoomListRoomSummary import io.element.android.features.roomlist.impl.search.RoomListSearchResultView import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewLight -import io.element.android.libraries.designsystem.theme.components.HorizontalDivider import io.element.android.libraries.designsystem.theme.components.FloatingActionButton +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.Scaffold import io.element.android.libraries.designsystem.utils.LogCompositions @@ -210,6 +212,11 @@ fun RoomListContent( HorizontalDivider() } } + // Add a last Spacer item to ensure that the FAB does not hide the last room item + // FAB height is 56dp, bottom padding is 16dp, we add 8dp as extra margin -> 56+16+8 = 80 + item { + Spacer(modifier = Modifier.height(80.dp)) + } } }, floatingActionButton = { From a3940ddc5b9bfb97e6a464f7a4dbfef1b66c3957 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 7 Sep 2023 15:52:41 +0200 Subject: [PATCH 070/234] Use roomInfo instead of individually access roomListItem properties --- changelog.d/1251.misc | 1 + .../roomlist/RoomSummaryDetailsFactory.kt | 23 ++++++++++--------- .../impl/roomlist/RoomSummaryListProcessor.kt | 16 +++---------- .../impl/roomlist/RustRoomListService.kt | 4 ++-- 4 files changed, 18 insertions(+), 26 deletions(-) create mode 100644 changelog.d/1251.misc diff --git a/changelog.d/1251.misc b/changelog.d/1251.misc new file mode 100644 index 0000000000..ba3b37b8ff --- /dev/null +++ b/changelog.d/1251.misc @@ -0,0 +1 @@ +Improve RoomSummary mapping by using RoomInfo. diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt index b57eb892e0..d33e2f58fc 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt @@ -20,25 +20,26 @@ import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails import io.element.android.libraries.matrix.impl.room.RoomMemberMapper import io.element.android.libraries.matrix.impl.room.message.RoomMessageFactory -import org.matrix.rustcomponents.sdk.Room -import org.matrix.rustcomponents.sdk.RoomListItem +import org.matrix.rustcomponents.sdk.RoomInfo +import org.matrix.rustcomponents.sdk.use class RoomSummaryDetailsFactory(private val roomMessageFactory: RoomMessageFactory = RoomMessageFactory()) { - suspend fun create(roomListItem: RoomListItem, room: Room?): RoomSummaryDetails { - val latestRoomMessage = roomListItem.latestEvent()?.use { + fun create(roomInfo: RoomInfo): RoomSummaryDetails { + val latestRoomMessage = roomInfo.latestEvent?.use { roomMessageFactory.create(it) } return RoomSummaryDetails( - roomId = RoomId(roomListItem.id()), - name = roomListItem.name() ?: roomListItem.id(), - canonicalAlias = roomListItem.canonicalAlias(), - isDirect = roomListItem.isDirect(), - avatarURLString = roomListItem.avatarUrl(), - unreadNotificationCount = roomListItem.unreadNotifications().use { it.notificationCount().toInt() }, + roomId = RoomId(roomInfo.id), + name = roomInfo.name ?: roomInfo.id, + canonicalAlias = roomInfo.canonicalAlias, + isDirect = roomInfo.isDirect, + avatarURLString = roomInfo.avatarUrl, + unreadNotificationCount = roomInfo.notificationCount.toInt(), lastMessage = latestRoomMessage, lastMessageTimestamp = latestRoomMessage?.originServerTs, - inviter = room?.inviter()?.let(RoomMemberMapper::map), + inviter = roomInfo.inviter?.let(RoomMemberMapper::map), ) } } + diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt index 9a67ff1f30..03b58ed2ce 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt @@ -22,11 +22,10 @@ import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock -import org.matrix.rustcomponents.sdk.Room import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate import org.matrix.rustcomponents.sdk.RoomListEntry -import org.matrix.rustcomponents.sdk.RoomListItem import org.matrix.rustcomponents.sdk.RoomListService +import org.matrix.rustcomponents.sdk.use import timber.log.Timber import java.util.UUID @@ -34,7 +33,6 @@ class RoomSummaryListProcessor( private val roomSummaries: MutableStateFlow>, private val roomListService: RoomListService, private val roomSummaryDetailsFactory: RoomSummaryDetailsFactory = RoomSummaryDetailsFactory(), - private val shouldFetchFullRoom: Boolean = false, ) { private val roomSummariesByIdentifier = HashMap() @@ -120,9 +118,9 @@ class RoomSummaryListProcessor( private suspend fun buildAndCacheRoomSummaryForIdentifier(identifier: String): RoomSummary { val builtRoomSummary = roomListService.roomOrNull(identifier)?.use { roomListItem -> - roomListItem.fullRoomOrNull().use { fullRoom -> + roomListItem.roomInfo().use { roomInfo -> RoomSummary.Filled( - details = roomSummaryDetailsFactory.create(roomListItem, fullRoom) + details = roomSummaryDetailsFactory.create(roomInfo) ) } } ?: buildEmptyRoomSummary() @@ -130,14 +128,6 @@ class RoomSummaryListProcessor( return builtRoomSummary } - private fun RoomListItem.fullRoomOrNull(): Room? { - return if (shouldFetchFullRoom) { - fullRoom() - } else { - null - } - } - private suspend fun updateRoomSummaries(block: suspend MutableList.() -> Unit) = mutex.withLock { val mutableRoomSummaries = roomSummaries.value.toMutableList() diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt index 655c634502..5dade3b1c7 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt @@ -52,9 +52,9 @@ class RustRoomListService( private val inviteRooms = MutableStateFlow>(emptyList()) private val allRoomsLoadingState: MutableStateFlow = MutableStateFlow(RoomList.LoadingState.NotLoaded) - private val allRoomsListProcessor = RoomSummaryListProcessor(allRooms, innerRoomListService, roomSummaryDetailsFactory, shouldFetchFullRoom = false) + private val allRoomsListProcessor = RoomSummaryListProcessor(allRooms, innerRoomListService, roomSummaryDetailsFactory) private val invitesLoadingState: MutableStateFlow = MutableStateFlow(RoomList.LoadingState.NotLoaded) - private val inviteRoomsListProcessor = RoomSummaryListProcessor(inviteRooms, innerRoomListService, roomSummaryDetailsFactory, shouldFetchFullRoom = true) + private val inviteRoomsListProcessor = RoomSummaryListProcessor(inviteRooms, innerRoomListService, roomSummaryDetailsFactory) init { sessionCoroutineScope.launch(dispatcher) { From f503eba02105d4bd198448958f7683cd625012f0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 7 Sep 2023 19:01:23 +0000 Subject: [PATCH 071/234] Update dependency org.matrix.rustcomponents:sdk-android to v0.1.50 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ebbc937bfa..be044a9e13 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -147,7 +147,7 @@ jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" } appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = { module = "app.cash.molecule:molecule-runtime", version.ref = "molecule" } timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.49" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.50" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "com.squareup.sqldelight:android-driver", version.ref = "sqldelight" } From d2898d2bcaa9c9000f9b18c2833bebe4f88759e3 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 7 Sep 2023 21:59:17 +0200 Subject: [PATCH 072/234] Add changelog. --- changelog.d/1244.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/1244.misc diff --git a/changelog.d/1244.misc b/changelog.d/1244.misc new file mode 100644 index 0000000000..ab0bbf5178 --- /dev/null +++ b/changelog.d/1244.misc @@ -0,0 +1 @@ +Use the new SyncIndicator API. From 61f5983b2ba6e184e53865f29f71bef46162d024 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 7 Sep 2023 22:59:56 +0200 Subject: [PATCH 073/234] Remove unused val. --- .../io/element/android/appnav/loggedin/LoggedInPresenter.kt | 2 -- 1 file changed, 2 deletions(-) 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 49253edc99..7683b7278f 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 @@ -30,8 +30,6 @@ import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.push.api.PushService import javax.inject.Inject -private const val DELAY_BEFORE_SHOWING_SYNC_SPINNER_IN_MILLIS = 1500L - class LoggedInPresenter @Inject constructor( private val matrixClient: MatrixClient, private val networkMonitor: NetworkMonitor, From 26118a968d088558272e70c081adcd3e5a38c899 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 8 Sep 2023 01:27:46 +0000 Subject: [PATCH 074/234] Update anvil to v2.4.8-1-8 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6bf00e9c02..6d415faf59 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -50,7 +50,7 @@ wysiwyg = "2.9.0" # DI dagger = "2.48" -anvil = "2.4.7-1-8" +anvil = "2.4.8-1-8" # Auto service autoservice = "1.1.1" From 0e1d61bc12c0274dccfd7397b682478aabb8c279 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 8 Sep 2023 08:22:41 +0200 Subject: [PATCH 075/234] rename parameter to match parent name. --- .../libraries/matrix/impl/roomlist/RoomListExtensions.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListExtensions.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListExtensions.kt index ea932be896..1e599a184d 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListExtensions.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListExtensions.kt @@ -88,8 +88,8 @@ fun RoomListService.stateFlow(): Flow = fun RoomListService.syncIndicator(): Flow = mxCallbackFlow { val listener = object : RoomListServiceSyncIndicatorListener { - override fun onUpdate(indicator: RoomListServiceSyncIndicator) { - trySendBlocking(indicator) + override fun onUpdate(syncIndicator: RoomListServiceSyncIndicator) { + trySendBlocking(syncIndicator) } } tryOrNull { From 896c2325db5b64ce9abe691079ad054574c69e8c Mon Sep 17 00:00:00 2001 From: jonnyandrew Date: Fri, 8 Sep 2023 17:23:15 +0100 Subject: [PATCH 076/234] [Rich text editor] Add formatting menu (#1261) --------- Co-authored-by: ElementBot --- changelog.d/1261.feature | 1 + .../messagecomposer/AttachmentsBottomSheet.kt | 6 + .../messagecomposer/MessageComposerEvents.kt | 1 + .../MessageComposerPresenter.kt | 6 + .../messagecomposer/MessageComposerState.kt | 1 + .../MessageComposerStateProvider.kt | 2 + .../messagecomposer/MessageComposerView.kt | 6 + .../MessageComposerPresenterTest.kt | 23 + .../libraries/designsystem/VectorIcons.kt | 12 + .../src/main/res/drawable/ic_bold.xml | 9 + .../src/main/res/drawable/ic_bullet_list.xml | 9 + .../src/main/res/drawable/ic_code_block.xml | 9 + .../main/res/drawable/ic_indent_decrease.xml | 9 + .../main/res/drawable/ic_indent_increase.xml | 9 + .../src/main/res/drawable/ic_inline_code.xml | 15 + .../src/main/res/drawable/ic_italic.xml | 9 + .../src/main/res/drawable/ic_link.xml | 9 + .../main/res/drawable/ic_numbered_list.xml | 9 + .../src/main/res/drawable/ic_quote.xml | 18 + .../main/res/drawable/ic_strikethrough.xml | 9 + .../src/main/res/drawable/ic_underline.xml | 9 + libraries/textcomposer/impl/build.gradle.kts | 2 + .../libraries/textcomposer/TextComposer.kt | 496 +++++++++++++----- .../components/FormattingOption.kt | 69 +++ .../components/FormattingOptionState.kt | 22 + .../main/res/drawable/ic_add_attachment.xml | 10 - .../impl/src/main/res/drawable/ic_cancel.xml | 9 + .../impl/src/main/res/drawable/ic_plus.xml | 9 + .../impl/src/main/res/drawable/ic_send.xml | 12 +- ...ePickerMenu-D-1_2_null,NEXUS_5,1.0,en].png | 4 +- ...ePickerMenu-N-1_3_null,NEXUS_5,1.0,en].png | 4 +- ...poserViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...oserViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...sagesViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...sagesViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 +- ...sagesViewDark_0_null_2,NEXUS_5,1.0,en].png | 4 +- ...sagesViewDark_0_null_4,NEXUS_5,1.0,en].png | 4 +- ...sagesViewDark_0_null_5,NEXUS_5,1.0,en].png | 4 +- ...agesViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...agesViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 +- ...agesViewLight_0_null_2,NEXUS_5,1.0,en].png | 4 +- ...agesViewLight_0_null_4,NEXUS_5,1.0,en].png | 4 +- ...agesViewLight_0_null_5,NEXUS_5,1.0,en].png | 4 +- ...omposerEdit-D-1_2_null,NEXUS_5,1.0,en].png | 3 - ...omposerEdit-D-2_3_null,NEXUS_5,1.0,en].png | 3 + ...omposerEdit-N-1_3_null,NEXUS_5,1.0,en].png | 3 - ...omposerEdit-N-2_4_null,NEXUS_5,1.0,en].png | 3 + ...rFormatting-D-1_2_null,NEXUS_5,1.0,en].png | 3 + ...rFormatting-N-1_3_null,NEXUS_5,1.0,en].png | 3 + ...mposerReply-D-2_3_null,NEXUS_5,1.0,en].png | 3 - ...mposerReply-D-3_4_null,NEXUS_5,1.0,en].png | 3 + ...mposerReply-N-2_4_null,NEXUS_5,1.0,en].png | 3 - ...mposerReply-N-3_5_null,NEXUS_5,1.0,en].png | 3 + ...poserSimple-D-0_1_null,NEXUS_5,1.0,en].png | 4 +- ...poserSimple-N-0_2_null,NEXUS_5,1.0,en].png | 4 +- 55 files changed, 700 insertions(+), 204 deletions(-) create mode 100644 changelog.d/1261.feature create mode 100644 libraries/designsystem/src/main/res/drawable/ic_bold.xml create mode 100644 libraries/designsystem/src/main/res/drawable/ic_bullet_list.xml create mode 100644 libraries/designsystem/src/main/res/drawable/ic_code_block.xml create mode 100644 libraries/designsystem/src/main/res/drawable/ic_indent_decrease.xml create mode 100644 libraries/designsystem/src/main/res/drawable/ic_indent_increase.xml create mode 100644 libraries/designsystem/src/main/res/drawable/ic_inline_code.xml create mode 100644 libraries/designsystem/src/main/res/drawable/ic_italic.xml create mode 100644 libraries/designsystem/src/main/res/drawable/ic_link.xml create mode 100644 libraries/designsystem/src/main/res/drawable/ic_numbered_list.xml create mode 100644 libraries/designsystem/src/main/res/drawable/ic_quote.xml create mode 100644 libraries/designsystem/src/main/res/drawable/ic_strikethrough.xml create mode 100644 libraries/designsystem/src/main/res/drawable/ic_underline.xml create mode 100644 libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/FormattingOption.kt create mode 100644 libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/FormattingOptionState.kt delete mode 100644 libraries/textcomposer/impl/src/main/res/drawable/ic_add_attachment.xml create mode 100644 libraries/textcomposer/impl/src/main/res/drawable/ic_cancel.xml create mode 100644 libraries/textcomposer/impl/src/main/res/drawable/ic_plus.xml delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-D-1_2_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-D-2_3_null,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-N-1_3_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-N-2_4_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-D-1_2_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-N-1_3_null,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-2_3_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-2_4_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png diff --git a/changelog.d/1261.feature b/changelog.d/1261.feature new file mode 100644 index 0000000000..bf7dd2399d --- /dev/null +++ b/changelog.d/1261.feature @@ -0,0 +1 @@ +[Rich text editor] Add formatting menu (accessible via the '+' button) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt index 43805bb5c0..38ef458bd9 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt @@ -26,6 +26,7 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.AttachFile import androidx.compose.material.icons.filled.BarChart import androidx.compose.material.icons.filled.Collections +import androidx.compose.material.icons.filled.FormatColorText import androidx.compose.material.icons.filled.LocationOn import androidx.compose.material.icons.filled.PhotoCamera import androidx.compose.material.icons.filled.Videocam @@ -145,6 +146,11 @@ internal fun AttachmentSourcePickerMenu( text = { Text(stringResource(R.string.screen_room_attachment_source_poll)) }, ) } + ListItem( + modifier = Modifier.clickable { state.eventSink(MessageComposerEvents.ToggleTextFormatting(enabled = true)) }, + icon = { Icon(Icons.Default.FormatColorText, null) }, + text = { Text(stringResource(R.string.screen_room_attachment_text_formatting)) }, + ) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerEvents.kt index 4bfd290a77..92b180f326 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerEvents.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerEvents.kt @@ -36,6 +36,7 @@ sealed interface MessageComposerEvents { data object Location : PickAttachmentSource data object Poll : PickAttachmentSource } + data class ToggleTextFormatting(val enabled: Boolean) : MessageComposerEvents data object CancelSendAttachment : MessageComposerEvents data class Error(val error: Throwable) : MessageComposerEvents } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt index 687e951933..3c3ebc2db9 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt @@ -110,6 +110,7 @@ class MessageComposerPresenter @Inject constructor( val ongoingSendAttachmentJob = remember { mutableStateOf(null) } var showAttachmentSourcePicker: Boolean by remember { mutableStateOf(false) } + var showTextFormatting: Boolean by remember { mutableStateOf(false) } LaunchedEffect(messageComposerContext.composerMode) { when (val modeValue = messageComposerContext.composerMode) { @@ -190,6 +191,10 @@ class MessageComposerPresenter @Inject constructor( ongoingSendAttachmentJob.value == null } } + is MessageComposerEvents.ToggleTextFormatting -> { + showAttachmentSourcePicker = false + showTextFormatting = event.enabled + } is MessageComposerEvents.Error -> { analyticsService.trackError(event.error) } @@ -201,6 +206,7 @@ class MessageComposerPresenter @Inject constructor( isFullScreen = isFullScreen.value, mode = messageComposerContext.composerMode, showAttachmentSourcePicker = showAttachmentSourcePicker, + showTextFormatting = showTextFormatting, canShareLocation = canShareLocation.value, canCreatePoll = canCreatePoll.value, attachmentsState = attachmentsState.value, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt index bdff621521..65fac53fdc 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerState.kt @@ -28,6 +28,7 @@ data class MessageComposerState( val isFullScreen: Boolean, val mode: MessageComposerMode, val showAttachmentSourcePicker: Boolean, + val showTextFormatting: Boolean, val canShareLocation: Boolean, val canCreatePoll: Boolean, val attachmentsState: AttachmentsState, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt index ab15d8ccd8..d86969fc19 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerStateProvider.kt @@ -32,6 +32,7 @@ fun aMessageComposerState( composerState: RichTextEditorState = RichTextEditorState("", fake = true), isFullScreen: Boolean = false, mode: MessageComposerMode = MessageComposerMode.Normal(content = ""), + showTextFormatting: Boolean = false, showAttachmentSourcePicker: Boolean = false, canShareLocation: Boolean = true, canCreatePoll: Boolean = true, @@ -40,6 +41,7 @@ fun aMessageComposerState( richTextEditorState = composerState.apply { if(requestFocus) requestFocus() }, isFullScreen = isFullScreen, mode = mode, + showTextFormatting = showTextFormatting, showAttachmentSourcePicker = showAttachmentSourcePicker, canShareLocation = canShareLocation, canCreatePoll = canCreatePoll, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerView.kt index 5106a3359b..4ea5a7cf76 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerView.kt @@ -49,6 +49,10 @@ fun MessageComposerView( state.eventSink(MessageComposerEvents.CloseSpecialMode) } + fun onDismissTextFormatting() { + state.eventSink(MessageComposerEvents.ToggleTextFormatting(enabled = false)) + } + fun onError(error: Throwable) { state.eventSink(MessageComposerEvents.Error(error)) } @@ -66,8 +70,10 @@ fun MessageComposerView( onRequestFocus = { state.richTextEditorState.requestFocus() }, onSendMessage = ::sendMessage, composerMode = state.mode, + showTextFormatting = state.showTextFormatting, onResetComposerMode = ::onCloseSpecialMode, onAddAttachment = ::onAddAttachment, + onDismissTextFormatting = ::onDismissTextFormatting, onError = ::onError, ) } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt index 7284fb3b7e..d1d4a54073 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt @@ -539,6 +539,29 @@ class MessageComposerPresenterTest { } } + @Test + fun `present - ToggleTextFormatting toggles text formatting`() = runTest { + val presenter = createPresenter(this) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + skipItems(1) + val initialState = awaitItem() + assertThat(initialState.showTextFormatting).isFalse() + initialState.eventSink(MessageComposerEvents.AddAttachment) + val composerOptions = awaitItem() + assertThat(composerOptions.showAttachmentSourcePicker).isTrue() + composerOptions.eventSink(MessageComposerEvents.ToggleTextFormatting(true)) + awaitItem() // composer options closed + val showTextFormatting = awaitItem() + assertThat(showTextFormatting.showAttachmentSourcePicker).isFalse() + assertThat(showTextFormatting.showTextFormatting).isTrue() + showTextFormatting.eventSink(MessageComposerEvents.ToggleTextFormatting(false)) + val finished = awaitItem() + assertThat(finished.showTextFormatting).isFalse() + } + } + private suspend fun ReceiveTurbine.backToNormalMode(state: MessageComposerState, skipCount: Int = 0) { state.eventSink.invoke(MessageComposerEvents.CloseSpecialMode) skipItems(skipCount) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt index 4f06b3ebcb..cd1b408a99 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt @@ -28,4 +28,16 @@ object VectorIcons { val Groups = R.drawable.ic_groups val Share = R.drawable.ic_share val EndPoll = R.drawable.ic_poll_end + val Bold = R.drawable.ic_bold + val BulletList = R.drawable.ic_bullet_list + val CodeBlock = R.drawable.ic_code_block + val IndentIncrease = R.drawable.ic_indent_increase + val IndentDecrease = R.drawable.ic_indent_decrease + val InlineCode = R.drawable.ic_inline_code + val Italic = R.drawable.ic_italic + val Link = R.drawable.ic_link + val NumberedList = R.drawable.ic_numbered_list + val Quote = R.drawable.ic_quote + val Strikethrough = R.drawable.ic_strikethrough + val Underline = R.drawable.ic_underline } diff --git a/libraries/designsystem/src/main/res/drawable/ic_bold.xml b/libraries/designsystem/src/main/res/drawable/ic_bold.xml new file mode 100644 index 0000000000..c361f85d3d --- /dev/null +++ b/libraries/designsystem/src/main/res/drawable/ic_bold.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/designsystem/src/main/res/drawable/ic_bullet_list.xml b/libraries/designsystem/src/main/res/drawable/ic_bullet_list.xml new file mode 100644 index 0000000000..72d8324622 --- /dev/null +++ b/libraries/designsystem/src/main/res/drawable/ic_bullet_list.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/designsystem/src/main/res/drawable/ic_code_block.xml b/libraries/designsystem/src/main/res/drawable/ic_code_block.xml new file mode 100644 index 0000000000..6e622f5b27 --- /dev/null +++ b/libraries/designsystem/src/main/res/drawable/ic_code_block.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/designsystem/src/main/res/drawable/ic_indent_decrease.xml b/libraries/designsystem/src/main/res/drawable/ic_indent_decrease.xml new file mode 100644 index 0000000000..5a0b284223 --- /dev/null +++ b/libraries/designsystem/src/main/res/drawable/ic_indent_decrease.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/designsystem/src/main/res/drawable/ic_indent_increase.xml b/libraries/designsystem/src/main/res/drawable/ic_indent_increase.xml new file mode 100644 index 0000000000..367686ceac --- /dev/null +++ b/libraries/designsystem/src/main/res/drawable/ic_indent_increase.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/designsystem/src/main/res/drawable/ic_inline_code.xml b/libraries/designsystem/src/main/res/drawable/ic_inline_code.xml new file mode 100644 index 0000000000..c0dc504ed9 --- /dev/null +++ b/libraries/designsystem/src/main/res/drawable/ic_inline_code.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/libraries/designsystem/src/main/res/drawable/ic_italic.xml b/libraries/designsystem/src/main/res/drawable/ic_italic.xml new file mode 100644 index 0000000000..f640c109f4 --- /dev/null +++ b/libraries/designsystem/src/main/res/drawable/ic_italic.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/designsystem/src/main/res/drawable/ic_link.xml b/libraries/designsystem/src/main/res/drawable/ic_link.xml new file mode 100644 index 0000000000..fd69ec4703 --- /dev/null +++ b/libraries/designsystem/src/main/res/drawable/ic_link.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/designsystem/src/main/res/drawable/ic_numbered_list.xml b/libraries/designsystem/src/main/res/drawable/ic_numbered_list.xml new file mode 100644 index 0000000000..f4f5862656 --- /dev/null +++ b/libraries/designsystem/src/main/res/drawable/ic_numbered_list.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/designsystem/src/main/res/drawable/ic_quote.xml b/libraries/designsystem/src/main/res/drawable/ic_quote.xml new file mode 100644 index 0000000000..e17565a6cc --- /dev/null +++ b/libraries/designsystem/src/main/res/drawable/ic_quote.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/libraries/designsystem/src/main/res/drawable/ic_strikethrough.xml b/libraries/designsystem/src/main/res/drawable/ic_strikethrough.xml new file mode 100644 index 0000000000..d1994f8045 --- /dev/null +++ b/libraries/designsystem/src/main/res/drawable/ic_strikethrough.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/designsystem/src/main/res/drawable/ic_underline.xml b/libraries/designsystem/src/main/res/drawable/ic_underline.xml new file mode 100644 index 0000000000..09f92f2104 --- /dev/null +++ b/libraries/designsystem/src/main/res/drawable/ic_underline.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/textcomposer/impl/build.gradle.kts b/libraries/textcomposer/impl/build.gradle.kts index 3aaae7ca6e..633491d3b3 100644 --- a/libraries/textcomposer/impl/build.gradle.kts +++ b/libraries/textcomposer/impl/build.gradle.kts @@ -31,6 +31,8 @@ dependencies { implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrixui) implementation(projects.libraries.designsystem) + implementation(libs.androidx.constraintlayout) + implementation(libs.androidx.constraintlayout.compose) implementation(libs.matrix.richtexteditor) api(libs.matrix.richtexteditor.compose) diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt index 04fa08c9ce..d137af18bb 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt @@ -18,29 +18,29 @@ package io.element.android.libraries.textcomposer import androidx.compose.animation.core.animateDpAsState import androidx.compose.animation.core.tween -import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable +import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.interaction.MutableInteractionSource 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.PaddingValues 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.heightIn import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Close import androidx.compose.material.ripple.rememberRipple -import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -51,21 +51,22 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.ColorFilter -import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalSoftwareKeyboardController -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.res.vectorResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp +import androidx.constraintlayout.compose.ConstraintLayout +import androidx.constraintlayout.compose.Dimension.Companion.fillToConstraints +import androidx.constraintlayout.compose.Visibility import io.element.android.libraries.designsystem.VectorIcons -import io.element.android.libraries.designsystem.modifiers.applyIf import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.text.applyScaleUp import io.element.android.libraries.designsystem.theme.components.Icon -import io.element.android.libraries.designsystem.theme.components.Surface +import io.element.android.libraries.designsystem.theme.components.IconButton import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.TransactionId @@ -73,12 +74,17 @@ import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.ui.components.AttachmentThumbnail import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType +import io.element.android.libraries.textcomposer.components.FormattingOption +import io.element.android.libraries.textcomposer.components.FormattingOptionState import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.wysiwyg.compose.RichTextEditor import io.element.android.wysiwyg.compose.RichTextEditorDefaults import io.element.android.wysiwyg.compose.RichTextEditorState +import io.element.android.wysiwyg.view.models.InlineFormat import kotlinx.coroutines.android.awaitFrame +import uniffi.wysiwyg_composer.ActionState +import uniffi.wysiwyg_composer.ComposerAction @Composable fun TextComposer( @@ -86,112 +92,130 @@ fun TextComposer( composerMode: MessageComposerMode, canSendMessage: Boolean, modifier: Modifier = Modifier, + showTextFormatting: Boolean = false, onRequestFocus: () -> Unit = {}, onSendMessage: (Message) -> Unit = {}, onResetComposerMode: () -> Unit = {}, onAddAttachment: () -> Unit = {}, + onDismissTextFormatting: () -> Unit = {}, onError: (Throwable) -> Unit = {}, ) { - Row( - modifier.padding( - horizontal = 12.dp, - vertical = 8.dp - ), verticalAlignment = Alignment.Bottom - ) { - AttachmentButton(onClick = onAddAttachment, modifier = Modifier.padding(vertical = 6.dp)) - Spacer(modifier = Modifier.width(12.dp)) - val roundCornerSmall = 20.dp.applyScaleUp() - val roundCornerLarge = 28.dp.applyScaleUp() + val onSendClicked = { + onSendMessage(Message(html = state.messageHtml, markdown = state.messageMarkdown)) + } - val roundedCornerSize = remember(state.lineCount, composerMode) { - if (state.lineCount > 1 || composerMode is MessageComposerMode.Special) { - roundCornerSmall - } else { - roundCornerLarge - } - } - val roundedCornerSizeState = animateDpAsState( - targetValue = roundedCornerSize, - animationSpec = tween( - durationMillis = 100, + Column( + modifier = modifier + .padding( + start = 3.dp, + end = 6.dp, + top = 8.dp, + bottom = 5.dp, ) - ) - val roundedCorners = RoundedCornerShape(roundedCornerSizeState.value) - val minHeight = 42.dp.applyScaleUp() - val colors = ElementTheme.colors - val bgColor = colors.bgSubtleSecondary - - val borderColor by remember(state.hasFocus, colors) { - derivedStateOf { - if (state.hasFocus) colors.borderDisabled else bgColor + .fillMaxWidth(), + ) { + ConstraintLayout( + modifier = Modifier.fillMaxWidth(), + ) { + val (composeOptions, textInput, sendButton) = createRefs() + val showComposerOptionsButton by remember(showTextFormatting) { + derivedStateOf { !showTextFormatting } } - } + IconButton( + modifier = Modifier + .size(48.dp) + .constrainAs(composeOptions) { + start.linkTo(parent.start) + bottom.linkTo(parent.bottom) + visibility = if (showComposerOptionsButton) Visibility.Visible else Visibility.Gone + }, + onClick = onAddAttachment + ) { + Icon( + modifier = Modifier.size(30.dp.applyScaleUp()), + resourceId = R.drawable.ic_plus, // TODO Replace with design system icon when available + contentDescription = stringResource(R.string.rich_text_editor_a11y_add_attachment), + tint = ElementTheme.colors.iconPrimary, + ) + } + val roundCornerSmall = 20.dp.applyScaleUp() + val roundCornerLarge = 28.dp.applyScaleUp() - Column( - modifier = Modifier - .fillMaxWidth() - .clip(roundedCorners) - .background(color = bgColor) - .border(1.dp, borderColor, roundedCorners) - ) { - if (composerMode is MessageComposerMode.Special) { - ComposerModeView(composerMode = composerMode, onResetComposerMode = onResetComposerMode) + val roundedCornerSize = remember(state.lineCount, composerMode) { + if (state.lineCount > 1 || composerMode is MessageComposerMode.Special) { + roundCornerSmall + } else { + roundCornerLarge + } } - val defaultTypography = ElementTheme.typography.fontBodyLgRegular + val roundedCornerSizeState = animateDpAsState( + targetValue = roundedCornerSize, + animationSpec = tween( + durationMillis = 100, + ) + ) + val roundedCorners = RoundedCornerShape(roundedCornerSizeState.value) + val colors = ElementTheme.colors + val bgColor = colors.bgSubtleSecondary - Box { - Box( - modifier = Modifier - .heightIn(min = minHeight) - .background(color = bgColor, shape = roundedCorners) - .padding( - PaddingValues( - top = 4.dp.applyScaleUp(), - bottom = 4.dp.applyScaleUp(), - start = 12.dp.applyScaleUp(), - end = 42.dp.applyScaleUp() - ) - ), - contentAlignment = Alignment.CenterStart, - ) { + val borderColor by remember(state.hasFocus, colors) { + derivedStateOf { + if (state.hasFocus) colors.borderDisabled else bgColor + } + } - // Placeholder - if (state.messageHtml.isEmpty()) { - Text( - stringResource(CommonStrings.common_message), - style = defaultTypography.copy( - color = ElementTheme.colors.textDisabled, - ), - ) + Column( + modifier = Modifier + .constrainAs(textInput) { + start.linkTo(composeOptions.end, margin = 3.dp, goneMargin = 9.dp) + end.linkTo(sendButton.start, margin = 6.dp, goneMargin = 6.dp) + bottom.linkTo(parent.bottom) + width = fillToConstraints } - - RichTextEditor( - state = state, - modifier = Modifier - .fillMaxWidth(), - style = RichTextEditorDefaults.style( - text = RichTextEditorDefaults.textStyle( - color = if (state.hasFocus) { - MaterialTheme.colorScheme.primary - } else { - MaterialTheme.colorScheme.secondary - } - ), - cursor = RichTextEditorDefaults.cursorStyle( - color = ElementTheme.colors.iconAccentTertiary, - ) - ), - onError = onError - ) + .padding(vertical = 3.dp) + .fillMaxWidth() + .clip(roundedCorners) + .background(color = bgColor) + .border(1.dp, borderColor, roundedCorners) + ) { + if (composerMode is MessageComposerMode.Special) { + ComposerModeView(composerMode = composerMode, onResetComposerMode = onResetComposerMode) } - SendButton( - canSendMessage = canSendMessage, - onClick = { onSendMessage(Message(html = state.messageHtml, markdown = state.messageMarkdown)) }, - composerMode = composerMode, - modifier = Modifier.padding(end = 6.dp.applyScaleUp(), bottom = 6.dp.applyScaleUp()) + TextInput( + state = state, + roundedCorners = roundedCorners, + bgColor = bgColor, + onError = onError, ) } + + SendButton( + canSendMessage = canSendMessage, + onClick = onSendClicked, + composerMode = composerMode, + modifier = Modifier + .constrainAs(sendButton) { + bottom.linkTo(parent.bottom) + end.linkTo(parent.end) + visibility = if (!showTextFormatting) Visibility.Visible else Visibility.Gone + } + ) + } + + if (showTextFormatting) { + TextFormatting( + state = state, + onDismiss = onDismissTextFormatting, + sendButton = { + SendButton( + canSendMessage = canSendMessage, + onClick = onSendClicked, + composerMode = composerMode, + modifier = it + ) + }, + ) } } @@ -208,6 +232,192 @@ fun TextComposer( } } +@Composable +private fun TextInput( + state: RichTextEditorState, + roundedCorners: RoundedCornerShape, + bgColor: Color, + modifier: Modifier = Modifier, + onError: (Throwable) -> Unit = {}, +) { + val minHeight = 42.dp.applyScaleUp() + val defaultTypography = ElementTheme.typography.fontBodyLgRegular + Box( + modifier = modifier + .heightIn(min = minHeight) + .background(color = bgColor, shape = roundedCorners) + .padding( + PaddingValues( + top = 4.dp.applyScaleUp(), + bottom = 4.dp.applyScaleUp(), + start = 12.dp.applyScaleUp(), + end = 42.dp.applyScaleUp() + ) + ), + contentAlignment = Alignment.CenterStart, + ) { + + // Placeholder + if (state.messageHtml.isEmpty()) { + Text( + stringResource(CommonStrings.common_message), + style = defaultTypography.copy( + color = ElementTheme.colors.textDisabled, + ), + ) + } + + RichTextEditor( + state = state, + modifier = Modifier + .fillMaxWidth(), + style = RichTextEditorDefaults.style( + text = RichTextEditorDefaults.textStyle( + color = if (state.hasFocus) { + MaterialTheme.colorScheme.primary + } else { + MaterialTheme.colorScheme.secondary + } + ), + cursor = RichTextEditorDefaults.cursorStyle( + color = ElementTheme.colors.iconAccentTertiary, + ) + ), + onError = onError + ) + } +} + +@Composable +private fun TextFormatting( + state: RichTextEditorState, + onDismiss: () -> Unit, + modifier: Modifier = Modifier, + sendButton: @Composable (modifier: Modifier) -> Unit, +) { + ConstraintLayout( + modifier = modifier + .fillMaxWidth() + ) { + val (close, formatting, send) = createRefs() + + IconButton( + modifier = Modifier + .size(48.dp) + .constrainAs(close) { + start.linkTo(parent.start) + top.linkTo(parent.top) + bottom.linkTo(parent.bottom) + }, + onClick = onDismiss + ) { + Icon( + modifier = Modifier.size(30.dp.applyScaleUp()), + resourceId = R.drawable.ic_cancel, // TODO Replace with design system icon when available + contentDescription = stringResource(CommonStrings.action_close), + tint = ElementTheme.colors.iconPrimary, + ) + } + + val scrollState = rememberScrollState() + Row( + modifier = Modifier + .constrainAs(formatting) { + top.linkTo(parent.top) + bottom.linkTo(parent.bottom) + start.linkTo(close.end, margin = 3.dp) + end.linkTo(send.start, margin = 20.dp) + width = fillToConstraints + } + .horizontalScroll(scrollState), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(4.dp), + ) { + FormattingOption( + state = state.actions[ComposerAction.BOLD].toButtonState(), + onClick = { state.toggleInlineFormat(InlineFormat.Bold) }, + imageVector = ImageVector.vectorResource(VectorIcons.Bold), + contentDescription = stringResource(CommonStrings.rich_text_editor_format_bold) + ) + FormattingOption( + state = state.actions[ComposerAction.ITALIC].toButtonState(), + onClick = { state.toggleInlineFormat(InlineFormat.Italic) }, + imageVector = ImageVector.vectorResource(VectorIcons.Italic), + contentDescription = stringResource(CommonStrings.rich_text_editor_format_italic) + ) + FormattingOption( + state = state.actions[ComposerAction.UNDERLINE].toButtonState(), + onClick = { state.toggleInlineFormat(InlineFormat.Underline) }, + imageVector = ImageVector.vectorResource(VectorIcons.Underline), + contentDescription = stringResource(CommonStrings.rich_text_editor_format_underline) + ) + FormattingOption( + state = state.actions[ComposerAction.STRIKE_THROUGH].toButtonState(), + onClick = { state.toggleInlineFormat(InlineFormat.StrikeThrough) }, + imageVector = ImageVector.vectorResource(VectorIcons.Strikethrough), + contentDescription = stringResource(CommonStrings.rich_text_editor_format_strikethrough) + ) + FormattingOption( + state = state.actions[ComposerAction.UNORDERED_LIST].toButtonState(), + onClick = { state.toggleList(ordered = false) }, + imageVector = ImageVector.vectorResource(VectorIcons.BulletList), + contentDescription = stringResource(CommonStrings.rich_text_editor_bullet_list) + ) + FormattingOption( + state = state.actions[ComposerAction.ORDERED_LIST].toButtonState(), + onClick = { state.toggleList(ordered = true) }, + imageVector = ImageVector.vectorResource(VectorIcons.NumberedList), + contentDescription = stringResource(CommonStrings.rich_text_editor_numbered_list) + ) + FormattingOption( + state = state.actions[ComposerAction.INDENT].toButtonState(), + onClick = { state.indent() }, + imageVector = ImageVector.vectorResource(VectorIcons.IndentIncrease), + contentDescription = stringResource(CommonStrings.rich_text_editor_indent) + ) + FormattingOption( + state = state.actions[ComposerAction.UNINDENT].toButtonState(), + onClick = { state.unindent() }, + imageVector = ImageVector.vectorResource(VectorIcons.IndentDecrease), + contentDescription = stringResource(CommonStrings.rich_text_editor_unindent) + ) + FormattingOption( + state = state.actions[ComposerAction.INLINE_CODE].toButtonState(), + onClick = { state.toggleInlineFormat(InlineFormat.InlineCode) }, + imageVector = ImageVector.vectorResource(VectorIcons.InlineCode), + contentDescription = stringResource(CommonStrings.rich_text_editor_inline_code) + ) + FormattingOption( + state = state.actions[ComposerAction.CODE_BLOCK].toButtonState(), + onClick = { state.toggleCodeBlock() }, + imageVector = ImageVector.vectorResource(VectorIcons.CodeBlock), + contentDescription = stringResource(CommonStrings.rich_text_editor_code_block) + ) + FormattingOption( + state = state.actions[ComposerAction.QUOTE].toButtonState(), + onClick = { state.toggleQuote() }, + imageVector = ImageVector.vectorResource(VectorIcons.Quote), + contentDescription = stringResource(CommonStrings.rich_text_editor_quote) + ) + } + + sendButton( + Modifier.constrainAs(send) { + top.linkTo(parent.top) + bottom.linkTo(parent.bottom) + end.linkTo(parent.end) + }, + ) + } +} + +private fun ActionState?.toButtonState(): FormattingOptionState = + when (this) { + ActionState.ENABLED -> FormattingOptionState.Default + ActionState.REVERSED -> FormattingOptionState.Selected + ActionState.DISABLED, null -> FormattingOptionState.Disabled + } + @Composable private fun ComposerModeView( composerMode: MessageComposerMode, @@ -341,53 +551,17 @@ private fun ReplyToModeView( } @Composable -private fun AttachmentButton( - onClick: () -> Unit, - modifier: Modifier = Modifier -) { - Surface( - modifier - .size(30.dp.applyScaleUp()) - .clickable(onClick = onClick), - shape = CircleShape, - color = ElementTheme.colors.iconPrimary - ) { - Image( - modifier = Modifier.size(12.5f.dp.applyScaleUp()), - painter = painterResource(R.drawable.ic_add_attachment), - contentDescription = stringResource(R.string.rich_text_editor_a11y_add_attachment), - contentScale = ContentScale.Inside, - colorFilter = ColorFilter.tint( - LocalContentColor.current - ) - ) - } -} - -@Composable -private fun BoxScope.SendButton( +private fun SendButton( canSendMessage: Boolean, onClick: () -> Unit, composerMode: MessageComposerMode, modifier: Modifier = Modifier, ) { - val interactionSource = remember { MutableInteractionSource() } - Box( + IconButton( modifier = modifier - .clip(CircleShape) - .background(if (canSendMessage) ElementTheme.colors.iconAccentTertiary else Color.Transparent) - .size(30.dp.applyScaleUp()) - .align(Alignment.BottomEnd) - .applyIf(composerMode !is MessageComposerMode.Edit, ifTrue = { - padding(start = 1.dp.applyScaleUp()) // Center the arrow in the circle - }) - .clickable( - enabled = canSendMessage, - interactionSource = interactionSource, - indication = rememberRipple(bounded = false), - onClick = onClick, - ), - contentAlignment = Alignment.Center, + .size(48.dp.applyScaleUp()), + onClick = onClick, + enabled = canSendMessage, ) { val iconId = when (composerMode) { is MessageComposerMode.Edit -> R.drawable.ic_tick @@ -397,13 +571,22 @@ private fun BoxScope.SendButton( is MessageComposerMode.Edit -> stringResource(CommonStrings.action_edit) else -> stringResource(CommonStrings.action_send) } - Icon( - modifier = Modifier.size(16.dp.applyScaleUp()), - resourceId = iconId, - contentDescription = contentDescription, - // Exception here, we use Color.White instead of ElementTheme.colors.iconOnSolidPrimary - tint = if (canSendMessage) Color.White else ElementTheme.colors.iconDisabled - ) + Box( + modifier = Modifier + .clip(CircleShape) + .size(36.dp.applyScaleUp()) + .background(if (canSendMessage) ElementTheme.colors.iconAccentTertiary else Color.Transparent) + ) { + Icon( + modifier = Modifier + .height(18.dp.applyScaleUp()) + .align(Alignment.Center), + resourceId = iconId, + contentDescription = contentDescription, + // Exception here, we use Color.White instead of ElementTheme.colors.iconOnSolidPrimary + tint = if (canSendMessage) Color.White else ElementTheme.colors.iconDisabled + ) + } } } @@ -447,6 +630,31 @@ internal fun TextComposerSimplePreview() = ElementPreview { } } +@DayNightPreviews +@Composable +internal fun TextComposerFormattingPreview() = ElementPreview { + Column { + TextComposer( + RichTextEditorState("", fake = true), + canSendMessage = false, + showTextFormatting = true, + composerMode = MessageComposerMode.Normal(""), + ) + TextComposer( + RichTextEditorState("A message", fake = true), + canSendMessage = true, + showTextFormatting = true, + composerMode = MessageComposerMode.Normal(""), + ) + TextComposer( + RichTextEditorState("A message\nWith several lines\nTo preview larger textfields and long lines with overflow", fake = true), + canSendMessage = true, + showTextFormatting = true, + composerMode = MessageComposerMode.Normal(""), + ) + } +} + @DayNightPreviews @Composable internal fun TextComposerEditPreview() = ElementPreview { diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/FormattingOption.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/FormattingOption.kt new file mode 100644 index 0000000000..7eb1d08293 --- /dev/null +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/FormattingOption.kt @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.textcomposer.components + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.unit.dp +import io.element.android.libraries.designsystem.text.applyScaleUp +import io.element.android.libraries.designsystem.theme.components.Icon +import io.element.android.libraries.theme.ElementTheme +import io.element.android.libraries.theme.compound.generated.SemanticColors + +@Composable +internal fun FormattingOption( + state: FormattingOptionState, + onClick: () -> Unit, + imageVector: ImageVector, + contentDescription: String, + modifier: Modifier = Modifier, + colors: SemanticColors = ElementTheme.colors, +) { + val backgroundColor = when (state) { + FormattingOptionState.Selected -> colors.bgActionPrimaryRest + FormattingOptionState.Default, + FormattingOptionState.Disabled -> Color.Transparent + } + + val foregroundColor = when (state) { + FormattingOptionState.Selected -> colors.iconOnSolidPrimary + FormattingOptionState.Default -> colors.iconPrimary + FormattingOptionState.Disabled -> colors.iconDisabled + } + Box( + modifier = modifier + .clickable { onClick() } + .size(44.dp.applyScaleUp()) + .background(backgroundColor, shape = RoundedCornerShape(4.dp.applyScaleUp())) + ) { + Icon( + modifier = Modifier.align(Alignment.Center), + imageVector = imageVector, + contentDescription = contentDescription, + tint = foregroundColor, + ) + } +} + diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/FormattingOptionState.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/FormattingOptionState.kt new file mode 100644 index 0000000000..386fa5a668 --- /dev/null +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/FormattingOptionState.kt @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.textcomposer.components + +internal enum class FormattingOptionState { + Default, Selected, Disabled +} + diff --git a/libraries/textcomposer/impl/src/main/res/drawable/ic_add_attachment.xml b/libraries/textcomposer/impl/src/main/res/drawable/ic_add_attachment.xml deleted file mode 100644 index ac9d53639b..0000000000 --- a/libraries/textcomposer/impl/src/main/res/drawable/ic_add_attachment.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/libraries/textcomposer/impl/src/main/res/drawable/ic_cancel.xml b/libraries/textcomposer/impl/src/main/res/drawable/ic_cancel.xml new file mode 100644 index 0000000000..5c27ba82d9 --- /dev/null +++ b/libraries/textcomposer/impl/src/main/res/drawable/ic_cancel.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/textcomposer/impl/src/main/res/drawable/ic_plus.xml b/libraries/textcomposer/impl/src/main/res/drawable/ic_plus.xml new file mode 100644 index 0000000000..ead38721dc --- /dev/null +++ b/libraries/textcomposer/impl/src/main/res/drawable/ic_plus.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/textcomposer/impl/src/main/res/drawable/ic_send.xml b/libraries/textcomposer/impl/src/main/res/drawable/ic_send.xml index 64e0f120c4..bf346b3a01 100644 --- a/libraries/textcomposer/impl/src/main/res/drawable/ic_send.xml +++ b/libraries/textcomposer/impl/src/main/res/drawable/ic_send.xml @@ -1,9 +1,9 @@ + android:width="21dp" + android:height="18dp" + android:viewportWidth="21" + android:viewportHeight="18"> + android:pathData="M20.252,10.085 L4.681,17.867c-1.049,0.525 -2.141,-0.601 -1.628,-1.627 0,0 1.93,-3.897 2.461,-4.918 0.531,-1.021 1.138,-1.197 6.781,-1.927 0.209,-0.027 0.38,-0.185 0.38,-0.395 0,-0.21 -0.171,-0.368 -0.38,-0.395C6.652,7.876 6.045,7.699 5.514,6.678 4.983,5.658 3.053,1.76 3.053,1.76 2.54,0.734 3.632,-0.391 4.681,0.133L20.252,7.915c0.894,0.446 0.894,1.723 0,2.17z" + android:fillColor="@android:color/white"/> diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_AttachmentSourcePickerMenu-D-1_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_AttachmentSourcePickerMenu-D-1_2_null,NEXUS_5,1.0,en].png index 58ebf07374..efcd596b40 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_AttachmentSourcePickerMenu-D-1_2_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_AttachmentSourcePickerMenu-D-1_2_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:79aeef6875265e119c3b4b97cea4d36ba3354ae52c4b94b69bbc09461b7bc319 -size 22259 +oid sha256:e67b171ca09fd2efb25338a20fe7af7464e0e1ecb1b02afd679dbfc7cd3cd7df +size 25646 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_AttachmentSourcePickerMenu-N-1_3_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_AttachmentSourcePickerMenu-N-1_3_null,NEXUS_5,1.0,en].png index 6e91b56f10..a385dd8498 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_AttachmentSourcePickerMenu-N-1_3_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_AttachmentSourcePickerMenu-N-1_3_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8dafa9a97ebc77f00fdb0432c7b94272f6ea1873c3475353be47ecde95e8b057 -size 20670 +oid sha256:e92e96cc117bf42ffb9fa282bcb9e40fd51c414e1d432862940c0f8fb6600fd0 +size 23453 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewDark_0_null_0,NEXUS_5,1.0,en].png index fa68f3bd24..ee0937d439 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4013454094701004f3c132df1ea1c3db2aa56a025b9edea80417fdd16fe55b19 -size 10422 +oid sha256:f3ea303577f655368800debe9c40e1292dc08a20da7f2ea6ddddb87f8407b112 +size 10431 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewLight_0_null_0,NEXUS_5,1.0,en].png index f6040d0e1a..e537e910e3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:db74b1655e377e4fd8c35aa18c22ef5f5641586b64d5e582ab2079afeac4b8c3 -size 10775 +oid sha256:b646c06e55b50b64eb7b566fbc0bcafa7f7e348398f87152d008a47e7448f4e0 +size 10736 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_0,NEXUS_5,1.0,en].png index 2a10272dac..00cfa0d87e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cfc6f54988e4fab08ff443f0c2ea285d47e3d030a8e6c92a1294ee0f85dc1269 -size 51967 +oid sha256:ba052f24e62aabc015da4b38bb893148c888a858a097669b2191e7880867e371 +size 52114 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_1,NEXUS_5,1.0,en].png index 5cf07497cd..57d6580a12 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d2ffd4fc93e7da38836fd860ce5e505c5f0c25fdd6558efef480aaeb05d00dd5 -size 53327 +oid sha256:4f8f7fd27e56aa2ca42053c249353836187467b99a9225c93c22f38365e63ccb +size 53285 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png index 41f0170682..8a4f9bc201 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:96864552336c65b464251c262f330856fc82c69a5f92f89b1357a185d654fccd -size 52252 +oid sha256:fbfc5593de6c7dda915b3a8bc881f0485b4b8400f52412547aa914862d1d8840 +size 52245 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_4,NEXUS_5,1.0,en].png index a022fb7675..6907cccce9 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2411212e87f95415e0b4ed6732387922faed891cde5e78fa9f0691a185873129 -size 51026 +oid sha256:d56d5666d1d7749484f19c983e3cb2125110039c80e5898684e20b7e24a3e56b +size 51312 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_5,NEXUS_5,1.0,en].png index 5fe74737cf..b2e621fc71 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:255560f478c093f4ca7d021646f4cf9064c16b420d5eeec7cbce97d26c751d92 -size 49540 +oid sha256:db0107e648e2acfc253d83f5e3b2f3e41de1abc9bdc4922dfd923ad4e50b8f5f +size 49700 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_0,NEXUS_5,1.0,en].png index caf6d5a3da..1746cfeb84 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a384aa84ae514aa4989d4b4a5ef8048cb8810f1f37056137c77fd0ee798a0bab -size 53941 +oid sha256:398f4b1c7b21ab4c57802fb724d62b8c904f5a0c700eba507a811cb58881df49 +size 53896 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_1,NEXUS_5,1.0,en].png index 93163a476e..69a8b67d95 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a48badf15c59ab5c42fc7cc200971f00cefa7838461ad0cb59537c2b4065bfff -size 55409 +oid sha256:2913fc7ee2c4b32e79e0d813ee8fa54e6d3f863466b798b8194462cbd9ef4fde +size 55137 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png index 1ff65d3301..f8b59bb375 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:88a498b9070653513b3e27aa2b597367ee85c8526c6e4c3712a4cb0c06e5313b -size 54353 +oid sha256:a20479945a552e2d3d3fb309c07ac7b9a66d4dfac0ad1ddf2c86c40fa0d34db9 +size 54175 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_4,NEXUS_5,1.0,en].png index be91f54717..367b0dc907 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bf493a9cb7325b4f68924abd86864b37c72226afcf1c4179a06c17e923cfd0ae -size 55837 +oid sha256:1e7697c3f1eb995fc0bbf084853fce1cc10e841d0275d6ff4f2d857afd81b31d +size 56103 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_5,NEXUS_5,1.0,en].png index 432e114fd5..cbdda6b794 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8ac3dbf36380fa273d82ebe8836c525bbeee004d6348822d965b216f9bcdb920 -size 51335 +oid sha256:7e162503c27609f01e05bb2c634c2d3123abf6e786ecfe763c902d400ead050f +size 51283 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-D-1_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-D-1_2_null,NEXUS_5,1.0,en].png deleted file mode 100644 index b1144213da..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-D-1_2_null,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ce08e8c81d5494d2d803da43612a137df881e359646878b1d38cdfe77e0857ff -size 13829 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-D-2_3_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-D-2_3_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..9d906ebe35 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-D-2_3_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:46683edccf9c7686a07d7098c4387f296556ad2678381aad35efe2787cf6ad0a +size 14173 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-N-1_3_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-N-1_3_null,NEXUS_5,1.0,en].png deleted file mode 100644 index 62264fcf27..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-N-1_3_null,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3c2ba0ac13c81c707f0d00e3ff69737163dfc450a3d21aa468dd0b34deeeb7e1 -size 12916 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-N-2_4_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-N-2_4_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..4b9d77d2b1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-N-2_4_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6485de8235af05a9815a558b1af03b51e8c4b30ad0372aea0aa9fb2303525c9b +size 13286 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-D-1_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-D-1_2_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..760cf75800 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-D-1_2_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d0e4c8da669ee5383a7d0f828a3300b923ec38ab5e04bc388da0e83f1cf1ccf3 +size 38291 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-N-1_3_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-N-1_3_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..0b9f9f3ab7 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-N-1_3_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1f26aa7b13403cfaa864778a6ec5c26edde5932f3d887c7148d3a2b9f60f6e6a +size 36392 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-2_3_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-2_3_null,NEXUS_5,1.0,en].png deleted file mode 100644 index 3e872eda82..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-2_3_null,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f15bc37e2a3d052e8d79e663f2c03223c27ddff3c02cd69f95a140c33fc6952c -size 79320 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..37e8a8561f --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e65e15c721a939ed700719cacbdee57e1ccb89d984e88bdb5ed772c4b583472a +size 81494 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-2_4_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-2_4_null,NEXUS_5,1.0,en].png deleted file mode 100644 index 8bd9e09c69..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-2_4_null,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6aa9b8849a2bbd7b487de6fee7fd355300091bc14d647973c4beea02e6009ac4 -size 76465 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..466f321959 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:49f6d3b7f93008640abf30a5a65ddca6845e16343ef97c3450faf9dd6d9b9cec +size 78788 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-D-0_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-D-0_1_null,NEXUS_5,1.0,en].png index 8afc6fc94a..d6beb7c22c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-D-0_1_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-D-0_1_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:501734b297cec566a008d3492690cf75b46ab68e662d2835a0b195fd0740c13f -size 42912 +oid sha256:2a998d3db9e4454fe74f31028b1dc61e4d6c07c824192f5e75563234dedf0b26 +size 44108 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-N-0_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-N-0_2_null,NEXUS_5,1.0,en].png index de57e08951..863e8b8628 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-N-0_2_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-N-0_2_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ff69ed7056380df3279a39b7544bc1887d2e455b43fb069b547e32cf5c92dc0f -size 40229 +oid sha256:97ab0a0b64ea7704a1557fc34b24d7caea34f9951948f5f5637f0bda596288dd +size 41455 From baebe419e745197daf81320eb221edcd4bcc1adb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 10 Sep 2023 13:12:46 +0000 Subject: [PATCH 077/234] Update dependency io.nlopez.compose.rules:detekt to v0.2.2 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index bd0f84177a..5c958fc397 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -62,7 +62,7 @@ allprojects { config.from(files("$rootDir/tools/detekt/detekt.yml")) } dependencies { - detektPlugins("io.nlopez.compose.rules:detekt:0.2.1") + detektPlugins("io.nlopez.compose.rules:detekt:0.2.2") } // KtLint From 33457e9c58f9c2309e0f5b69c3074cb17d81a2f9 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 11 Sep 2023 07:54:44 +0200 Subject: [PATCH 078/234] Make sure notification permission screen is dismissed (#1263) * Make sure notification permission screen is dismissed --- .../notifications/NotificationsOptInPresenter.kt | 16 ++++++++++++---- .../impl/notifications/NotificationsOptInView.kt | 7 ------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenter.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenter.kt index f7e4b6b26d..f3bffca590 100644 --- a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenter.kt +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenter.kt @@ -20,6 +20,7 @@ import android.Manifest import android.os.Build import androidx.annotation.RequiresApi import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject @@ -56,15 +57,15 @@ class NotificationsOptInPresenter @AssistedInject constructor( @Composable override fun present(): NotificationsOptInState { - val notificationPremissionsState = postNotificationPermissionsPresenter.present() + val notificationsPermissionsState = postNotificationPermissionsPresenter.present() fun handleEvents(event: NotificationsOptInEvents) { when (event) { NotificationsOptInEvents.ContinueClicked -> { - if (notificationPremissionsState.permissionGranted) { + if (notificationsPermissionsState.permissionGranted) { callback.onNotificationsOptInFinished() } else { - notificationPremissionsState.eventSink(PermissionsEvents.OpenSystemDialog) + notificationsPermissionsState.eventSink(PermissionsEvents.OpenSystemDialog) } } NotificationsOptInEvents.NotNowClicked -> { @@ -76,8 +77,15 @@ class NotificationsOptInPresenter @AssistedInject constructor( } } + LaunchedEffect(notificationsPermissionsState) { + if (notificationsPermissionsState.permissionGranted + || notificationsPermissionsState.permissionAlreadyDenied) { + callback.onNotificationsOptInFinished() + } + } + return NotificationsOptInState( - notificationsPermissionState = notificationPremissionsState, + notificationsPermissionState = notificationsPermissionsState, eventSink = ::handleEvents ) } diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt index 73135cafdc..0b0676074b 100644 --- a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt @@ -32,7 +32,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Notifications import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -64,12 +63,6 @@ fun NotificationsOptInView( ) { BackHandler(onBack = onBack) - if (state.notificationsPermissionState.permissionAlreadyDenied) { - LaunchedEffect(Unit) { - state.eventSink(NotificationsOptInEvents.NotNowClicked) - } - } - HeaderFooterPage( modifier = modifier .systemBarsPadding() From 5059d67238f168a49ca2791e78425ebe2f431089 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 Sep 2023 15:04:21 +0200 Subject: [PATCH 079/234] Iterate on tracing configuration - Add targets matrix_sdk, matrix_sdk::client and matrix_sdk::oidc - introduce default log level. --- .../tracing/TargetLogLevelMapBuilder.kt | 2 -- .../api/tracing/TracingFilterConfiguration.kt | 17 ++++++++--------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/tracing/TargetLogLevelMapBuilder.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/tracing/TargetLogLevelMapBuilder.kt index c70d573430..b851c15279 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/tracing/TargetLogLevelMapBuilder.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/tracing/TargetLogLevelMapBuilder.kt @@ -29,7 +29,6 @@ class TargetLogLevelMapBuilder @Inject constructor( fun getDefaultMap(): Map { return Target.entries.associateWith { target -> defaultConfig.getLogLevel(target) - ?: LogLevel.INFO } } @@ -37,7 +36,6 @@ class TargetLogLevelMapBuilder @Inject constructor( return Target.entries.associateWith { target -> tracingConfigurationStore.getLogLevel(target) ?: defaultConfig.getLogLevel(target) - ?: LogLevel.INFO } } } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/TracingFilterConfiguration.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/TracingFilterConfiguration.kt index d34911644e..3062fa3aa3 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/TracingFilterConfiguration.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/tracing/TracingFilterConfiguration.kt @@ -19,27 +19,25 @@ package io.element.android.libraries.matrix.api.tracing data class TracingFilterConfiguration( val overrides: Map = emptyMap(), ) { + private val defaultLogLevel = LogLevel.INFO // Order should matters private val targetsToLogLevel: Map = mapOf( - Target.COMMON to LogLevel.INFO, Target.HYPER to LogLevel.WARN, Target.MATRIX_SDK_CRYPTO to LogLevel.DEBUG, Target.MATRIX_SDK_HTTP_CLIENT to LogLevel.DEBUG, Target.MATRIX_SDK_SLIDING_SYNC to LogLevel.TRACE, Target.MATRIX_SDK_BASE_SLIDING_SYNC to LogLevel.TRACE, - Target.MATRIX_SDK_UI_TIMELINE to LogLevel.INFO, ) - fun getLogLevel(target: Target): LogLevel? { - return overrides[target] ?: targetsToLogLevel[target] + fun getLogLevel(target: Target): LogLevel { + return overrides[target] ?: targetsToLogLevel[target] ?: defaultLogLevel } val filter: String get() { - val fullMap = targetsToLogLevel.toMutableMap() - overrides.forEach { (target, logLevel) -> - fullMap[target] = logLevel + val fullMap = Target.values().associateWith { + overrides[it] ?: targetsToLogLevel[it] ?: defaultLogLevel } return fullMap.map { if (it.key.filter.isEmpty()) { @@ -58,7 +56,10 @@ enum class Target(open val filter: String) { MATRIX_SDK_FFI("matrix_sdk_ffi"), MATRIX_SDK_UNIFFI_API("matrix_sdk_ffi::uniffi_api"), MATRIX_SDK_CRYPTO("matrix_sdk_crypto"), + MATRIX_SDK("matrix_sdk"), MATRIX_SDK_HTTP_CLIENT("matrix_sdk::http_client"), + MATRIX_SDK_CLIENT("matrix_sdk::client"), + MATRIX_SDK_OIDC("matrix_sdk::oidc"), MATRIX_SDK_SLIDING_SYNC("matrix_sdk::sliding_sync"), MATRIX_SDK_BASE_SLIDING_SYNC("matrix_sdk_base::sliding_sync"), MATRIX_SDK_UI_TIMELINE("matrix_sdk_ui::timeline"), @@ -75,13 +76,11 @@ enum class LogLevel(open val filter: String) { object TracingFilterConfigurations { val release = TracingFilterConfiguration( overrides = mapOf( - Target.COMMON to LogLevel.INFO, Target.ELEMENT to LogLevel.DEBUG ), ) val debug = TracingFilterConfiguration( overrides = mapOf( - Target.COMMON to LogLevel.INFO, Target.ELEMENT to LogLevel.TRACE ) ) From 9f02de45b864a15d542deaa61cb1fb09674a0fba Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 11 Sep 2023 09:17:50 +0200 Subject: [PATCH 080/234] setenv "RUST_BACKTRACE" to "1" to get more info when a Rust stacktrace is printed out. --- .../io/element/android/x/initializer/TracingInitializer.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/kotlin/io/element/android/x/initializer/TracingInitializer.kt b/app/src/main/kotlin/io/element/android/x/initializer/TracingInitializer.kt index 7b93812d35..853412e403 100644 --- a/app/src/main/kotlin/io/element/android/x/initializer/TracingInitializer.kt +++ b/app/src/main/kotlin/io/element/android/x/initializer/TracingInitializer.kt @@ -17,6 +17,7 @@ package io.element.android.x.initializer import android.content.Context +import android.system.Os import androidx.preference.PreferenceManager import androidx.startup.Initializer import io.element.android.features.preferences.impl.developer.tracing.SharedPrefTracingConfigurationStore @@ -57,6 +58,8 @@ class TracingInitializer : Initializer { } bugReporter.cleanLogDirectoryIfNeeded() tracingService.setupTracing(tracingConfiguration) + // Also set env variable for rust back trace + Os.setenv("RUST_BACKTRACE", "1", true) } override fun dependencies(): List>> = mutableListOf() From a30af97ecd8dd9a6de160948f2bf79cd5838f83e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 11 Sep 2023 09:57:45 +0200 Subject: [PATCH 081/234] Add ConfigureTracingEntryPoint to be able to access the screen from outside the Preference screen. --- .../api/ConfigureTracingEntryPoint.kt | 21 ++++++++++++ .../impl/DefaultConfigureTracingEntryPoint.kt | 33 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 features/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/ConfigureTracingEntryPoint.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/DefaultConfigureTracingEntryPoint.kt diff --git a/features/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/ConfigureTracingEntryPoint.kt b/features/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/ConfigureTracingEntryPoint.kt new file mode 100644 index 0000000000..803c0c9232 --- /dev/null +++ b/features/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/ConfigureTracingEntryPoint.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.api + +import io.element.android.libraries.architecture.SimpleFeatureEntryPoint + +interface ConfigureTracingEntryPoint : SimpleFeatureEntryPoint diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/DefaultConfigureTracingEntryPoint.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/DefaultConfigureTracingEntryPoint.kt new file mode 100644 index 0000000000..372acbd1f4 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/DefaultConfigureTracingEntryPoint.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl + +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.features.preferences.api.ConfigureTracingEntryPoint +import io.element.android.features.preferences.impl.developer.tracing.ConfigureTracingNode +import io.element.android.libraries.architecture.createNode +import io.element.android.libraries.di.AppScope +import javax.inject.Inject + +@ContributesBinding(AppScope::class) +class DefaultConfigureTracingEntryPoint @Inject constructor() : ConfigureTracingEntryPoint { + override fun createNode(parentNode: Node, buildContext: BuildContext): Node { + return parentNode.createNode(buildContext) + } +} From 9c9a6ce7be5388c8299f2d5b1c3dd0995094d3cc Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 11 Sep 2023 09:58:40 +0200 Subject: [PATCH 082/234] Add a way to configure tracing when the session does not exist yet. --- .../android/appnav/NotLoggedInFlowNode.kt | 12 ++++++ .../onboarding/api/OnBoardingEntryPoint.kt | 1 + .../onboarding/impl/OnBoardingNode.kt | 6 +++ .../onboarding/impl/OnBoardingPresenter.kt | 4 ++ .../onboarding/impl/OnBoardingState.kt | 1 + .../impl/OnBoardingStateProvider.kt | 3 ++ .../onboarding/impl/OnBoardingView.kt | 41 ++++++++++++++++--- 7 files changed, 62 insertions(+), 6 deletions(-) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/NotLoggedInFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/NotLoggedInFlowNode.kt index 17f3a44eb8..6c22644658 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/NotLoggedInFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/NotLoggedInFlowNode.kt @@ -32,6 +32,7 @@ import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode import io.element.android.features.login.api.LoginEntryPoint import io.element.android.features.onboarding.api.OnBoardingEntryPoint +import io.element.android.features.preferences.api.ConfigureTracingEntryPoint import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.di.AppScope @@ -43,6 +44,7 @@ class NotLoggedInFlowNode @AssistedInject constructor( @Assisted buildContext: BuildContext, @Assisted plugins: List, private val onBoardingEntryPoint: OnBoardingEntryPoint, + private val configureTracingEntryPoint: ConfigureTracingEntryPoint, private val loginEntryPoint: LoginEntryPoint, private val notLoggedInImageLoaderFactory: NotLoggedInImageLoaderFactory, ) : BackstackNode( @@ -70,6 +72,9 @@ class NotLoggedInFlowNode @AssistedInject constructor( data class LoginFlow( val isAccountCreation: Boolean, ) : NavTarget + + @Parcelize + data object ConfigureTracing : NavTarget } override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { @@ -83,6 +88,10 @@ class NotLoggedInFlowNode @AssistedInject constructor( override fun onSignIn() { backstack.push(NavTarget.LoginFlow(isAccountCreation = false)) } + + override fun onOpenDeveloperSettings() { + backstack.push(NavTarget.ConfigureTracing) + } } onBoardingEntryPoint .nodeBuilder(this, buildContext) @@ -94,6 +103,9 @@ class NotLoggedInFlowNode @AssistedInject constructor( .params(LoginEntryPoint.Params(isAccountCreation = navTarget.isAccountCreation)) .build() } + NavTarget.ConfigureTracing -> { + configureTracingEntryPoint.createNode(this, buildContext) + } } } diff --git a/features/onboarding/api/src/main/kotlin/io/element/android/features/onboarding/api/OnBoardingEntryPoint.kt b/features/onboarding/api/src/main/kotlin/io/element/android/features/onboarding/api/OnBoardingEntryPoint.kt index 7be45ce236..d183b05386 100644 --- a/features/onboarding/api/src/main/kotlin/io/element/android/features/onboarding/api/OnBoardingEntryPoint.kt +++ b/features/onboarding/api/src/main/kotlin/io/element/android/features/onboarding/api/OnBoardingEntryPoint.kt @@ -33,5 +33,6 @@ interface OnBoardingEntryPoint : FeatureEntryPoint { interface Callback : Plugin { fun onSignUp() fun onSignIn() + fun onOpenDeveloperSettings() } } diff --git a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingNode.kt b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingNode.kt index d86623cae2..21322657c1 100644 --- a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingNode.kt +++ b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingNode.kt @@ -46,6 +46,10 @@ class OnBoardingNode @AssistedInject constructor( plugins().forEach { it.onSignUp() } } + private fun onOpenDeveloperSettings() { + plugins().forEach { it.onOpenDeveloperSettings() } + } + @Composable override fun View(modifier: Modifier) { val state = presenter.present() @@ -54,6 +58,8 @@ class OnBoardingNode @AssistedInject constructor( modifier = modifier, onSignIn = ::onSignIn, onCreateAccount = ::onSignUp, + onSignInWithQrCode = { /* Not supported yet */ }, + onOpenDeveloperSettings = ::onOpenDeveloperSettings, ) } } diff --git a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenter.kt b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenter.kt index 48a360e6c9..b26752fdbe 100644 --- a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenter.kt +++ b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenter.kt @@ -18,6 +18,8 @@ package io.element.android.features.onboarding.impl import androidx.compose.runtime.Composable import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.core.meta.BuildMeta +import io.element.android.libraries.core.meta.BuildType import javax.inject.Inject /** @@ -25,10 +27,12 @@ import javax.inject.Inject * When this presenter get more code in it, please remove the ignore rule in the kover configuration. */ class OnBoardingPresenter @Inject constructor( + private val buildMeta: BuildMeta, ) : Presenter { @Composable override fun present(): OnBoardingState { return OnBoardingState( + isDebugBuild = buildMeta.buildType != BuildType.RELEASE, canLoginWithQrCode = OnBoardingConfig.canLoginWithQrCode, canCreateAccount = OnBoardingConfig.canCreateAccount, ) diff --git a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingState.kt b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingState.kt index 88215c0c1e..5bd7718033 100644 --- a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingState.kt +++ b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingState.kt @@ -17,6 +17,7 @@ package io.element.android.features.onboarding.impl data class OnBoardingState( + val isDebugBuild: Boolean, val canLoginWithQrCode: Boolean, val canCreateAccount: Boolean, ) diff --git a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingStateProvider.kt b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingStateProvider.kt index 1c60a56018..926d2a2303 100644 --- a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingStateProvider.kt +++ b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingStateProvider.kt @@ -25,13 +25,16 @@ open class OnBoardingStateProvider : PreviewParameterProvider { anOnBoardingState(canLoginWithQrCode = true), anOnBoardingState(canCreateAccount = true), anOnBoardingState(canLoginWithQrCode = true, canCreateAccount = true), + anOnBoardingState(isDebugBuild = true), ) } fun anOnBoardingState( + isDebugBuild: Boolean = false, canLoginWithQrCode: Boolean = false, canCreateAccount: Boolean = false ) = OnBoardingState( + isDebugBuild = isDebugBuild, canLoginWithQrCode = canLoginWithQrCode, canCreateAccount = canCreateAccount ) diff --git a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingView.kt b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingView.kt index 1adfe6bd93..875b79d8f2 100644 --- a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingView.kt +++ b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingView.kt @@ -25,7 +25,9 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.QrCode +import androidx.compose.material.icons.filled.Settings import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment.Companion.CenterHorizontally import androidx.compose.ui.BiasAlignment import androidx.compose.ui.Modifier @@ -41,6 +43,8 @@ import io.element.android.libraries.designsystem.atomic.pages.OnBoardingPage import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.theme.components.Button +import io.element.android.libraries.designsystem.theme.components.Icon +import io.element.android.libraries.designsystem.theme.components.IconButton import io.element.android.libraries.designsystem.theme.components.IconSource import io.element.android.libraries.designsystem.theme.components.OutlinedButton import io.element.android.libraries.designsystem.theme.components.Text @@ -58,14 +62,18 @@ import io.element.android.libraries.ui.strings.CommonStrings fun OnBoardingView( state: OnBoardingState, modifier: Modifier = Modifier, - onSignInWithQrCode: () -> Unit = {}, - onSignIn: () -> Unit = {}, - onCreateAccount: () -> Unit = {}, + onSignInWithQrCode: () -> Unit, + onSignIn: () -> Unit, + onCreateAccount: () -> Unit, + onOpenDeveloperSettings: () -> Unit, ) { OnBoardingPage( modifier = modifier, content = { - OnBoardingContent() + OnBoardingContent( + state = state, + onOpenDeveloperSettings = onOpenDeveloperSettings + ) }, footer = { OnBoardingButtons( @@ -79,7 +87,11 @@ fun OnBoardingView( } @Composable -private fun OnBoardingContent(modifier: Modifier = Modifier) { +private fun OnBoardingContent( + state: OnBoardingState, + onOpenDeveloperSettings: () -> Unit, + modifier: Modifier = Modifier +) { Box( modifier = modifier.fillMaxSize(), ) { @@ -122,6 +134,17 @@ private fun OnBoardingContent(modifier: Modifier = Modifier) { ) } } + if (state.isDebugBuild) { + IconButton( + modifier = Modifier.align(Alignment.TopEnd), + onClick = onOpenDeveloperSettings, + ) { + Icon( + imageVector = Icons.Filled.Settings, + contentDescription = stringResource(CommonStrings.common_settings) + ) + } + } } } @@ -172,5 +195,11 @@ private fun OnBoardingButtons( internal fun OnBoardingScreenPreview( @PreviewParameter(OnBoardingStateProvider::class) state: OnBoardingState ) = ElementPreview { - OnBoardingView(state) + OnBoardingView( + state = state, + onSignInWithQrCode = {}, + onSignIn = {}, + onCreateAccount = {}, + onOpenDeveloperSettings = {} + ) } From eb4fc1d3000d120db1b0db5e031c778624e318a6 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Mon, 11 Sep 2023 08:08:27 +0000 Subject: [PATCH 083/234] Update screenshots --- ...impl_null_OnBoardingScreen-D-0_0_null_4,NEXUS_5,1.0,en].png | 3 +++ ...impl_null_OnBoardingScreen-N-0_1_null_4,NEXUS_5,1.0,en].png | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.onboarding.impl_null_OnBoardingScreen-D-0_0_null_4,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.onboarding.impl_null_OnBoardingScreen-N-0_1_null_4,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.onboarding.impl_null_OnBoardingScreen-D-0_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.onboarding.impl_null_OnBoardingScreen-D-0_0_null_4,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..63eb2c9cdc --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.onboarding.impl_null_OnBoardingScreen-D-0_0_null_4,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c2c67243e8def6f8d188eb918b0dbd57dec3aae03fe8fca90ef5529658de537b +size 327304 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.onboarding.impl_null_OnBoardingScreen-N-0_1_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.onboarding.impl_null_OnBoardingScreen-N-0_1_null_4,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..cfc1433bcd --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.onboarding.impl_null_OnBoardingScreen-N-0_1_null_4,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:84e5641cce0113690d0d626bd3b17e8945728b3835a06b06a645418d12a05022 +size 421112 From ac5acd4949c2d970bd2f91ab77fec6030b9fbc25 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 11 Sep 2023 10:40:49 +0200 Subject: [PATCH 084/234] Reorder params. --- .../element/android/features/onboarding/impl/OnBoardingView.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingView.kt b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingView.kt index 875b79d8f2..424c24839a 100644 --- a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingView.kt +++ b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingView.kt @@ -61,11 +61,11 @@ import io.element.android.libraries.ui.strings.CommonStrings @Composable fun OnBoardingView( state: OnBoardingState, - modifier: Modifier = Modifier, onSignInWithQrCode: () -> Unit, onSignIn: () -> Unit, onCreateAccount: () -> Unit, onOpenDeveloperSettings: () -> Unit, + modifier: Modifier = Modifier, ) { OnBoardingPage( modifier = modifier, From c73d41e7680b4f08cf7153ba260dca753b97c331 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 8 Sep 2023 13:16:17 +0200 Subject: [PATCH 085/234] Add warning about issue on alpha07 --- gradle/libs.versions.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6d415faf59..c59d7359a6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -93,6 +93,8 @@ androidx_startup = { module = "androidx.startup:startup-runtime", version.ref = androidx_preference = "androidx.preference:preference:1.2.1" androidx_compose_bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose_bom" } +# Warning: issue on alpha07, make sure this is working when upgrading +# Context in https://github.com/vector-im/element-x-android/pull/1239#issuecomment-1711500332 androidx_compose_material3 = "androidx.compose.material3:material3:1.2.0-alpha06" # Coroutines From 046453170c2cf3c0b9198033667f9164ee677f04 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 7 Sep 2023 22:56:01 +0200 Subject: [PATCH 086/234] Add @OptIn(ExperimentalCoroutinesApi::class) Fix warning on runCurrent() --- .../ftue/impl/notifications/NotificationsOptInPresenterTests.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenterTests.kt b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenterTests.kt index 0c55992367..74a867a0fc 100644 --- a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenterTests.kt +++ b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenterTests.kt @@ -27,6 +27,7 @@ import io.element.android.libraries.permissions.impl.FakePermissionStateProvider import io.element.android.libraries.permissions.test.FakePermissionsPresenter import io.element.android.services.toolbox.test.sdk.FakeBuildVersionSdkIntProvider import io.element.android.tests.testutils.WarmUpRule +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.first import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.StandardTestDispatcher @@ -99,6 +100,7 @@ class NotificationsOptInPresenterTests { } } + @OptIn(ExperimentalCoroutinesApi::class) @Test fun `set permission denied on not now clicked in API 33`() = runTest(StandardTestDispatcher()) { val permissionPresenter = FakePermissionsPresenter() From 3201358cb5fb35b44ce85af64c06a4c68beb35e0 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 8 Sep 2023 09:43:53 +0200 Subject: [PATCH 087/234] Fix preview 3 of AddPeopleView. --- .../impl/addpeople/AddPeopleUserListStateProvider.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleUserListStateProvider.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleUserListStateProvider.kt index 48ad56caf4..79969eeac7 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleUserListStateProvider.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleUserListStateProvider.kt @@ -23,6 +23,7 @@ import io.element.android.features.createroom.impl.userlist.aListOfSelectedUsers import io.element.android.features.createroom.impl.userlist.aUserListState import io.element.android.libraries.designsystem.theme.components.SearchBarResultState import io.element.android.libraries.matrix.ui.components.aMatrixUserList +import io.element.android.libraries.usersearch.api.UserSearchResult import kotlinx.collections.immutable.toImmutableList open class AddPeopleUserListStateProvider : PreviewParameterProvider { @@ -36,7 +37,11 @@ open class AddPeopleUserListStateProvider : PreviewParameterProvider + UserSearchResult(matrixUser, index % 2 == 0) + } + .toImmutableList()), selectedUsers = aListOfSelectedUsers(), isSearchActive = true, selectionMode = SelectionMode.Multiple, From 5d89647a899dbb05f0dca7c6f79ef98b5537d966 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 8 Sep 2023 13:35:46 +0200 Subject: [PATCH 088/234] Apply avatar colors to all the avatars across the app. --- .../designsystem/components/avatar/Avatar.kt | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt index 958f4ca29e..ce39be4df7 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt @@ -26,7 +26,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter @@ -34,6 +33,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import coil.compose.AsyncImage import io.element.android.libraries.designsystem.colors.AvatarColors +import io.element.android.libraries.designsystem.colors.avatarColors import io.element.android.libraries.designsystem.preview.ElementThemedPreview import io.element.android.libraries.designsystem.preview.PreviewGroup import io.element.android.libraries.designsystem.preview.debugPlaceholderAvatar @@ -53,9 +53,10 @@ fun Avatar( .size(avatarData.size.dp) .clip(CircleShape) if (avatarData.url.isNullOrBlank()) { + val avatarColors = initialAvatarColors ?: avatarColors(avatarData.id) InitialsAvatar( avatarData = avatarData, - avatarColors = initialAvatarColors, + avatarColors = avatarColors, modifier = commonModifier, ) } else { @@ -88,13 +89,11 @@ private fun ImageAvatar( @Composable private fun InitialsAvatar( avatarData: AvatarData, - avatarColors: AvatarColors?, + avatarColors: AvatarColors, modifier: Modifier = Modifier, ) { - // Use temporary color for default avatar background, if avatarColors is not provided - val avatarColor = ElementTheme.colors.bgActionPrimaryDisabled Box( - modifier.background(color = avatarColors?.background ?: avatarColor) + modifier.background(color = avatarColors.background) ) { val fontSize = avatarData.size.dp.toSp() / 2 val originalFont = ElementTheme.typography.fontHeadingMdBold @@ -104,7 +103,7 @@ private fun InitialsAvatar( modifier = Modifier.align(Alignment.Center), text = avatarData.initial, style = originalFont.copy(fontSize = fontSize, lineHeight = lineHeight, letterSpacing = 0.sp), - color = avatarColors?.foreground ?: Color.White, + color = avatarColors.foreground, ) } } From f8b630ecb2ee426d46020e678d58466728cf111c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 8 Sep 2023 13:51:46 +0200 Subject: [PATCH 089/234] Implement a in-memory cache for user avatar colors. --- .../notifications/NotificationsOptInView.kt | 8 ++-- .../components/TimelineItemEventRow.kt | 4 +- .../designsystem/colors/AvatarColors.kt | 44 +++++++++++++------ .../designsystem/components/avatar/Avatar.kt | 4 +- .../components/avatar/UserAvatarPreview.kt | 5 ++- 5 files changed, 42 insertions(+), 23 deletions(-) diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt index 0b0676074b..cc467585cb 100644 --- a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt @@ -43,7 +43,7 @@ import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMo import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage import io.element.android.libraries.designsystem.colors.AvatarColors -import io.element.android.libraries.designsystem.colors.avatarColors +import io.element.android.libraries.designsystem.colors.AvatarColorsProvider import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize @@ -119,21 +119,21 @@ private fun NotificationsOptInContent( ) { NotificationRow( avatarLetter = "M", - avatarColors = avatarColors("5"), + avatarColors = AvatarColorsProvider.provide("5", ElementTheme.isLightTheme), firstRowPercent = 1f, secondRowPercent = 0.4f ) NotificationRow( avatarLetter = "A", - avatarColors = avatarColors("1"), + avatarColors = AvatarColorsProvider.provide("1", ElementTheme.isLightTheme), firstRowPercent = 1f, secondRowPercent = 1f ) NotificationRow( avatarLetter = "T", - avatarColors = avatarColors("4"), + avatarColors = AvatarColorsProvider.provide("4", ElementTheme.isLightTheme), firstRowPercent = 0.65f, secondRowPercent = 0f ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index 30478c6ef0..d62513f95f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -75,7 +75,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemPollContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent -import io.element.android.libraries.designsystem.colors.avatarColors +import io.element.android.libraries.designsystem.colors.AvatarColorsProvider import io.element.android.libraries.designsystem.components.EqualWidthColumn import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData @@ -328,7 +328,7 @@ private fun MessageSenderInformation( ) { val avatarStrokeColor = MaterialTheme.colorScheme.background val avatarSize = senderAvatar.size.dp - val avatarColors = avatarColors(senderAvatar.id) + val avatarColors = AvatarColorsProvider.provide(senderAvatar.id, ElementTheme.isLightTheme) Box( modifier = modifier ) { diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColors.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColors.kt index fb379c751e..c12be3b37d 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColors.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColors.kt @@ -16,9 +16,8 @@ package io.element.android.libraries.designsystem.colors -import androidx.compose.runtime.Composable +import androidx.collection.LruCache import androidx.compose.ui.graphics.Color -import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.colors.avatarColorsDark import io.element.android.libraries.theme.colors.avatarColorsLight @@ -27,18 +26,37 @@ data class AvatarColors( val foreground: Color, ) -@Composable -fun avatarColors(userId: String): AvatarColors { - val hash = userId.toHash() - val colors = if (ElementTheme.isLightTheme) { - avatarColorsLight[hash] - } else { - avatarColorsDark[hash] +object AvatarColorsProvider { + private val cache = LruCache(200) + private var currentThemeIsLight = true + + fun provide(id: String, isLightTheme: Boolean): AvatarColors { + if (currentThemeIsLight != isLightTheme) { + currentThemeIsLight = isLightTheme + cache.evictAll() + } + val valueFromCache = cache.get(id) + return if (valueFromCache != null) { + valueFromCache + } else { + val colors = avatarColors(id, isLightTheme) + cache.put(id, colors) + colors + } + } + + private fun avatarColors(id: String, isLightTheme: Boolean): AvatarColors { + val hash = id.toHash() + val colors = if (isLightTheme) { + avatarColorsLight[hash] + } else { + avatarColorsDark[hash] + } + return AvatarColors( + background = colors.first, + foreground = colors.second, + ) } - return AvatarColors( - background = colors.first, - foreground = colors.second, - ) } internal fun String.toHash(): Int { diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt index ce39be4df7..a0349931fe 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt @@ -33,7 +33,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import coil.compose.AsyncImage import io.element.android.libraries.designsystem.colors.AvatarColors -import io.element.android.libraries.designsystem.colors.avatarColors +import io.element.android.libraries.designsystem.colors.AvatarColorsProvider import io.element.android.libraries.designsystem.preview.ElementThemedPreview import io.element.android.libraries.designsystem.preview.PreviewGroup import io.element.android.libraries.designsystem.preview.debugPlaceholderAvatar @@ -53,7 +53,7 @@ fun Avatar( .size(avatarData.size.dp) .clip(CircleShape) if (avatarData.url.isNullOrBlank()) { - val avatarColors = initialAvatarColors ?: avatarColors(avatarData.id) + val avatarColors = initialAvatarColors ?: AvatarColorsProvider.provide(avatarData.id, ElementTheme.isLightTheme) InitialsAvatar( avatarData = avatarData, avatarColors = avatarColors, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/UserAvatarPreview.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/UserAvatarPreview.kt index 817650ffa7..2cfd820420 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/UserAvatarPreview.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/UserAvatarPreview.kt @@ -24,10 +24,11 @@ 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.libraries.designsystem.colors.avatarColors +import io.element.android.libraries.designsystem.colors.AvatarColorsProvider import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.colors.avatarColorsLight @DayNightPreviews @@ -43,7 +44,7 @@ internal fun UserAvatarPreview() = ElementPreview { verticalAlignment = Alignment.CenterVertically, ) { // Note: it's OK, since the hash of "0" is 0, the hash of "1" is 1, etc. - Avatar(anAvatarData(), initialAvatarColors = avatarColors("$it")) + Avatar(anAvatarData(), initialAvatarColors = AvatarColorsProvider.provide("$it", ElementTheme.isLightTheme)) Text(text = "Color index $it") } } From 72497b584d989e6521eb45226f6c15b9b0f87f05 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 8 Sep 2023 13:59:03 +0200 Subject: [PATCH 090/234] Now that we use a cache, there is no need to provide AvatarColors to the Avatar composable. --- .../notifications/NotificationsOptInView.kt | 18 ++++++++---------- .../components/TimelineItemEventRow.kt | 2 +- .../designsystem/components/avatar/Avatar.kt | 6 +----- .../components/avatar/UserAvatarPreview.kt | 4 +--- 4 files changed, 11 insertions(+), 19 deletions(-) diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt index cc467585cb..d22d6ab6ff 100644 --- a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt @@ -42,8 +42,6 @@ import io.element.android.features.ftue.impl.R import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage -import io.element.android.libraries.designsystem.colors.AvatarColors -import io.element.android.libraries.designsystem.colors.AvatarColorsProvider import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize @@ -67,7 +65,7 @@ fun NotificationsOptInView( modifier = modifier .systemBarsPadding() .fillMaxSize(), - header = { NotificationsOptInHeader(modifier = Modifier.padding(top = 60.dp, bottom = 12.dp),) }, + header = { NotificationsOptInHeader(modifier = Modifier.padding(top = 60.dp, bottom = 12.dp)) }, footer = { NotificationsOptInFooter(state) }, ) { NotificationsOptInContent(modifier = Modifier.fillMaxWidth()) @@ -119,21 +117,21 @@ private fun NotificationsOptInContent( ) { NotificationRow( avatarLetter = "M", - avatarColors = AvatarColorsProvider.provide("5", ElementTheme.isLightTheme), + avatarColorsId = "5", firstRowPercent = 1f, secondRowPercent = 0.4f ) NotificationRow( avatarLetter = "A", - avatarColors = AvatarColorsProvider.provide("1", ElementTheme.isLightTheme), + avatarColorsId = "1", firstRowPercent = 1f, secondRowPercent = 1f ) NotificationRow( avatarLetter = "T", - avatarColors = AvatarColorsProvider.provide("4", ElementTheme.isLightTheme), + avatarColorsId = "4", firstRowPercent = 0.65f, secondRowPercent = 0f ) @@ -144,7 +142,7 @@ private fun NotificationsOptInContent( @Composable private fun NotificationRow( avatarLetter: String, - avatarColors: AvatarColors, + avatarColorsId: String, firstRowPercent: Float, secondRowPercent: Float, modifier: Modifier = Modifier @@ -161,8 +159,7 @@ private fun NotificationRow( verticalAlignment = Alignment.CenterVertically ) { Avatar( - avatarData = AvatarData(id = "", name = avatarLetter, size = AvatarSize.NotificationsOptIn), - initialAvatarColors = avatarColors, + avatarData = AvatarData(id = avatarColorsId, name = avatarLetter, size = AvatarSize.NotificationsOptIn), ) Column(Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(12.dp)) { Box( @@ -174,7 +171,8 @@ private fun NotificationRow( ) if (secondRowPercent > 0f) { Box( - modifier = Modifier.clip(CircleShape) + modifier = Modifier + .clip(CircleShape) .fillMaxWidth(secondRowPercent) .height(10.dp) .background(ElementTheme.colors.borderInteractiveSecondary) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index d62513f95f..7e21ff649d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -346,7 +346,7 @@ private fun MessageSenderInformation( } // Content Row { - Avatar(senderAvatar, initialAvatarColors = avatarColors) + Avatar(senderAvatar) Spacer(modifier = Modifier.width(4.dp)) Text( text = sender, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt index a0349931fe..4ce4aa8f14 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/Avatar.kt @@ -32,7 +32,6 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import coil.compose.AsyncImage -import io.element.android.libraries.designsystem.colors.AvatarColors import io.element.android.libraries.designsystem.colors.AvatarColorsProvider import io.element.android.libraries.designsystem.preview.ElementThemedPreview import io.element.android.libraries.designsystem.preview.PreviewGroup @@ -46,17 +45,14 @@ import timber.log.Timber fun Avatar( avatarData: AvatarData, modifier: Modifier = Modifier, - initialAvatarColors: AvatarColors? = null, contentDescription: String? = null, ) { val commonModifier = modifier .size(avatarData.size.dp) .clip(CircleShape) if (avatarData.url.isNullOrBlank()) { - val avatarColors = initialAvatarColors ?: AvatarColorsProvider.provide(avatarData.id, ElementTheme.isLightTheme) InitialsAvatar( avatarData = avatarData, - avatarColors = avatarColors, modifier = commonModifier, ) } else { @@ -89,9 +85,9 @@ private fun ImageAvatar( @Composable private fun InitialsAvatar( avatarData: AvatarData, - avatarColors: AvatarColors, modifier: Modifier = Modifier, ) { + val avatarColors = AvatarColorsProvider.provide(avatarData.id, ElementTheme.isLightTheme) Box( modifier.background(color = avatarColors.background) ) { diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/UserAvatarPreview.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/UserAvatarPreview.kt index 2cfd820420..ab1ec70db4 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/UserAvatarPreview.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/UserAvatarPreview.kt @@ -24,11 +24,9 @@ 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.libraries.designsystem.colors.AvatarColorsProvider import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.theme.components.Text -import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.colors.avatarColorsLight @DayNightPreviews @@ -44,7 +42,7 @@ internal fun UserAvatarPreview() = ElementPreview { verticalAlignment = Alignment.CenterVertically, ) { // Note: it's OK, since the hash of "0" is 0, the hash of "1" is 1, etc. - Avatar(anAvatarData(), initialAvatarColors = AvatarColorsProvider.provide("$it", ElementTheme.isLightTheme)) + Avatar(anAvatarData(id = "$it")) Text(text = "Color index $it") } } From 4e40d694e76bbbf906a5174932eee56da5f00445 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 8 Sep 2023 14:53:46 +0200 Subject: [PATCH 091/234] Move class AvatarColorsProvider to its own file. --- .../designsystem/colors/AvatarColors.kt | 40 ------------- .../colors/AvatarColorsProvider.kt | 58 +++++++++++++++++++ 2 files changed, 58 insertions(+), 40 deletions(-) create mode 100644 libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColorsProvider.kt diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColors.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColors.kt index c12be3b37d..abac299ca6 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColors.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColors.kt @@ -16,50 +16,10 @@ package io.element.android.libraries.designsystem.colors -import androidx.collection.LruCache import androidx.compose.ui.graphics.Color -import io.element.android.libraries.theme.colors.avatarColorsDark -import io.element.android.libraries.theme.colors.avatarColorsLight data class AvatarColors( val background: Color, val foreground: Color, ) -object AvatarColorsProvider { - private val cache = LruCache(200) - private var currentThemeIsLight = true - - fun provide(id: String, isLightTheme: Boolean): AvatarColors { - if (currentThemeIsLight != isLightTheme) { - currentThemeIsLight = isLightTheme - cache.evictAll() - } - val valueFromCache = cache.get(id) - return if (valueFromCache != null) { - valueFromCache - } else { - val colors = avatarColors(id, isLightTheme) - cache.put(id, colors) - colors - } - } - - private fun avatarColors(id: String, isLightTheme: Boolean): AvatarColors { - val hash = id.toHash() - val colors = if (isLightTheme) { - avatarColorsLight[hash] - } else { - avatarColorsDark[hash] - } - return AvatarColors( - background = colors.first, - foreground = colors.second, - ) - } -} - -internal fun String.toHash(): Int { - return toList().sumOf { it.code } % avatarColorsLight.size -} - diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColorsProvider.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColorsProvider.kt new file mode 100644 index 0000000000..bf195e8160 --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/colors/AvatarColorsProvider.kt @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.designsystem.colors + +import androidx.collection.LruCache +import io.element.android.libraries.theme.colors.avatarColorsDark +import io.element.android.libraries.theme.colors.avatarColorsLight + +object AvatarColorsProvider { + private val cache = LruCache(200) + private var currentThemeIsLight = true + + fun provide(id: String, isLightTheme: Boolean): AvatarColors { + if (currentThemeIsLight != isLightTheme) { + currentThemeIsLight = isLightTheme + cache.evictAll() + } + val valueFromCache = cache.get(id) + return if (valueFromCache != null) { + valueFromCache + } else { + val colors = avatarColors(id, isLightTheme) + cache.put(id, colors) + colors + } + } + + private fun avatarColors(id: String, isLightTheme: Boolean): AvatarColors { + val hash = id.toHash() + val colors = if (isLightTheme) { + avatarColorsLight[hash] + } else { + avatarColorsDark[hash] + } + return AvatarColors( + background = colors.first, + foreground = colors.second, + ) + } +} + +internal fun String.toHash(): Int { + return toList().sumOf { it.code } % avatarColorsLight.size +} From b2dcd4c4677d6ddaa2d124e76c99a5bb047ff7fd Mon Sep 17 00:00:00 2001 From: ElementBot Date: Mon, 11 Sep 2023 09:08:37 +0000 Subject: [PATCH 092/234] Update screenshots --- ...people_null_AddPeopleViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...people_null_AddPeopleViewDark_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...eople_null_AddPeopleViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...eople_null_AddPeopleViewLight_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...l_SearchMultipleUsersResultItem_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...null_SearchSingleUserResultItem_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...ponents_null_UserListViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...ponents_null_UserListViewDark_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...ponents_null_UserListViewDark_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...onents_null_UserListViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...onents_null_UserListViewLight_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...onents_null_UserListViewLight_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...om_null_ConfigureRoomViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...m_null_ConfigureRoomViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...t_null_CreateRoomRootViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...t_null_CreateRoomRootViewDark_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ..._null_CreateRoomRootViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ..._null_CreateRoomRootViewLight_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...nts_null_InviteSummaryRowDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...nts_null_InviteSummaryRowDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...nts_null_InviteSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...nts_null_InviteSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...nts_null_InviteSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...ts_null_InviteSummaryRowLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ts_null_InviteSummaryRowLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...ts_null_InviteSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...ts_null_InviteSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...ts_null_InviteSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_InviteListViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_InviteListViewDark_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_InviteListViewDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_InviteListViewDark_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_InviteListViewDark_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_InviteListViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_InviteListViewLight_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_InviteListViewLight_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_InviteListViewLight_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_InviteListViewLight_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...ionlist_null_SheetContent-D-0_1_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...ionlist_null_SheetContent-D-0_1_null_8,NEXUS_5,1.0,en].png | 4 ++-- ...ionlist_null_SheetContent-N-0_2_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...ionlist_null_SheetContent-N-0_2_null_8,NEXUS_5,1.0,en].png | 4 ++-- ..._null_ForwardMessagesViewDark_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ..._null_ForwardMessagesViewDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ..._null_ForwardMessagesViewDark_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ..._null_ForwardMessagesViewDark_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ..._null_ForwardMessagesViewDark_0_null_7,NEXUS_5,1.0,en].png | 4 ++-- ...null_ForwardMessagesViewLight_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...null_ForwardMessagesViewLight_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...null_ForwardMessagesViewLight_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...null_ForwardMessagesViewLight_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...null_ForwardMessagesViewLight_0_null_7,NEXUS_5,1.0,en].png | 4 ++-- ...mmary_null_SheetContent-D-14_15_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...mmary_null_SheetContent-N-14_16_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...es.impl_null_MessagesViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...es.impl_null_MessagesViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...es.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...es.impl_null_MessagesViewDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...es.impl_null_MessagesViewDark_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...s.impl_null_MessagesViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...s.impl_null_MessagesViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...s.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...s.impl_null_MessagesViewLight_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...s.impl_null_MessagesViewLight_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...ll_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ll_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...l_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...l_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...user_null_UserPreferencesDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...user_null_UserPreferencesDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...ser_null_UserPreferencesLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ser_null_UserPreferencesLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ..._null_RoomDetailsEditViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ..._null_RoomDetailsEditViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ..._null_RoomDetailsEditViewDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ..._null_RoomDetailsEditViewDark_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ..._null_RoomDetailsEditViewDark_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ..._null_RoomDetailsEditViewDark_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...null_RoomDetailsEditViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...null_RoomDetailsEditViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...null_RoomDetailsEditViewLight_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...null_RoomDetailsEditViewLight_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...null_RoomDetailsEditViewLight_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...null_RoomDetailsEditViewLight_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...te_null_RoomInviteMembersDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...te_null_RoomInviteMembersDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...te_null_RoomInviteMembersDark_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...te_null_RoomInviteMembersDark_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...e_null_RoomInviteMembersLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...e_null_RoomInviteMembersLight_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...e_null_RoomInviteMembersLight_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...e_null_RoomInviteMembersLight_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ..._RoomMemberDetailsViewDark--3_3_null_0,NEXUS_5,1.0,en].png | 4 ++-- ..._RoomMemberDetailsViewDark--3_3_null_1,NEXUS_5,1.0,en].png | 4 ++-- ..._RoomMemberDetailsViewDark--3_3_null_2,NEXUS_5,1.0,en].png | 4 ++-- ..._RoomMemberDetailsViewDark--3_3_null_3,NEXUS_5,1.0,en].png | 4 ++-- ..._RoomMemberDetailsViewDark--3_3_null_4,NEXUS_5,1.0,en].png | 4 ++-- ..._RoomMemberDetailsViewDark--3_3_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...RoomMemberDetailsViewLight--2_2_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...RoomMemberDetailsViewLight--2_2_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...RoomMemberDetailsViewLight--2_2_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...RoomMemberDetailsViewLight--2_2_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...RoomMemberDetailsViewLight--2_2_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...RoomMemberDetailsViewLight--2_2_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...mbers_null_RoomMemberListDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...mbers_null_RoomMemberListDark_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...bers_null_RoomMemberListLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...bers_null_RoomMemberListLight_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png | 4 ++-- ..._null_DefaultRoomListTopBarDark_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...null_DefaultRoomListTopBarLight_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...nents_null_RoomSummaryRowDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...nents_null_RoomSummaryRowDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...nents_null_RoomSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...nents_null_RoomSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...nents_null_RoomSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...nents_null_RoomSummaryRowDark_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...ents_null_RoomSummaryRowLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ents_null_RoomSummaryRowLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...ents_null_RoomSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...ents_null_RoomSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...ents_null_RoomSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...ents_null_RoomSummaryRowLight_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...list.impl.search_null_ContentTo_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...RoomListSearchResultContentDark_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...oomListSearchResultContentLight_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...st.impl_null_RoomListViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...st.impl_null_RoomListViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...st.impl_null_RoomListViewDark_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...st.impl_null_RoomListViewDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...st.impl_null_RoomListViewDark_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...st.impl_null_RoomListViewDark_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...st.impl_null_RoomListViewDark_0_null_7,NEXUS_5,1.0,en].png | 4 ++-- ...t.impl_null_RoomListViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...t.impl_null_RoomListViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...t.impl_null_RoomListViewLight_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...t.impl_null_RoomListViewLight_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...t.impl_null_RoomListViewLight_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...t.impl_null_RoomListViewLight_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...t.impl_null_RoomListViewLight_0_null_7,NEXUS_5,1.0,en].png | 4 ++-- ...ts.avatar_null_Avatars_Avatar_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ts.avatar_null_Avatars_Avatar_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_10,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_12,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_13,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_15,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_16,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_18,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_19,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_21,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_22,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_24,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_25,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_27,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_28,NEXUS_5,1.0,en].png | 4 ++-- ...ts.avatar_null_Avatars_Avatar_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_30,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_31,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_33,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_34,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_36,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_37,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_39,NEXUS_5,1.0,en].png | 4 ++-- ...ts.avatar_null_Avatars_Avatar_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_40,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_42,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_43,NEXUS_5,1.0,en].png | 4 ++-- ...ts.avatar_null_Avatars_Avatar_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...ts.avatar_null_Avatars_Avatar_0_null_7,NEXUS_5,1.0,en].png | 4 ++-- ...ts.avatar_null_Avatars_Avatar_0_null_9,NEXUS_5,1.0,en].png | 4 ++-- ...ll_CheckableMatrixUserRowDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ll_CheckableMatrixUserRowDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...l_CheckableMatrixUserRowLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...l_CheckableMatrixUserRowLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...null_CheckableUnresolvedUserRow_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...nts_null_MatrixUserHeaderDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...nts_null_MatrixUserHeaderDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...ts_null_MatrixUserHeaderLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ts_null_MatrixUserHeaderLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...onents_null_MatrixUserRowDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...onents_null_MatrixUserRowDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...nents_null_MatrixUserRowLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...nents_null_MatrixUserRowLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...omponents_null_SelectedRoomDark_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...mponents_null_SelectedRoomLight_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...omponents_null_SelectedUserDark_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...mponents_null_SelectedUserLight_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...ents_null_SelectedUsersListDark_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...nts_null_SelectedUsersListLight_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...mponents_null_UnresolvedUserRow_0_null,NEXUS_5,1.0,en].png | 4 ++-- 207 files changed, 414 insertions(+), 414 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewDark_0_null_1,NEXUS_5,1.0,en].png index 9031993cc7..f0232ef1fc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ff5cb940c05656ed7debf230c7c2d780395e30f20c5d3da3abef136afb5359fe -size 28541 +oid sha256:2dc520372ac1b4ae340a1e75e0a1f4cc65f54c9e9ebf44c750309018613fa5d4 +size 28865 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewDark_0_null_2,NEXUS_5,1.0,en].png index fae8a6fca3..dffeee671e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8c89ac73df77c2bccb0c2aa80cee1420f78e7d07f0eda89a90bffef55e8cf753 -size 4464 +oid sha256:7bf3e51b483ca9600d9f589721bdfe93e0977ebcfe59ff66484fcbd7cfb12e20 +size 81101 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewLight_0_null_1,NEXUS_5,1.0,en].png index d65aa5499e..439ea49b7b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:edf63c7ae4b058c94cd611948f2bb3c3304c2646af0200e08f7b480f1ba965d8 -size 29245 +oid sha256:f8b78908805bb8745613be2f9fad2c1c4fd0d6087dce7f9b301b4fe3dc485d19 +size 30273 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewLight_0_null_2,NEXUS_5,1.0,en].png index 665c8811ac..75c9154caf 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.addpeople_null_AddPeopleViewLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bb0d3bfcfd75cbd75fd9270ff1dc27090e5dbac79ca8db8a46d91a4c12bc966b -size 4457 +oid sha256:25b86e5211512c4a676cb142b847455ba34c13eb3712f75a22c8b313ca725eeb +size 83750 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_SearchMultipleUsersResultItem_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_SearchMultipleUsersResultItem_0_null,NEXUS_5,1.0,en].png index b027f127c4..19e170130f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_SearchMultipleUsersResultItem_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_SearchMultipleUsersResultItem_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3fe351b3d0b78473fdab1d4bc806468485939734e46cb3fa6d9f9058513d4dba -size 86421 +oid sha256:b051a4492303db0e5a1343269cb57301939105ab4c062db67326edb699a02d0f +size 86337 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_SearchSingleUserResultItem_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_SearchSingleUserResultItem_0_null,NEXUS_5,1.0,en].png index 0f8dfab3d3..037a2c9e40 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_SearchSingleUserResultItem_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_SearchSingleUserResultItem_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9dbfb671a112ae3bab099db959b30dcd4185d48bd365f63373da62971df51e00 -size 45246 +oid sha256:88608834541e31673c52014cc56072953f1ff1814bb3f89852822ebc6f762188 +size 45269 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_1,NEXUS_5,1.0,en].png index 1b3c77ebaa..b87255406a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:137a71939d978e2f10d94d49faed208c54a5fa82b32d9ba2b47a3946641d361f -size 25688 +oid sha256:dda8e627414be70d99e5d7055fe32cb4d31014e5b55fb6fce326f90eb210a32f +size 26147 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_5,NEXUS_5,1.0,en].png index ee833eae85..fd718e2025 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eb84e5f7f23db39d8d2d162f0d55d8129ae88e984dcde816c86682981226bf4f -size 64074 +oid sha256:c67a25ba48fdd4edc640f848712427656299cfd397a24805e6ebb89da533e1d9 +size 63838 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_6,NEXUS_5,1.0,en].png index 1a18f078da..3bb77b278a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewDark_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eeeb724c3797679434f580261071602e2b8991b466e0e47806c7d7b0e4e4be2a -size 67838 +oid sha256:67861c2fc225ca366c3c2206fcee0d59f77b232eedd29b1bce9ed630af002ea0 +size 68143 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_1,NEXUS_5,1.0,en].png index ed8846c5f4..85cb7efca2 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c2044763a0297a9d89c2a4ebb7fbd3ba967a5ac99a28375aeccf4766bc1a3be3 -size 25762 +oid sha256:7c01cba121aac57126e79becb6b5d2de7c3bee0f50418f9c17ab9228156c2030 +size 26274 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_5,NEXUS_5,1.0,en].png index b014ceeaa4..09e93acea2 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:675584b016f10890e13008152ade861de50b3463de9a253353f0d1af4f57c200 -size 65789 +oid sha256:663b97daf508ebb9e619c1a6a14c5ea005b93bf004ed6ef7c08a202284b87e33 +size 64676 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_6,NEXUS_5,1.0,en].png index 3160672512..dc6259ef33 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.components_null_UserListViewLight_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:708d5201ded559e388a453d0df87d97aa7068f4892d6acb8a3bf50497a6754eb -size 69831 +oid sha256:e85d3ebafb87a593fa8977f9def17c8f45f9e067e02fe05c48b3f9650835a000 +size 69456 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.configureroom_null_ConfigureRoomViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.configureroom_null_ConfigureRoomViewDark_0_null_1,NEXUS_5,1.0,en].png index aebe6c0c19..6e3c656d80 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.configureroom_null_ConfigureRoomViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.configureroom_null_ConfigureRoomViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7816a99e6460155c0d4c8f74fec6b2f09ec724f3442f5b1e77b45e98b5d43be1 -size 83585 +oid sha256:a88f6e1fdc1b3cd26f21a94866d0348e458509c5ce129c86c69b2673c7dc75f1 +size 84357 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.configureroom_null_ConfigureRoomViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.configureroom_null_ConfigureRoomViewLight_0_null_1,NEXUS_5,1.0,en].png index 2b4f8e8e26..80d8dc14fd 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.configureroom_null_ConfigureRoomViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.configureroom_null_ConfigureRoomViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ec1b567e5175c9e83aee05623270f2f2d5497c901438042075a2b57a1284a368 -size 87153 +oid sha256:e116827aaa9d30b356088805bf6a820cce3ba42c49e6ffca2460aab1a4cdc8ba +size 87872 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewDark_0_null_1,NEXUS_5,1.0,en].png index 11393a5279..20ea3618e0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a59a7d481cdcc7b3fa216bc3ec4a20195730d27fe518a6610d9a61fb4a3b347f -size 20753 +oid sha256:8f04a88c84cb7e4e6d0f487b47aaf5e80c9ae1472ab25bf5412e084c356d4bbe +size 20765 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewDark_0_null_2,NEXUS_5,1.0,en].png index 786c163f1e..d8fa732c18 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:22ac66742c1e14c8f9ddf8f56f86fd155f6f8d3adfc90483772f4f78c71fe81c -size 27063 +oid sha256:b85cf6982f409276e1bedc1a06322ecefef8ea86d4e5459a39d607fe10f5d08b +size 27093 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewLight_0_null_1,NEXUS_5,1.0,en].png index a4ed8eb2e3..3de381303a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd1cce3d0a456d3501f0f5c5160821210fd1060c24a66f1cacb65f9f95b44bb8 -size 23792 +oid sha256:d0be20df5f6bdf095fd9a93df3dc6ca81939365e4f27c8f605a1ab12b4959fc6 +size 23724 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewLight_0_null_2,NEXUS_5,1.0,en].png index 05509fabe3..49c0cecf77 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.createroom.impl.root_null_CreateRoomRootViewLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2f26d62e7ca9b98ca9314305b0659f7919b58f5d7805684832e91d5f3cb6ece4 -size 31162 +oid sha256:31bfc0054eff2bce1e43c49fa628968504e16853a198579710d08a2134d24efd +size 31099 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_0,NEXUS_5,1.0,en].png index 16876034a0..dd4b64afcf 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5740c7f4d76a786612c5a1cb9e58c29c87778f3e8d11878f310cfda3da1bed8a -size 28445 +oid sha256:245c5b206b5f560c9457069761694f0198a89ad700cfc39241b22441a7f2c31e +size 28345 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_1,NEXUS_5,1.0,en].png index 9f6e875358..6c1fee3405 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fbb6813f970b0fcfa9489d06b28b2e17d6d0fc97d2f0494553a629df930af48c -size 32919 +oid sha256:70b2df85168ea6d5d7f7cbae84a91f45a9ec7fe716d4d6c087d21f8b787a3fb6 +size 32648 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png index da5124b675..124e9ba417 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:633165e86d70889024469309db5a4f44eaa00456f0452e6c1447ed7e24b7bc4b -size 33059 +oid sha256:4e3ad562682d7e0df76faf0041947158c0e90b93a60d2aa4129ea1d222e439ce +size 32762 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png index e3e06b6a66..83bcdc038e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6fb2d663532efdd393063f3a1a53ad0da2bad91033dec2d6bad971f681a56a45 -size 14016 +oid sha256:88b77b856b1a6582aad3fe26f08a48f405d2a0cbc1a495f691de7af569bc7370 +size 13744 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png index 986ba9ee23..14139948d0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1e030b3d98c9d4e6a37a983b180e664b45697705a966bc9348ea432e123a3b6d -size 28604 +oid sha256:9e2d4495246144df6f91ed8ad6ef5f32b507f56c2f8ab9713230e7212078d7ea +size 28479 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_0,NEXUS_5,1.0,en].png index 27daa2fd10..9af73d58bd 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d75bae2ae2ee8a407d2b4652d699e664e619cffa5a7888cdf6169395abb97c6a -size 29142 +oid sha256:730f27b45cb2176ac6f8415780b74e2f117b9cc3f64d4602e6c42253f65b23e7 +size 29181 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_1,NEXUS_5,1.0,en].png index c1dc2207c0..84b761658b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:13fa1f840184a20cea94d1cd9d76480eda1c458225b4514e37213080c936d3fd -size 34888 +oid sha256:5bcafa377dfdd0a3e3db955c2d81791f1c36c95b22d978090b8d4e6b063c7d69 +size 34866 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png index c45e89835f..149ea8dca8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5abcb5badc21e715c6f7c4330e5721b0275fdcc678ca3920ce64ae5d34829250 -size 35005 +oid sha256:0b77b77a20d1c3d936dea733542f1b2bd8e575ccb6d3021ce1c2d84a701bea35 +size 34965 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png index 23a8c73c75..e9a0097fe1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:772d4d50bbed5bc5cebc8f636ce952fdc4951b714e4d621030a87db7a1df9c01 -size 14162 +oid sha256:d3092c176ec732f3e378430779a8645c02cd6c47756a6dafaf09a7fe28e79608 +size 14112 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png index 1ce40f977b..18eb4c8c8a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl.components_null_InviteSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e3cd5c467381c74c579e62405bc6016da1b9b050365d04a335845a19d1ae2c41 -size 29448 +oid sha256:8b3cf23c4ef3ee18a3dd4a20a683266b2cdc6b6bca90b1006c109e23c82c6ebb +size 29445 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_0,NEXUS_5,1.0,en].png index 3552000829..af4db9ed9a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2aad1e4a3ba3691a37c9a2df872609ce7b7cbfb326deca6e5a81e6a0a50fb19b -size 52305 +oid sha256:079fe39c7dced18433ef0c768b30ec0c66bda3d910b392bfc33319f6be7ce892 +size 51852 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_2,NEXUS_5,1.0,en].png index fb13cb54ab..68751cdec3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bb5f62cf093e48c40732d801cb27c51005c82f84aaf96ce86e5dc50c54ff27cb -size 49589 +oid sha256:e002caef4c4be424468938e2ca05a25c6f6502340f216eca908ba8784a4d98b2 +size 49289 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_3,NEXUS_5,1.0,en].png index 42cdd40e09..4ba1ea763c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d4954c0ae06d16a0058b88eb9b648911eb0c8b36eba19e40031bcf5ec6c262ff -size 50257 +oid sha256:d7bfc8f00d9286162292ed04e9a53f21f5f8f2f44bab88c00356d330b56fd426 +size 49965 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_4,NEXUS_5,1.0,en].png index 568bdb2d89..c7a3568641 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0623f68ed17b1d7e39b2737255a2f3d5448a984bcef00ee58558a7581af84074 -size 40173 +oid sha256:6f23a5df96bb6faca94a8096cf4b884af1dc97a755f0664ca05c9d64657052f8 +size 39772 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_5,NEXUS_5,1.0,en].png index 568bdb2d89..c7a3568641 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewDark_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0623f68ed17b1d7e39b2737255a2f3d5448a984bcef00ee58558a7581af84074 -size 40173 +oid sha256:6f23a5df96bb6faca94a8096cf4b884af1dc97a755f0664ca05c9d64657052f8 +size 39772 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_0,NEXUS_5,1.0,en].png index 44650d97d4..6b5fc9bfeb 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9357fbad1987326b891699fb5e176e4458d1b7dbe660df95d20c079d8f38bc52 -size 55154 +oid sha256:9766ca3ad7562ead5bbc4b40eaf4712383a8c90876010fc0a23fc3ba4eb7eb42 +size 54662 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_2,NEXUS_5,1.0,en].png index 0e6271869c..39c860e6f5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:840b7a0a23d458680f59f328d2a8b756e80ab76e368d749a511e7352d31d0f4f -size 54196 +oid sha256:b564f1c08b839c6758e3abba916a0b20f6cc0f590b27773de1d6a1e88a2cdc56 +size 53899 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_3,NEXUS_5,1.0,en].png index 7c71ef8088..7e1c4760e3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:062f857b2b2339f54543b70a864786b1463747cb7e45db54f76b1831938dd98f -size 54984 +oid sha256:6881032ea2d387c2bb8f8dd776fe6b581c100328d13b023e190c22dc0832e4a1 +size 54689 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_4,NEXUS_5,1.0,en].png index 31b2eb0efb..cb2628494c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:63070cf809fe17adedc37b9df0b9a421c453d09e8edd95869fb62f4b1b066a16 -size 44827 +oid sha256:9717ce6ae0559ae73cc9397976887b7acb1a534a957a3a29b0d0da2442e77130 +size 44397 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_5,NEXUS_5,1.0,en].png index 31b2eb0efb..cb2628494c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.invitelist.impl_null_InviteListViewLight_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:63070cf809fe17adedc37b9df0b9a421c453d09e8edd95869fb62f4b1b066a16 -size 44827 +oid sha256:9717ce6ae0559ae73cc9397976887b7acb1a534a957a3a29b0d0da2442e77130 +size 44397 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_2,NEXUS_5,1.0,en].png index 0ccf45d0dd..04e2ba64b3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b64a7ad8a711dcb67a5b130bac5f3083421ff79b4476060fa5f54f3b14dac173 -size 38511 +oid sha256:db2d848fded08ca0532f718f12ee9dab007d7bb129afcf949d26585e47efa054 +size 38389 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_8,NEXUS_5,1.0,en].png index 3b48d22222..a008402361 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4e335de03505f63e0b02ef98b916a1fd979b32a58f3c91bf0dc6194d6b66d671 -size 28302 +oid sha256:20847fc7ab9e27171ae0ae37a95e7524aac0bd2479ff5b8b1130a5bc26dbb3e6 +size 28232 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_2,NEXUS_5,1.0,en].png index 1e64e85760..a5a732b30f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5366117e506df73eb6073bfcdc76738a89262c4ff83182a381c50b98230c71c2 -size 37051 +oid sha256:67060b3bd4d09915ec4eda311726a8657cf09e455b5e8ca42631fa3b448ad5b7 +size 37049 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_8,NEXUS_5,1.0,en].png index 53b1988ad5..ceec7820f1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:286f4ed93711fe203aace6e629971b6681ed74cb2a9cd7cb8544125144d4fb17 -size 26867 +oid sha256:a62ebcf0024a1876984c936c29037cf04e2e02aefb3bea461030c092fbde2937 +size 26983 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_2,NEXUS_5,1.0,en].png index d41ab12fd3..80a6200a6c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:98bfdfa99e207e5f50aa6a6aa08914b8f2be407d5547f39984a0a3e05d41bab7 -size 26932 +oid sha256:7afef32647fb7ca666ba516c3f348d1fb168be290279869b73c3b64522e20301 +size 27069 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_3,NEXUS_5,1.0,en].png index a6fc15351a..28307e18cc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:05e62d2584c3eda7e22068731de56223393e869c8e91ac547a148a7f84e870dc -size 26485 +oid sha256:e2d9ea4c550094975fbdaa0f42c85dd871e414b1553c96b1256c8534233d6050 +size 26618 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_4,NEXUS_5,1.0,en].png index e7d3a908ec..58213edfc0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e72e276a8a0fefafe36314ec82f6ea1ca8f9bcb077afecc49f65ba977a59595f -size 26473 +oid sha256:2a216a2aefd132b3ffb64e89de3c8b2013595573783f7dcb9ad6e0f04e1cbf1c +size 26607 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_5,NEXUS_5,1.0,en].png index e7d3a908ec..58213edfc0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e72e276a8a0fefafe36314ec82f6ea1ca8f9bcb077afecc49f65ba977a59595f -size 26473 +oid sha256:2a216a2aefd132b3ffb64e89de3c8b2013595573783f7dcb9ad6e0f04e1cbf1c +size 26607 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_7,NEXUS_5,1.0,en].png index e7d3a908ec..58213edfc0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewDark_0_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e72e276a8a0fefafe36314ec82f6ea1ca8f9bcb077afecc49f65ba977a59595f -size 26473 +oid sha256:2a216a2aefd132b3ffb64e89de3c8b2013595573783f7dcb9ad6e0f04e1cbf1c +size 26607 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_2,NEXUS_5,1.0,en].png index 6b74783202..3c82e866f9 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:080d58220454a98725f418f931c6e18c4af11821076d8cd446525098a52db6d2 -size 28739 +oid sha256:2333902757fee47ccdcab42188b5f5379fe48e2419896a4d525855510b7925a1 +size 28241 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_3,NEXUS_5,1.0,en].png index 2ce5fc6bc0..2281938ed5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7da900d8aab1134bbcc472104a876c390f156a9531f1f3f7d57e2e9211be5ba6 -size 28146 +oid sha256:7c4bcdf48d7ba2f11cb7e09ad56fb1facce1722fe71b2b10ac5c4a86ed201e37 +size 27646 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_4,NEXUS_5,1.0,en].png index 24919e87b8..605e036675 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f70d7796f416ec68599128d2da46304150b57d83262aa706e70fcf85d3b80a3 -size 28198 +oid sha256:fa25fe1ec3626e1726043987c5b727d5fd10660c4134d7b714616933a9e0d01c +size 27678 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_5,NEXUS_5,1.0,en].png index 24919e87b8..605e036675 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f70d7796f416ec68599128d2da46304150b57d83262aa706e70fcf85d3b80a3 -size 28198 +oid sha256:fa25fe1ec3626e1726043987c5b727d5fd10660c4134d7b714616933a9e0d01c +size 27678 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_7,NEXUS_5,1.0,en].png index 24919e87b8..605e036675 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.forward_null_ForwardMessagesViewLight_0_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f70d7796f416ec68599128d2da46304150b57d83262aa706e70fcf85d3b80a3 -size 28198 +oid sha256:fa25fe1ec3626e1726043987c5b727d5fd10660c4134d7b714616933a9e0d01c +size 27678 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_null_SheetContent-D-14_15_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_null_SheetContent-D-14_15_null_0,NEXUS_5,1.0,en].png index 9572127bae..56702cb5b9 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_null_SheetContent-D-14_15_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_null_SheetContent-D-14_15_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:094a0f5436527308d2a37b52f6e0c5f12e267f214b79fae980e409da116a07ec -size 25277 +oid sha256:fbe739da995dca5700bcbb6a944c611e7c0b427d39b5e085345d8a7e93759e7c +size 25201 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_null_SheetContent-N-14_16_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_null_SheetContent-N-14_16_null_0,NEXUS_5,1.0,en].png index 73180b7d05..a61dfbb6e3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_null_SheetContent-N-14_16_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.reactionsummary_null_SheetContent-N-14_16_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f0a29a48138febe8b13b1e1099fbeab2280f1b0567233614187d97117df05de0 -size 24943 +oid sha256:09864a80f5eaf0874dfdde8698b3fb6ef8ad95059f2d955e822f80009f49849f +size 24966 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_0,NEXUS_5,1.0,en].png index 00cfa0d87e..a80b2ce36d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba052f24e62aabc015da4b38bb893148c888a858a097669b2191e7880867e371 -size 52114 +oid sha256:2b55dbcb731dfc40a1e100e8caf26802f759b4bcd186dbbc4432644db08f8316 +size 52141 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_1,NEXUS_5,1.0,en].png index 57d6580a12..03f50fe82f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4f8f7fd27e56aa2ca42053c249353836187467b99a9225c93c22f38365e63ccb -size 53285 +oid sha256:d5953ae4bb021c39157b4118ea628ca9bb2277f9672749cc6313f0b378d31cb8 +size 53312 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png index 8a4f9bc201..eb75a98270 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fbfc5593de6c7dda915b3a8bc881f0485b4b8400f52412547aa914862d1d8840 -size 52245 +oid sha256:fd991a67e7d6c1169e08e62cb74ed6fa7d12ad7f91d69bbfa778e0053efebfec +size 52284 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_3,NEXUS_5,1.0,en].png index 57b61342dc..3c98269fe1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7225f3510289f07d4c273e3bb179d05df0ac9f1a2ec868f061a2622c6f9d0b84 -size 54030 +oid sha256:1d6ba255d9b1aee8d560b51f2bf0c1d4433c63502c83f6cf18ef8eaa598f05c4 +size 54071 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_4,NEXUS_5,1.0,en].png index 6907cccce9..35d5965ff3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d56d5666d1d7749484f19c983e3cb2125110039c80e5898684e20b7e24a3e56b -size 51312 +oid sha256:dc662d180d1766706f249f1585fb100f5933206b65d4644fae65abc6a121a633 +size 51331 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_0,NEXUS_5,1.0,en].png index 1746cfeb84..65cdf717bb 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:398f4b1c7b21ab4c57802fb724d62b8c904f5a0c700eba507a811cb58881df49 -size 53896 +oid sha256:3eb1479510a8cd04d133265e33ea15115158ac55c93387d1dafa93a3a3a858f0 +size 53620 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_1,NEXUS_5,1.0,en].png index 69a8b67d95..a5959f6d60 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2913fc7ee2c4b32e79e0d813ee8fa54e6d3f863466b798b8194462cbd9ef4fde -size 55137 +oid sha256:c0d5272b14b347f18b2d67d5fae6eaf507b8d6f7c9d361317bb6b8a062e63ceb +size 54899 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png index f8b59bb375..9603a65588 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a20479945a552e2d3d3fb309c07ac7b9a66d4dfac0ad1ddf2c86c40fa0d34db9 -size 54175 +oid sha256:d421656ae8ad316e65f406c74dffa2ceb4e47b868b7f033f9cc4139e3e6be788 +size 53909 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_3,NEXUS_5,1.0,en].png index cd18a11803..47d15c2bf6 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c9f686208853c864a9aada2c809a43e1de230e422e93af7c6330b8e78dffffec -size 55730 +oid sha256:fa96d668bd220fb1e47850c86c7ded9fe99b14b9704f1a5662cfde1e932c5299 +size 55443 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_4,NEXUS_5,1.0,en].png index 367b0dc907..8212494315 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1e7697c3f1eb995fc0bbf084853fce1cc10e841d0275d6ff4f2d857afd81b31d -size 56103 +oid sha256:dff46ed537c81602be0dea8782e37bb78669ee798ec4d422c23ff29cbbdebc17 +size 55927 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png index 5fcb6cc260..21903d1663 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:46bdcc0dcd5dd9ae0740eeb0af0b0587f1989689ec744c2f38cb4813c860bfab -size 39711 +oid sha256:239a01988afb77f399b9488e3c314846a59d368ba2a7fd8bec1514ff60dbd8ab +size 39772 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png index 3b7938f529..2fbb0cbc02 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae44b96af239aee5fc7839df08f9298490add53d76c51f4778d2af4d57aa746b -size 39043 +oid sha256:1b3670c1508e8548a32e51c8d1bd75d2dabce73a2bc710dc673a85f98901b5fb +size 39100 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png index f973a24462..b38a248d82 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:66cf5b700fefe4839d6956e83d7590711bc38a659e41d0aff829cf877e7dc209 -size 42351 +oid sha256:ec1f4a968f58c9c7faf6d51ec5dc8e31f00d867eb506b35a466e6a2242945c74 +size 42131 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png index e400a8de25..fffb00c7f3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9372f8f7e0a173d680fd860fbbe7e4319409b82b02cad8b83eca2059fbf35bba -size 42486 +oid sha256:4b0006728215e73456e78192ce7d774d8bc792d04fef9fcfa3b76c081dfc8deb +size 41996 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesDark_0_null_0,NEXUS_5,1.0,en].png index f7d8135d0b..c53281b9c1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:964d97909629c1228e96d923ddb478735475839b8540c02142444f9ebd5bf400 -size 13100 +oid sha256:115262f8a16f26506139c7b8f630e85520639ae5dca424028bc9a721942aebc5 +size 13168 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesDark_0_null_1,NEXUS_5,1.0,en].png index bff7b81448..658eb46874 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bd8ff4a09babf30be0eb3c336f3cbe6a1508a21696512d0dadbcc9d543e6e34f -size 12356 +oid sha256:5055b4cc1bdf5a4b00e901e5e40c0cdcc415d22d7154ef38888936928100928e +size 12365 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesLight_0_null_0,NEXUS_5,1.0,en].png index fe1fe39c26..85665e2302 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:85530997942e39ce73512513ab0698494778168bc28cfab543b50b721c1807f5 -size 12855 +oid sha256:1c4ce3a10a671acfb2e619356cf792b5f11325a55edca30c57813aa7823e878d +size 12591 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesLight_0_null_1,NEXUS_5,1.0,en].png index 23211c9508..119c55ec0b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user_null_UserPreferencesLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2e0a638be5745c75c2663116877d380c83df093d226d2c969d4f6620e8cee109 -size 12965 +oid sha256:28f315ebf657e95e666b6599b096d1779b1c9f3cefea3e679a9054d80f89d53b +size 12412 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_0,NEXUS_5,1.0,en].png index 3703690be4..e0211eacbe 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:48311f503e47fc462a1f4d5afa2ea82c0e0eef99aaddea9cfabf5517af37bcd5 -size 29796 +oid sha256:19ac99f81f3e72f0492d33278a9e549763493ea7ff111412821c62d934a6b9f6 +size 29522 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_1,NEXUS_5,1.0,en].png index d19b6c9ec9..e548c3c81f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1aaa12b291dc1e187835114eb8c5c49bb4eb5bf16d87b039272a6e32e16cc6e2 -size 23369 +oid sha256:d15154d8ad933acf9a52a73fb650d28489d780cae71b44c7edf10b682cec1ff9 +size 23143 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_3,NEXUS_5,1.0,en].png index 46ed873359..487800c8dd 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:82e2cd2caae9b20cb2e3990216b0ecdf0bcfde4478911f00168e4f936c223889 -size 28736 +oid sha256:0958e2a99818be0125b700df470a944a3202e0336d440b073cc73ccc6305173f +size 28482 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_4,NEXUS_5,1.0,en].png index ac9817e2c7..241c7e1400 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b2cb829eadcf07760a073af775be6d15e91624a9366d7bde366d7c9cfabe2c9b -size 28456 +oid sha256:da07b8de2fd24e9e6bc7fea309e4d5fce68f2143316a5940a41f4270e9d48646 +size 28099 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_5,NEXUS_5,1.0,en].png index ade52ae50b..1de6e8de96 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e142fdf51287c82112267ac8070ff4d6c2fc3f92c14c82c16127aa1822823312 -size 28839 +oid sha256:1a7e0644fff4f219712719b4837cf4e5db5c8cf4c9ec1e21fcd1362859a155f3 +size 28607 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_6,NEXUS_5,1.0,en].png index abb2875d87..c078ce120e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:447fdfc57825e1da34d294b7e212984b088e283810fe961c5b21b66f3c770cbb -size 24971 +oid sha256:8444587bfa6ac65c6464b102bbac0bf679fecc0b193cc664540f39518b30c25d +size 24785 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_0,NEXUS_5,1.0,en].png index 9fa729c209..dc1ba40727 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b27f3e2719d238b61a8f83264417c9c2d9e561bbaf12eea20f9169366c90489 -size 31076 +oid sha256:22b0a03bec31400bd88a51c160bf63132f0c8f7e1cf02041a901778c3f1e27ef +size 30856 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_1,NEXUS_5,1.0,en].png index 1408e43788..cc49e4274d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b5b4b04d5163e8acec4f156396fd239296b7fe3fc251fc5efa78200f4b6a0e83 -size 24352 +oid sha256:8308dc746a7a51a7bffa49cbf1436097565a175298073afe3d94558d77307510 +size 24145 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_3,NEXUS_5,1.0,en].png index 1dddcbf124..ce4af21fcf 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:61b56cbc0193c9081ceb3c8662afc2da8686a7de4a3e8ed12af2f7dadfd0328a -size 30784 +oid sha256:32f3030c3bfb1bc9ed4c4378698df073cb29285477538c81592c38668953ffc8 +size 30562 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_4,NEXUS_5,1.0,en].png index d108a47a92..090bda7bbf 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f7ff9340f9788a65fe6ec4707cba125196fed08bb57ead4dce8bce2efb70f1f6 -size 29714 +oid sha256:0587640a3ffb707c94d25da38d9f327500c3d3a96d0b57ba92a3c4201014fc11 +size 29448 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_5,NEXUS_5,1.0,en].png index 68b91dcaaf..03d72aa037 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3ab65feb9ba77f6a08e52fae42f32133845f169c651049e90c32c3abfbd8cea1 -size 30835 +oid sha256:1017fcd62a71f7a2a82dbee3ee2a5233747eb3c888c4b6302f65d9aa02c5492c +size 30673 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_6,NEXUS_5,1.0,en].png index 29f2bfe96a..acd3d83443 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bf0735290b594857c52df56f2704b3e9ac7bae00a61a26b956febd5c6679357a -size 28228 +oid sha256:4e01d7e598c771260bf4ef91d0ae99081e80f318c1e0300cda3dc1ce780c80ee +size 28078 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_1,NEXUS_5,1.0,en].png index 774ae616b9..56e17f1b80 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:41c029826a7f0d722ff9493a287dc45ed01c4e0f02e1fbdb4f69abd0b762b5ac -size 28592 +oid sha256:44917f87510b19e963ab02f1324057b694815af1437300c8c4763ba617848dc5 +size 29113 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_3,NEXUS_5,1.0,en].png index 4ace7951a5..cdc1d79045 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5b4898e10aef39b1e7e9d16d9f214fab756dd203403de00e263a6049d4ff8b86 -size 26594 +oid sha256:c5fc0b0ad8f0b5524db430195f56526cf4c0d0ec48ac3bb90e7f339e4859507c +size 27041 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_5,NEXUS_5,1.0,en].png index 1d6c880873..ce2912e13f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:473160d4ce97eecd9bc9ed67011c505e536272ce1acf838516c34f3b992f74a8 -size 45367 +oid sha256:6d289d744e4ab63c6f9fc679b3e431ca4a8a3e905b0a34f4dd4b6d8ec5f345b3 +size 45347 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_6,NEXUS_5,1.0,en].png index 866984d7e3..ae4b8097c8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersDark_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b20115a793c0b021d077d816061b5b221f8e40581a6cf715fb4701941a38c207 -size 38583 +oid sha256:c61dfd03185e0eff646f3e6d4c433881825299129d979369645d689305a6234c +size 38500 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_1,NEXUS_5,1.0,en].png index 36b034bdb4..f4b3fc01a4 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:695041dfecf9415914d4f642c81154c8f90c8460bbd5c2023c9cce91352d2245 -size 29528 +oid sha256:d1071bdafa2d9c1aa08e81ecc4b7017957725eb90d0fcb23f455b5f80f98691e +size 30568 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_3,NEXUS_5,1.0,en].png index 9ac987f959..205a77a3e7 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2f8b8e95fc48731162ddf10a3b00bee300ba6fcaa02ea48455a68ce834915b8d -size 27532 +oid sha256:e391357db9d24d00fa2dcadb4cad590c7e71971b113ccccf7370edc396ae4da7 +size 28171 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_5,NEXUS_5,1.0,en].png index a7e212f2f3..33303a2529 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:867deebdc8a7e1844718508501e05d1f2f811f9847c60815fea86113ccb82bbd -size 47057 +oid sha256:6fec1683e88a36fa4c95f9bd83b01030f9b375cfff2034f723c81c31c6615f5d +size 46229 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_6,NEXUS_5,1.0,en].png index b204cae7f5..e50fd62303 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.invite_null_RoomInviteMembersLight_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2d99677b0930567cae7f6e356137ed98e701ff9ed2a6bd8aad66f9d12d8a1f27 -size 40726 +oid sha256:03881c5bc6ce8b1008679cdb0db2e86f713db25c9bea1eacecb713fc8274b91a +size 40281 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_0,NEXUS_5,1.0,en].png index ba78172dd9..74a3f56bee 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ceb363a42cce169fe6458d98f267feb22b87ced5f1bf6d73e5f41a6c2600199 -size 19574 +oid sha256:33c80b7d24e8f0ea86d22ac1fa92c72926edc2d51ede177046787c2d43440790 +size 19399 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_1,NEXUS_5,1.0,en].png index 3a070189ae..54685640c5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:29fa748333d5bfaebc2877ba66677687a0ac40581c1a4c61bc7cfd67f627f85b -size 17375 +oid sha256:a89af486f34afce8a092954f6adbc4a4a38154a8219de751982cddaeec6029d5 +size 17181 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_2,NEXUS_5,1.0,en].png index 2245a0502d..4d2060d15e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dc56b1324ca0206fe25eb83b1bfc0ceb559ec86581227e3db766ed52c4b314e1 -size 19992 +oid sha256:235918bd815cadfd3f202ab259081ef48da0e2fd563547ce7173b098c585bca4 +size 19814 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_3,NEXUS_5,1.0,en].png index ba78172dd9..74a3f56bee 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ceb363a42cce169fe6458d98f267feb22b87ced5f1bf6d73e5f41a6c2600199 -size 19574 +oid sha256:33c80b7d24e8f0ea86d22ac1fa92c72926edc2d51ede177046787c2d43440790 +size 19399 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_4,NEXUS_5,1.0,en].png index ba78172dd9..74a3f56bee 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ceb363a42cce169fe6458d98f267feb22b87ced5f1bf6d73e5f41a6c2600199 -size 19574 +oid sha256:33c80b7d24e8f0ea86d22ac1fa92c72926edc2d51ede177046787c2d43440790 +size 19399 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_5,NEXUS_5,1.0,en].png index e366ece74c..4a93a6cfa8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewDark--3_3_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:84218b0e445d477223d7dc7aa87e043671b6c4a5ce24f431af4860ba04fc8f02 -size 20591 +oid sha256:cd3658bdce62cf7ca62c9138271df8b2d44ad5c0229b468fb40049a575036070 +size 20418 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_0,NEXUS_5,1.0,en].png index 9aefe59c7c..c0ca95c0ed 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9830d6448948fad763093ccf0b8ca8df7cdc60e425d9fab1b1406f893329d620 -size 20054 +oid sha256:342a89e74b6067ff1fa1213edeb76dd05099d91083b6be92f48aff6ea6979393 +size 19817 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_1,NEXUS_5,1.0,en].png index 23ead15fc3..42407d39fa 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:85bb085789a6c4fa5cfa4379ef19eea470b4e7f276823362cb06f49903c01788 -size 17754 +oid sha256:c276773e89fbaba8b81ca5ace972364f2c4de24f670ac8a39f3a66c243a56699 +size 17517 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_2,NEXUS_5,1.0,en].png index 2d1bd42c0e..bb14682c7d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d21c65c4d5c0070c8a75156cadfa8b7a6f97a4ea8e2ab8b52339792a21638c63 -size 20512 +oid sha256:b6bdeb3f25b2f7a98ac55e3ba32858bc2fd2154f1f211e50a9bc36ac1be3090e +size 20270 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_3,NEXUS_5,1.0,en].png index 9aefe59c7c..c0ca95c0ed 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9830d6448948fad763093ccf0b8ca8df7cdc60e425d9fab1b1406f893329d620 -size 20054 +oid sha256:342a89e74b6067ff1fa1213edeb76dd05099d91083b6be92f48aff6ea6979393 +size 19817 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_4,NEXUS_5,1.0,en].png index 9aefe59c7c..c0ca95c0ed 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9830d6448948fad763093ccf0b8ca8df7cdc60e425d9fab1b1406f893329d620 -size 20054 +oid sha256:342a89e74b6067ff1fa1213edeb76dd05099d91083b6be92f48aff6ea6979393 +size 19817 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_5,NEXUS_5,1.0,en].png index 121f05a71c..4f768927cb 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members.details_null_RoomMemberDetailsViewLight--2_2_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:be5e1b77f5a7d9673f4c498a99e40cb633d536de608408a54dcb78fae7434d45 -size 21068 +oid sha256:427da8bbf67861ee3214540b57e573ff8b2879aaf3639769d4b9fccd591676c5 +size 20881 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListDark_0_null_0,NEXUS_5,1.0,en].png index 592eb43fad..22ab8f88bb 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c59cb5eb1538494a95a4dd531127afc8cae252b08c7812bee79db4b32cce500e -size 38214 +oid sha256:deecef6a5d8161828745db707304195d360e3454c1d092fe92c57cf87f55cb9c +size 38196 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListDark_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListDark_0_null_6,NEXUS_5,1.0,en].png index 5e988eb0b1..de021bcb26 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListDark_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListDark_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3535a659e893592ba4010c91049f0595d900d9f0aeea7bc2cb8317484bda58d5 -size 24897 +oid sha256:ae2b5be95736d02b76b34d3156b61a626edb738f3dd64f75c1a6c36b9413df0b +size 24968 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListLight_0_null_0,NEXUS_5,1.0,en].png index 8ac709d1b5..5de307f4aa 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da07b9156d4e27aaecf0d3860d927660a688f46caa305940f57ae2f783402c8e -size 39429 +oid sha256:c6312be03f23e39df742082f9886490107939fef35971c4476f3afe7285848fb +size 38836 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListLight_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListLight_0_null_6,NEXUS_5,1.0,en].png index d8fd92355c..4f504958a5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListLight_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.members_null_RoomMemberListLight_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3237f778a1be6d86fcc107942ed8d19d38f4c332c1c307391b70521f9b11c8c8 -size 25600 +oid sha256:c526ac195ee5c2d3f691a0fd13ea10a1efdd10b1c56bca579885d90d2f1658ac +size 25308 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png index 211bbf07bc..ae23a77cbc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:49bd51a32dbd3615364a6039163a36c08d0096a8c511a7084e21b7c1780131db -size 52810 +oid sha256:470a655997e6cd489a74d31e6db8641b48fd7974db87547f2d2efc9a4c8901bf +size 52503 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png index 19f56b887f..1f23fa479a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2c61e5d0eabb1f9cae83c3df0f73f14545e0c61bd7393d6e2862e0f48b9e3d7a -size 51272 +oid sha256:70b8a0df5f3184e54b372a07bba99381ddc107e6dea58eee96dcfd4f0d04c022 +size 50857 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png index ec15315140..00c3f8d140 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:adf48ade91c22ce7f98bf2773ec4e14ce0c290f7ba25e8c76d9f722677c46277 -size 44388 +oid sha256:fc70f4008e918612b15ce7d55d26092c632a08f3179c98452bd3acc9111dbb9f +size 43979 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png index d72802868e..ab80b1cf18 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:262ba970549c3c137ab90ffc607279479dfc4fbf86468e18b08ea6c5ef5b0710 -size 53634 +oid sha256:dd9f45108f2ec9739cb414bd11751e9ed41044948d5ddd70e9afaf7d75b52b3a +size 53305 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png index 04edeb3284..40942f08a9 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:49d92579bffadd59f89e79217b5e6148bbfeda0c5750a06ad7aa36f8125d6d29 -size 50616 +oid sha256:c01f60be5fdd30d9f75de6dc8a272954123e14a05eca2dc3fe643fe8769ff218 +size 50239 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png index 2150b91f12..0efa94ce47 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b742f507ba11be8bdf733e5e751fc5d9fe1c0cc2eb070abf9abcffb605783ab3 -size 52151 +oid sha256:275e0112aeed3097ef7eb295ef6dc7aedf6bccb0add1167c823b78953c887e33 +size 51963 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png index 2150b91f12..0efa94ce47 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b742f507ba11be8bdf733e5e751fc5d9fe1c0cc2eb070abf9abcffb605783ab3 -size 52151 +oid sha256:275e0112aeed3097ef7eb295ef6dc7aedf6bccb0add1167c823b78953c887e33 +size 51963 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png index f94aa99b7b..1b87302d36 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:467ca1b17857b053881cb9999c3d6b099949c6b4279188da57383fdb9083041f -size 53946 +oid sha256:eb9e612cc985121de0a8a506066dfecad22eb283232a6815e7a50197c1af5a1c +size 53640 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png index dbddc54999..5914da7d56 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d8e1ede8c0ea34595e90b2031c9607b99e72c3d7d1e9a778bbfbece98eb23875 -size 53035 +oid sha256:2efcf4a4db75ffdf8f2a2bcc841eb8c27b5497f8724754360256dec83b494f5b +size 52747 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png index ca3e37d42a..cd275d2b96 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a9f1d200ef2c93d557a67a29700918bd70439c7d7d8d247d60473b26f0c44eb3 -size 53851 +oid sha256:b845bb8d92a35424cd81a5355c0eb69cd069bdf327d28caf69326355e4c33e93 +size 53658 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png index c27ccdc333..4f5d817402 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b06e1652745ceff912734b9bf74543c95f4d420eaf3aec4b388dd101ea1428f8 -size 53838 +oid sha256:6825637037556cf9440d0cc2303f73e88e29385d1fce9e7670106c96ea3143f6 +size 53597 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png index 087bd78cc4..53423131be 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d4a381a3c99a7f04a11a2e93cd7c4145fa0bd33a1f7461038b3918c5cd94571 -size 46676 +oid sha256:6cca72e75685d2dbc6eb1b2025f8c487c443006d077cc560e6abafd16e06e6c9 +size 46510 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png index 0ebb4bdfc9..8425c5405e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:61add95d28096c65f94764df109d253c7b589058cea324d908616312e7dffc3e -size 54723 +oid sha256:6a4c6e92b895251c2c075f3679f7d31480bf1eacfa3592ef17e7d11c79120397 +size 54529 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png index 8a3a6dddf4..7b04c98e13 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3197e871e4b4c39dc714610b54e351c4061149bfc0b5511f78a0c73e8ec2236b -size 51824 +oid sha256:2072ec79ee1aad73cd20eaf0d87106b8757223a2499fff67c5c806223a705c66 +size 51626 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png index 6547257b66..e54b8591f4 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a0cf7d5d0c91aa7946586e5258077b07b329f387f46b0df0a29c49cc211ed584 -size 54021 +oid sha256:537e9ab994b8a6c6589b03e9c4231cd9b984cad4f233d106425d3d0e65af8864 +size 53852 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png index 6547257b66..e54b8591f4 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a0cf7d5d0c91aa7946586e5258077b07b329f387f46b0df0a29c49cc211ed584 -size 54021 +oid sha256:537e9ab994b8a6c6589b03e9c4231cd9b984cad4f233d106425d3d0e65af8864 +size 53852 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png index 6879d4dfb5..dc6c756bd1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cd4be4f49a78aba83c4b5f9c350f8b64cfe96d50890df16154cd7b0e20546d25 -size 55020 +oid sha256:183145910ec9cd8a5c19e30bcdf0995dcfc70c7a9a176fe28f6106b2dd5b21d3 +size 54827 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png index 92a37ad86d..185288adb1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da79bef2bd54301f2724269719d93d1d9212fd17b9dc0d2a7ba935693c6170ac -size 54107 +oid sha256:3202fed8c4344f427442905d4088441ea97446b4ef9350e588df26d5497192e4 +size 53932 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarDark_0_null,NEXUS_5,1.0,en].png index 72105204f5..48f8da47ee 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:efe240e29b1e9565edf56390c4ed5cb67a7e342cdfb96361782dd2d5dd28c939 -size 10554 +oid sha256:bbfb4b373449d3ce3ff06ad67e8c4ecfcbb0ec8d0bcb400d3c010952d11e8ad5 +size 10480 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarLight_0_null,NEXUS_5,1.0,en].png index afcb237bb8..82c658503e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarLight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarLight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:62f986c59715c6f74b0c2bf98afe7ea9df4619b833919183863c2550419e8dc7 -size 10412 +oid sha256:1d0cc556a6c431fc0f10958a4760fe63d0dd3d7f976ce3507643308c50f37c2e +size 10381 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_0,NEXUS_5,1.0,en].png index 96ad4b73cb..1af63ca5ba 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bf5694071227c215dfeee78347b20575aab8456c97ba33129386fa7b156beee0 -size 12089 +oid sha256:701e8c9761795b0d7b31d2e08afe502a56882d7a6ec6b61db1b1c13c59471b9a +size 11864 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_1,NEXUS_5,1.0,en].png index 4e2a983e69..5d349ba526 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9a186c8be46410cd829bcbc46f2e2360816e6d50f6476d1bfa5dbd970d9fe609 -size 9367 +oid sha256:329326c10ecb636896916019d113e777cb606d1ee1ded5578b7dbfbc38e0189e +size 9143 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png index fcf7318f4f..5d673a1cff 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:50826af8c22e844eca956ae277f09ff4c69a262507d32144313bb4638436a186 -size 12465 +oid sha256:e710857b4a1c3da12ceb51e7400229d0fd7f42d6d6158a07e2c2814c728abfdc +size 12229 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png index d4ff97ad67..d0ec7b4cb1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dd7d6642bde8e6062a2a87829741b23a18c9a08ecca3f8f1b291ddee9cac8a29 -size 13363 +oid sha256:db014e76a88015053b1be458ac758dde99f8cf01a7a78850c0bf6ff4db27dcbc +size 13173 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png index 8a1c18bb99..606a183dce 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bb25fca8bf0a2c4567e1687b37c4eba72cf8d7830cb74555f4bcf72941c66b2b -size 13694 +oid sha256:4d062feda6fc808aa87df5a5f4b3229153f7e50925e3c55a8c8a99a583212857 +size 13458 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_6,NEXUS_5,1.0,en].png index 7d4841a54c..7078257343 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3b7fed22743d761141600d8c1f0df0ed9799acc3d2087d693da2fffe53605a30 -size 22092 +oid sha256:79b24ca5c6426aa966024d79bdbbc4a612169037cf6bda7496299ea298fa7517 +size 21951 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_0,NEXUS_5,1.0,en].png index 0d10b79070..d80e1cc282 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b0959e717c4964cd8c5acf05fcbbadb2e44bee3217ab451a7b2d77e534be08e3 -size 11868 +oid sha256:fde0cc6b7268856b611db66b66b22c51df155f605988fc54f5c7ba18e5f1f713 +size 11456 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_1,NEXUS_5,1.0,en].png index d58e9f7aa0..73ca4a2eb7 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:17dd1974f121b1bf0c769cb005f0b1cfb57b11e8cfe94f752b4e9d491e554af5 -size 9216 +oid sha256:ca1cb753204502aa929f52e8b222b86bd845086f841fb9ff2936886e1dcea526 +size 8778 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png index 7b034632db..e471eae254 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d90d24f83b8ef1d33ddeefe7942728d1b8de914de97b5724f1413fc88acac771 -size 12247 +oid sha256:9c9b33e480bfad9c55d55e25cef2a0ab1f25235382e1b53c93107a75e95fa90e +size 11840 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png index cf650bfb41..582d30fdfc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:193959145770210881785866b3951a5fc9c02f11604d96d2f4dcf9154b69328f -size 13211 +oid sha256:824e708f277ea66a161f17cb07a3070e03ddcfc326b9dd73d0ad6b7e62da32c1 +size 12807 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png index 07acdce0af..0de6b64bec 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a439996ea530d83c8f40baf0c4320a8ac21966cff838922e8fab926f7d3af5a4 -size 13683 +oid sha256:39b7b8354b98bca791698ad65f4e21619136f446b2fd050c302bdd27ce138a4a +size 13263 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_6,NEXUS_5,1.0,en].png index 5f190faa9e..fcf8b20fdc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9ff4b3f9f077ba9a62878463e3153e89e033bc631c4b627d31324d4f9af511e4 -size 22486 +oid sha256:64e7ca21b0213413ed45d0640295ceb2764b01b2bce20a01518e55e620925086 +size 22193 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_ContentTo_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_ContentTo_0_null,NEXUS_5,1.0,en].png index aebe17e861..976af63965 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_ContentTo_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_ContentTo_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c0d63e4326bdec31177615bc924c0fbde49842bb895601ae31036813dd7ba669 -size 30482 +oid sha256:0a7a00ebee01aea35dd50cfa5155f6ff58efb21fdf62efb934bf70411563d7cc +size 29908 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_RoomListSearchResultContentDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_RoomListSearchResultContentDark_0_null,NEXUS_5,1.0,en].png index 26664565ca..5d23ac3205 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_RoomListSearchResultContentDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_RoomListSearchResultContentDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:15198a0c45657bcfa1f945349b18106e3239def6e869aa000030e3354ddc03d6 -size 29732 +oid sha256:392c865a3d45c0ab5270241d31159075edfe020526b0fbe39593e46b29da958b +size 29819 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_RoomListSearchResultContentLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_RoomListSearchResultContentLight_0_null,NEXUS_5,1.0,en].png index aebe17e861..976af63965 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_RoomListSearchResultContentLight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_null_RoomListSearchResultContentLight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c0d63e4326bdec31177615bc924c0fbde49842bb895601ae31036813dd7ba669 -size 30482 +oid sha256:0a7a00ebee01aea35dd50cfa5155f6ff58efb21fdf62efb934bf70411563d7cc +size 29908 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_0,NEXUS_5,1.0,en].png index 50d588999b..c00ff9fa1a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4482b15d928567822dc984a1f19c698f6a9d981d907b70635b3054795292306a -size 36543 +oid sha256:66bf2e3b890ab75c77f1a9e4e80a374cbb5af35e72b8f53c86424c56f1a9f524 +size 36582 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_1,NEXUS_5,1.0,en].png index 9ffc58dd11..d47352bb7c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b22df92cc4ec3e9622f23f6fb7e800e17afbe3a12f9f3d4121b1981ac0350f8 -size 59635 +oid sha256:1aff1b446de80f7535a71fbc77d7955a679ff2846bb240b70f2d410114f29b16 +size 59749 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_2,NEXUS_5,1.0,en].png index 50d588999b..c00ff9fa1a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4482b15d928567822dc984a1f19c698f6a9d981d907b70635b3054795292306a -size 36543 +oid sha256:66bf2e3b890ab75c77f1a9e4e80a374cbb5af35e72b8f53c86424c56f1a9f524 +size 36582 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_3,NEXUS_5,1.0,en].png index 58940cb17b..d054685464 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c78072a5ab2e95aaf7abb085db0d66761eb987b22c0e1dcd6da901f3fbe2a3d7 -size 38438 +oid sha256:0fd240006e3b08b081fccdcc29cb8911fbde7f923c4f8207de817ea6a42d3d6f +size 38475 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_4,NEXUS_5,1.0,en].png index 98f9563247..144beef563 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2cbf0a4e9ca5d3471d361890737d5aa9636abe3143f5de9218e0568951d59bf5 -size 37887 +oid sha256:77d78ad2cabaac211517c129a42d8164b02ba2cc5b75a13f27f2ae113b2b9f06 +size 37924 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_5,NEXUS_5,1.0,en].png index 3db493ae46..7125e2cb27 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:12cac3731fd61b4cbfec09b0f439b2744a5374b6d9ee2b79880507af2224b969 -size 38241 +oid sha256:9701408630ece8c6178e792920688eb41a8fe1a4621c45f8cf34338f134dded2 +size 38290 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_7,NEXUS_5,1.0,en].png index 26664565ca..5d23ac3205 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:15198a0c45657bcfa1f945349b18106e3239def6e869aa000030e3354ddc03d6 -size 29732 +oid sha256:392c865a3d45c0ab5270241d31159075edfe020526b0fbe39593e46b29da958b +size 29819 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_0,NEXUS_5,1.0,en].png index 7b757a00fd..c12e094911 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b03c0240edcc58f64bd1dc7e9ef619081f4019c5825c6e4133f3aab4b7cf9b7a -size 39711 +oid sha256:56f0ecce5efe141fa2181e2c16dc654e79c4de43cb11b18004b03ce2ddad991d +size 38801 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_1,NEXUS_5,1.0,en].png index b624add247..87770b930d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f2ca4bee47e6beaf4b79c0417dbfe132f6e92974c33484bb0440929a35ada794 -size 63618 +oid sha256:f9d7be89279d30e82a689654eac67137678ca4eb079e80372011580bcf0e9e22 +size 62757 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_2,NEXUS_5,1.0,en].png index 7b757a00fd..c12e094911 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b03c0240edcc58f64bd1dc7e9ef619081f4019c5825c6e4133f3aab4b7cf9b7a -size 39711 +oid sha256:56f0ecce5efe141fa2181e2c16dc654e79c4de43cb11b18004b03ce2ddad991d +size 38801 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_3,NEXUS_5,1.0,en].png index d046533d4d..861787a0b8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:19e78d44954b0cde8ea83873f40e6b0a5cf53a02b4bd523e8b8710a483471e32 -size 41698 +oid sha256:db76df516d6c7a4bff5b830e423145c448b076846b8b7f75032be6f65585cd31 +size 40846 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_4,NEXUS_5,1.0,en].png index 479929ff78..0968936113 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6ff479b11d48f3bdf5adc02d466b6427cbf778b2d2184d6e88d7abe8c12043c5 -size 40960 +oid sha256:405842db16444b958899fe174ca1c0157c0c6384f8ae0be37be104de8613f140 +size 40126 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_5,NEXUS_5,1.0,en].png index 7d8cdf7415..1033a71853 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1f9e4cc9f63f4414fbe1f82e82b9eca7b5071e26aa057b1137daa75cecccf150 -size 41329 +oid sha256:658ee0f231146446810d7c0d09d280148d68475d2411c59cf0ac70caabf4e3ec +size 40496 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_7,NEXUS_5,1.0,en].png index aebe17e861..976af63965 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c0d63e4326bdec31177615bc924c0fbde49842bb895601ae31036813dd7ba669 -size 30482 +oid sha256:0a7a00ebee01aea35dd50cfa5155f6ff58efb21fdf62efb934bf70411563d7cc +size 29908 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_0,NEXUS_5,1.0,en].png index dd5e1401fb..9b60e19c06 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3d5e1eec999486b11a48ae992708adb8634a46fc89114de463894fd5730330a8 -size 17895 +oid sha256:0a2a737eb81f74c50efb44c03ac9eb528c38ff393dc1a32efa0c148e27da4668 +size 17880 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_1,NEXUS_5,1.0,en].png index 83cf5299d7..fbbc1e6a37 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8a66c143d05cad7db2ca195bcd0d9a3007169c123c96f11fb66dfade6904db1e -size 17359 +oid sha256:ff929a3cfa47f93176817cc844b9ef2f5ff6146f016606515efe858fadd00247 +size 17199 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_10,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_10,NEXUS_5,1.0,en].png index 8321f05002..56cb2f3f4d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_10,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_10,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8da740d8a43f978b1da59585326848fe18b71b7cbd4cbaecbf520a7219bf5df4 -size 19100 +oid sha256:385ccb31d2b5a286e2bc4db603d0332295fb6f31841e59440f042c99c5c3d5d5 +size 18837 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_12,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_12,NEXUS_5,1.0,en].png index 7dc547ba61..86f5cac7e8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_12,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_12,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae676fe3063c21680f87ba11f7f68d11250c67365a4da0541397c4fb635f939f -size 20231 +oid sha256:ed8573768b874987b1a313482c9dd38695711ab8e67e81c2cc263da8236e9dc1 +size 19998 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_13,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_13,NEXUS_5,1.0,en].png index c0d18e4417..3cbd9f9818 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_13,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_13,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2834d0f7335480a35ca041091c8d7062d64501d52855458864505a1eb12453c1 -size 19043 +oid sha256:7e8e8e31b6f3b43b53d43ec0e067e1f554d2b287909425af625f3c3a187d3b57 +size 18571 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_15,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_15,NEXUS_5,1.0,en].png index 7c3c298a92..2c47cc04a5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_15,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_15,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:71ea9ad8c4934ee391d94836e57e06f5332963c09ed4c689c125337bb4f66504 -size 22821 +oid sha256:fd6f03742a1840a794f6d506a70ab1dbbb5a1e745e054e47dd4d2292983cdaa1 +size 22491 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_16,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_16,NEXUS_5,1.0,en].png index c6c2cca49b..3a9f7dafc8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_16,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_16,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:02d3fc1981a83b1635b89cecbfe2ffac65b070060f28050fbafcbb35fa4222b1 -size 20911 +oid sha256:c9d94151ec126ccd1780326a56cce74bcd2a6bafb4a39ff06d6787c9be078d3a +size 20049 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_18,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_18,NEXUS_5,1.0,en].png index 0f4969c23d..fdc359107b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_18,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_18,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:34aab6f95f04977d64f97c5a9391806cae363408f011bd57a7a2954f6af6c5a2 -size 16654 +oid sha256:ce07aa02c49b32690e95f626edf7b9d6152eac078f4bd46a96ccb3c9c9c69859 +size 16531 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_19,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_19,NEXUS_5,1.0,en].png index b66d0a9445..b1d7be7920 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_19,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_19,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5222d968327e6de88f6f1f2bc02e47da51b6bd2fb2dc109279e5b240762966df -size 15899 +oid sha256:a57d40118355c3b039b915462987b1bc960d9ca501d6c725937112fd8cb0b84b +size 15644 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_21,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_21,NEXUS_5,1.0,en].png index 8a9e08a783..d10bba8289 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_21,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_21,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:677d553d6098e0534d81e7c4218698f8e0b9635225332d484108917332350494 -size 19540 +oid sha256:c0593fb2b66b37bfd2abc3b4c5cc44a9fd808bb192ab8c972998d424c30aca36 +size 19310 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_22,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_22,NEXUS_5,1.0,en].png index 200d140d83..6868bc07ad 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_22,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_22,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:34e763d9617c7023f3f365ca00e75dcc0d4e80a7a9a2c74bede55456c73f3fea -size 18349 +oid sha256:c0bfae52f5a63263322d31c60a63f8715afd8b1846bc1cb264bcb1f5629927d2 +size 17871 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_24,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_24,NEXUS_5,1.0,en].png index 12f34d2fe0..7d870f1ce4 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_24,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_24,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7acf87fd6c7da93132c9c89974b6e82728b7aee91f078146ba9a002ed1ae261b -size 20457 +oid sha256:4f43a9df02fb5e54b9a0cba1e4975c5029dfa5e71ed14efb0e435dc8c27617b6 +size 20213 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_25,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_25,NEXUS_5,1.0,en].png index d6b341d0f2..23724b3516 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_25,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_25,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a6654898419c10c0fc2f96aa975295ac94a68bf1362c3ac955388e5f9bf8e67c -size 19301 +oid sha256:6747bc029d66697c13e7ec048020ad77391dfac6a60ca30d1e01fe3fd8a53beb +size 18784 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_27,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_27,NEXUS_5,1.0,en].png index 300f3e1ba0..5f02a6a11d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_27,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_27,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cba6dc7fb2520afe1553ba63b92195708fd77f8ef852ecae0a1407e65970b31e -size 16263 +oid sha256:451a6870ceebaafc86252e72c71c96aebfa92a70dcc0516946c0879850f530da +size 16135 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_28,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_28,NEXUS_5,1.0,en].png index a94d27f33c..cd8e301f95 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_28,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_28,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0271737aee4d0922d0613bce60098a921b1b9f717e9be68d5288f7bef07bd76d -size 15576 +oid sha256:7abb38bc4f7c9fca7875d9b5c8c7674c4c2b24c6cae6a122d833cd63ff16a0fe +size 15344 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_3,NEXUS_5,1.0,en].png index ae8c04c855..4b307b5a87 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ea7a72ca0a5e99b0c906342ed34830b7e9ac75cb1e370fc7c9eb33441492aff -size 23247 +oid sha256:c6c2991436f603bc75c9838008c30201ae3dade211852bfc713c8c2ab9d795d9 +size 22929 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_30,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_30,NEXUS_5,1.0,en].png index 203e9e5ca2..2ca5005092 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_30,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_30,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1fbe133ecfff74a27273db57f40991cc3f4676f454a85a18162e0c9bc75b55d -size 17065 +oid sha256:c61707b4444693c7e4d58edeec7bb32de1bcaeb76e03a806a883eea7685a9bf0 +size 16962 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_31,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_31,NEXUS_5,1.0,en].png index 6d763a36c3..a510b71d5c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_31,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_31,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9665e21d61256c77e239a587e45529edd30db85448bb768070d48ccf42a90c32 -size 16407 +oid sha256:8a637c8d265e3cd9c8ff0e8e804e46c415338bdbb4bc842c81bf5ef31146d53e +size 16177 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_33,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_33,NEXUS_5,1.0,en].png index 95df6d421f..df93febb6f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_33,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_33,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:46ffbd54e3171340f0b6b8d632964b3b91480cfd6d99871c0f1d6bb7b8cfecc6 -size 20738 +oid sha256:748a2562d8c3e9b5e4def3b8ea3c782868e56f449de1b1ddb4bc36cd84945318 +size 20642 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_34,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_34,NEXUS_5,1.0,en].png index 59e8eac7f5..f97e401957 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_34,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_34,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:10989322060483d1948f297cf66d7442444f613e9a883fa1377941d73b57be22 -size 20096 +oid sha256:9a6ce0c3b6fe3ac503ee7019dee234a9f96552e1106fe6858030a7c70c506d4f +size 19869 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_36,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_36,NEXUS_5,1.0,en].png index d455ea4877..d21aa10955 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_36,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_36,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:736bd589ada20b9ac5d653fcc78acbedf08d406c0aab7a8159b0bd52db49d8be -size 18774 +oid sha256:0c49437c9f943cf044ec64a0ecab2b70d1fa811a34aff4baa8ed0ed846a4f5c5 +size 18595 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_37,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_37,NEXUS_5,1.0,en].png index 3a075cd929..726d7087b0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_37,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_37,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1a494c20b5047c925aa60b8253b4ea1bd90a95013df3d711bded444f1cbb0941 -size 17683 +oid sha256:063cdf0bbdfc846d3040af143f79a0b6eb325beab62cba5657236d028db6bc26 +size 17267 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_39,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_39,NEXUS_5,1.0,en].png index 9b2e1e6381..38c479cfdc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_39,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_39,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1fed24563d497b368859de9de4e4c9ae27cb645d89888f7fa7402df64d447471 -size 14589 +oid sha256:032ed67865d3ad800371e193ea922589f27cf03697e3c91c8d698957befa8d42 +size 14590 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_4,NEXUS_5,1.0,en].png index c479e6007c..b109475f03 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bc087aeecec205ff20e45fbe27003409591e9ecada4c2f2b4322537deac6b490 -size 21381 +oid sha256:c5b4dbf61e9b79fa1a884941cc5b92b71b13287109d28837a7fe76fd9c4286db +size 20533 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_40,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_40,NEXUS_5,1.0,en].png index 46cc322fde..8152088666 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_40,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_40,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4ff8361d32597bea90e830056f00846b9e2392685eb6ac000c8c930ba5c981cd -size 14296 +oid sha256:54b00e4382ea77eb90e6de983ec1b363b504456cebd1754946759fd2ee1e9b85 +size 14232 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_42,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_42,NEXUS_5,1.0,en].png index 1483a5ea12..d69da80047 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_42,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_42,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5c50d9aee05b3e8b8be0b403a0621bc949c08dbca46695f6c70666002d5101d2 -size 18355 +oid sha256:820b23e9b9175b48461a4e7e359c2440b8c45cb598f512ea360519b0815621fc +size 18259 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_43,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_43,NEXUS_5,1.0,en].png index 868cdd8e71..4cf9f8f839 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_43,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_43,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d56abddf692484f8e2f3795c6cd3c62e8497a2d03042ef770fb75e8863921d40 -size 17689 +oid sha256:3ce4abbf622711cf6a106cb6c74ed729c6e609d329579b7b00ba8c1581b4b953 +size 17463 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_6,NEXUS_5,1.0,en].png index 7165d890d3..6d21931fa0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6e2070fbae74dff21576afcd623f73ceacd018b934d44247066f469c9690d2f1 -size 18679 +oid sha256:250b9abfa2b27ea622f43a7d553ee6323eb44afa2288ebc110c0ce2b192f40b0 +size 18504 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_7,NEXUS_5,1.0,en].png index 92daab450b..217c6fc156 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:86660baa06208b38f8201d9155a64fade6fb3ba49689982fa013488f8cbd6f83 -size 17595 +oid sha256:a87e06ec084f377cc608790d326adced33100f8821162ca28bab24856f7ee52d +size 17176 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_9,NEXUS_5,1.0,en].png index 3c81ba86b6..b886f9140e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_9,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_9,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:febcacfbb96dcd0cf8815760409d105847b1fadc65e8254d386d774e41178a38 -size 19849 +oid sha256:73356882450cd90a01b8056379848967d3bea1e640ee4e901d9d21a1e823054d +size 19753 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowDark_0_null_0,NEXUS_5,1.0,en].png index f6663c9291..4dc5242c19 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:775f1249eded2e16bc7e03a827256020504379a6999b7ca3a1eeae2fdbf8415a -size 29227 +oid sha256:49f83ea2049468223d654efe71eb572af225fae3563f307ee45b95d220e8fa6e +size 29450 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowDark_0_null_1,NEXUS_5,1.0,en].png index f06a8e0ce6..03afa4ded3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:12c84950e69b760e32bb59c9d90a01d4ec1e17a28ac3c6ba53bd16c8d561db05 -size 27552 +oid sha256:de59712837eaa588f9daaa55983f44bfa39fd9d0fa3b10678b4e04c7b5571f5e +size 27655 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowLight_0_null_0,NEXUS_5,1.0,en].png index 454bbe5c79..28c78fd115 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f5882ca765a08118f6e23925d0621b882d41eb6ead7f8e62240c3473f3aa029d -size 29599 +oid sha256:2d91c6228c80d1d38217e557552e18e64494a94d284de8702d07cc3793150406 +size 29177 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowLight_0_null_1,NEXUS_5,1.0,en].png index 6533078c75..f1abda92fc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableMatrixUserRowLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:73fc004c07b36c64f08a65a8b9b62352e9a69f634629141dc1da3aa28397d6f1 -size 29347 +oid sha256:eeb5b50675e186318458d0900b2d3872ec52710df8e25ba7b633a4be7e13c8da +size 28196 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableUnresolvedUserRow_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableUnresolvedUserRow_0_null,NEXUS_5,1.0,en].png index a645112020..a65a5470e1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableUnresolvedUserRow_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_CheckableUnresolvedUserRow_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:84714adab3d3fc1a8f076589fd49bb35562913d99d353e9a9e318615568fe3a7 -size 116049 +oid sha256:fd6796e3461493cde5e861a05dfccd8bf40e1ceebb66273d1c5486a7a96684b1 +size 116160 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderDark_0_null_0,NEXUS_5,1.0,en].png index f7d8135d0b..c53281b9c1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:964d97909629c1228e96d923ddb478735475839b8540c02142444f9ebd5bf400 -size 13100 +oid sha256:115262f8a16f26506139c7b8f630e85520639ae5dca424028bc9a721942aebc5 +size 13168 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderDark_0_null_1,NEXUS_5,1.0,en].png index bff7b81448..658eb46874 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bd8ff4a09babf30be0eb3c336f3cbe6a1508a21696512d0dadbcc9d543e6e34f -size 12356 +oid sha256:5055b4cc1bdf5a4b00e901e5e40c0cdcc415d22d7154ef38888936928100928e +size 12365 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderLight_0_null_0,NEXUS_5,1.0,en].png index fe1fe39c26..85665e2302 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:85530997942e39ce73512513ab0698494778168bc28cfab543b50b721c1807f5 -size 12855 +oid sha256:1c4ce3a10a671acfb2e619356cf792b5f11325a55edca30c57813aa7823e878d +size 12591 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderLight_0_null_1,NEXUS_5,1.0,en].png index 23211c9508..119c55ec0b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserHeaderLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2e0a638be5745c75c2663116877d380c83df093d226d2c969d4f6620e8cee109 -size 12965 +oid sha256:28f315ebf657e95e666b6599b096d1779b1c9f3cefea3e679a9054d80f89d53b +size 12412 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowDark_0_null_0,NEXUS_5,1.0,en].png index ad70967875..2e089c96eb 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1acf91a8440717f3467e62a533a6172a7eba01c65b2d8d32b3b3b44d514f52b4 -size 11227 +oid sha256:3c174381b49b1d3d4043164db6621867193576e3b90cc7ff1c5eddf7244074f8 +size 11249 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowDark_0_null_1,NEXUS_5,1.0,en].png index 0563bc9ae3..8c97c7049c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:01b6759a944884c2c6c7c0631984dc904da890c3a05ac65f4648729065c4f26c -size 10669 +oid sha256:8b7ad04703963062b5a6490434a572473582ec7f9fd5f96155f5723b0dfaae2c +size 10693 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowLight_0_null_0,NEXUS_5,1.0,en].png index 847d11231f..76b6e0d9ab 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6c881c08f6501f8a7d2b865360510ec8b2cfc5819d398b477aa1ca970b20fac3 -size 10983 +oid sha256:7eb78dcf579ebd555e77fa74a40732458ae11bca79c8244f12e93eee605d9694 +size 10862 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowLight_0_null_1,NEXUS_5,1.0,en].png index f133082603..739a9ec9c9 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_MatrixUserRowLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ea7db4fd34a741fecff2a084941a55582e167d72a66a4e206102b5cf8d52c806 -size 11014 +oid sha256:20a51ed0238f83b99d849325c254919028c0011616698b042fc1f407841805b8 +size 10713 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedRoomDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedRoomDark_0_null,NEXUS_5,1.0,en].png index 14155e5999..e008079f3b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedRoomDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedRoomDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:64ca46029a544e74b05f4a1bc84f17082832b5fdaa9d76a1b5dd3aa755241951 -size 9297 +oid sha256:9a70b86bbd2db875ab61aabd34084aaebc9c12472e8548817be628bb1980547d +size 9311 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedRoomLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedRoomLight_0_null,NEXUS_5,1.0,en].png index 0c18e4464d..0fa91f8ca3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedRoomLight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedRoomLight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:78d437e9257a4e8e0f8478607cb852a18e188f65adc30c2297f1d18ef4fbccf1 -size 9108 +oid sha256:5d725ba73157dbb895b34594538ebc149765db558d87a463e7ec24b424bac4da +size 8791 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUserDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUserDark_0_null,NEXUS_5,1.0,en].png index b640b61655..6cc609e8ec 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUserDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUserDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e4f6d3ffbe069775e1110e49d7e95d43cb81919642062953d6d8a7ab3b82987e -size 9464 +oid sha256:0046609fce701f35dd8a81cca93aba806782924a893919a6582bccc019899d3b +size 9467 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUserLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUserLight_0_null,NEXUS_5,1.0,en].png index 6a1f4eaa15..e766c6c946 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUserLight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUserLight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c77400352729ec572955725cd8afd6149e7ae86aab18a82dcbd51f4c2cdc0e81 -size 9161 +oid sha256:2b00ab54a071453b87e3243bc8bc2f07520af89864c3776c112b23748e2e6e5e +size 8965 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUsersListDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUsersListDark_0_null,NEXUS_5,1.0,en].png index 0d23f92aad..46ab9e4895 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUsersListDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUsersListDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d3677896ec686f3b9cff36bc947de97bfa3b9274dd19705d6fc79b26bcdcc82 -size 74472 +oid sha256:ebb4d2e8a884af7bbded12fcee2b6e74ebaa1c54223566d62cd5e9cdb8f78bed +size 75290 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUsersListLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUsersListLight_0_null,NEXUS_5,1.0,en].png index bd01feb258..ac50871cb5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUsersListLight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_SelectedUsersListLight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d3c61acf6eff591fb7765468aa981b8a87fb6da4054175ea60968f5d81370677 -size 73693 +oid sha256:0d3fa7cc10b81df36f01ef13c39f033d5cda8489bc2226f5358f21fb7ad9801f +size 74098 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_UnresolvedUserRow_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_UnresolvedUserRow_0_null,NEXUS_5,1.0,en].png index c5a2a4a248..89a8e3dcfd 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_UnresolvedUserRow_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.matrix.ui.components_null_UnresolvedUserRow_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9aa050bd40cae65f3a2fbcd396f525238d182d5e99656adc706692e8feeffd42 -size 32134 +oid sha256:7beca493206b2dd0c48792e391ae5b980ee6bd5e12ee435dadabaab647b816f6 +size 32239 From 3ff7b752a10bc2601674bb9563764f6502b748a7 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 11 Sep 2023 11:31:21 +0200 Subject: [PATCH 093/234] Ensure Posthog data are sent to "https://posthog.element.io" for release build. --- .../posthog/PostHogFactory.kt | 6 ++- .../posthog/PosthogAnalyticsProvider.kt | 4 +- ...thogConfig.kt => PosthogEndpointConfig.kt} | 9 ++--- .../posthog/PosthogEndpointConfigProvider.kt | 39 +++++++++++++++++++ 4 files changed, 49 insertions(+), 9 deletions(-) rename services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/{PosthogConfig.kt => PosthogEndpointConfig.kt} (77%) create mode 100644 services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogEndpointConfigProvider.kt diff --git a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PostHogFactory.kt b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PostHogFactory.kt index b4fd6dcd18..ca6e5a18e1 100644 --- a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PostHogFactory.kt +++ b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PostHogFactory.kt @@ -22,13 +22,15 @@ import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.di.ApplicationContext import javax.inject.Inject -class PostHogFactory @Inject constructor( +internal class PostHogFactory @Inject constructor( @ApplicationContext private val context: Context, private val buildMeta: BuildMeta, + private val posthogEndpointConfigProvider: PosthogEndpointConfigProvider, ) { fun createPosthog(): PostHog { - return PostHog.Builder(context, PosthogConfig.postHogApiKey, PosthogConfig.postHogHost) + val endpoint = posthogEndpointConfigProvider.provide() + return PostHog.Builder(context, endpoint.apiKey, endpoint.host) // Record certain application events automatically! (off/false by default) // .captureApplicationLifecycleEvents() // Record screen views automatically! (off/false by default) diff --git a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogAnalyticsProvider.kt b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogAnalyticsProvider.kt index 1f21c0beb5..ca5ac527d9 100644 --- a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogAnalyticsProvider.kt +++ b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogAnalyticsProvider.kt @@ -32,10 +32,10 @@ import javax.inject.Inject // private val IGNORED_OPTIONS: Options? = null @ContributesMultibinding(AppScope::class) -class PosthogAnalyticsProvider @Inject constructor( +internal class PosthogAnalyticsProvider @Inject constructor( private val postHogFactory: PostHogFactory, ) : AnalyticsProvider { - override val name = PosthogConfig.name + override val name = "Posthog" private var posthog: PostHog? = null private var analyticsId: String? = null diff --git a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogConfig.kt b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogEndpointConfig.kt similarity index 77% rename from services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogConfig.kt rename to services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogEndpointConfig.kt index 96d8659b11..06f10fc07b 100644 --- a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogConfig.kt +++ b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogEndpointConfig.kt @@ -16,8 +16,7 @@ package io.element.android.services.analyticsproviders.posthog -object PosthogConfig { - const val name = "Posthog" - const val postHogHost = "https://posthog.element.dev" - const val postHogApiKey = "phc_VtA1L35nw3aeAtHIx1ayrGdzGkss7k1xINeXcoIQzXN" -} +internal data class PosthogEndpointConfig( + val host: String, + val apiKey: String, +) diff --git a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogEndpointConfigProvider.kt b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogEndpointConfigProvider.kt new file mode 100644 index 0000000000..841f41b807 --- /dev/null +++ b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogEndpointConfigProvider.kt @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.services.analyticsproviders.posthog + +import io.element.android.libraries.core.meta.BuildMeta +import io.element.android.libraries.core.meta.BuildType +import javax.inject.Inject + +internal class PosthogEndpointConfigProvider @Inject constructor( + private val buildMeta: BuildMeta, +) { + fun provide(): PosthogEndpointConfig { + return when (buildMeta.buildType) { + BuildType.RELEASE -> PosthogEndpointConfig( + host = "https://posthog.element.io", + apiKey = "phc_Jzsm6DTm6V2705zeU5dcNvQDlonOR68XvX2sh1sEOHO", + ) + BuildType.NIGHTLY, + BuildType.DEBUG -> PosthogEndpointConfig( + host = "https://posthog.element.dev", + apiKey = "phc_VtA1L35nw3aeAtHIx1ayrGdzGkss7k1xINeXcoIQzXN", + ) + } + } +} From 3b24990a9fb668fb2dd763f67de1722affc9814c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 11 Sep 2023 11:37:56 +0200 Subject: [PATCH 094/234] changelog. --- changelog.d/1269.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/1269.misc diff --git a/changelog.d/1269.misc b/changelog.d/1269.misc new file mode 100644 index 0000000000..1b3205917c --- /dev/null +++ b/changelog.d/1269.misc @@ -0,0 +1 @@ +Ensure Posthog data are sent to "https://posthog.element.io" From cbb27cb5e596b7088fbca4fe4f97bff31df205bc Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 11 Sep 2023 12:03:17 +0200 Subject: [PATCH 095/234] Class annotated with `@ContributesMultibinding` cannot be internal. --- .../services/analyticsproviders/posthog/PostHogFactory.kt | 2 +- .../analyticsproviders/posthog/PosthogAnalyticsProvider.kt | 2 +- .../analyticsproviders/posthog/PosthogEndpointConfig.kt | 2 +- .../analyticsproviders/posthog/PosthogEndpointConfigProvider.kt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PostHogFactory.kt b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PostHogFactory.kt index ca6e5a18e1..40c72142c6 100644 --- a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PostHogFactory.kt +++ b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PostHogFactory.kt @@ -22,7 +22,7 @@ import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.di.ApplicationContext import javax.inject.Inject -internal class PostHogFactory @Inject constructor( +class PostHogFactory @Inject constructor( @ApplicationContext private val context: Context, private val buildMeta: BuildMeta, private val posthogEndpointConfigProvider: PosthogEndpointConfigProvider, diff --git a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogAnalyticsProvider.kt b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogAnalyticsProvider.kt index ca5ac527d9..e371c6fef4 100644 --- a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogAnalyticsProvider.kt +++ b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogAnalyticsProvider.kt @@ -32,7 +32,7 @@ import javax.inject.Inject // private val IGNORED_OPTIONS: Options? = null @ContributesMultibinding(AppScope::class) -internal class PosthogAnalyticsProvider @Inject constructor( +class PosthogAnalyticsProvider @Inject constructor( private val postHogFactory: PostHogFactory, ) : AnalyticsProvider { override val name = "Posthog" diff --git a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogEndpointConfig.kt b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogEndpointConfig.kt index 06f10fc07b..a037c53797 100644 --- a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogEndpointConfig.kt +++ b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogEndpointConfig.kt @@ -16,7 +16,7 @@ package io.element.android.services.analyticsproviders.posthog -internal data class PosthogEndpointConfig( +data class PosthogEndpointConfig( val host: String, val apiKey: String, ) diff --git a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogEndpointConfigProvider.kt b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogEndpointConfigProvider.kt index 841f41b807..53fdb0947f 100644 --- a/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogEndpointConfigProvider.kt +++ b/services/analyticsproviders/posthog/src/main/kotlin/io/element/android/services/analyticsproviders/posthog/PosthogEndpointConfigProvider.kt @@ -20,7 +20,7 @@ import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.core.meta.BuildType import javax.inject.Inject -internal class PosthogEndpointConfigProvider @Inject constructor( +class PosthogEndpointConfigProvider @Inject constructor( private val buildMeta: BuildMeta, ) { fun provide(): PosthogEndpointConfig { From d69728c0ffddf53a1e013c2dbc4a03fdea308fb0 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 11 Sep 2023 12:12:48 +0200 Subject: [PATCH 096/234] Fix and add test. --- .../onboarding/impl/OnBoardingPresenterTest.kt | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/features/onboarding/impl/src/test/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenterTest.kt b/features/onboarding/impl/src/test/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenterTest.kt index c2db28631c..538fba98d5 100644 --- a/features/onboarding/impl/src/test/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenterTest.kt +++ b/features/onboarding/impl/src/test/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenterTest.kt @@ -20,6 +20,8 @@ import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.core.meta.BuildType +import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest import org.junit.Rule @@ -33,13 +35,25 @@ class OnBoardingPresenterTest { @Test fun `present - initial state`() = runTest { - val presenter = OnBoardingPresenter() + val presenter = OnBoardingPresenter(aBuildMeta()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitItem() + assertThat(initialState.isDebugBuild).isTrue() assertThat(initialState.canLoginWithQrCode).isFalse() assertThat(initialState.canCreateAccount).isFalse() } } + + @Test + fun `present - initial state release`() = runTest { + val presenter = OnBoardingPresenter(aBuildMeta(buildType = BuildType.RELEASE)) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + assertThat(initialState.isDebugBuild).isFalse() + } + } } From 995d4e9f6de8c00772fcc7a9c58ff66973a5a628 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 11 Sep 2023 14:51:12 +0200 Subject: [PATCH 097/234] Just try using `actions/checkout@v4` --- .github/workflows/build.yml | 2 +- .github/workflows/danger.yml | 2 +- .github/workflows/gradle-wrapper-update.yml | 2 +- .github/workflows/gradle-wrapper-validation.yml | 2 +- .github/workflows/maestro.yml | 2 +- .github/workflows/nightly.yml | 2 +- .github/workflows/nightlyReports.yml | 2 +- .github/workflows/quality.yml | 4 ++-- .github/workflows/release.yml | 2 +- .github/workflows/sonar.yml | 2 +- .github/workflows/sync-localazy.yml | 2 +- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 709d7ccd58..724060aa40 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,7 +27,7 @@ jobs: group: ${{ github.ref == 'refs/heads/develop' && format('build-develop-{0}-{1}', matrix.variant, github.sha) || format('build-{0}-{1}', matrix.variant, github.ref) }} cancel-in-progress: true steps: - - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 + - uses: actions/checkout@v4 with: # Ensure we are building the branch and not the branch after being merged on develop # https://github.com/actions/checkout/issues/881 diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml index e2aa8e1266..f05db3c791 100644 --- a/.github/workflows/danger.yml +++ b/.github/workflows/danger.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest name: Danger main check steps: - - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 + - uses: actions/checkout@v4 - run: | npm install --save-dev @babel/plugin-transform-flow-strip-types - name: Danger diff --git a/.github/workflows/gradle-wrapper-update.yml b/.github/workflows/gradle-wrapper-update.yml index f9e998b1a0..351057fc89 100644 --- a/.github/workflows/gradle-wrapper-update.yml +++ b/.github/workflows/gradle-wrapper-update.yml @@ -8,7 +8,7 @@ jobs: update-gradle-wrapper: runs-on: ubuntu-latest steps: - - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 + - uses: actions/checkout@v4 - name: Update Gradle Wrapper uses: gradle-update/update-gradle-wrapper-action@v1 # Skip in forks diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index bf1ca46700..4746aa3885 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -11,5 +11,5 @@ jobs: runs-on: ubuntu-latest # No concurrency required, this is a prerequisite to other actions and should run every time. steps: - - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 + - uses: actions/checkout@v4 - uses: gradle/wrapper-validation-action@v1 diff --git a/.github/workflows/maestro.yml b/.github/workflows/maestro.yml index 6f6edd9a31..8b78a3c447 100644 --- a/.github/workflows/maestro.yml +++ b/.github/workflows/maestro.yml @@ -24,7 +24,7 @@ jobs: group: ${{ format('maestro-{0}', github.ref) }} cancel-in-progress: true steps: - - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 + - uses: actions/checkout@v4 with: # Ensure we are building the branch and not the branch after being merged on develop # https://github.com/actions/checkout/issues/881 diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index e2b027aebe..179b001131 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest if: ${{ github.repository == 'vector-im/element-x-android' }} steps: - - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 + - uses: actions/checkout@v4 - name: Use JDK 17 uses: actions/setup-java@v3 with: diff --git a/.github/workflows/nightlyReports.yml b/.github/workflows/nightlyReports.yml index c1d73117b9..124afbc98f 100644 --- a/.github/workflows/nightlyReports.yml +++ b/.github/workflows/nightlyReports.yml @@ -55,7 +55,7 @@ jobs: name: Dependency analysis runs-on: ubuntu-latest steps: - - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 + - uses: actions/checkout@v4 - name: Use JDK 17 uses: actions/setup-java@v3 with: diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index fad3b13cb2..8fbcacba48 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -17,7 +17,7 @@ jobs: name: Search for forbidden patterns runs-on: ubuntu-latest steps: - - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 + - uses: actions/checkout@v4 - name: Run code quality check suite run: ./tools/check/check_code_quality.sh @@ -29,7 +29,7 @@ jobs: group: ${{ github.ref == 'refs/heads/main' && format('check-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('check-develop-{0}', github.sha) || format('check-{0}', github.ref) }} cancel-in-progress: true steps: - - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 + - uses: actions/checkout@v4 with: # Ensure we are building the branch and not the branch after being merged on develop # https://github.com/actions/checkout/issues/881 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b701b7d69e..cc8fc9055c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,7 +18,7 @@ jobs: group: ${{ github.ref == 'refs/head/main' && format('build-release-main-{0}', github.sha) }} cancel-in-progress: true steps: - - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 + - uses: actions/checkout@v4 - name: Use JDK 17 uses: actions/setup-java@v3 with: diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index 3a37e9ead1..f176984476 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -21,7 +21,7 @@ jobs: group: ${{ github.ref == 'refs/heads/main' && format('sonar-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('sonar-develop-{0}', github.sha) || format('sonar-{0}', github.ref) }} cancel-in-progress: true steps: - - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 + - uses: actions/checkout@v4 with: # Ensure we are building the branch and not the branch after being merged on develop # https://github.com/actions/checkout/issues/881 diff --git a/.github/workflows/sync-localazy.yml b/.github/workflows/sync-localazy.yml index e4242aa634..f3acb4675b 100644 --- a/.github/workflows/sync-localazy.yml +++ b/.github/workflows/sync-localazy.yml @@ -11,7 +11,7 @@ jobs: # Skip in forks if: github.repository == 'vector-im/element-x-android' steps: - - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 + - uses: actions/checkout@v4 - name: Set up Python 3.9 uses: actions/setup-python@v4 with: From e6ecedf7bb236dab3062573d65b1721ed34f5997 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 11 Sep 2023 15:24:56 +0200 Subject: [PATCH 098/234] Take screen density into account when requesting thumbnails (#1262) * Take screen density into account when requesting thumbnails Otherwise, we could be asking for images with N size while we needed images for N@2x or N@3x size i.e. --- .../libraries/matrix/ui/media/CoilMediaFetcher.kt | 11 +++++++++-- .../libraries/matrix/ui/media/ImageLoaderFactories.kt | 4 ++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/CoilMediaFetcher.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/CoilMediaFetcher.kt index 8b421c6c28..8945c46817 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/CoilMediaFetcher.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/CoilMediaFetcher.kt @@ -16,6 +16,7 @@ package io.element.android.libraries.matrix.ui.media +import android.content.Context import coil.ImageLoader import coil.decode.DataSource import coil.decode.ImageSource @@ -32,8 +33,10 @@ import okio.Buffer import okio.Path.Companion.toOkioPath import timber.log.Timber import java.nio.ByteBuffer +import kotlin.math.roundToLong internal class CoilMediaFetcher( + private val scalingFunction: (Float) -> Float, private val mediaLoader: MatrixMediaLoader, private val mediaData: MediaRequestData?, private val options: Options @@ -80,8 +83,8 @@ internal class CoilMediaFetcher( private suspend fun fetchThumbnail(mediaSource: MediaSource, kind: MediaRequestData.Kind.Thumbnail, options: Options): FetchResult? { return mediaLoader.loadMediaThumbnail( source = mediaSource, - width = kind.width, - height = kind.height + width = scalingFunction(kind.width.toFloat()).roundToLong(), + height = scalingFunction(kind.height.toFloat()).roundToLong(), ).map { byteArray -> byteArray.asSourceResult(options) }.getOrNull() @@ -102,6 +105,7 @@ internal class CoilMediaFetcher( } class MediaRequestDataFactory( + private val context: Context, private val client: MatrixClient ) : Fetcher.Factory { @@ -111,6 +115,7 @@ internal class CoilMediaFetcher( imageLoader: ImageLoader ): Fetcher { return CoilMediaFetcher( + scalingFunction = { context.resources.displayMetrics.density * it }, mediaLoader = client.mediaLoader, mediaData = data, options = options @@ -119,6 +124,7 @@ internal class CoilMediaFetcher( } class AvatarFactory( + private val context: Context, private val client: MatrixClient ) : Fetcher.Factory { @@ -129,6 +135,7 @@ internal class CoilMediaFetcher( imageLoader: ImageLoader ): Fetcher { return CoilMediaFetcher( + scalingFunction = { context.resources.displayMetrics.density * it }, mediaLoader = client.mediaLoader, mediaData = data.toMediaRequestData(), options = options diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/ImageLoaderFactories.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/ImageLoaderFactories.kt index c5b7f1ed44..c495558fd9 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/ImageLoaderFactories.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/ImageLoaderFactories.kt @@ -46,8 +46,8 @@ class LoggedInImageLoaderFactory @Inject constructor( } add(AvatarDataKeyer()) add(MediaRequestDataKeyer()) - add(CoilMediaFetcher.AvatarFactory(matrixClient)) - add(CoilMediaFetcher.MediaRequestDataFactory(matrixClient)) + add(CoilMediaFetcher.AvatarFactory(context, matrixClient)) + add(CoilMediaFetcher.MediaRequestDataFactory(context, matrixClient)) } .build() } From 41061da76825bacd2bc2f5b82883f779af96e8e8 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 11 Sep 2023 15:43:23 +0200 Subject: [PATCH 099/234] [Compound] Bloom (#1253) * Add `bloom` and `avatarBloom` modifiers. * Add `ConnectivityIndicatorContainer` to control the padding needed at the top. --------- Co-authored-by: ElementBot --- changelog.d/1217.feature | 1 + .../api/ui/ConnectivityIndicatorView.kt | 57 +- .../features/roomlist/impl/RoomListView.kt | 13 +- .../impl/components/RoomListTopBar.kt | 235 +++++--- .../designsystem/components/Bloom.kt | 534 ++++++++++++++++++ .../components/avatar/AvatarSize.kt | 2 +- .../designsystem/preview/PreviewGroup.kt | 1 + .../src/main/res/drawable/ic_search.xml | 25 + ...etContent-D-0_1_null_3,NEXUS_5,1.0,en].png | 4 +- ...etContent-N-0_2_null_3,NEXUS_5,1.0,en].png | 4 +- ...ImageViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...ImageViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 +- ...ImageViewDark_0_null_2,NEXUS_5,1.0,en].png | 4 +- ...mageViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...mageViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 +- ...mageViewLight_0_null_2,NEXUS_5,1.0,en].png | 4 +- ...VideoViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...VideoViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 +- ...VideoViewDark_0_null_2,NEXUS_5,1.0,en].png | 4 +- ...ideoViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...ideoViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 +- ...ideoViewLight_0_null_2,NEXUS_5,1.0,en].png | 4 +- ...temEventRowDark_0_null,NEXUS_5,1.0,en].png | 4 +- ...emEventRowLight_0_null,NEXUS_5,1.0,en].png | 4 +- ...owWithReplyDark_0_null,NEXUS_5,1.0,en].png | 4 +- ...wWithReplyLight_0_null,NEXUS_5,1.0,en].png | 4 +- ...elineView-D-2_3_null_2,NEXUS_5,1.0,en].png | 4 +- ...elineView-D-2_3_null_3,NEXUS_5,1.0,en].png | 4 +- ...elineView-N-2_4_null_2,NEXUS_5,1.0,en].png | 4 +- ...elineView-N-2_4_null_3,NEXUS_5,1.0,en].png | 4 +- ...mListTopBarDark_0_null,NEXUS_5,1.0,en].png | 4 +- ...ListTopBarLight_0_null,NEXUS_5,1.0,en].png | 4 +- ...mListViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...mListViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 +- ...mListViewDark_0_null_2,NEXUS_5,1.0,en].png | 4 +- ...mListViewDark_0_null_3,NEXUS_5,1.0,en].png | 4 +- ...mListViewDark_0_null_4,NEXUS_5,1.0,en].png | 4 +- ...mListViewDark_0_null_5,NEXUS_5,1.0,en].png | 4 +- ...ListViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...ListViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 +- ...ListViewLight_0_null_2,NEXUS_5,1.0,en].png | 4 +- ...ListViewLight_0_null_3,NEXUS_5,1.0,en].png | 4 +- ...ListViewLight_0_null_4,NEXUS_5,1.0,en].png | 4 +- ...ListViewLight_0_null_5,NEXUS_5,1.0,en].png | 4 +- ...vatars_Avatar_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...vatars_Avatar_0_null_1,NEXUS_5,1.0,en].png | 4 +- ...vatars_Avatar_0_null_2,NEXUS_5,1.0,en].png | 4 +- ...ts_null_Bloom-N_1_null,NEXUS_5,1.0,en].png | 3 + ...oomInitials-N_1_null_0,NEXUS_5,1.0,en].png | 3 + ...oomInitials-N_1_null_1,NEXUS_5,1.0,en].png | 3 + ...oomInitials-N_1_null_2,NEXUS_5,1.0,en].png | 3 + ...oomInitials-N_1_null_3,NEXUS_5,1.0,en].png | 3 + ...oomInitials-N_1_null_4,NEXUS_5,1.0,en].png | 3 + ...oomInitials-N_1_null_5,NEXUS_5,1.0,en].png | 3 + ...oomInitials-N_1_null_6,NEXUS_5,1.0,en].png | 3 + ...oomInitials-N_1_null_7,NEXUS_5,1.0,en].png | 3 + ...BloomInitials_0_null_0,NEXUS_5,1.0,en].png | 3 + ...BloomInitials_0_null_1,NEXUS_5,1.0,en].png | 3 + ...BloomInitials_0_null_2,NEXUS_5,1.0,en].png | 3 + ...BloomInitials_0_null_3,NEXUS_5,1.0,en].png | 3 + ...BloomInitials_0_null_4,NEXUS_5,1.0,en].png | 3 + ...BloomInitials_0_null_5,NEXUS_5,1.0,en].png | 3 + ...BloomInitials_0_null_6,NEXUS_5,1.0,en].png | 3 + ...BloomInitials_0_null_7,NEXUS_5,1.0,en].png | 3 + ...ull_Bloom_Bloom_0_null,NEXUS_5,1.0,en].png | 3 + ...mposerReply-D-3_4_null,NEXUS_5,1.0,en].png | 4 +- ...mposerReply-N-3_5_null,NEXUS_5,1.0,en].png | 4 +- 67 files changed, 913 insertions(+), 173 deletions(-) create mode 100644 changelog.d/1217.feature create mode 100644 libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/Bloom.kt create mode 100644 libraries/designsystem/src/main/res/drawable/ic_search.xml create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom-N_1_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_0,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_1,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_2,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_3,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_4,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_5,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_6,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_7,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_0,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_1,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_2,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_3,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_4,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_5,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_6,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_7,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_Bloom_0_null,NEXUS_5,1.0,en].png diff --git a/changelog.d/1217.feature b/changelog.d/1217.feature new file mode 100644 index 0000000000..24941e4ed3 --- /dev/null +++ b/changelog.d/1217.feature @@ -0,0 +1 @@ +Implement Bloom effect modifier. diff --git a/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/ConnectivityIndicatorView.kt b/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/ConnectivityIndicatorView.kt index 855bf067dd..7c03be6a41 100644 --- a/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/ConnectivityIndicatorView.kt +++ b/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/ConnectivityIndicatorView.kt @@ -18,6 +18,9 @@ package io.element.android.features.networkmonitor.api.ui import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.MutableTransitionState +import androidx.compose.animation.core.Spring +import androidx.compose.animation.core.animateDpAsState +import androidx.compose.animation.core.spring import androidx.compose.animation.expandVertically import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut @@ -27,34 +30,44 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.layout.width -import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.WifiOff import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.text.toDp +import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.ui.strings.CommonStrings +/** + * A view that displays a connectivity indicator when the device is offline, adding a default + * padding to make sure the status bar is not overlapped. + */ @Composable fun ConnectivityIndicatorView( isOnline: Boolean, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, ) { val isIndicatorVisible = remember { MutableTransitionState(!isOnline) }.apply { targetState = !isOnline } val isStatusBarPaddingVisible = remember { MutableTransitionState(isOnline) }.apply { targetState = isOnline } @@ -78,6 +91,46 @@ fun ConnectivityIndicatorView( } } +/** + * A view that displays a connectivity indicator when the device is offline, passing the padding + * needed to make sure the status bar is not overlapped to its content views. + */ +@Composable +fun ConnectivityIndicatorContainer( + isOnline: Boolean, + modifier: Modifier = Modifier, + content: @Composable (topPadding: Dp) -> Unit, +) { + val isIndicatorVisible = remember { MutableTransitionState(!isOnline) }.apply { targetState = !isOnline } + + val statusBarTopPadding = if (LocalInspectionMode.current) { + // Needed to get valid UI previews + 24.dp + } else { + WindowInsets.statusBars.asPaddingValues().calculateTopPadding() + 6.dp + } + val target = remember(isOnline) { if (isOnline) 0.dp else statusBarTopPadding } + val animationStateOffset by animateDpAsState( + targetValue = target, + animationSpec = spring( + stiffness = Spring.StiffnessMediumLow, + visibilityThreshold = 1.dp, + ), + label = "insets-animation", + ) + + content(animationStateOffset) + + // Display the network indicator with an animation + AnimatedVisibility( + visibleState = isIndicatorVisible, + enter = fadeIn() + expandVertically(), + exit = fadeOut() + shrinkVertically(), + ) { + Indicator(modifier) + } +} + @Composable private fun Indicator(modifier: Modifier = Modifier) { Row( diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt index f7f712fbc3..80d183a91b 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt @@ -18,13 +18,13 @@ package io.element.android.features.roomlist.impl import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.rememberLazyListState @@ -45,7 +45,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.Velocity import androidx.compose.ui.unit.dp import io.element.android.features.leaveroom.api.LeaveRoomView -import io.element.android.features.networkmonitor.api.ui.ConnectivityIndicatorView +import io.element.android.features.networkmonitor.api.ui.ConnectivityIndicatorContainer import io.element.android.features.roomlist.impl.components.RequestVerificationHeader import io.element.android.features.roomlist.impl.components.RoomListMenuAction import io.element.android.features.roomlist.impl.components.RoomListTopBar @@ -76,8 +76,10 @@ fun RoomListView( onMenuActionClicked: (RoomListMenuAction) -> Unit, modifier: Modifier = Modifier, ) { - Column(modifier = modifier) { - ConnectivityIndicatorView(isOnline = state.hasNetworkConnection) + ConnectivityIndicatorContainer( + modifier = modifier, + isOnline = state.hasNetworkConnection, + ) { topPadding -> Box { fun onRoomLongClicked( roomListRoomSummary: RoomListRoomSummary @@ -96,6 +98,7 @@ fun RoomListView( LeaveRoomView(state = state.leaveRoomState) RoomListContent( + modifier = Modifier.padding(top = topPadding), state = state, onVerifyClicked = onVerifyClicked, onRoomClicked = onRoomClicked, @@ -111,6 +114,8 @@ fun RoomListView( onRoomClicked = onRoomClicked, onRoomLongClicked = { onRoomLongClicked(it) }, modifier = Modifier + .statusBarsPadding() + .padding(top = topPadding) .fillMaxSize() .background(MaterialTheme.colorScheme.background) ) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListTopBar.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListTopBar.kt index 001c048e4e..a5113d33ce 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListTopBar.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListTopBar.kt @@ -17,10 +17,13 @@ package io.element.android.features.roomlist.impl.components import androidx.activity.compose.BackHandler +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.statusBars +import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.MoreVert -import androidx.compose.material.icons.filled.Search import androidx.compose.material.icons.outlined.BugReport import androidx.compose.material.icons.outlined.Share import androidx.compose.material3.ExperimentalMaterial3Api @@ -30,24 +33,37 @@ import androidx.compose.material3.rememberTopAppBarState import androidx.compose.runtime.Composable import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.DpOffset +import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp import io.element.android.features.roomlist.impl.R import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.components.avatarBloom import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.text.applyScaleDown +import io.element.android.libraries.designsystem.text.roundToPx +import io.element.android.libraries.designsystem.text.toDp import io.element.android.libraries.designsystem.text.toSp import io.element.android.libraries.designsystem.theme.aliasScreenTitle import io.element.android.libraries.designsystem.theme.components.DropdownMenu import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem +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.IconButton import io.element.android.libraries.designsystem.theme.components.MediumTopAppBar @@ -60,6 +76,9 @@ import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.ui.strings.CommonStrings +import io.element.android.libraries.designsystem.R as CommonR + +private val avatarBloomSize = 430.dp @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -89,6 +108,7 @@ fun RoomListTopBar( DefaultRoomListTopBar( matrixUser = matrixUser, + areSearchResultsDisplayed = areSearchResultsDisplayed, onOpenSettings = onOpenSettings, onSearchClicked = onToggleSearch, onMenuActionClicked = onMenuActionClicked, @@ -101,6 +121,7 @@ fun RoomListTopBar( @Composable private fun DefaultRoomListTopBar( matrixUser: MatrixUser?, + areSearchResultsDisplayed: Boolean, scrollBehavior: TopAppBarScrollBehavior, onOpenSettings: () -> Unit, onSearchClicked: () -> Unit, @@ -108,94 +129,139 @@ private fun DefaultRoomListTopBar( modifier: Modifier = Modifier, ) { var showMenu by remember { mutableStateOf(false) } - MediumTopAppBar( - modifier = modifier - .nestedScroll(scrollBehavior.nestedScrollConnection), - title = { - val fontStyle = if (scrollBehavior.state.collapsedFraction > 0.5) - ElementTheme.typography.aliasScreenTitle - else - ElementTheme.typography.fontHeadingLgBold.copy( - // Due to a limitation of MediumTopAppBar, and to avoid the text to be truncated, - // ensure that the font size will never be bigger than 28.dp. - fontSize = 28.dp.applyScaleDown().toSp() - ) - Text( - style = fontStyle, - text = stringResource(id = R.string.screen_roomlist_main_space_title) - ) - }, - navigationIcon = { - if (matrixUser != null) { - IconButton( - modifier = Modifier.testTag(TestTags.homeScreenSettings), - onClick = onOpenSettings - ) { - val avatarData by remember { - derivedStateOf { - matrixUser.getAvatarData(size = AvatarSize.CurrentUserTopBar) - } - } - Avatar(avatarData, contentDescription = stringResource(CommonStrings.common_settings)) + + // We need this to manually clip the top app bar in preview mode + val previewAppBarHeight = if (LocalInspectionMode.current) { + 112.dp.roundToPx() + } else { + null + } + val collapsedFraction = scrollBehavior.state.collapsedFraction + var appBarHeight by remember { + mutableIntStateOf(previewAppBarHeight ?: 0) + } + + val avatarData by remember(matrixUser) { + derivedStateOf { + matrixUser?.getAvatarData(size = AvatarSize.CurrentUserTopBar) + } + } + + val statusBarPadding = with (LocalDensity.current) { WindowInsets.statusBars.getTop(this).toDp() } + + Box(modifier = modifier) { + MediumTopAppBar( + modifier = Modifier + .onSizeChanged { + appBarHeight = it.height } - } - }, - actions = { - IconButton( - onClick = onSearchClicked, - ) { - Icon( - imageVector = Icons.Default.Search, - tint = ElementTheme.materialColors.secondary, - contentDescription = stringResource(CommonStrings.action_search), - ) - } - IconButton( - onClick = { showMenu = !showMenu } - ) { - Icon( - imageVector = Icons.Default.MoreVert, - tint = ElementTheme.materialColors.secondary, - contentDescription = null, + .nestedScroll(scrollBehavior.nestedScrollConnection) + .avatarBloom( + avatarData = avatarData, + background = ElementTheme.materialColors.background, + blurSize = DpSize(avatarBloomSize, avatarBloomSize), + offset = DpOffset(24.dp, 24.dp + statusBarPadding), + clipToSize = if (appBarHeight > 0) DpSize( + avatarBloomSize, + appBarHeight.toDp() + ) else DpSize.Unspecified, + bottomSoftEdgeAlpha = 1f - collapsedFraction, + alpha = if (areSearchResultsDisplayed) 0f else 1f, ) - } - DropdownMenu( - expanded = showMenu, - onDismissRequest = { showMenu = false } - ) { - DropdownMenuItem( - onClick = { - showMenu = false - onMenuActionClicked(RoomListMenuAction.InviteFriends) - }, - text = { Text(stringResource(id = CommonStrings.action_invite)) }, - leadingIcon = { - Icon( - Icons.Outlined.Share, - tint = ElementTheme.materialColors.secondary, - contentDescription = null, - ) - } + .statusBarsPadding(), + colors = TopAppBarDefaults.mediumTopAppBarColors( + containerColor = Color.Transparent, + scrolledContainerColor = Color.Transparent, + ), + title = { + val fontStyle = if (scrollBehavior.state.collapsedFraction > 0.5) + ElementTheme.typography.aliasScreenTitle + else + ElementTheme.typography.fontHeadingLgBold.copy( + // Due to a limitation of MediumTopAppBar, and to avoid the text to be truncated, + // ensure that the font size will never be bigger than 28.dp. + fontSize = 28.dp.applyScaleDown().toSp() + ) + Text( + style = fontStyle, + text = stringResource(id = R.string.screen_roomlist_main_space_title) ) - DropdownMenuItem( - onClick = { - showMenu = false - onMenuActionClicked(RoomListMenuAction.ReportBug) - }, - text = { Text(stringResource(id = CommonStrings.common_report_a_bug)) }, - leadingIcon = { - Icon( - Icons.Outlined.BugReport, - tint = ElementTheme.materialColors.secondary, - contentDescription = null, + }, + navigationIcon = { + avatarData?.let { + IconButton( + modifier = Modifier.testTag(TestTags.homeScreenSettings), + onClick = onOpenSettings + ) { + Avatar( + avatarData = it, + contentDescription = stringResource(CommonStrings.common_settings), ) } - ) - } - }, - scrollBehavior = scrollBehavior, - windowInsets = WindowInsets(0.dp), - ) + } + }, + actions = { + IconButton( + onClick = onSearchClicked, + ) { + Icon( + resourceId = CommonR.drawable.ic_search, + contentDescription = stringResource(CommonStrings.action_search), + ) + } + IconButton( + onClick = { showMenu = !showMenu } + ) { + Icon( + imageVector = Icons.Default.MoreVert, + contentDescription = null, + ) + } + DropdownMenu( + expanded = showMenu, + onDismissRequest = { showMenu = false } + ) { + DropdownMenuItem( + onClick = { + showMenu = false + onMenuActionClicked(RoomListMenuAction.InviteFriends) + }, + text = { Text(stringResource(id = CommonStrings.action_invite)) }, + leadingIcon = { + Icon( + Icons.Outlined.Share, + tint = ElementTheme.materialColors.secondary, + contentDescription = null, + ) + } + ) + DropdownMenuItem( + onClick = { + showMenu = false + onMenuActionClicked(RoomListMenuAction.ReportBug) + }, + text = { Text(stringResource(id = CommonStrings.common_report_a_bug)) }, + leadingIcon = { + Icon( + Icons.Outlined.BugReport, + tint = ElementTheme.materialColors.secondary, + contentDescription = null, + ) + } + ) + } + }, + scrollBehavior = scrollBehavior, + windowInsets = WindowInsets(0.dp), + ) + + HorizontalDivider(modifier = + Modifier.fillMaxWidth() + .alpha(collapsedFraction) + .align(Alignment.BottomCenter), + color = ElementTheme.materialColors.outlineVariant, + ) + } } @Preview @@ -211,6 +277,7 @@ internal fun DefaultRoomListTopBarDarkPreview() = ElementPreviewDark { DefaultRo private fun DefaultRoomListTopBarPreview() { DefaultRoomListTopBar( matrixUser = MatrixUser(UserId("@id:domain"), "Alice"), + areSearchResultsDisplayed = false, scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(rememberTopAppBarState()), onOpenSettings = {}, onSearchClicked = {}, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/Bloom.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/Bloom.kt new file mode 100644 index 0000000000..5e1d7116ba --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/Bloom.kt @@ -0,0 +1,534 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.designsystem.components + +import android.graphics.Bitmap +import android.graphics.Typeface +import android.graphics.drawable.BitmapDrawable +import android.os.Build +import android.text.TextPaint +import androidx.annotation.FloatRange +import androidx.compose.foundation.Image +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.consumeWindowInsets +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Share +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.IconButton +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.material3.rememberTopAppBarState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.composed +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.drawWithCache +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.geometry.Rect +import androidx.compose.ui.geometry.center +import androidx.compose.ui.graphics.BlendMode +import androidx.compose.ui.graphics.ClipOp +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.graphics.LinearGradientShader +import androidx.compose.ui.graphics.Paint +import androidx.compose.ui.graphics.Path +import androidx.compose.ui.graphics.RadialGradientShader +import androidx.compose.ui.graphics.ShaderBrush +import androidx.compose.ui.graphics.asAndroidBitmap +import androidx.compose.ui.graphics.asImageBitmap +import androidx.compose.ui.graphics.drawscope.DrawScope +import androidx.compose.ui.graphics.drawscope.clipPath +import androidx.compose.ui.graphics.nativeCanvas +import androidx.compose.ui.graphics.painter.BitmapPainter +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.LocalFontFamilyResolver +import androidx.compose.ui.platform.LocalLayoutDirection +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.rememberTextMeasurer +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import androidx.compose.ui.unit.Density +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.DpOffset +import androidx.compose.ui.unit.DpSize +import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.IntSize +import androidx.compose.ui.unit.LayoutDirection +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.isSpecified +import androidx.compose.ui.unit.toOffset +import androidx.compose.ui.unit.toSize +import coil.compose.rememberAsyncImagePainter +import coil.request.ImageRequest +import com.airbnb.android.showkase.annotation.ShowkaseComposable +import com.vanniktech.blurhash.BlurHash +import io.element.android.libraries.designsystem.R +import io.element.android.libraries.designsystem.colors.AvatarColorsProvider +import io.element.android.libraries.designsystem.components.avatar.AvatarData +import io.element.android.libraries.designsystem.preview.DayNightPreviews +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewGroup +import io.element.android.libraries.designsystem.text.toDp +import io.element.android.libraries.designsystem.theme.components.Icon +import io.element.android.libraries.designsystem.theme.components.MediumTopAppBar +import io.element.android.libraries.designsystem.theme.components.Scaffold +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.theme.ElementTheme +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf +import kotlin.math.max +import kotlin.math.roundToInt + +/** + * Default bloom configuration values. + */ +object BloomDefaults { + /** + * Number of components to use with BlurHash to generate the blur effect. + * Larger values mean more detailed blurs. + */ + const val HASH_COMPONENTS = 8 + + /** Default bloom layers. */ + @Composable + fun defaultLayers() = persistentListOf( + // Bottom layer + if (isSystemInDarkTheme()) { + BloomLayer(0.5f, BlendMode.Exclusion) + } else { + BloomLayer(0.2f, BlendMode.Hardlight) + }, + // Top layer + BloomLayer(if (isSystemInDarkTheme()) 0.2f else 0.8f, BlendMode.Color), + ) +} + +/** + * Bloom layer configuration. + * @param alpha The alpha value to apply to the layer. + * @param blendMode The blend mode to apply to the layer. + */ +data class BloomLayer( + val alpha: Float, + val blendMode: BlendMode, +) + +/** + * Bloom effect modifier. Applies a bloom effect to the component. + * @param hash The BlurHash to use as the bloom source. + * @param background The background color to use for the bloom effect. Since we use blend modes it must be non-transparent. + * @param blurSize The size of the bloom effect. If not specified the bloom effect will be the size of the component. + * @param offset The offset to use for the bloom effect. If not specified the bloom effect will be centered on the component. + * @param clipToSize The size to use for clipping the bloom effect. If not specified the bloom effect will not be clipped. + * @param layerConfiguration The configuration for the bloom layers. If not specified the default layers configuration will be used. + * @param bottomSoftEdgeHeight The height of the bottom soft edge. If not specified the bottom soft edge will not be drawn. + * @param bottomSoftEdgeAlpha The alpha value to apply to the bottom soft edge. + * @param alpha The alpha value to apply to the bloom effect. + */ +fun Modifier.bloom( + hash: String?, + background: Color, + blurSize: DpSize = DpSize.Unspecified, + offset: DpOffset = DpOffset.Unspecified, + clipToSize: DpSize = DpSize.Unspecified, + layerConfiguration: ImmutableList? = null, + bottomSoftEdgeHeight: Dp = 40.dp, + @FloatRange(from = 0.0, to = 1.0) + bottomSoftEdgeAlpha: Float = 1.0f, + @FloatRange(from = 0.0, to = 1.0) + alpha: Float = 1f, +) = composed { + val defaultLayers = BloomDefaults.defaultLayers() + val layers = layerConfiguration ?: defaultLayers + // Bloom only works on API 29+ + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return@composed this + if (hash == null) return@composed this + + val hashedBitmap = remember(hash) { + BlurHash.decode(hash, BloomDefaults.HASH_COMPONENTS, BloomDefaults.HASH_COMPONENTS)?.asImageBitmap() + } ?: return@composed this + val density = LocalDensity.current + val pixelSize = remember(blurSize, density) { blurSize.toIntSize(density) } + val clipToPixelSize = remember(clipToSize, density) { clipToSize.toIntSize(density) } + val bottomSoftEdgeHeightPixels = remember(bottomSoftEdgeHeight, density) { with(density) { bottomSoftEdgeHeight.roundToPx() } } + val isRTL = LocalLayoutDirection.current == LayoutDirection.Rtl + drawWithCache { + val dstSize = if (pixelSize != IntSize.Zero) { + pixelSize + } else { + IntSize(size.width.toInt(), size.height.toInt()) + } + // Calculate where to place the center of the bloom effect + val centerOffset = if (offset.isSpecified) { + if (isRTL) { + IntOffset( + size.width.roundToInt() - offset.x.roundToPx(), + size.height.roundToInt() - offset.y.roundToPx(), + ) + } else { + IntOffset( + offset.x.roundToPx(), + offset.y.roundToPx(), + ) + } + } else { + IntOffset( + size.center.x.toInt(), + size.center.y.toInt(), + ) + } + // Calculate the offset to draw the different layers and apply clipping + // This offset is applied to place the top left corner of the bloom effect + val layersOffset = if (offset.isSpecified) { + // Offsets the layers so the center of the bloom effect is at the provided offset value + IntOffset( + centerOffset.x - dstSize.width / 2, + centerOffset.y - dstSize.height / 2, + ) + } else { + // Places the layers at the center of the component + IntOffset.Zero + } + val radius = max(dstSize.width, dstSize.height).toFloat() / 2 + val circularGradientShader = RadialGradientShader( + centerOffset.toOffset(), + radius, + listOf(Color.Red, Color.Transparent), + listOf(0f, 1f) + ) + val circularGradientBrush = ShaderBrush(circularGradientShader) + val bottomEdgeGradient = LinearGradientShader( + from = IntOffset(0, clipToPixelSize.height - bottomSoftEdgeHeightPixels).toOffset(), + to = IntOffset(0, clipToPixelSize.height).toOffset(), + listOf(Color.Transparent, background), + listOf(0f, 1f) + ) + val bottomEdgeGradientBrush = ShaderBrush(bottomEdgeGradient) + onDrawBehind { + if (dstSize != IntSize.Zero) { + val circleClipPath = Path().apply { + addOval(Rect(centerOffset.toOffset(), radius - 1)) + } + // Clip the external radius of bloom gradient too, otherwise we have a 1px border + clipPath(circleClipPath, clipOp = ClipOp.Intersect) { + // Draw the bloom layers + drawWithLayer { + // Clip rect to the provided size if needed + if (clipToPixelSize != IntSize.Zero) { + drawContext.canvas.clipRect(Rect(Offset.Zero, clipToPixelSize.toSize()), ClipOp.Intersect) + } + // Draw background color for blending + drawRect(background, size = pixelSize.toSize()) + // Draw layers + for (layer in layers) { + drawImage( + hashedBitmap, + srcSize = IntSize(BloomDefaults.HASH_COMPONENTS, BloomDefaults.HASH_COMPONENTS), + dstSize = dstSize, + dstOffset = layersOffset, + alpha = layer.alpha * alpha, + blendMode = layer.blendMode, + ) + } + // Mask the layers erasing the outer radius using the gradient brush + drawCircle( + circularGradientBrush, + radius, + centerOffset.toOffset(), + blendMode = BlendMode.DstIn + ) + } + } + // Draw the bottom soft edge + drawRect( + bottomEdgeGradientBrush, + topLeft = IntOffset(0, clipToPixelSize.height - bottomSoftEdgeHeight.roundToPx()).toOffset(), + size = IntSize(pixelSize.width, bottomSoftEdgeHeight.roundToPx()).toSize(), + alpha = bottomSoftEdgeAlpha + ) + } + } + } +} + +/** + * Bloom effect modifier for avatars. Applies a bloom effect to the component. + * @param avatarData The avatar data to use as the bloom source. + * If the avatar data has a URL it will be used as the bloom source, otherwise the initials will be used. If `null` is passed, no bloom effect will be applied. + * @param background The background color to use for the bloom effect. Since we use blend modes it must be non-transparent. + * @param blurSize The size of the bloom effect. If not specified the bloom effect will be the size of the component. + * @param offset The offset to use for the bloom effect. If not specified the bloom effect will be centered on the component. + * @param clipToSize The size to use for clipping the bloom effect. If not specified the bloom effect will not be clipped. + * @param bottomSoftEdgeHeight The height of the bottom soft edge. If not specified the bottom soft edge will not be drawn. + * @param bottomSoftEdgeAlpha The alpha value to apply to the bottom soft edge. + * @param alpha The alpha value to apply to the bloom effect. + */ +fun Modifier.avatarBloom( + avatarData: AvatarData?, + background: Color, + blurSize: DpSize = DpSize.Unspecified, + offset: DpOffset = DpOffset.Unspecified, + clipToSize: DpSize = DpSize.Unspecified, + bottomSoftEdgeHeight: Dp = 40.dp, + @FloatRange(from = 0.0, to = 1.0) + bottomSoftEdgeAlpha: Float = 1.0f, + @FloatRange(from = 0.0, to = 1.0) + alpha: Float = 1f, +) = composed { + // Bloom only works on API 29+ + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return@composed this + avatarData ?: return@composed this + + if (avatarData.url != null) { + // Request the avatar contents to use as the bloom source + val painter = rememberAsyncImagePainter( + ImageRequest.Builder(LocalContext.current) + .data(avatarData) + // Needed to be able to read pixels from the Bitmap for the hash + .allowHardware(false) + .build() + ) + var blurHash by remember { mutableStateOf(null) } + + LaunchedEffect(avatarData) { + val drawable = painter.imageLoader.execute(painter.request).drawable ?: return@LaunchedEffect + val bitmap = (drawable as? BitmapDrawable)?.bitmap ?: return@LaunchedEffect + blurHash = BlurHash.encode(bitmap, BloomDefaults.HASH_COMPONENTS, BloomDefaults.HASH_COMPONENTS) + } + + bloom( + hash = blurHash, + background = background, + blurSize = blurSize, + offset = offset, + clipToSize = clipToSize, + bottomSoftEdgeHeight = bottomSoftEdgeHeight, + bottomSoftEdgeAlpha = bottomSoftEdgeAlpha, + alpha = alpha, + ) + } else { + // There is no URL so we'll generate an avatar with the initials and use that as the bloom source + val avatarColors = AvatarColorsProvider.provide(avatarData.id, ElementTheme.isLightTheme) + val initialsBitmap = initialsBitmap( + width = avatarData.size.dp, + height = avatarData.size.dp, + text = avatarData.initial, + textColor = avatarColors.foreground, + backgroundColor = avatarColors.background, + ) + val hash = remember(avatarData, avatarColors) { + BlurHash.encode(initialsBitmap.asAndroidBitmap(), BloomDefaults.HASH_COMPONENTS, BloomDefaults.HASH_COMPONENTS) + } + bloom( + hash = hash, + background = background, + blurSize = blurSize, + offset = offset, + clipToSize = clipToSize, + bottomSoftEdgeHeight = bottomSoftEdgeHeight, + bottomSoftEdgeAlpha = bottomSoftEdgeAlpha, + alpha = alpha, + ) + } +} + +// Used to create a Bitmap version of the initials avatar +@Composable +private fun initialsBitmap( + text: String, + backgroundColor: Color, + textColor: Color, + width: Dp = 32.dp, + height: Dp = 32.dp, +): ImageBitmap = with(LocalDensity.current) { + val backgroundPaint = remember(backgroundColor) { + Paint().also { it.color = backgroundColor } + } + val resolver: FontFamily.Resolver = LocalFontFamilyResolver.current + val fontSize = remember { height.toSp() / 2 } + val typeface: Typeface = remember(resolver) { + resolver.resolve( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Bold, + fontStyle = FontStyle.Normal, + ) + }.value as Typeface + val textPaint = remember(textColor, typeface) { + TextPaint().apply { + color = textColor.toArgb() + textSize = fontSize.toPx() + this.typeface = typeface + } + } + val textMeasurer = rememberTextMeasurer() + val result = remember(text) { textMeasurer.measure(text, TextStyle.Default.copy(fontSize = fontSize)) } + val centerPx = remember(width, height) { IntOffset(width.roundToPx() / 2, height.roundToPx() / 2) } + remember(text, width, height, backgroundColor, textColor) { + val bitmap = Bitmap.createBitmap(width.roundToPx(), height.roundToPx(), Bitmap.Config.ARGB_8888).asImageBitmap() + androidx.compose.ui.graphics.Canvas(bitmap).also { canvas -> + canvas.drawCircle(centerPx.toOffset(), width.toPx() / 2, backgroundPaint) + canvas.nativeCanvas.drawText(text, centerPx.x.toFloat() - result.size.width/2, centerPx.y * 2f - result.size.height/2 - 4, textPaint) + } + bitmap + } +} + +// Translates DP sizes into pixel sizes, taking into account unspecified values +private fun DpSize.toIntSize(density: Density) = with(density) { + if (isSpecified) { + IntSize(width.roundToPx(), height.roundToPx()) + } else { + IntSize.Zero + } +} + +/** + * Helper to draw to a canvas using layers. This allows us to apply clipping to those layers only. + */ +fun DrawScope.drawWithLayer(block: DrawScope.() -> Unit) { + with(drawContext.canvas.nativeCanvas) { + val checkPoint = saveLayer(null, null) + block() + restoreToCount(checkPoint) + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@DayNightPreviews +@ShowkaseComposable(group = PreviewGroup.Bloom) +@Composable +internal fun BloomPreview() { + val blurhash = "eePn{tI?xExEja}ooKWWodjtNJoKR,j@a|sBWpS3WDbGazoKWWWWj@" + var topAppBarHeight by remember { mutableIntStateOf(-1) } + val topAppBarState = rememberTopAppBarState() + val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(topAppBarState) + ElementPreview { + Scaffold( + modifier = Modifier.fillMaxSize().nestedScroll(scrollBehavior.nestedScrollConnection), + topBar = { + Box { + MediumTopAppBar( + modifier = Modifier + .onSizeChanged { size -> + topAppBarHeight = size.height + } + .bloom( + hash = blurhash, + background = ElementTheme.materialColors.background, + blurSize = DpSize(430.dp, 430.dp), + offset = DpOffset(24.dp, 24.dp), + clipToSize = if (topAppBarHeight > 0) DpSize(430.dp, topAppBarHeight.toDp()) else DpSize.Zero, + ), + colors = TopAppBarDefaults.largeTopAppBarColors( + containerColor = Color.Transparent, + scrolledContainerColor = Color.Black.copy(alpha = 0.05f), + ), + navigationIcon = { + Image( + modifier = Modifier + .padding(start = 8.dp) + .size(32.dp) + .clip(CircleShape), + painter = painterResource(id = R.drawable.sample_avatar), + contentScale = ContentScale.Crop, + contentDescription = null + ) + }, + actions = { + IconButton(onClick = {}) { + Icon(imageVector = Icons.Default.Share, contentDescription = null) + } + }, + title = { + Text("Title") + }, + scrollBehavior = scrollBehavior, + ) + } + }, + ) { paddingValues -> + Column( + modifier = Modifier + .padding(paddingValues) + .consumeWindowInsets(paddingValues) + .fillMaxSize() + .verticalScroll(rememberScrollState()), + ) { + repeat(20) { + Text("Content", modifier = Modifier.padding(vertical = 20.dp)) + } + } + } + } +} + +class InitialsColorStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf(0, 1, 2, 3, 4, 5, 6, 7) +} + +@DayNightPreviews +@Composable +@ShowkaseComposable(group = PreviewGroup.Bloom) +internal fun BloomInitialsPreview(@PreviewParameter(InitialsColorStateProvider::class) color: Int) { + ElementPreview { + val avatarColors = AvatarColorsProvider.provide("$color", ElementTheme.isLightTheme) + val bitmap = initialsBitmap(text = "F", backgroundColor = avatarColors.background, textColor = avatarColors.foreground) + val hash = BlurHash.encode(bitmap.asAndroidBitmap(), BloomDefaults.HASH_COMPONENTS, BloomDefaults.HASH_COMPONENTS) + Box( + modifier = Modifier.size(256.dp) + .bloom( + hash = hash, + background = ElementTheme.materialColors.background, + blurSize = DpSize(256.dp, 256.dp), + ), + contentAlignment = Alignment.Center + ) { + Image( + modifier = Modifier + .size(32.dp) + .clip(CircleShape), + painter = BitmapPainter(bitmap), + contentDescription = null + ) + } + } +} 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 372aecea32..38b1df6dce 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 @@ -20,7 +20,7 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp enum class AvatarSize(val dp: Dp) { - CurrentUserTopBar(28.dp), + CurrentUserTopBar(32.dp), RoomHeader(96.dp), RoomListItem(52.dp), diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/PreviewGroup.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/PreviewGroup.kt index 8bfd198f1c..a1f458ee08 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/PreviewGroup.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/PreviewGroup.kt @@ -19,6 +19,7 @@ package io.element.android.libraries.designsystem.preview object PreviewGroup { const val AppBars = "App Bars" const val Avatars = "Avatars" + const val Bloom = "Bloom" const val BottomSheets = "Bottom Sheets" const val Buttons = "Buttons" const val DateTimePickers = "DateTime pickers" diff --git a/libraries/designsystem/src/main/res/drawable/ic_search.xml b/libraries/designsystem/src/main/res/drawable/ic_search.xml new file mode 100644 index 0000000000..440aef72f6 --- /dev/null +++ b/libraries/designsystem/src/main/res/drawable/ic_search.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_3,NEXUS_5,1.0,en].png index 1f851222f4..540f71b5a7 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8421be9fe6518a4a610e561692352c28c63b1e588fae4f7617f6be94439852f2 -size 45078 +oid sha256:ee62a7f77e591d238878e72e3f2fbe489e8c4e8c6a5c121b16e120ad5c43836d +size 44185 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_3,NEXUS_5,1.0,en].png index 8fae4446ea..cf7a8a2c81 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4c30a6c0c7169044216a02dde5605d59fba9307499855ffc1fa0d3fcd1650f5e -size 43291 +oid sha256:d4bdf3944d30980e9bfd7cfffbabe2dac9861748cc3006e751bfd5cbf59c86db +size 42475 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_0,NEXUS_5,1.0,en].png index affcb49660..7ff6d4dec6 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c40273c36eb1479f284e75fa91d4a75b1ae97edd0242dda37a2d4a8f10394928 -size 138700 +oid sha256:6c0485788c8776536a01613058ab001bad02a67519cf0cb4892505c7c3715fea +size 144681 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_1,NEXUS_5,1.0,en].png index cb4b57910b..7dae7dddb0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d7c47c713c74766c39d3b349d9e421ea588261e043105a5475cd8e68af782806 -size 185325 +oid sha256:b4a259f036e555fdc52ecc8f0c9578dae70ed677235fbfd344bc31cbabc76be5 +size 181478 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_2,NEXUS_5,1.0,en].png index db705106e0..00c4b05824 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d5479f3a6ea138b00c8f6a376cc4a67984385a087fb32bcdb764b2996e89402 -size 137137 +oid sha256:d5966cae164fed6a3a12c1e1dd940ae7b0601e4ba69d11f49d18740bdab8c520 +size 130130 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_0,NEXUS_5,1.0,en].png index affcb49660..7ff6d4dec6 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c40273c36eb1479f284e75fa91d4a75b1ae97edd0242dda37a2d4a8f10394928 -size 138700 +oid sha256:6c0485788c8776536a01613058ab001bad02a67519cf0cb4892505c7c3715fea +size 144681 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_1,NEXUS_5,1.0,en].png index cb4b57910b..7dae7dddb0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d7c47c713c74766c39d3b349d9e421ea588261e043105a5475cd8e68af782806 -size 185325 +oid sha256:b4a259f036e555fdc52ecc8f0c9578dae70ed677235fbfd344bc31cbabc76be5 +size 181478 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_2,NEXUS_5,1.0,en].png index db705106e0..a603a6cc61 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d5479f3a6ea138b00c8f6a376cc4a67984385a087fb32bcdb764b2996e89402 -size 137137 +oid sha256:b8cb21e08faf31779111d78c2be1e4e68e6f3bc994b16c108bd654f13d39fa02 +size 130130 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_0,NEXUS_5,1.0,en].png index 5361cd1a24..0e6ff544a1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:06617cda0f93ce0ea26b2a77a243371cdaf4f9a2956d8159ecb7196f7f6fe082 -size 139282 +oid sha256:f2782edd31f68b7aa27e0c35b29d7c84574326cb56c65394738357479d408f5f +size 144667 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_1,NEXUS_5,1.0,en].png index 0e14867b04..b8b527778b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:55d2d11ba729a68b1b62e9a69c3308594839fdb3612ff3db59850f0b346c28da -size 186118 +oid sha256:cd352f748e3fd08225aa714181fdc18d53e91a8c62f8e5e860b67ff5aaeb7b8e +size 181969 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_2,NEXUS_5,1.0,en].png index da8a3d6499..6ee90c4b3a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:62c57a45c2cb1aac23fa0c3af44f90a5d7b9a1e1626ec49eb94a2c126f53f96d -size 137535 +oid sha256:43da903ec671dd1cb591396306ce8c057432ffa8c1bfce7a509f28576e82b530 +size 130337 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_0,NEXUS_5,1.0,en].png index 5361cd1a24..0e6ff544a1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:06617cda0f93ce0ea26b2a77a243371cdaf4f9a2956d8159ecb7196f7f6fe082 -size 139282 +oid sha256:f2782edd31f68b7aa27e0c35b29d7c84574326cb56c65394738357479d408f5f +size 144667 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_1,NEXUS_5,1.0,en].png index 0e14867b04..b8b527778b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:55d2d11ba729a68b1b62e9a69c3308594839fdb3612ff3db59850f0b346c28da -size 186118 +oid sha256:cd352f748e3fd08225aa714181fdc18d53e91a8c62f8e5e860b67ff5aaeb7b8e +size 181969 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_2,NEXUS_5,1.0,en].png index da8a3d6499..c4150178a1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:62c57a45c2cb1aac23fa0c3af44f90a5d7b9a1e1626ec49eb94a2c126f53f96d -size 137535 +oid sha256:8141eaa257454258d2926df5ee970daf5ee165b774e4b948256b90e22a388d4c +size 130337 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowDark_0_null,NEXUS_5,1.0,en].png index 722bd8c6a5..5fd48ba7e6 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f0ad6895582183b697732ef032f89a6a0cad32106c9bbf30925c390dcab65ee6 -size 151752 +oid sha256:f95fbf1b51966c1c6b7b149c771f33400455d3c999b505e1aa65f0e3eb41c0ef +size 140928 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowLight_0_null,NEXUS_5,1.0,en].png index fb9457779e..3798fc1bc8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowLight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowLight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:676b62ab782652c45a7267aac5df12943fd181bea48964d28dce664884ae4182 -size 156619 +oid sha256:e8d522eb99079792d010e053d488f78a95e91f5a1b614b9d512bd005f0df81cf +size 146976 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyDark_0_null,NEXUS_5,1.0,en].png index c39b41db87..5bc3b72bec 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b991a34a137d82ff4dedf48316a05ebbc008233984b11af70e64889a5fb5eda8 -size 127438 +oid sha256:eebf95f938f483da9b087eda86ae4a1baac594bc4b6f1f893d869b759679526c +size 123267 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyLight_0_null,NEXUS_5,1.0,en].png index a6500ca748..6e52c4b6d3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyLight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyLight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:43b6514716d18382c8962520928d9d2ff6d0f665b2471e8a24e5d2e44a25c88c -size 132295 +oid sha256:4875df98092a8ef8bd1c2fda8c4a038ae2830b9ffa57e4ab71859523f97c26c9 +size 128062 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_2,NEXUS_5,1.0,en].png index 307e6a7acf..18e6545be9 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0d7bc773e70c57226840b30675f14a7fd99026100d61f48eeab64fb55d43f7c6 -size 230426 +oid sha256:30119e8fcb65e8cbf058191268f0d70633a62b160b9f49f71879272d0d076537 +size 241818 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_3,NEXUS_5,1.0,en].png index 4d97155b83..cc3ad6b40e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:87f93b06f658352e7d97617c28dc0a4bd7454263fd402abfc2676f548c41d6b2 -size 231314 +oid sha256:73ca2b85c0f1f8f13cd3a0aae9d394116a460aa2c511ca1f2672a356eee496d2 +size 241553 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_2,NEXUS_5,1.0,en].png index 946096b37e..7fa7a38d87 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f13fbb9bc776fa230b69c41e3faab659c52083d4e4f737f84b472c966f42c8dd -size 229746 +oid sha256:ff7953fabf75b346e61bd4335f3753331b498dbe5f17f9af3aad8a6a1ce051cd +size 239490 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_3,NEXUS_5,1.0,en].png index 419a96a180..45eafc5baa 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d312c80758e940b368e0b9eb2d41efb55c158691164bfde3456d7540080e46a9 -size 230651 +oid sha256:e262b1128df681c9a98bbefe426a891d02e0500646319f2e1756c1b5c93f2d23 +size 239303 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarDark_0_null,NEXUS_5,1.0,en].png index 48f8da47ee..434058e988 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bbfb4b373449d3ce3ff06ad67e8c4ecfcbb0ec8d0bcb400d3c010952d11e8ad5 -size 10480 +oid sha256:51931b01aa27677c8d29a79bf92f4e8b48fc2be05e80fdabedfb9026dcbd8899 +size 31634 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarLight_0_null,NEXUS_5,1.0,en].png index 82c658503e..70b7534b8c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarLight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarLight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1d0cc556a6c431fc0f10958a4760fe63d0dd3d7f976ce3507643308c50f37c2e -size 10381 +oid sha256:5441c89fc077720b52479d4daf1ebd5fe5b98b63f35141a550dac228fe1c649f +size 10617 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_0,NEXUS_5,1.0,en].png index c00ff9fa1a..c6ce4ced6b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:66bf2e3b890ab75c77f1a9e4e80a374cbb5af35e72b8f53c86424c56f1a9f524 -size 36582 +oid sha256:9156202a9f621b75cff3ca45aac33d72a938620049948828fc34aab3b9e0980d +size 55382 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_1,NEXUS_5,1.0,en].png index d47352bb7c..21a3ec4a13 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1aff1b446de80f7535a71fbc77d7955a679ff2846bb240b70f2d410114f29b16 -size 59749 +oid sha256:0c7ee3acbf4653e49633e68f896fe0f5f73591c2cbc889204cc244b319996e0d +size 78348 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_2,NEXUS_5,1.0,en].png index c00ff9fa1a..c6ce4ced6b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:66bf2e3b890ab75c77f1a9e4e80a374cbb5af35e72b8f53c86424c56f1a9f524 -size 36582 +oid sha256:9156202a9f621b75cff3ca45aac33d72a938620049948828fc34aab3b9e0980d +size 55382 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_3,NEXUS_5,1.0,en].png index d054685464..3cc44b882b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0fd240006e3b08b081fccdcc29cb8911fbde7f923c4f8207de817ea6a42d3d6f -size 38475 +oid sha256:55800431dfe4453fa3c11f97bfae53ceaf95f1c18b72bcc8620b8c3295b26b27 +size 56388 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_4,NEXUS_5,1.0,en].png index 144beef563..0f8a496726 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:77d78ad2cabaac211517c129a42d8164b02ba2cc5b75a13f27f2ae113b2b9f06 -size 37924 +oid sha256:b2d288f46eb76b8a71a8c1a2ec60ba7c3b8b1bf2a92be9d8daf33c06b3a0f126 +size 56593 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_5,NEXUS_5,1.0,en].png index 7125e2cb27..0306387553 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9701408630ece8c6178e792920688eb41a8fe1a4621c45f8cf34338f134dded2 -size 38290 +oid sha256:c0e5bc6abe96bff50960c5ace2c4eccd5aabdd9f3ccd015fae867b4c3bc2b423 +size 56902 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_0,NEXUS_5,1.0,en].png index c12e094911..6b5e25ce2f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:56f0ecce5efe141fa2181e2c16dc654e79c4de43cb11b18004b03ce2ddad991d -size 38801 +oid sha256:1f385e70f3a8bda7c0c2f7c090ba665575239299472c0fbd62f2821783ceb065 +size 39016 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_1,NEXUS_5,1.0,en].png index 87770b930d..c0b73d2764 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f9d7be89279d30e82a689654eac67137678ca4eb079e80372011580bcf0e9e22 -size 62757 +oid sha256:4bdb22d629e4bc3273aac4944802d1c91b43065858f4f4cc90052bd78ae6dd89 +size 62998 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_2,NEXUS_5,1.0,en].png index c12e094911..6b5e25ce2f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:56f0ecce5efe141fa2181e2c16dc654e79c4de43cb11b18004b03ce2ddad991d -size 38801 +oid sha256:1f385e70f3a8bda7c0c2f7c090ba665575239299472c0fbd62f2821783ceb065 +size 39016 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_3,NEXUS_5,1.0,en].png index 861787a0b8..8fe1fefb5d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:db76df516d6c7a4bff5b830e423145c448b076846b8b7f75032be6f65585cd31 -size 40846 +oid sha256:8ec1d951c96737ff8c5b401ef7c3af944f76be69348559401e40a12f60d5d459 +size 40807 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_4,NEXUS_5,1.0,en].png index 0968936113..c0550bff56 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:405842db16444b958899fe174ca1c0157c0c6384f8ae0be37be104de8613f140 -size 40126 +oid sha256:ef7d9c31a72334294e93c67af1ca068ddff0062ae909ee8b682f0117c5c0ab6c +size 40331 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_5,NEXUS_5,1.0,en].png index 1033a71853..340f3d07c3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:658ee0f231146446810d7c0d09d280148d68475d2411c59cf0ac70caabf4e3ec -size 40496 +oid sha256:54ebfc606c04f37ed72edf5e9168a55628b59e69ea8a03cc3925cf25ca807195 +size 40695 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_0,NEXUS_5,1.0,en].png index 9b60e19c06..b0851b0bde 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0a2a737eb81f74c50efb44c03ac9eb528c38ff393dc1a32efa0c148e27da4668 -size 17880 +oid sha256:877bec872499d1a1f15b50c95c507be6233a2ea121cf3429e255b3bde66c1d7b +size 18331 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_1,NEXUS_5,1.0,en].png index fbbc1e6a37..3cf0d12761 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ff929a3cfa47f93176817cc844b9ef2f5ff6146f016606515efe858fadd00247 -size 17199 +oid sha256:84da3f320738e96b2c90724b278b0b2538e55f4089753f10e4913f7f759fd1c3 +size 17533 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_2,NEXUS_5,1.0,en].png index d05e5b744b..2b087814f2 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d9b589643f99328d44a38a263b50c4447df7104a6fc0494dd80bbb2920752cb1 -size 19519 +oid sha256:ce86a5fe5ee55b411bd1f76b59e12baafb0cbc963251c9e58d047b1a2a200331 +size 20274 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom-N_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom-N_1_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..42af4e3ccb --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom-N_1_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3bd86a694456603dce070a7bef0646e553cefdb365f81c9d835b28d6b2521950 +size 71026 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_0,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..622b4080c5 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_0,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:67be26f120cbce266651737206a5f444b9a0605a4528cea30971f4629b340501 +size 85653 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_1,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..2006811bc7 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_1,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7142834262eb7db1909a5a48621979cb1a2ee00bc3b70de08e90523f53083e2d +size 85294 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_2,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..637c2b6594 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_2,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3424334cf7831701633ebe3b865a5696d6843c41acc372a6dcddadaaa371160f +size 83088 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_3,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..474bb5ca7a --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_3,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0e5583fd71bfe7ae518b4b90c3d3b00f1a65829dc015c6384ddd1a560ca77bdb +size 88567 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_4,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..a69eca99b4 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_4,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88902f2d5512e22e1f5cd50d0628c7f968a0ee9e88b16a9d0d55fd2e11aefcba +size 85255 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_5,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..07783dd2d7 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_5,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a55cef72cf73e76104b74d55fe0abe92efa60e094116d871686fc4f525ca3649 +size 84298 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_6,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..97b62022c8 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_6,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:70919d061d76126b09642e2d0f1b41b3d0b6a4cff68f68c6bd2e43d141732dd3 +size 87805 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_7,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..8c93c67eb8 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_7,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1b62cd8043e21bed0a323d657f79605aa9a0ad3fae632387d175fdd764baf8ce +size 81507 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_0,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..5df89eca37 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_0,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aafacbe3b1d14fdb11144d65148a24400fe964c4cd880796f8cc829abf37ae05 +size 5294 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_1,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..c40dfa4088 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_1,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:30bb9d0a709868ff29803e45265069aad6e75ea2e65cdd8524b83a490a666831 +size 5272 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_2,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..553e8c904c --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_2,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3c56746d71fa25bf610f041b6c72e4559282407808bedbcdcc3c71a4497b3244 +size 5417 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_3,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..29ceb833be --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_3,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8be31e6a338f76e28550062911766dab5e4744e3e514f1348636100885ac1fe7 +size 5310 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_4,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..9cb6b0bb87 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_4,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:813856d48fdb7b168b5cd662113a54dad9286b5f4191379471866ef6eda55e84 +size 5336 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_5,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..7faff66c03 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_5,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:83adb2ece84370f3f7249765b391ca30dcb5ba9a2ceb04872bbb7f66101890a7 +size 5340 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_6,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..888d88b06c --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_6,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a71d6d556b72e3be69f0a9902771066259123f002f7fd35652a64aa8c26c9eea +size 5256 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_7,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..3d3e4db08f --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_7,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:667ecdc1069d2111044ca8f55f2fe12ff7aff84529b65c89e1c0223d841fb455 +size 5465 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_Bloom_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_Bloom_0_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..24f73f516c --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_Bloom_0_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9c452593117cb003aca6d7d3c547b96a879c1bb10a169926c507c57a2abdc9b1 +size 77557 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png index 37e8a8561f..6d92ba07bc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e65e15c721a939ed700719cacbdee57e1ccb89d984e88bdb5ed772c4b583472a -size 81494 +oid sha256:700c12595cb3df0b342b36816dd336424ae1a94245874cb1e989528e89964336 +size 79384 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png index 466f321959..d51e1ad32f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:49f6d3b7f93008640abf30a5a65ddca6845e16343ef97c3450faf9dd6d9b9cec -size 78788 +oid sha256:9f562083dcd0746eab20db445fce2836628faf5b57077dbb63ddbc32a479a9a0 +size 76138 From 962acc08f6f21cfab4f29b96f89f89559c073745 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 11 Sep 2023 16:02:26 +0200 Subject: [PATCH 100/234] Hide Reply action if user cannot post to the room. --- .../features/messages/impl/MessagesView.kt | 12 +++- .../impl/actionlist/ActionListEvents.kt | 6 +- .../impl/actionlist/ActionListPresenter.kt | 6 +- .../actionlist/ActionListPresenterTest.kt | 59 ++++++++++++++----- 4 files changed, 64 insertions(+), 19 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt index 9810845228..ab11ca05d7 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt @@ -123,7 +123,13 @@ fun MessagesView( fun onMessageLongClicked(event: TimelineItem.Event) { Timber.v("OnMessageLongClicked= ${event.id}") localView.hideKeyboard() - state.actionListState.eventSink(ActionListEvents.ComputeForMessage(event, state.userHasPermissionToRedact)) + state.actionListState.eventSink( + ActionListEvents.ComputeForMessage( + event = event, + canRedact = state.userHasPermissionToRedact, + canSendMessage = state.userHasPermissionToSendMessage, + ) + ) } fun onActionSelected(action: TimelineItemAction, event: TimelineItem.Event) { @@ -203,8 +209,8 @@ fun MessagesView( CustomReactionBottomSheet( state = state.customReactionState, onEmojiSelected = { eventId, emoji -> - state.eventSink(MessagesEvents.ToggleReaction(emoji.unicode, eventId)) - state.customReactionState.eventSink(CustomReactionEvents.DismissCustomReactionSheet) + state.eventSink(MessagesEvents.ToggleReaction(emoji.unicode, eventId)) + state.customReactionState.eventSink(CustomReactionEvents.DismissCustomReactionSheet) } ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListEvents.kt index c5e6618736..7c8fad6c7c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListEvents.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListEvents.kt @@ -20,5 +20,9 @@ import io.element.android.features.messages.impl.timeline.model.TimelineItem sealed interface ActionListEvents { data object Clear : ActionListEvents - data class ComputeForMessage(val event: TimelineItem.Event, val canRedact: Boolean) : ActionListEvents + data class ComputeForMessage( + val event: TimelineItem.Event, + val canRedact: Boolean, + val canSendMessage: Boolean, + ) : ActionListEvents } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt index d0fa46175a..510c375bc5 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt @@ -62,6 +62,7 @@ class ActionListPresenter @Inject constructor( is ActionListEvents.ComputeForMessage -> localCoroutineScope.computeForMessage( timelineItem = event.event, userCanRedact = event.canRedact, + userCanSendMessage = event.canSendMessage, target = target, ) } @@ -77,6 +78,7 @@ class ActionListPresenter @Inject constructor( private fun CoroutineScope.computeForMessage( timelineItem: TimelineItem.Event, userCanRedact: Boolean, + userCanSendMessage: Boolean, target: MutableState ) = launch { target.value = ActionListState.Target.Loading(timelineItem) @@ -126,7 +128,9 @@ class ActionListPresenter @Inject constructor( else -> buildList { if (timelineItem.isRemote) { // Can only reply or forward messages already uploaded to the server - add(TimelineItemAction.Reply) + if (userCanSendMessage) { + add(TimelineItemAction.Reply) + } add(TimelineItemAction.Forward) } if (timelineItem.isMine && timelineItem.isTextMessage) { diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt index 3f3114dff3..5e68906216 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt @@ -64,7 +64,7 @@ class ActionListPresenterTest { }.test { val initialState = awaitItem() val messageEvent = aMessageEvent(isMine = true, content = TimelineItemRedactedContent) - initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, false)) + initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, canRedact = false, canSendMessage = true)) // val loadingState = awaitItem() // assertThat(loadingState.target).isEqualTo(ActionListState.Target.Loading(messageEvent)) val successState = awaitItem() @@ -89,7 +89,7 @@ class ActionListPresenterTest { }.test { val initialState = awaitItem() val messageEvent = aMessageEvent(isMine = false, content = TimelineItemRedactedContent) - initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, false)) + initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, canRedact = false, canSendMessage = true)) // val loadingState = awaitItem() // assertThat(loadingState.target).isEqualTo(ActionListState.Target.Loading(messageEvent)) val successState = awaitItem() @@ -117,7 +117,7 @@ class ActionListPresenterTest { isMine = false, content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false) ) - initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, false)) + initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, canRedact = false, canSendMessage = true)) // val loadingState = awaitItem() // assertThat(loadingState.target).isEqualTo(ActionListState.Target.Loading(messageEvent)) val successState = awaitItem() @@ -138,6 +138,37 @@ class ActionListPresenterTest { } } + @Test + fun `present - compute for others message cannot sent message`() = runTest { + val presenter = anActionListPresenter(isBuildDebuggable = true) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + val messageEvent = aMessageEvent( + isMine = false, + content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false) + ) + initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, canRedact = false, canSendMessage = false)) + // val loadingState = awaitItem() + // assertThat(loadingState.target).isEqualTo(ActionListState.Target.Loading(messageEvent)) + val successState = awaitItem() + assertThat(successState.target).isEqualTo( + ActionListState.Target.Success( + messageEvent, + persistentListOf( + TimelineItemAction.Forward, + TimelineItemAction.Copy, + TimelineItemAction.Developer, + TimelineItemAction.ReportContent, + ) + ) + ) + initialState.eventSink.invoke(ActionListEvents.Clear) + assertThat(awaitItem().target).isEqualTo(ActionListState.Target.None) + } + } + @Test fun `present - compute for others message and can redact`() = runTest { val presenter = anActionListPresenter(isBuildDebuggable = true) @@ -149,7 +180,7 @@ class ActionListPresenterTest { isMine = false, content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false) ) - initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, true)) + initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, canRedact = true, canSendMessage = true)) val successState = awaitItem() assertThat(successState.target).isEqualTo( ActionListState.Target.Success( @@ -180,7 +211,7 @@ class ActionListPresenterTest { isMine = true, content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false) ) - initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, false)) + initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, canRedact = false, canSendMessage = true)) // val loadingState = awaitItem() // assertThat(loadingState.target).isEqualTo(ActionListState.Target.Loading(messageEvent)) val successState = awaitItem() @@ -213,7 +244,7 @@ class ActionListPresenterTest { isMine = true, content = aTimelineItemImageContent(), ) - initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, false)) + initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, canRedact = false, canSendMessage = true)) // val loadingState = awaitItem() // assertThat(loadingState.target).isEqualTo(ActionListState.Target.Loading(messageEvent)) val successState = awaitItem() @@ -244,7 +275,7 @@ class ActionListPresenterTest { isMine = true, content = aTimelineItemStateEventContent(), ) - initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(stateEvent, false)) + initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(stateEvent, canRedact = false, canSendMessage = true)) // val loadingState = awaitItem() // assertThat(loadingState.target).isEqualTo(ActionListState.Target.Loading(messageEvent)) val successState = awaitItem() @@ -273,7 +304,7 @@ class ActionListPresenterTest { isMine = true, content = aTimelineItemStateEventContent(), ) - initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(stateEvent, false)) + initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(stateEvent, canRedact = false, canSendMessage = true)) // val loadingState = awaitItem() // assertThat(loadingState.target).isEqualTo(ActionListState.Target.Loading(messageEvent)) val successState = awaitItem() @@ -301,7 +332,7 @@ class ActionListPresenterTest { isMine = true, content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false) ) - initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, false)) + initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, canRedact = false, canSendMessage = true)) // val loadingState = awaitItem() // assertThat(loadingState.target).isEqualTo(ActionListState.Target.Loading(messageEvent)) val successState = awaitItem() @@ -338,10 +369,10 @@ class ActionListPresenterTest { content = TimelineItemRedactedContent, ) - initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, false)) + initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, canRedact = false, canSendMessage = true)) assertThat(awaitItem().target).isInstanceOf(ActionListState.Target.Success::class.java) - initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(redactedEvent, false)) + initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(redactedEvent, canRedact = false, canSendMessage = true)) awaitItem().run { assertThat(target).isEqualTo(ActionListState.Target.None) assertThat(displayEmojiReactions).isFalse() @@ -362,7 +393,7 @@ class ActionListPresenterTest { content = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false), ) - initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, false)) + initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, canRedact = false, canSendMessage = true)) val successState = awaitItem() assertThat(successState.target).isEqualTo( ActionListState.Target.Success( @@ -389,7 +420,7 @@ class ActionListPresenterTest { isMine = true, content = aTimelineItemPollContent(), ) - initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, false)) + initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, canRedact = false, canSendMessage = true)) val successState = awaitItem() assertThat(successState.target).isEqualTo( ActionListState.Target.Success( @@ -415,7 +446,7 @@ class ActionListPresenterTest { isMine = true, content = aTimelineItemPollContent(isEnded = true), ) - initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, false)) + initialState.eventSink.invoke(ActionListEvents.ComputeForMessage(messageEvent, canRedact = false, canSendMessage = true)) val successState = awaitItem() assertThat(successState.target).isEqualTo( ActionListState.Target.Success( From 23358b9edbb5c8e857cbe2ea62ca51c2ea681c43 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 11 Sep 2023 16:23:29 +0200 Subject: [PATCH 101/234] Disable swipe to reply action for unsupported events. --- .../messages/impl/actionlist/ActionListPresenter.kt | 3 ++- .../messages/impl/timeline/TimelinePresenter.kt | 2 +- .../features/messages/impl/timeline/TimelineState.kt | 2 +- .../messages/impl/timeline/TimelineStateProvider.kt | 2 +- .../features/messages/impl/timeline/TimelineView.kt | 9 +++++---- .../timeline/model/event/TimelineItemEventContent.kt | 12 ++++++++++++ 6 files changed, 22 insertions(+), 8 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt index 510c375bc5..b179261c72 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt @@ -103,7 +103,8 @@ class ActionListPresenter @Inject constructor( buildList { val isMineOrCanRedact = timelineItem.isMine || userCanRedact - // TODO Poll: Reply to poll + // TODO Poll: Reply to poll. Ensure to update `fun TimelineItemEventContent.canBeReplied()` + // when touching this // if (timelineItem.isRemote) { // // Can only reply or forward messages already uploaded to the server // add(TimelineItemAction.Reply) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt index f5e6b45fe6..bf0f61e258 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt @@ -116,7 +116,7 @@ class TimelinePresenter @Inject constructor( return TimelineState( highlightedEventId = highlightedEventId.value, - canReply = userHasPermissionToSendMessage, + userHasPermissionToSendMessage = userHasPermissionToSendMessage, paginationState = paginationState, timelineItems = timelineItems, hasNewItems = hasNewItems.value, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt index ab5874d39c..1c7ff1b87c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt @@ -26,7 +26,7 @@ import kotlinx.collections.immutable.ImmutableList data class TimelineState( val timelineItems: ImmutableList, val highlightedEventId: EventId?, - val canReply: Boolean, + val userHasPermissionToSendMessage: Boolean, val paginationState: MatrixTimeline.PaginationState, val hasNewItems: Boolean, val eventSink: (TimelineEvents) -> Unit diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt index 6172da0469..8a4d45e40c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt @@ -44,7 +44,7 @@ fun aTimelineState(timelineItems: ImmutableList = persistentListOf timelineItems = timelineItems, paginationState = MatrixTimeline.PaginationState(isBackPaginating = false, hasMoreToLoadBackwards = true), highlightedEventId = null, - canReply = true, + userHasPermissionToSendMessage = true, hasNewItems = false, eventSink = {}, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index ff90e8d29a..b5187b4b30 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -63,6 +63,7 @@ import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContentProvider import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent +import io.element.android.features.messages.impl.timeline.model.event.canBeReplied import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.theme.components.FloatingActionButton @@ -119,7 +120,7 @@ fun TimelineView( TimelineItemRow( timelineItem = timelineItem, highlightedItem = state.highlightedEventId?.value, - canReply = state.canReply, + userHasPermissionToSendMessage = state.userHasPermissionToSendMessage, onClick = onMessageClicked, onLongClick = onMessageLongClicked, onUserDataClick = onUserDataClicked, @@ -156,7 +157,7 @@ fun TimelineView( fun TimelineItemRow( timelineItem: TimelineItem, highlightedItem: String?, - canReply: Boolean, + userHasPermissionToSendMessage: Boolean, onUserDataClick: (UserId) -> Unit, onClick: (TimelineItem.Event) -> Unit, onLongClick: (TimelineItem.Event) -> Unit, @@ -189,7 +190,7 @@ fun TimelineItemRow( TimelineItemEventRow( event = timelineItem, isHighlighted = highlightedItem == timelineItem.identifier(), - canReply = canReply, + canReply = userHasPermissionToSendMessage && timelineItem.content.canBeReplied(), onClick = { onClick(timelineItem) }, onLongClick = { onLongClick(timelineItem) }, onUserDataClick = onUserDataClick, @@ -228,7 +229,7 @@ fun TimelineItemRow( TimelineItemRow( timelineItem = subGroupEvent, highlightedItem = highlightedItem, - canReply = false, + userHasPermissionToSendMessage = false, onClick = onClick, onLongClick = onLongClick, inReplyToClick = inReplyToClick, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt index 02837bd6b4..4501e98e79 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt @@ -34,6 +34,18 @@ fun TimelineItemEventContent.canBeCopied(): Boolean = else -> false } +/** + * Determine if the event content can be replied to. + * Note: it should match the logic in [io.element.android.features.messages.impl.actionlist.ActionListPresenter]. + */ +fun TimelineItemEventContent.canBeReplied(): Boolean = + when (this) { + is TimelineItemRedactedContent, + is TimelineItemStateContent, + is TimelineItemPollContent -> false + else -> true + } + /** * Return true if user can react (i.e. send a reaction) on the event content. */ From e3d2fe9ec91dcfa7a5e258937701df53a838e23a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 11 Sep 2023 16:39:01 +0200 Subject: [PATCH 102/234] Changelog --- changelog.d/1173.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/1173.bugfix diff --git a/changelog.d/1173.bugfix b/changelog.d/1173.bugfix new file mode 100644 index 0000000000..354aaaa3c4 --- /dev/null +++ b/changelog.d/1173.bugfix @@ -0,0 +1 @@ +Reply action: harmonize conditions in bottom sheet and swipe to reply. From 4b6a44db0010f5919d7e104cdcbb6b5142b8b0b7 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 11 Sep 2023 17:47:58 +0200 Subject: [PATCH 103/234] TimelineEvent : fix memory leak --- .../item/event/TimelineEventContentMapper.kt | 145 +++++++++--------- 1 file changed, 76 insertions(+), 69 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt index 22f8a062f0..3d02346bb3 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt @@ -34,84 +34,91 @@ import io.element.android.libraries.matrix.impl.media.map import io.element.android.libraries.matrix.impl.poll.map import org.matrix.rustcomponents.sdk.TimelineItemContent import org.matrix.rustcomponents.sdk.TimelineItemContentKind +import org.matrix.rustcomponents.sdk.use import org.matrix.rustcomponents.sdk.EncryptedMessage as RustEncryptedMessage import org.matrix.rustcomponents.sdk.MembershipChange as RustMembershipChange import org.matrix.rustcomponents.sdk.OtherState as RustOtherState class TimelineEventContentMapper(private val eventMessageMapper: EventMessageMapper = EventMessageMapper()) { - fun map(content: TimelineItemContent): EventContent = content.use { - when (val kind = it.kind()) { - is TimelineItemContentKind.FailedToParseMessageLike -> { - FailedToParseMessageLikeContent( - eventType = kind.eventType, - error = kind.error - ) + fun map(content: TimelineItemContent): EventContent { + return content.use { _ -> + content.kind().use { kind -> + map(content, kind) } - is TimelineItemContentKind.FailedToParseState -> { - FailedToParseStateContent( - eventType = kind.eventType, - stateKey = kind.stateKey, - error = kind.error - ) - } - TimelineItemContentKind.Message -> { - val message = it.asMessage() - if (message == null) { - UnknownContent - } else { - eventMessageMapper.map(message) - } - } - is TimelineItemContentKind.ProfileChange -> { - ProfileChangeContent( - displayName = kind.displayName, - prevDisplayName = kind.prevDisplayName, - avatarUrl = kind.avatarUrl, - prevAvatarUrl = kind.prevAvatarUrl - ) - } - TimelineItemContentKind.RedactedMessage -> { - RedactedContent - } - is TimelineItemContentKind.RoomMembership -> { - RoomMembershipContent( - UserId(kind.userId), - kind.change?.map() - ) - } - is TimelineItemContentKind.State -> { - StateContent( - stateKey = kind.stateKey, - content = kind.content.map() - ) - } - is TimelineItemContentKind.Sticker -> { - StickerContent( - body = kind.body, - info = kind.info.map(), - url = kind.url, - ) - } - is TimelineItemContentKind.Poll -> { - PollContent( - question = kind.question, - kind = kind.kind.map(), - maxSelections = kind.maxSelections, - answers = kind.answers.map { answer -> answer.map() }, - votes = kind.votes.mapValues { vote -> - vote.value.map { userId -> UserId(userId) } - }, - endTime = kind.endTime, - ) - } - is TimelineItemContentKind.UnableToDecrypt -> { - UnableToDecryptContent( - data = kind.msg.map() - ) + } + } + + private fun map(content: TimelineItemContent, kind: TimelineItemContentKind) = when (kind) { + is TimelineItemContentKind.FailedToParseMessageLike -> { + FailedToParseMessageLikeContent( + eventType = kind.eventType, + error = kind.error + ) + } + is TimelineItemContentKind.FailedToParseState -> { + FailedToParseStateContent( + eventType = kind.eventType, + stateKey = kind.stateKey, + error = kind.error + ) + } + TimelineItemContentKind.Message -> { + val message = content.asMessage() + if (message == null) { + UnknownContent + } else { + eventMessageMapper.map(message) } - else -> UnknownContent } + is TimelineItemContentKind.ProfileChange -> { + ProfileChangeContent( + displayName = kind.displayName, + prevDisplayName = kind.prevDisplayName, + avatarUrl = kind.avatarUrl, + prevAvatarUrl = kind.prevAvatarUrl + ) + } + TimelineItemContentKind.RedactedMessage -> { + RedactedContent + } + is TimelineItemContentKind.RoomMembership -> { + RoomMembershipContent( + UserId(kind.userId), + kind.change?.map() + ) + } + is TimelineItemContentKind.State -> { + StateContent( + stateKey = kind.stateKey, + content = kind.content.map() + ) + } + is TimelineItemContentKind.Sticker -> { + StickerContent( + body = kind.body, + info = kind.info.map(), + url = kind.url, + ) + } + is TimelineItemContentKind.Poll -> { + PollContent( + question = kind.question, + kind = kind.kind.map(), + maxSelections = kind.maxSelections, + answers = kind.answers.map { answer -> answer.map() }, + votes = kind.votes.mapValues { vote -> + vote.value.map { userId -> UserId(userId) } + }, + endTime = kind.endTime, + ) + } + is TimelineItemContentKind.UnableToDecrypt -> { + UnableToDecryptContent( + data = kind.msg.map() + ) + } + else -> UnknownContent } } From a0ac324e3fa9230a36ad168e017da00323b47438 Mon Sep 17 00:00:00 2001 From: David Langley Date: Tue, 12 Sep 2023 01:11:13 +0100 Subject: [PATCH 104/234] Implement Notification Settings - Add UI and logic to inform the user of mismatched notification settings and help them correct it. - Display a warning when the system notification settings are disabled and a link out to the app settings. - A toggle to disable notifications for the device - A screen for editing the group and direct chat notification defaults. - A toggle for switching on/off atRoom and call notifications. --- features/preferences/impl/build.gradle.kts | 1 + .../preferences/impl/PreferencesFlowNode.kt | 16 +- .../NotificationSettingsEvents.kt | 31 +++ .../notifications/NotificationSettingsNode.kt | 16 +- .../NotificationSettingsPresenter.kt | 164 +++++++++++++++- .../NotificationSettingsState.kt | 37 +++- .../NotificationSettingsStateProvider.kt | 16 +- .../notifications/NotificationSettingsView.kt | 180 ++++++++++++++++-- .../SystemNotificationsEnabledProvider.kt | 39 ++++ .../edit/DefaultNotificationSettingOption.kt | 98 ++++++++++ .../EditDefaultNotificationSettingNode.kt | 54 ++++++ ...EditDefaultNotificationSettingPresenter.kt | 92 +++++++++ .../EditDefaultNotificationSettingState.kt | 25 +++ ...itDefaultNotificationSettingStateEvents.kt | 23 +++ .../EditDefaultNotificationSettingView.kt | 71 +++++++ .../roomdetails/impl/RoomDetailsPresenter.kt | 2 +- .../RoomNotificationSettingsPresenter.kt | 4 +- .../NotificationSettingsService.kt | 12 +- .../libraries/matrix/api/room/MatrixRoom.kt | 7 + .../RustNotificationSettingsService.kt | 47 +++-- .../matrix/impl/room/RustMatrixRoom.kt | 2 +- .../FakeNotificationSettingsService.kt | 27 ++- .../push/impl/push/DefaultPushHandler.kt | 3 +- libraries/pushstore/api/build.gradle.kts | 1 + .../libraries/pushstore/api/UserPushStore.kt | 4 +- .../impl/DefaultUserPushStoreFactoryTest.kt | 5 +- .../pushstore/impl/UserPushStoreDataStore.kt | 6 +- 27 files changed, 924 insertions(+), 59 deletions(-) create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsEvents.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/SystemNotificationsEnabledProvider.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/DefaultNotificationSettingOption.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingNode.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingPresenter.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingState.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingStateEvents.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt diff --git a/features/preferences/impl/build.gradle.kts b/features/preferences/impl/build.gradle.kts index 2773379ccc..b868dd6b81 100644 --- a/features/preferences/impl/build.gradle.kts +++ b/features/preferences/impl/build.gradle.kts @@ -40,6 +40,7 @@ dependencies { implementation(projects.libraries.featureflag.api) implementation(projects.libraries.featureflag.ui) implementation(projects.libraries.network) + implementation(projects.libraries.pushstore.api) implementation(projects.libraries.testtags) implementation(projects.libraries.uiStrings) implementation(projects.features.rageshake.api) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt index 5470a788e9..0998318abf 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt @@ -34,11 +34,13 @@ import io.element.android.features.preferences.impl.about.AboutNode import io.element.android.features.preferences.impl.analytics.AnalyticsSettingsNode import io.element.android.features.preferences.impl.developer.DeveloperSettingsNode import io.element.android.features.preferences.impl.notifications.NotificationSettingsNode +import io.element.android.features.preferences.impl.notifications.edit.EditDefaultNotificationSettingNode import io.element.android.features.preferences.impl.root.PreferencesRootNode import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.createNode import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.core.UserId import kotlinx.parcelize.Parcelize @ContributesNode(SessionScope::class) @@ -70,6 +72,9 @@ class PreferencesFlowNode @AssistedInject constructor( @Parcelize data object NotificationSettings : NavTarget + + @Parcelize + data class EditDefaultNotificationSetting(val isOneToOne: Boolean) : NavTarget } override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { @@ -112,7 +117,16 @@ class PreferencesFlowNode @AssistedInject constructor( createNode(buildContext) } NavTarget.NotificationSettings -> { - createNode(buildContext) + val notificationSettingsCallback = object : NotificationSettingsNode.Callback { + override fun editDefaultNotificationMode(isOneToOne: Boolean) { + backstack.push(NavTarget.EditDefaultNotificationSetting(isOneToOne)) + } + } + createNode(buildContext, listOf(notificationSettingsCallback)) + } + is NavTarget.EditDefaultNotificationSetting -> { + val input = EditDefaultNotificationSettingNode.Inputs(navTarget.isOneToOne) + createNode(buildContext, plugins = listOf(input)) } } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsEvents.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsEvents.kt new file mode 100644 index 0000000000..f1ee07f6b1 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsEvents.kt @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.notifications + +import io.element.android.libraries.matrix.api.room.RoomNotificationMode + +sealed interface NotificationSettingsEvents { + + data object RefreshSystemNotificationsEnabled : NotificationSettingsEvents + data class SetNotificationsEnabled(val enabled: Boolean) : NotificationSettingsEvents + data class SetAtRoomNotificationsEnabled(val enabled: Boolean) : NotificationSettingsEvents + data class SetCallNotificationsEnabled(val enabled: Boolean) : NotificationSettingsEvents + data class SetDefaultGroupNotificationMode(val mode: RoomNotificationMode) : NotificationSettingsEvents + data class SetDefaultOneToOneNotificationMode(val mode: RoomNotificationMode) : NotificationSettingsEvents + data object FixConfigurationMismatch : NotificationSettingsEvents + data object ClearConfigurationMismatchError : NotificationSettingsEvents +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsNode.kt index d0db81ea7a..d7a9532219 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsNode.kt @@ -21,10 +21,12 @@ import androidx.compose.ui.Modifier import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin +import com.bumble.appyx.core.plugin.plugins import dagger.assisted.Assisted import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.core.UserId @ContributesNode(SessionScope::class) class NotificationSettingsNode @AssistedInject constructor( @@ -32,13 +34,25 @@ class NotificationSettingsNode @AssistedInject constructor( @Assisted plugins: List, private val presenter: NotificationSettingsPresenter, ) : Node(buildContext, plugins = plugins) { + + interface Callback : Plugin { + fun editDefaultNotificationMode(isOneToOne: Boolean) + } + + private val callbacks = plugins() + + private fun openEditDefault(isOneToOne: Boolean) { + callbacks.forEach { it.editDefaultNotificationMode(isOneToOne) } + } + @Composable override fun View(modifier: Modifier) { val state = presenter.present() NotificationSettingsView( state = state, + onOpenEditDefault = { openEditDefault(it) }, onBackPressed = ::navigateUp, - modifier = modifier + modifier = modifier, ) } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt index 255284f003..84d140b470 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt @@ -17,18 +17,170 @@ package io.element.android.features.preferences.impl.notifications import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.pushstore.api.UserPushStore +import io.element.android.libraries.pushstore.api.UserPushStoreFactory +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.FlowPreview +import kotlinx.coroutines.flow.debounce +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch import javax.inject.Inject +import kotlin.time.Duration.Companion.seconds -class NotificationSettingsPresenter @Inject constructor() : Presenter { - +class NotificationSettingsPresenter @Inject constructor( + private val notificationSettingsService: NotificationSettingsService, + private val userPushStoreFactory: UserPushStoreFactory, + private val matrixClient: MatrixClient, + private val systemNotificationsEnabledProvider: SystemNotificationsEnabledProvider +) : Presenter { @Composable override fun present(): NotificationSettingsState { + val userPushStore = userPushStoreFactory.create(matrixClient.sessionId) + val systemNotificationsEnabled: MutableState = remember { + mutableStateOf(systemNotificationsEnabledProvider.notificationsEnabled()) + } + + val localCoroutineScope = rememberCoroutineScope() + val appNotificationsEnabled = userPushStore + .getNotificationEnabledForDevice() + .collectAsState(initial = false) + + val matrixSettings: MutableState = remember { + mutableStateOf(NotificationSettingsState.MatrixNotificationSettings.Uninitialized) + } + + LaunchedEffect(Unit) { + fetchSettings(matrixSettings) + observeNotificationSettings(matrixSettings) + } + + fun handleEvents(event: NotificationSettingsEvents) { + when (event) { + is NotificationSettingsEvents.SetAtRoomNotificationsEnabled -> localCoroutineScope.setAtRoomNotificationsEnabled(event.enabled) + is NotificationSettingsEvents.SetCallNotificationsEnabled -> localCoroutineScope.setCallNotificationsEnabled(event.enabled) + is NotificationSettingsEvents.SetDefaultGroupNotificationMode -> localCoroutineScope.setDefaultGroupNotificationMode(event.mode) + is NotificationSettingsEvents.SetDefaultOneToOneNotificationMode -> localCoroutineScope.setDefaultOneToOneNotificationMode(event.mode) + is NotificationSettingsEvents.SetNotificationsEnabled -> localCoroutineScope.setNotificationsEnabled(userPushStore, event.enabled) + NotificationSettingsEvents.ClearConfigurationMismatchError -> matrixSettings.value = NotificationSettingsState.MatrixNotificationSettings.InvalidNotificationSettingsState(fixFailed = false) + NotificationSettingsEvents.FixConfigurationMismatch -> localCoroutineScope.fixConfigurationMismatch(matrixSettings) + NotificationSettingsEvents.RefreshSystemNotificationsEnabled -> systemNotificationsEnabled.value = systemNotificationsEnabledProvider.notificationsEnabled() + } + } + return NotificationSettingsState( - isEnabled = true, - hasSystemPermission = true, - notifyMeOnRoom = true, - acceptCalls = true + matrixNotificationSettings = matrixSettings.value, + appNotificationSettings = NotificationSettingsState.AppNotificationSettings( + systemNotificationsEnabled = systemNotificationsEnabled.value, + appNotificationsEnabled = appNotificationsEnabled.value + ), + eventSink = ::handleEvents ) } + + @OptIn(FlowPreview::class) + private fun CoroutineScope.observeNotificationSettings(target: MutableState) { + notificationSettingsService.notificationSettingsChangeFlow + .debounce(0.5.seconds) + .onEach { + fetchSettings(target) + } + .launchIn(this) + } + + private fun CoroutineScope.fetchSettings(target: MutableState) = launch { + val groupDefaultMode = notificationSettingsService.getDefaultRoomNotificationMode(isEncrypted = false, isOneToOne = false).getOrThrow() + val encryptedGroupDefaultMode = notificationSettingsService.getDefaultRoomNotificationMode(isEncrypted = true, isOneToOne = false).getOrThrow() + + val oneToOneDefaultMode = notificationSettingsService.getDefaultRoomNotificationMode(isEncrypted = false, isOneToOne = true).getOrThrow() + val encryptedOneToOneDefaultMode = notificationSettingsService.getDefaultRoomNotificationMode(isEncrypted = true, isOneToOne = true).getOrThrow() + + if(groupDefaultMode != encryptedGroupDefaultMode || oneToOneDefaultMode != encryptedOneToOneDefaultMode) { + target.value = NotificationSettingsState.MatrixNotificationSettings.InvalidNotificationSettingsState(fixFailed = false) + return@launch + } + + val callNotificationsEnabled = notificationSettingsService.isCallEnabled().getOrThrow() + val atRoomNotificationsEnabled = notificationSettingsService.isRoomMentionEnabled().getOrThrow() + + target.value = NotificationSettingsState.MatrixNotificationSettings.ValidNotificationSettingsState( + atRoomNotificationsEnabled = atRoomNotificationsEnabled, + callNotificationsEnabled = callNotificationsEnabled, + defaultGroupNotificationMode = encryptedGroupDefaultMode, + defaultOneToOneNotificationMode = encryptedOneToOneDefaultMode, + ) + } + + private fun CoroutineScope.fixConfigurationMismatch(target: MutableState) = launch { + runCatching { + val groupDefaultMode = notificationSettingsService.getDefaultRoomNotificationMode(isEncrypted = false, isOneToOne = false).getOrThrow() + val encryptedGroupDefaultMode = notificationSettingsService.getDefaultRoomNotificationMode(isEncrypted = true, isOneToOne = false).getOrThrow() + + if (groupDefaultMode != encryptedGroupDefaultMode) { + notificationSettingsService.setDefaultRoomNotificationMode( + isEncrypted = encryptedGroupDefaultMode != RoomNotificationMode.ALL_MESSAGES, + mode = RoomNotificationMode.ALL_MESSAGES, + isOneToOne = false, + ) + } + + val oneToOneDefaultMode = notificationSettingsService.getDefaultRoomNotificationMode(isEncrypted = false, isOneToOne = true).getOrThrow() + val encryptedOneToOneDefaultMode = notificationSettingsService.getDefaultRoomNotificationMode(isEncrypted = true, isOneToOne = true).getOrThrow() + + if (oneToOneDefaultMode != encryptedOneToOneDefaultMode) { + notificationSettingsService.setDefaultRoomNotificationMode( + isEncrypted = encryptedOneToOneDefaultMode != RoomNotificationMode.ALL_MESSAGES, + mode = RoomNotificationMode.ALL_MESSAGES, + isOneToOne = true, + ) + } + }.fold( + onSuccess = {}, + onFailure = { + target.value = NotificationSettingsState.MatrixNotificationSettings.InvalidNotificationSettingsState(fixFailed = true) + } + ) + } + + private fun CoroutineScope.setAtRoomNotificationsEnabled(enabled: Boolean) = launch { + notificationSettingsService.setRoomMentionEnabled(enabled) + } + + private fun CoroutineScope.setCallNotificationsEnabled(enabled: Boolean) = launch { + notificationSettingsService.setCallEnabled(enabled) + } + + private fun CoroutineScope.setDefaultGroupNotificationMode(mode: RoomNotificationMode) = launch { + notificationSettingsService.setDefaultRoomNotificationMode(false, mode, false) + notificationSettingsService.setDefaultRoomNotificationMode(true, mode, false) + } + + private fun CoroutineScope.setDefaultOneToOneNotificationMode(mode: RoomNotificationMode) = launch { + notificationSettingsService.setDefaultRoomNotificationMode(false, mode, true) + notificationSettingsService.setDefaultRoomNotificationMode(true, mode, true) + } + + private fun CoroutineScope.setNotificationsEnabled(userPushStore: UserPushStore, enabled: Boolean) = launch { + userPushStore.setNotificationEnabledForDevice(enabled) + } + + private fun CoroutineScope.getDefaultRoomNotificationMode(isOneToOne: Boolean, defaultRoomNotificationMode: MutableState) = launch { + val encryptedMode = notificationSettingsService.getDefaultRoomNotificationMode(true, isOneToOne).getOrThrow() + val unencryptedMode = notificationSettingsService.getDefaultRoomNotificationMode(false, isOneToOne).getOrThrow() + if (encryptedMode == unencryptedMode) { + defaultRoomNotificationMode.value + } else { + defaultRoomNotificationMode.value = null + } + } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsState.kt index ca65fcf5d0..ac3502b89b 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsState.kt @@ -16,10 +16,35 @@ package io.element.android.features.preferences.impl.notifications +import androidx.compose.runtime.Immutable +import io.element.android.libraries.matrix.api.room.RoomNotificationMode + +@Immutable data class NotificationSettingsState( - val hasSystemPermission: Boolean, - val isEnabled: Boolean, - val notifyMeOnRoom: Boolean, - val acceptCalls: Boolean -// val eventSink: (AnalyticsOptInEvents) -> Unit, -) + val matrixNotificationSettings: MatrixNotificationSettings, + val appNotificationSettings: AppNotificationSettings, + val eventSink: (NotificationSettingsEvents) -> Unit, +) { + sealed interface MatrixNotificationSettings { + data object Uninitialized : MatrixNotificationSettings + data class ValidNotificationSettingsState( + val atRoomNotificationsEnabled: Boolean, + val callNotificationsEnabled: Boolean, + val defaultGroupNotificationMode: RoomNotificationMode?, + val defaultOneToOneNotificationMode: RoomNotificationMode?, + ) : MatrixNotificationSettings + + data class InvalidNotificationSettingsState( + val fixFailed: Boolean + ) : MatrixNotificationSettings + } + + data class AppNotificationSettings( + val systemNotificationsEnabled: Boolean, + val appNotificationsEnabled: Boolean, + ) +} + + + + diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsStateProvider.kt index c6c72f3acc..a4b9014b0c 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsStateProvider.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsStateProvider.kt @@ -17,6 +17,7 @@ package io.element.android.features.preferences.impl.notifications import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.matrix.api.room.RoomNotificationMode open class NotificationSettingsStateProvider : PreviewParameterProvider { override val values: Sequence @@ -26,8 +27,15 @@ open class NotificationSettingsStateProvider : PreviewParameterProvider Unit, onBackPressed: () -> Unit, modifier: Modifier = Modifier, ) { + OnLifecycleEvent { _, event -> + when (event) { + Lifecycle.Event.ON_RESUME -> state.eventSink.invoke(NotificationSettingsEvents.RefreshSystemNotificationsEnabled) + else -> Unit + } + } PreferenceView( modifier = modifier, onBackPressed = onBackPressed, title = stringResource(id = CommonStrings.screen_notification_settings_title) ) { - if (state.isEnabled && !state.hasSystemPermission) { + when (state.matrixNotificationSettings) { + is NotificationSettingsState.MatrixNotificationSettings.InvalidNotificationSettingsState -> InvalidNotificationSettingsView( + showError = state.matrixNotificationSettings.fixFailed, + onContinueClicked = { state.eventSink(NotificationSettingsEvents.FixConfigurationMismatch) }, + onDismissError = { state.eventSink(NotificationSettingsEvents.ClearConfigurationMismatchError) }, + modifier = modifier, + ) + NotificationSettingsState.MatrixNotificationSettings.Uninitialized -> return@PreferenceView + is NotificationSettingsState.MatrixNotificationSettings.ValidNotificationSettingsState -> NotificationSettingsContentView( + matrixSettings = state.matrixNotificationSettings, + systemSettings = state.appNotificationSettings, + onNotificationsEnabledChanged = { state.eventSink(NotificationSettingsEvents.SetNotificationsEnabled(it))}, + onGroupChatsClicked = { onOpenEditDefault(false) }, + onDirectChatsClicked = { onOpenEditDefault(true) }, + onMentionNotificationsChanged = { state.eventSink(NotificationSettingsEvents.SetAtRoomNotificationsEnabled(it)) }, + onCallsNotificationsChanged = { state.eventSink(NotificationSettingsEvents.SetCallNotificationsEnabled(it)) }, + modifier = modifier, + ) + } + } +} + +@Composable +private fun NotificationSettingsContentView( + matrixSettings: NotificationSettingsState.MatrixNotificationSettings.ValidNotificationSettingsState, + systemSettings: NotificationSettingsState.AppNotificationSettings, + onNotificationsEnabledChanged: (Boolean) -> Unit, + onGroupChatsClicked: () -> Unit, + onDirectChatsClicked: () -> Unit, + onMentionNotificationsChanged: (Boolean) -> Unit, + onCallsNotificationsChanged: (Boolean) -> Unit, + modifier: Modifier = Modifier, +) { + val context = LocalContext.current + if (systemSettings.appNotificationsEnabled && !systemSettings.systemNotificationsEnabled) { PreferenceText( icon = Icons.Filled.NotificationsOff, title = stringResource(id = CommonStrings.screen_notification_settings_system_notifications_turned_off), subtitle = stringResource(id = CommonStrings.screen_notification_settings_system_notifications_action_required, stringResource(id = CommonStrings.screen_notification_settings_system_notifications_action_required_content_link)), - onClick = {} + onClick = { + val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + val uri: Uri = Uri.fromParts("package", context.packageName, null) + intent.data = uri + context.startActivity(intent) + } ) } PreferenceSwitch( - modifier = Modifier, + modifier = modifier, title = stringResource(id = CommonStrings.screen_notification_settings_enable_notifications), - isChecked = state.isEnabled, + isChecked = systemSettings.appNotificationsEnabled, switchAlignment = Alignment.Top, + onCheckedChange = onNotificationsEnabledChanged ) - if (state.isEnabled) { + if (systemSettings.appNotificationsEnabled) { PreferenceCategory(title = stringResource(id = CommonStrings.screen_notification_settings_notification_section_title)) { PreferenceText( title = stringResource(id = CommonStrings.screen_notification_settings_group_chats), - subtitle = "All messages" + subtitle = getTitleForRoomNotificationMode(mode = matrixSettings.defaultGroupNotificationMode), + onClick = onGroupChatsClicked ) PreferenceText( title = stringResource(id = CommonStrings.screen_notification_settings_direct_chats), - subtitle = "Mentions and Keywords" + subtitle = getTitleForRoomNotificationMode(mode = matrixSettings.defaultOneToOneNotificationMode), + onClick = onDirectChatsClicked ) } @@ -78,8 +151,9 @@ fun NotificationSettingsView( PreferenceSwitch( modifier = Modifier, title = stringResource(id = CommonStrings.screen_notification_settings_room_mention_label), - isChecked = state.notifyMeOnRoom, + isChecked = matrixSettings.atRoomNotificationsEnabled, switchAlignment = Alignment.Top, + onCheckedChange = onMentionNotificationsChanged ) } @@ -87,22 +161,83 @@ fun NotificationSettingsView( PreferenceSwitch( modifier = Modifier, title = stringResource(id = CommonStrings.screen_notification_settings_calls_label), - isChecked = state.acceptCalls, + isChecked = matrixSettings.callNotificationsEnabled, switchAlignment = Alignment.Top, + onCheckedChange = onCallsNotificationsChanged + ) + } + } +} + + +@Composable +private fun getTitleForRoomNotificationMode(mode: RoomNotificationMode?) = +when(mode) { + RoomNotificationMode.ALL_MESSAGES -> stringResource(id = R.string.screen_notification_settings_edit_mode_all_messages) + RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> stringResource(id = R.string.screen_notification_settings_edit_mode_mentions_and_keywords) + RoomNotificationMode.MUTE -> stringResource(id = CommonStrings.common_mute) + null -> "" +} + +@Composable +private fun InvalidNotificationSettingsView( + showError: Boolean, + onContinueClicked: () -> Unit, + onDismissError: () -> Unit, + modifier: Modifier = Modifier +) { + Box(modifier = modifier.padding(horizontal = 16.dp, vertical = 8.dp)) { + Surface( + Modifier.fillMaxWidth(), + shape = MaterialTheme.shapes.small, + color = MaterialTheme.colorScheme.surfaceVariant + ) { + Column( + Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 12.dp) + ) { + Row { + Text( + stringResource(R.string.screen_notification_settings_configuration_mismatch), + modifier = Modifier.weight(1f), + style = ElementTheme.typography.fontBodyLgMedium, + color = MaterialTheme.colorScheme.primary, + textAlign = TextAlign.Start, + ) + } + Spacer(modifier = Modifier.height(4.dp)) + Text( + stringResource(R.string.screen_notification_settings_configuration_mismatch_description), + style = ElementTheme.typography.fontBodyMdRegular, + ) + Spacer(modifier = Modifier.height(12.dp)) + Button( + text = stringResource(CommonStrings.action_continue), + size = ButtonSize.Medium, + modifier = Modifier.fillMaxWidth(), + onClick = onContinueClicked, ) } } } + if(showError) { + ErrorDialog( + title = stringResource(id = CommonStrings.dialog_title_error), + content = stringResource(id = CommonStrings.screen_notification_settings_failed_fixing_configuration), + onDismiss = onDismissError + ) + } } @Preview @Composable -internal fun AboutViewLightPreview(@PreviewParameter(NotificationSettingsStateProvider::class) state: NotificationSettingsState) = +internal fun NotificationSettingsViewLightPreview(@PreviewParameter(NotificationSettingsStateProvider::class) state: NotificationSettingsState) = ElementPreviewLight { ContentToPreview(state) } @Preview @Composable -internal fun AboutViewDarkPreview(@PreviewParameter(NotificationSettingsStateProvider::class) state: NotificationSettingsState) = +internal fun NotificationSettingsViewDarkPreview(@PreviewParameter(NotificationSettingsStateProvider::class) state: NotificationSettingsState) = ElementPreviewDark { ContentToPreview(state) } @Composable @@ -110,5 +245,26 @@ private fun ContentToPreview(state: NotificationSettingsState) { NotificationSettingsView( state = state, onBackPressed = {}, + onOpenEditDefault = {}, + ) +} + + +@Preview +@Composable +internal fun InvalidNotificationSettingsViewightPreview(@PreviewParameter(NotificationSettingsStateProvider::class) state: NotificationSettingsState) = + ElementPreviewLight { InvalidNotificationSettingsContentToPreview(state) } + +@Preview +@Composable +internal fun InvalidNotificationSettingsViewDarkPreview(@PreviewParameter(NotificationSettingsStateProvider::class) state: NotificationSettingsState) = + ElementPreviewDark { InvalidNotificationSettingsContentToPreview(state) } + +@Composable +private fun InvalidNotificationSettingsContentToPreview(state: NotificationSettingsState) { + InvalidNotificationSettingsView( + showError = false, + onContinueClicked = {}, + onDismissError = {}, ) } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/SystemNotificationsEnabledProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/SystemNotificationsEnabledProvider.kt new file mode 100644 index 0000000000..f33b1cb773 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/SystemNotificationsEnabledProvider.kt @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.notifications + +import android.content.Context +import androidx.core.app.NotificationManagerCompat +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.libraries.di.AppScope +import io.element.android.libraries.di.ApplicationContext +import io.element.android.libraries.di.SingleIn +import javax.inject.Inject + +interface SystemNotificationsEnabledProvider { + fun notificationsEnabled(): Boolean +} +@SingleIn(AppScope::class) +@ContributesBinding(AppScope::class, boundType = SystemNotificationsEnabledProvider::class) +class DefaultSystemNotificationsEnabledProvider @Inject constructor( + @ApplicationContext private val context: Context, +): SystemNotificationsEnabledProvider { + override fun notificationsEnabled(): Boolean { + return NotificationManagerCompat.from(context).areNotificationsEnabled() + } +} + diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/DefaultNotificationSettingOption.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/DefaultNotificationSettingOption.kt new file mode 100644 index 0000000000..b06df90d30 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/DefaultNotificationSettingOption.kt @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.notifications.edit +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.selection.selectable +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.unit.dp +import io.element.android.libraries.designsystem.preview.DayNightPreviews +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.theme.components.RadioButton +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.theme.ElementTheme +import io.element.android.libraries.ui.strings.R + +@Composable +fun DefaultNotificationSettingOption( + mode: RoomNotificationMode, + modifier: Modifier = Modifier, + isSelected: Boolean = false, + onOptionSelected: (RoomNotificationMode) -> Unit = {}, +) { + val subtitle = when(mode) { + RoomNotificationMode.ALL_MESSAGES -> stringResource(id = R.string.screen_notification_settings_edit_mode_all_messages) + RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> stringResource(id = R.string.screen_notification_settings_edit_mode_mentions_and_keywords) + else -> "" + } + Row( + modifier + .fillMaxWidth() + .selectable( + selected = isSelected, + onClick = { onOptionSelected(mode) }, + role = Role.RadioButton, + ) + .padding(8.dp), + ) { + Column( + Modifier + .weight(1f) + .padding(horizontal = 8.dp) + .align(Alignment.CenterVertically) + ) { + Text( + text = subtitle, + style = ElementTheme.typography.fontBodyLgRegular, + ) + } + + RadioButton( + modifier = Modifier + .align(Alignment.CenterVertically) + .size(48.dp), + selected = isSelected, + onClick = null // null recommended for accessibility with screenreaders + ) + } +} +@DayNightPreviews +@Composable +internal fun DefaultNotificationSettingOptionLightPreview() = ElementPreview { ContentToPreview() } + +@Composable +private fun ContentToPreview() { + Column { + DefaultNotificationSettingOption( + mode = RoomNotificationMode.ALL_MESSAGES, + isSelected = true, + ) + DefaultNotificationSettingOption( + mode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY, + isSelected = false, + ) + } +} + diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingNode.kt new file mode 100644 index 0000000000..6c4fd646f4 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingNode.kt @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.notifications.edit + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode +import io.element.android.libraries.architecture.NodeInputs +import io.element.android.libraries.architecture.inputs +import io.element.android.libraries.di.SessionScope + +@ContributesNode(SessionScope::class) +class EditDefaultNotificationSettingNode @AssistedInject constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + presenterFactory: EditDefaultNotificationSettingPresenter.Factory +) : Node(buildContext, plugins = plugins) { + + data class Inputs( + val isOneToOne: Boolean + ) : NodeInputs + + private val inputs = inputs() + private val presenter = presenterFactory.create(inputs.isOneToOne) + + @Composable + override fun View(modifier: Modifier) { + val state = presenter.present() + EditDefaultNotificationSettingView( + state = state, + onBackPressed = ::navigateUp, + modifier = modifier + ) + } +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingPresenter.kt new file mode 100644 index 0000000000..b146155486 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingPresenter.kt @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.notifications.edit + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.FlowPreview +import kotlinx.coroutines.flow.debounce +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch +import kotlin.time.Duration.Companion.seconds + +class EditDefaultNotificationSettingPresenter @AssistedInject constructor( + private val notificationSettingsService: NotificationSettingsService, + @Assisted private val isOneToOne: Boolean, +) : Presenter { + @AssistedFactory + interface Factory { + fun create(oneToOne: Boolean): EditDefaultNotificationSettingPresenter + } + @Composable + override fun present(): EditDefaultNotificationSettingState { + + val mode: MutableState = remember { + mutableStateOf(null) + } + val localCoroutineScope = rememberCoroutineScope() + LaunchedEffect(Unit) { + fetchSettings(mode) + observeNotificationSettings(mode) + } + + fun handleEvents(event: EditDefaultNotificationSettingStateEvents) { + when (event) { + is EditDefaultNotificationSettingStateEvents.SetNotificationMode -> localCoroutineScope.setDefaultNotificationMode(event.mode) + } + } + + return EditDefaultNotificationSettingState( + isOneToOne = isOneToOne, + mode = mode.value, + eventSink = ::handleEvents + ) + } + + private fun CoroutineScope.fetchSettings(mode: MutableState) = launch { + mode.value = notificationSettingsService.getDefaultRoomNotificationMode(isEncrypted = true, isOneToOne = isOneToOne).getOrThrow() + } + + @OptIn(FlowPreview::class) + private fun CoroutineScope.observeNotificationSettings(mode: MutableState) { + notificationSettingsService.notificationSettingsChangeFlow + .debounce(0.5.seconds) + .onEach { + fetchSettings(mode) + } + .launchIn(this) + } + + private fun CoroutineScope.setDefaultNotificationMode(mode: RoomNotificationMode) = launch { + notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = true, mode = mode, isOneToOne = isOneToOne) + notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = false, mode = mode, isOneToOne = isOneToOne) + } + +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingState.kt new file mode 100644 index 0000000000..62c708d988 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingState.kt @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.notifications.edit + +import io.element.android.libraries.matrix.api.room.RoomNotificationMode + +data class EditDefaultNotificationSettingState( + val isOneToOne: Boolean, + val mode: RoomNotificationMode?, + val eventSink: (EditDefaultNotificationSettingStateEvents) -> Unit, +) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingStateEvents.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingStateEvents.kt new file mode 100644 index 0000000000..75c9b6c1a4 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingStateEvents.kt @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.notifications.edit + +import io.element.android.libraries.matrix.api.room.RoomNotificationMode + +sealed interface EditDefaultNotificationSettingStateEvents { + data class SetNotificationMode(val mode: RoomNotificationMode): EditDefaultNotificationSettingStateEvents +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt new file mode 100644 index 0000000000..5c00cd49cb --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.notifications.edit + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.selection.selectableGroup +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import io.element.android.libraries.ui.strings.R +import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory +import io.element.android.libraries.designsystem.components.preferences.PreferenceView +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.ui.strings.CommonStrings + +@Composable +fun EditDefaultNotificationSettingView( + state: EditDefaultNotificationSettingState, + onBackPressed: () -> Unit, + modifier: Modifier = Modifier, +) { + + val title = if(state.isOneToOne) { + CommonStrings.screen_notification_settings_direct_chats + } else { + CommonStrings.screen_notification_settings_group_chats + } + PreferenceView( + modifier = modifier, + onBackPressed = onBackPressed, + title = stringResource(id = title) + ) { + + val validModes = listOf(RoomNotificationMode.ALL_MESSAGES, RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY) + + val categoryTitle = if(state.isOneToOne) { + R.string.screen_notification_settings_edit_screen_direct_section_header + } else { + R.string.screen_notification_settings_edit_screen_group_section_header + } + PreferenceCategory(title = stringResource(id = categoryTitle)) { + + if (state.mode != null) { + Column(modifier = modifier.selectableGroup()) { + validModes.forEach { item -> + DefaultNotificationSettingOption( + mode = item, + isSelected = state.mode == item, + onOptionSelected = { state.eventSink(EditDefaultNotificationSettingStateEvents.SetNotificationMode(it)) } + ) + } + } + } + } + } +} + diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt index b12d4710a0..34a0b2b2e1 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt @@ -106,7 +106,7 @@ class RoomDetailsPresenter @Inject constructor( } RoomDetailsEvent.UnmuteNotification -> { scope.launch(dispatchers.io) { - client.notificationSettingsService().unmuteRoom(room.roomId, room.isEncrypted, room.activeMemberCount) + client.notificationSettingsService().unmuteRoom(room.roomId, room.isEncrypted, room.isOneToOne) } } } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt index d5c88e53d4..f1993d27b1 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt @@ -75,8 +75,6 @@ class RoomNotificationSettingsPresenter @Inject constructor( } } - Timber.d("NotifState: $roomNotificationSettingsState") - return RoomNotificationSettingsState( roomNotificationSettings = roomNotificationSettingsState.roomNotificationSettings(), defaultRoomNotificationMode = defaultRoomNotificationMode.value, @@ -97,7 +95,7 @@ class RoomNotificationSettingsPresenter @Inject constructor( private fun CoroutineScope.getDefaultRoomNotificationMode(defaultRoomNotificationMode: MutableState) = launch { defaultRoomNotificationMode.value = notificationSettingsService.getDefaultRoomNotificationMode( room.isEncrypted, - room.activeMemberCount + room.isOneToOne ).getOrThrow() } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt index 0f82604aba..3e62b0c97f 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt @@ -21,16 +21,22 @@ import io.element.android.libraries.matrix.api.room.MatrixRoomNotificationSettin import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.RoomNotificationSettings import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.withContext interface NotificationSettingsService { /** * State of the current room notification settings flow ([MatrixRoomNotificationSettingsState.Unknown] if not started). */ val notificationSettingsChangeFlow : SharedFlow - suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, membersCount: Long): Result - suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, membersCount: Long): Result + suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, isOneToOne: Boolean): Result + suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, isOneToOne: Boolean): Result + suspend fun setDefaultRoomNotificationMode(isEncrypted: Boolean, mode: RoomNotificationMode, isOneToOne: Boolean): Result suspend fun setRoomNotificationMode(roomId: RoomId, mode: RoomNotificationMode): Result suspend fun restoreDefaultRoomNotificationMode(roomId: RoomId): Result suspend fun muteRoom(roomId: RoomId): Result - suspend fun unmuteRoom(roomId: RoomId, isEncrypted: Boolean, membersCount: Long): Result + suspend fun unmuteRoom(roomId: RoomId, isEncrypted: Boolean, isOneToOne: Boolean): Result + suspend fun isRoomMentionEnabled(): Result + suspend fun setRoomMentionEnabled(enabled: Boolean): Result + suspend fun isCallEnabled(): Result + suspend fun setCallEnabled(enabled: Boolean): Result } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt index 60c8b1ddd5..1f90913ef4 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt @@ -49,6 +49,12 @@ interface MatrixRoom : Closeable { val activeMemberCount: Long val joinedMemberCount: Long + /** + * A one-to-one is a room with exactly 2 members. + * See [the Matrix spec](https://spec.matrix.org/latest/client-server-api/#default-underride-rules). + */ + val isOneToOne: Boolean get() = joinedMemberCount == 2L + /** * The current loaded members as a StateFlow. * Initial value is [MatrixRoomMembersState.Unknown]. @@ -178,6 +184,7 @@ interface MatrixRoom : Closeable { suspend fun endPoll(pollStartId: EventId, text: String): Result override fun close() = destroy() + } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt index 1b1d51214f..7dea15a809 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt @@ -47,16 +47,22 @@ class RustNotificationSettingsService( notificationSettings.setDelegate(notificationSettingsDelegate) } - override suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, membersCount: Long): Result = + override suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, isOneToOne: Boolean): Result = runCatching { - notificationSettings.getRoomNotificationSettings(roomId.value, isEncrypted, isOneToOne(membersCount)).let(RoomNotificationSettingsMapper::map) + notificationSettings.getRoomNotificationSettings(roomId.value, isEncrypted, isOneToOne).let(RoomNotificationSettingsMapper::map) } - override suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, membersCount: Long): Result = + override suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, isOneToOne: Boolean): Result = runCatching { - notificationSettings.getDefaultRoomNotificationMode(isEncrypted, isOneToOne(membersCount)).let(RoomNotificationSettingsMapper::mapMode) + notificationSettings.getDefaultRoomNotificationMode(isEncrypted, isOneToOne).let(RoomNotificationSettingsMapper::mapMode) } + override suspend fun setDefaultRoomNotificationMode(isEncrypted: Boolean, mode: RoomNotificationMode, isOneToOne: Boolean): Result = withContext(dispatchers.io) { + runCatching { + notificationSettings.setDefaultRoomNotificationMode(isEncrypted, isOneToOne, mode.let(RoomNotificationSettingsMapper::mapMode)) + } + } + override suspend fun setRoomNotificationMode(roomId: RoomId, mode: RoomNotificationMode): Result = withContext(dispatchers.io) { runCatching { notificationSettings.setRoomNotificationMode(roomId.value, mode.let(RoomNotificationSettingsMapper::mapMode)) @@ -71,16 +77,33 @@ class RustNotificationSettingsService( override suspend fun muteRoom(roomId: RoomId): Result = setRoomNotificationMode(roomId, RoomNotificationMode.MUTE) - override suspend fun unmuteRoom(roomId: RoomId, isEncrypted: Boolean, membersCount: Long) = withContext(dispatchers.io) { + override suspend fun unmuteRoom(roomId: RoomId, isEncrypted: Boolean, isOneToOne: Boolean) = withContext(dispatchers.io) { + runCatching { + notificationSettings.unmuteRoom(roomId.value, isEncrypted, isOneToOne) + } + } + + override suspend fun isRoomMentionEnabled(): Result = withContext(dispatchers.io) { runCatching { - notificationSettings.unmuteRoom(roomId.value, isEncrypted, isOneToOne(membersCount)) + notificationSettings.isRoomMentionEnabled() } } - /** - * A one-to-one is a room with exactly 2 members. - * See [the Matrix spec](https://spec.matrix.org/latest/client-server-api/#default-underride-rules). - * @param membersCount The active members count in a room - */ - private fun isOneToOne(membersCount: Long) = membersCount == 2L + override suspend fun setRoomMentionEnabled(enabled: Boolean): Result = withContext(dispatchers.io) { + runCatching { + notificationSettings.setRoomMentionEnabled(enabled) + } + } + + override suspend fun isCallEnabled(): Result = withContext(dispatchers.io) { + runCatching { + notificationSettings.isCallEnabled() + } + } + + override suspend fun setCallEnabled(enabled: Boolean): Result = withContext(dispatchers.io) { + runCatching { + notificationSettings.setCallEnabled(enabled) + } + } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt index 461e43931e..53352ae640 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt @@ -210,7 +210,7 @@ class RustMatrixRoom( val currentRoomNotificationSettings = currentState.roomNotificationSettings() _roomNotificationSettingsStateFlow.value = MatrixRoomNotificationSettingsState.Pending(prevRoomNotificationSettings = currentRoomNotificationSettings) runCatching { - roomNotificationSettingsService.getRoomNotificationSettings(roomId, isEncrypted, activeMemberCount).getOrThrow() + roomNotificationSettingsService.getRoomNotificationSettings(roomId, isEncrypted, isOneToOne).getOrThrow() }.map { _roomNotificationSettingsStateFlow.value = MatrixRoomNotificationSettingsState.Ready(it) }.onFailure { diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt index 5e06d08de5..ccf5cd4155 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt @@ -36,14 +36,18 @@ class FakeNotificationSettingsService : NotificationSettingsService { override val notificationSettingsChangeFlow: SharedFlow get() = _roomNotificationSettingsStateFlow - override suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, membersCount: Long): Result { + override suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, isOneToOne: Boolean): Result { return getRoomNotificationSettingsResult } - override suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, membersCount: Long): Result { + override suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, isOneToOne: Boolean): Result { return getDefaultRoomNotificationMode } + override suspend fun setDefaultRoomNotificationMode(isEncrypted: Boolean, mode: RoomNotificationMode, isOneToOne: Boolean): Result { + TODO("Not yet implemented") + } + override suspend fun setRoomNotificationMode(roomId: RoomId, mode: RoomNotificationMode): Result { return setRoomNotificationMode } @@ -56,7 +60,24 @@ class FakeNotificationSettingsService : NotificationSettingsService { return muteRoomResult } - override suspend fun unmuteRoom(roomId: RoomId, isEncrypted: Boolean, membersCount: Long): Result { + override suspend fun unmuteRoom(roomId: RoomId, isEncrypted: Boolean, isOneToOne: Boolean): Result { return unmuteRoomResult } + + override suspend fun isRoomMentionEnabled(): Result { + return Result.success(false) + } + + override suspend fun setRoomMentionEnabled(enabled: Boolean): Result { + return Result.success(Unit) + } + + override suspend fun isCallEnabled(): Result { + return Result.success(false) + } + + override suspend fun setCallEnabled(enabled: Boolean): Result { + return Result.success(Unit) + } + } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt index c3d68e52ac..7c5d24c31a 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt @@ -35,6 +35,7 @@ import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject @@ -123,7 +124,7 @@ class DefaultPushHandler @Inject constructor( } val userPushStore = userPushStoreFactory.create(userId) - if (!userPushStore.areNotificationEnabledForDevice()) { + if (!userPushStore.getNotificationEnabledForDevice().first()) { // TODO We need to check if this is an incoming call Timber.tag(loggerTag.value).i("Notification are disabled for this device, ignore push.") return diff --git a/libraries/pushstore/api/build.gradle.kts b/libraries/pushstore/api/build.gradle.kts index fdfd794c2e..00d7776770 100644 --- a/libraries/pushstore/api/build.gradle.kts +++ b/libraries/pushstore/api/build.gradle.kts @@ -22,5 +22,6 @@ android { } dependencies { + implementation(libs.coroutines.core) implementation(projects.libraries.matrix.api) } diff --git a/libraries/pushstore/api/src/main/kotlin/io/element/android/libraries/pushstore/api/UserPushStore.kt b/libraries/pushstore/api/src/main/kotlin/io/element/android/libraries/pushstore/api/UserPushStore.kt index 28577ba3f8..a10413fdf5 100644 --- a/libraries/pushstore/api/src/main/kotlin/io/element/android/libraries/pushstore/api/UserPushStore.kt +++ b/libraries/pushstore/api/src/main/kotlin/io/element/android/libraries/pushstore/api/UserPushStore.kt @@ -15,6 +15,8 @@ */ package io.element.android.libraries.pushstore.api +import kotlinx.coroutines.flow.Flow + /** * Store data related to push about a user. @@ -25,7 +27,7 @@ interface UserPushStore { suspend fun getCurrentRegisteredPushKey(): String? suspend fun setCurrentRegisteredPushKey(value: String) - suspend fun areNotificationEnabledForDevice(): Boolean + fun getNotificationEnabledForDevice(): Flow suspend fun setNotificationEnabledForDevice(enabled: Boolean) /** diff --git a/libraries/pushstore/impl/src/androidTest/kotlin/io/element/android/libraries/pushstore/impl/DefaultUserPushStoreFactoryTest.kt b/libraries/pushstore/impl/src/androidTest/kotlin/io/element/android/libraries/pushstore/impl/DefaultUserPushStoreFactoryTest.kt index c87c772ddf..67b07bfd1d 100644 --- a/libraries/pushstore/impl/src/androidTest/kotlin/io/element/android/libraries/pushstore/impl/DefaultUserPushStoreFactoryTest.kt +++ b/libraries/pushstore/impl/src/androidTest/kotlin/io/element/android/libraries/pushstore/impl/DefaultUserPushStoreFactoryTest.kt @@ -20,6 +20,7 @@ import androidx.test.platform.app.InstrumentationRegistry import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.pushstore.api.UserPushStore import io.element.android.libraries.sessionstorage.test.observer.NoOpSessionObserver +import kotlinx.coroutines.flow.first import kotlinx.coroutines.runBlocking import org.junit.Test import kotlin.concurrent.thread @@ -49,8 +50,8 @@ class DefaultUserPushStoreFactoryTest { thread1.join() thread2.join() runBlocking { - userPushStore1!!.areNotificationEnabledForDevice() - userPushStore2!!.areNotificationEnabledForDevice() + userPushStore1!!.getNotificationEnabledForDevice().first() + userPushStore2!!.getNotificationEnabledForDevice().first() } } } diff --git a/libraries/pushstore/impl/src/main/kotlin/io/element/android/libraries/pushstore/impl/UserPushStoreDataStore.kt b/libraries/pushstore/impl/src/main/kotlin/io/element/android/libraries/pushstore/impl/UserPushStoreDataStore.kt index 56867a6584..718ddb51fa 100644 --- a/libraries/pushstore/impl/src/main/kotlin/io/element/android/libraries/pushstore/impl/UserPushStoreDataStore.kt +++ b/libraries/pushstore/impl/src/main/kotlin/io/element/android/libraries/pushstore/impl/UserPushStoreDataStore.kt @@ -26,7 +26,9 @@ import androidx.datastore.preferences.preferencesDataStore import io.element.android.libraries.core.bool.orTrue import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.pushstore.api.UserPushStore +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map /** * Store data related to push about a user. @@ -60,8 +62,8 @@ class UserPushStoreDataStore( } } - override suspend fun areNotificationEnabledForDevice(): Boolean { - return context.dataStore.data.first()[notificationEnabled].orTrue() + override fun getNotificationEnabledForDevice(): Flow { + return context.dataStore.data.map{ it[notificationEnabled].orTrue() } } override suspend fun setNotificationEnabledForDevice(enabled: Boolean) { From 557099995112b1a37dc5e7a5b2b4bc2246b71f8f Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 12 Sep 2023 09:46:12 +0200 Subject: [PATCH 105/234] PR review Co-authored-by: Benoit Marty --- .../impl/timeline/item/event/TimelineEventContentMapper.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt index 3d02346bb3..01dd32c048 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt @@ -42,7 +42,7 @@ import org.matrix.rustcomponents.sdk.OtherState as RustOtherState class TimelineEventContentMapper(private val eventMessageMapper: EventMessageMapper = EventMessageMapper()) { fun map(content: TimelineItemContent): EventContent { - return content.use { _ -> + return content.use { content.kind().use { kind -> map(content, kind) } From 04c82aa1a551e44be6473d829c6b1a1cdab1a84a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 12 Sep 2023 12:00:29 +0200 Subject: [PATCH 106/234] Update core to v1.12.0 (#1242) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update core to v1.12.0 * Fixed now nullable `PendingIntent` creation --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jorge Martín --- gradle/libs.versions.toml | 2 +- .../push/impl/notifications/factories/PendingIntentFactory.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c59d7359a6..b281ec73df 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,7 @@ molecule = "1.2.0" # AndroidX material = "1.9.0" -core = "1.10.1" +core = "1.12.0" datastore = "1.0.0" constraintlayout = "2.1.4" constraintlayout_compose = "1.0.1" diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/PendingIntentFactory.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/PendingIntentFactory.kt index 2fe02a8958..9752c621d5 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/PendingIntentFactory.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/PendingIntentFactory.kt @@ -131,6 +131,6 @@ class PendingIntentFactory @Inject constructor( fun createInviteListPendingIntent(sessionId: SessionId): PendingIntent { val intent = intentProvider.getInviteListIntent(sessionId) - return PendingIntentCompat.getActivity(context, 0, intent, 0, false) + return PendingIntentCompat.getActivity(context, 0, intent, 0, false)!! } } From be5bece629cc4f48e3327fe4b42f86311c7dd162 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 12 Sep 2023 13:20:29 +0200 Subject: [PATCH 107/234] Attempt to add extra spacing for Document (#1228) --- .../timeline/components/event/ExtraPadding.kt | 11 ++++++++ .../components/event/TimelineItemTextView.kt | 24 ++++++---------- .../timeline/components/html/HtmlDocument.kt | 28 ++++++++++++++----- 3 files changed, 40 insertions(+), 23 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/ExtraPadding.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/ExtraPadding.kt index 65101183d9..e5851c993b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/ExtraPadding.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/ExtraPadding.kt @@ -18,10 +18,14 @@ package io.element.android.features.messages.impl.timeline.components.event import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.TextUnit +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.times import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent import io.element.android.libraries.core.bool.orFalse +import io.element.android.libraries.designsystem.text.toDp import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.ui.strings.CommonStrings @@ -69,3 +73,10 @@ fun ExtraPadding.getStr(fontSize: TextUnit): String { // A space and some unbreakable spaces return " " + "\u00A0".repeat(nbOfSpaces) } + +@Composable +fun ExtraPadding.getDpSize(): Dp { + if (nbChars == 0) return 0.dp + val timestampFontSize = ElementTheme.typography.fontBodyXsRegular.fontSize // 11.sp + return nbChars * timestampFontSize.toDp() / 3 +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemTextView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemTextView.kt index c6b0218bba..b2dcc477a0 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemTextView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemTextView.kt @@ -18,9 +18,6 @@ package io.element.android.features.messages.impl.timeline.components.event import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height import androidx.compose.material3.LocalContentColor import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider @@ -28,7 +25,6 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter -import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import io.element.android.features.messages.impl.timeline.components.html.HtmlDocument import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextBasedContent @@ -51,18 +47,14 @@ fun TimelineItemTextView( CompositionLocalProvider(LocalContentColor provides ElementTheme.colors.textPrimary) { val htmlDocument = content.htmlDocument if (htmlDocument != null) { - // For now we ignore the extra padding for html content, so add some spacing - // below the content (as previous behavior) - Column(modifier = modifier) { - HtmlDocument( - document = htmlDocument, - modifier = Modifier, - onTextClicked = onTextClicked, - onTextLongClicked = onTextLongClicked, - interactionSource = interactionSource - ) - Spacer(Modifier.height(16.dp)) - } + HtmlDocument( + document = htmlDocument, + extraPadding = extraPadding, + modifier = modifier, + onTextClicked = onTextClicked, + onTextLongClicked = onTextLongClicked, + interactionSource = interactionSource + ) } else { Box(modifier) { val textWithPadding = remember(content.body) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/html/HtmlDocument.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/html/HtmlDocument.kt index 9c2798a638..11eb1f421f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/html/HtmlDocument.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/html/HtmlDocument.kt @@ -25,8 +25,10 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.FlowRow +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.InlineTextContent import androidx.compose.foundation.text.appendInlineContent @@ -53,6 +55,9 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import io.element.android.features.messages.impl.timeline.components.event.ExtraPadding +import io.element.android.features.messages.impl.timeline.components.event.getDpSize +import io.element.android.features.messages.impl.timeline.components.event.noExtraPadding import io.element.android.libraries.designsystem.components.ClickableLinkText import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewLight @@ -72,18 +77,23 @@ private const val CHIP_ID = "chip" @Composable fun HtmlDocument( document: Document, + extraPadding: ExtraPadding, interactionSource: MutableInteractionSource, modifier: Modifier = Modifier, onTextClicked: () -> Unit = {}, onTextLongClicked: () -> Unit = {}, ) { - HtmlBody( - body = document.body(), - interactionSource = interactionSource, + FlowRow( modifier = modifier, - onTextClicked = onTextClicked, - onTextLongClicked = onTextLongClicked, - ) + ) { + HtmlBody( + body = document.body(), + interactionSource = interactionSource, + onTextClicked = onTextClicked, + onTextLongClicked = onTextLongClicked, + ) + Spacer(modifier = Modifier.width(extraPadding.getDpSize())) + } } @Composable @@ -603,5 +613,9 @@ internal fun HtmlDocumentDarkPreview(@PreviewParameter(DocumentProvider::class) @Composable private fun ContentToPreview(document: Document) { - HtmlDocument(document, remember { MutableInteractionSource() }) + HtmlDocument( + document = document, + extraPadding = noExtraPadding, + interactionSource = remember { MutableInteractionSource() } + ) } From da0b691fecbc3ca855a0c6e9d702b0eda8e45d0e Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 12 Sep 2023 11:28:15 +0000 Subject: [PATCH 108/234] Update screenshots --- ...null_TimelineItemTextViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...null_TimelineItemTextViewDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...null_TimelineItemTextViewDark_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...lineItemEventRowTimestampDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...lineItemEventRowTimestampDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...lineItemEventRowTimestampDark_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...lineItemEventRowTimestampDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...ineItemEventRowTimestampLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ineItemEventRowTimestampLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...ineItemEventRowTimestampLight_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...ineItemEventRowTimestampLight_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- 11 files changed, 22 insertions(+), 22 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemTextViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemTextViewDark_0_null_1,NEXUS_5,1.0,en].png index a9f640a918..73cb512e55 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemTextViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemTextViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:367f76f13127a604d1fec6e86d56611b01765dc90462dd329cd567e55a52fdca -size 7827 +oid sha256:eb78a3bc85d7f9ead19ba7d2723b997af1a399167ce28004be8ccbf0dd8ce5fd +size 7736 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemTextViewDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemTextViewDark_0_null_3,NEXUS_5,1.0,en].png index a40d484b80..30d4d8b3f7 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemTextViewDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemTextViewDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a14f96fc1119481ca8e7336ac0a65cb831a2bfff3e8e43270b0da8844f419f0e -size 7982 +oid sha256:499df8785b50d0bd1d5466b8a5b65ab1a8eb358f0c1341ad5956f5d1931859ed +size 7987 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemTextViewDark_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemTextViewDark_0_null_5,NEXUS_5,1.0,en].png index 4f4adf041d..95464be951 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemTextViewDark_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemTextViewDark_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c9caf6d9b49cf7eeaa41025617a7cc5b1d89bbd7468f7ecbfc0cac73ca4a04cc -size 7452 +oid sha256:021d867d665e0fa77aa10a85e734e4a9416b96d627b21ce462f0e327c5e58333 +size 7392 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_0,NEXUS_5,1.0,en].png index 923bbeea49..5ff17ba18a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c196f9cb2da2366e4e67d59012f61c5f50a5775475230c3a0cbc8d823ba53dcd -size 63317 +oid sha256:5d1a1361432b343ef1bacc7e95bf1c4b50f9eab2e1bd3ab80024db4994f62508 +size 63028 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_1,NEXUS_5,1.0,en].png index b59ac27461..b7c334bef0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:59773d8a5435a37b3d47bf0c41412299b0b277af4be7a1a25ccb33b4b60a32db -size 65397 +oid sha256:d573380414ffbabcb509bc9ae8e34f155daae61edf5c3c406d20eec929cc91a9 +size 65158 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_2,NEXUS_5,1.0,en].png index c586722f7b..d07e5c3c1f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ee692fa3f3dbe4500cff084526a4537fef6444440c78f63a03d990a6a027f794 -size 69844 +oid sha256:be16428b678680bf888d33beb07377faba36515c2d9aa0632c089f32330185ce +size 69640 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_3,NEXUS_5,1.0,en].png index b518541c41..784f05fd57 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0b8155faa2599615048193667f540664c7185ac7b6a9159afdc14dfb6286d62e -size 71826 +oid sha256:d220bc3af69c6e576b639bb98c9696cee71232caae5e164cc2b306821a2cd4c1 +size 71603 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_0,NEXUS_5,1.0,en].png index 7cc47ddfae..372883de77 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:771343ea6a9d83160284b3a9248f744c68ab25c2ad64817269c3628a5ca67972 -size 62319 +oid sha256:c6dd7c3eff7191c6ca0232fa467ac2ac723c81d7c8fdc60653ec49e2427990e3 +size 62067 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_1,NEXUS_5,1.0,en].png index 903f4965cc..6bc82b809c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4663107c550f193aa9bb23b6bccf9229aed5ad30c380ce6b9a326e6a3fe5def7 -size 64854 +oid sha256:6dc81ed6a87958bd35754941d3a767b40f331822402db88fc21058bafae23628 +size 64681 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_2,NEXUS_5,1.0,en].png index 60029246ea..b280c416b8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ca51c27cb553709458343bf16d8402a55eb1b7187b4b85191c3318f5b88c29db -size 69312 +oid sha256:c3169984328bc0ff82f602b6b136bbafbe8361df269bbb6169ffffd803086d8e +size 69016 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_3,NEXUS_5,1.0,en].png index 08348ad401..4415a6052e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b0a825d8090414c617780bf2d7332b8e80e5e4de066cd117c53f5e90cae8d4f6 -size 72112 +oid sha256:3e5905aabbe47b08864e6f6f3992b9e3a42d5b36bc101b53835ad91e7d7fd5f5 +size 71691 From a4c9c55a8b2ef0bdddce08cdff8fa3ba43b0bd35 Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Tue, 12 Sep 2023 13:35:26 +0200 Subject: [PATCH 109/234] New icons for Poll and Poll end (#1280) Now both icons come from our designs and have a consistent size and padding (previously the poll one was coming from the material icons). --- .../actionlist/model/TimelineItemAction.kt | 2 +- .../features/poll/api/PollContentView.kt | 6 ++-- .../libraries/designsystem/VectorIcons.kt | 3 +- .../src/main/res/drawable/ic_poll.xml | 9 ++++++ .../src/main/res/drawable/ic_poll_end.xml | 31 ++++++++++++------- ...etContent-D-0_1_null_8,NEXUS_5,1.0,en].png | 4 +-- ...etContent-N-0_2_null_8,NEXUS_5,1.0,en].png | 4 +-- ...ollView-D-13_14_null_0,NEXUS_5,1.0,en].png | 4 +-- ...ollView-D-13_14_null_1,NEXUS_5,1.0,en].png | 4 +-- ...ollView-N-13_15_null_0,NEXUS_5,1.0,en].png | 4 +-- ...ollView-N-13_15_null_1,NEXUS_5,1.0,en].png | 4 +-- ...tTimestampBelow_0_null,NEXUS_5,1.0,en].png | 4 +-- ...ntDisclosed-D-1_1_null,NEXUS_5,1.0,en].png | 4 +-- ...ntDisclosed-N-1_2_null,NEXUS_5,1.0,en].png | 4 +-- ...ontentEnded-D-2_2_null,NEXUS_5,1.0,en].png | 4 +-- ...ontentEnded-N-2_3_null,NEXUS_5,1.0,en].png | 4 +-- ...Undisclosed-D-0_0_null,NEXUS_5,1.0,en].png | 4 +-- ...Undisclosed-N-0_1_null,NEXUS_5,1.0,en].png | 4 +-- 18 files changed, 59 insertions(+), 44 deletions(-) create mode 100644 libraries/designsystem/src/main/res/drawable/ic_poll.xml diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt index 8dc48f892e..7a8a1fa1db 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt @@ -35,5 +35,5 @@ sealed class TimelineItemAction( data object Edit : TimelineItemAction(CommonStrings.action_edit, VectorIcons.Edit) data object Developer : TimelineItemAction(CommonStrings.action_view_source, VectorIcons.DeveloperMode) data object ReportContent : TimelineItemAction(CommonStrings.action_report_content, VectorIcons.ReportContent, destructive = true) - data object EndPoll : TimelineItemAction(CommonStrings.action_end_poll, VectorIcons.EndPoll) + data object EndPoll : TimelineItemAction(CommonStrings.action_end_poll, VectorIcons.PollEnd) } diff --git a/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollContentView.kt b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollContentView.kt index 9301630b73..7e03d7a46e 100644 --- a/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollContentView.kt +++ b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollContentView.kt @@ -24,8 +24,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.selection.selectableGroup -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Poll import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -86,13 +84,13 @@ internal fun PollTitle( ) { if (isPollEnded) { Icon( - resourceId = VectorIcons.EndPoll, + resourceId = VectorIcons.PollEnd, contentDescription = null, modifier = Modifier.size(22.dp) ) } else { Icon( - imageVector = Icons.Outlined.Poll, + resourceId = VectorIcons.Poll, contentDescription = null, modifier = Modifier.size(22.dp) ) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt index cd1b408a99..20ebb85615 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt @@ -27,7 +27,8 @@ object VectorIcons { val ReportContent = R.drawable.ic_report_content val Groups = R.drawable.ic_groups val Share = R.drawable.ic_share - val EndPoll = R.drawable.ic_poll_end + val Poll = R.drawable.ic_poll + val PollEnd = R.drawable.ic_poll_end val Bold = R.drawable.ic_bold val BulletList = R.drawable.ic_bullet_list val CodeBlock = R.drawable.ic_code_block diff --git a/libraries/designsystem/src/main/res/drawable/ic_poll.xml b/libraries/designsystem/src/main/res/drawable/ic_poll.xml new file mode 100644 index 0000000000..6167653c82 --- /dev/null +++ b/libraries/designsystem/src/main/res/drawable/ic_poll.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/designsystem/src/main/res/drawable/ic_poll_end.xml b/libraries/designsystem/src/main/res/drawable/ic_poll_end.xml index 21d895e613..86c169cf41 100644 --- a/libraries/designsystem/src/main/res/drawable/ic_poll_end.xml +++ b/libraries/designsystem/src/main/res/drawable/ic_poll_end.xml @@ -1,14 +1,21 @@ - - + android:width="22dp" + android:height="22dp" + android:viewportWidth="22" + android:viewportHeight="22"> + + + + + diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_8,NEXUS_5,1.0,en].png index a008402361..c94ec815dd 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:20847fc7ab9e27171ae0ae37a95e7524aac0bd2479ff5b8b1130a5bc26dbb3e6 -size 28232 +oid sha256:d6a15254ca331bc6d8ec6a6408b0a5a3d4fd26961e7c6025805ec7841a22e017 +size 28313 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_8,NEXUS_5,1.0,en].png index ceec7820f1..3152bb0b19 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a62ebcf0024a1876984c936c29037cf04e2e02aefb3bea461030c092fbde2937 -size 26983 +oid sha256:e0355effa8376bc88f9474f4d0e7f595708702f4fda5e39becf811fef10b0d16 +size 27081 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_0,NEXUS_5,1.0,en].png index 9bd8087f0c..84f2abf39d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:15d14bf99af3cd0433870ebd6032d9bf4a45196e2ef1df7184cc55859a704dee -size 49008 +oid sha256:339e5f22a47e29b6f681ac169be3b65568b7fa5d1197b0e81fb68bef639ae5c2 +size 49033 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_1,NEXUS_5,1.0,en].png index 170f3d997a..0fbe7c6581 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6e47fc219bbd63b76d01a5e50c3e4c6b1b0a8b4ec40b08b13271d0b2673d8d5e -size 50932 +oid sha256:c439f506df4eaed4ad35148d1734630a89b0de3ccb097864b7ff853c679772c1 +size 50964 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_0,NEXUS_5,1.0,en].png index cb9d6334b0..dacffc90ea 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cacb91ffca97f21bbc19b29525813f58fc8017a858aa28ccd4e620b70a8cd9ca -size 46119 +oid sha256:f85799360092c7e2d02f64f32668279c4e0c39bca3d45c9db13d503ddb7bf753 +size 46162 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_1,NEXUS_5,1.0,en].png index ec2787d842..40e0174919 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f1c14a23ee598ece6843a68d3ca0b1d1f725f53174bd493e27c6137de70c508 -size 48296 +oid sha256:b05475d6509b15fcffeae54bdebf434a529a99af5173c48992677a88b654f3eb +size 48336 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventTimestampBelow_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventTimestampBelow_0_null,NEXUS_5,1.0,en].png index 6f6070772e..4ba636ed5c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventTimestampBelow_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventTimestampBelow_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fe0a95b6c94668709c75052feec2953d310b8bcfda42758b2898e28b384ce193 -size 56189 +oid sha256:bdcc950b0ce924a73ae742f0bb3fc7279de46f36ba01d377822a2a14b6f90343 +size 56239 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-D-1_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-D-1_1_null,NEXUS_5,1.0,en].png index 9bd8087f0c..84f2abf39d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-D-1_1_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-D-1_1_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:15d14bf99af3cd0433870ebd6032d9bf4a45196e2ef1df7184cc55859a704dee -size 49008 +oid sha256:339e5f22a47e29b6f681ac169be3b65568b7fa5d1197b0e81fb68bef639ae5c2 +size 49033 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-N-1_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-N-1_2_null,NEXUS_5,1.0,en].png index cb9d6334b0..dacffc90ea 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-N-1_2_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-N-1_2_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cacb91ffca97f21bbc19b29525813f58fc8017a858aa28ccd4e620b70a8cd9ca -size 46119 +oid sha256:f85799360092c7e2d02f64f32668279c4e0c39bca3d45c9db13d503ddb7bf753 +size 46162 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-D-2_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-D-2_2_null,NEXUS_5,1.0,en].png index 140c07a3ca..e700e58b7e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-D-2_2_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-D-2_2_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:434c4f6dc4ee4c66291eca2ff1a8ab2471aaf521dbbf0d32f53f277ea6519c07 -size 49107 +oid sha256:85fbaa916a38c9b75a527dc3fddded9e9d06a98ab20f9f3eb74596c24ba4b5b7 +size 49105 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-N-2_3_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-N-2_3_null,NEXUS_5,1.0,en].png index 0b32e49a00..26b2576508 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-N-2_3_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-N-2_3_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:63685437c43543115e8f509919ef179d70a620c012c8a46ebf6682dcfe9820c6 -size 45890 +oid sha256:cee9e96cfefa6f84fb924857a92fd4ba04bbd196d94a6345bb821ff769fbd56d +size 45889 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-D-0_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-D-0_0_null,NEXUS_5,1.0,en].png index 7319bf6694..41f7fba3e5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-D-0_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-D-0_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2264139761f7fe3977ece3c9a7d949ac51223dd209497b7b311987cba3e5a069 -size 47154 +oid sha256:53cffdc5ea12b16db3f87ab12c28fede82ce5a744c222c9f19e5c35ef751c583 +size 47179 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-N-0_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-N-0_1_null,NEXUS_5,1.0,en].png index 3a129abb0b..cb51eea54a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-N-0_1_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-N-0_1_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f3ff35998ce8558b5a7af84e378bee039e36099084b357fffccf329a4983b035 -size 43551 +oid sha256:96d696014b24a2a222ba331d754d6048063a9ec573158edc41ded92ed588b60d +size 43593 From 00d21e24e548f2e11a957754de1df712f494c4f7 Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Tue, 12 Sep 2023 14:01:33 +0200 Subject: [PATCH 110/234] Update analytics sdk to v0.8.0 (#1284) Integrates a few breaking changes introducing a `messageType` Composer prop: - Sends `messageType` = Text by default in composer. - Refactors existing location analytics to send the appropriate `messageType`. --- .../features/location/impl/send/SendLocationPresenter.kt | 8 +++----- .../location/impl/send/SendLocationPresenterTest.kt | 9 +++------ .../impl/messagecomposer/MessageComposerPresenter.kt | 2 +- gradle/libs.versions.toml | 2 +- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationPresenter.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationPresenter.kt index 2ea7dc20e1..94af55c01c 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationPresenter.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationPresenter.kt @@ -26,10 +26,10 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import im.vector.app.features.analytics.plan.Composer import io.element.android.features.location.impl.common.MapDefaults +import io.element.android.features.location.impl.common.actions.LocationActions import io.element.android.features.location.impl.common.permissions.PermissionsEvents import io.element.android.features.location.impl.common.permissions.PermissionsPresenter import io.element.android.features.location.impl.common.permissions.PermissionsState -import io.element.android.features.location.impl.common.actions.LocationActions import io.element.android.features.messages.api.MessageComposerContext import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.meta.BuildMeta @@ -119,9 +119,8 @@ class SendLocationPresenter @Inject constructor( Composer( inThread = messageComposerContext.composerMode.inThread, isEditing = messageComposerContext.composerMode.isEditing, - isLocation = true, isReply = messageComposerContext.composerMode.isReply, - locationType = Composer.LocationType.PinDrop, + messageType = Composer.MessageType.LocationPin, ) ) } @@ -138,9 +137,8 @@ class SendLocationPresenter @Inject constructor( Composer( inThread = messageComposerContext.composerMode.inThread, isEditing = messageComposerContext.composerMode.isEditing, - isLocation = true, isReply = messageComposerContext.composerMode.isReply, - locationType = Composer.LocationType.MyLocation, + messageType = Composer.MessageType.LocationUser, ) ) } diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/SendLocationPresenterTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/SendLocationPresenterTest.kt index 15afa48b26..af31f1bfeb 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/SendLocationPresenterTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/SendLocationPresenterTest.kt @@ -308,9 +308,8 @@ class SendLocationPresenterTest { Composer( inThread = false, isEditing = false, - isLocation = true, isReply = false, - locationType = Composer.LocationType.MyLocation, + messageType = Composer.MessageType.LocationUser, ) ) } @@ -365,9 +364,8 @@ class SendLocationPresenterTest { Composer( inThread = false, isEditing = false, - isLocation = true, isReply = false, - locationType = Composer.LocationType.PinDrop, + messageType = Composer.MessageType.LocationPin, ) ) } @@ -412,9 +410,8 @@ class SendLocationPresenterTest { Composer( inThread = false, isEditing = true, - isLocation = true, isReply = false, - locationType = Composer.LocationType.PinDrop, + messageType = Composer.MessageType.LocationPin, ) ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt index 3c3ebc2db9..215826dade 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt @@ -153,7 +153,7 @@ class MessageComposerPresenter @Inject constructor( inThread = messageComposerContext.composerMode.inThread, isEditing = messageComposerContext.composerMode.isEditing, isReply = messageComposerContext.composerMode.isReply, - isLocation = false, + messageType = Composer.MessageType.Text, ) ) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b281ec73df..d172bc120d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -169,7 +169,7 @@ maplibre_annotation = "org.maplibre.gl:android-plugin-annotation-v9:2.0.1" # Analytics posthog = "com.posthog.android:posthog:2.0.3" sentry = "io.sentry:sentry-android:6.29.0" -matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:42b2faa417c1e95f430bf8f6e379adba25ad5ef8" +matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:e9cd9adaf18cec52ed851395eb84358b4f9b8d7f" # Emojibase matrix_emojibase_bindings = "io.element.android:emojibase-bindings:1.1.3" From fb9d08bab090973f74c765838c1b240039bfad58 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 12 Sep 2023 14:02:59 +0200 Subject: [PATCH 111/234] [Compound] Improve Bloom (#1272) * Improve Bloom: - Simplify bloom blurred image. - Display very subtle bloom for avatars with soft colors. * Improve caching and performance --------- Co-authored-by: ElementBot --- .../impl/components/RoomListTopBar.kt | 8 ++- .../designsystem/components/Bloom.kt | 54 ++++++++++++++----- ...etContent-D-0_1_null_3,NEXUS_5,1.0,en].png | 4 +- ...etContent-N-0_2_null_3,NEXUS_5,1.0,en].png | 4 +- ...ImageViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...ImageViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 +- ...ImageViewDark_0_null_2,NEXUS_5,1.0,en].png | 4 +- ...mageViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...mageViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 +- ...mageViewLight_0_null_2,NEXUS_5,1.0,en].png | 4 +- ...VideoViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...VideoViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 +- ...VideoViewDark_0_null_2,NEXUS_5,1.0,en].png | 4 +- ...ideoViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...ideoViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 +- ...ideoViewLight_0_null_2,NEXUS_5,1.0,en].png | 4 +- ...temEventRowDark_0_null,NEXUS_5,1.0,en].png | 4 +- ...emEventRowLight_0_null,NEXUS_5,1.0,en].png | 4 +- ...owWithReplyDark_0_null,NEXUS_5,1.0,en].png | 4 +- ...wWithReplyLight_0_null,NEXUS_5,1.0,en].png | 4 +- ...elineView-D-2_3_null_2,NEXUS_5,1.0,en].png | 4 +- ...elineView-D-2_3_null_3,NEXUS_5,1.0,en].png | 4 +- ...elineView-N-2_4_null_2,NEXUS_5,1.0,en].png | 4 +- ...elineView-N-2_4_null_3,NEXUS_5,1.0,en].png | 4 +- ...mListTopBarDark_0_null,NEXUS_5,1.0,en].png | 4 +- ...ListTopBarLight_0_null,NEXUS_5,1.0,en].png | 4 +- ...mListViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...mListViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 +- ...mListViewDark_0_null_2,NEXUS_5,1.0,en].png | 4 +- ...mListViewDark_0_null_3,NEXUS_5,1.0,en].png | 4 +- ...mListViewDark_0_null_4,NEXUS_5,1.0,en].png | 4 +- ...mListViewDark_0_null_5,NEXUS_5,1.0,en].png | 4 +- ...ListViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...ListViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 +- ...ListViewLight_0_null_2,NEXUS_5,1.0,en].png | 4 +- ...ListViewLight_0_null_3,NEXUS_5,1.0,en].png | 4 +- ...ListViewLight_0_null_4,NEXUS_5,1.0,en].png | 4 +- ...ListViewLight_0_null_5,NEXUS_5,1.0,en].png | 4 +- ...ts_null_Bloom-N_1_null,NEXUS_5,1.0,en].png | 4 +- ...oomInitials-N_1_null_0,NEXUS_5,1.0,en].png | 4 +- ...oomInitials-N_1_null_1,NEXUS_5,1.0,en].png | 4 +- ...oomInitials-N_1_null_2,NEXUS_5,1.0,en].png | 4 +- ...oomInitials-N_1_null_3,NEXUS_5,1.0,en].png | 4 +- ...oomInitials-N_1_null_4,NEXUS_5,1.0,en].png | 4 +- ...oomInitials-N_1_null_5,NEXUS_5,1.0,en].png | 4 +- ...oomInitials-N_1_null_6,NEXUS_5,1.0,en].png | 4 +- ...oomInitials-N_1_null_7,NEXUS_5,1.0,en].png | 4 +- ...BloomInitials_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...BloomInitials_0_null_1,NEXUS_5,1.0,en].png | 4 +- ...BloomInitials_0_null_2,NEXUS_5,1.0,en].png | 4 +- ...BloomInitials_0_null_3,NEXUS_5,1.0,en].png | 4 +- ...BloomInitials_0_null_4,NEXUS_5,1.0,en].png | 4 +- ...BloomInitials_0_null_5,NEXUS_5,1.0,en].png | 4 +- ...BloomInitials_0_null_6,NEXUS_5,1.0,en].png | 4 +- ...BloomInitials_0_null_7,NEXUS_5,1.0,en].png | 4 +- ...ull_Bloom_Bloom_0_null,NEXUS_5,1.0,en].png | 2 +- ...mposerReply-D-3_4_null,NEXUS_5,1.0,en].png | 4 +- ...mposerReply-N-3_5_null,NEXUS_5,1.0,en].png | 4 +- 58 files changed, 160 insertions(+), 124 deletions(-) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListTopBar.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListTopBar.kt index a5113d33ce..508385dd84 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListTopBar.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListTopBar.kt @@ -158,13 +158,19 @@ private fun DefaultRoomListTopBar( .nestedScroll(scrollBehavior.nestedScrollConnection) .avatarBloom( avatarData = avatarData, - background = ElementTheme.materialColors.background, + background = if (ElementTheme.isLightTheme) { + // Workaround to display a very subtle bloom for avatars with very soft colors + Color(0xFFF9F9F9) + } else { + ElementTheme.materialColors.background + }, blurSize = DpSize(avatarBloomSize, avatarBloomSize), offset = DpOffset(24.dp, 24.dp + statusBarPadding), clipToSize = if (appBarHeight > 0) DpSize( avatarBloomSize, appBarHeight.toDp() ) else DpSize.Unspecified, + bottomSoftEdgeColor = ElementTheme.materialColors.background, bottomSoftEdgeAlpha = 1f - collapsedFraction, alpha = if (areSearchResultsDisplayed) 0f else 1f, ) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/Bloom.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/Bloom.kt index 5e1d7116ba..2a178af000 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/Bloom.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/Bloom.kt @@ -45,6 +45,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -96,8 +97,10 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.isSpecified import androidx.compose.ui.unit.toOffset import androidx.compose.ui.unit.toSize -import coil.compose.rememberAsyncImagePainter +import coil.imageLoader +import coil.request.DefaultRequestOptions import coil.request.ImageRequest +import coil.size.Size import com.airbnb.android.showkase.annotation.ShowkaseComposable import com.vanniktech.blurhash.BlurHash import io.element.android.libraries.designsystem.R @@ -114,6 +117,8 @@ import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.theme.ElementTheme import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext import kotlin.math.max import kotlin.math.roundToInt @@ -125,7 +130,7 @@ object BloomDefaults { * Number of components to use with BlurHash to generate the blur effect. * Larger values mean more detailed blurs. */ - const val HASH_COMPONENTS = 8 + const val HASH_COMPONENTS = 5 /** Default bloom layers. */ @Composable @@ -159,6 +164,7 @@ data class BloomLayer( * @param offset The offset to use for the bloom effect. If not specified the bloom effect will be centered on the component. * @param clipToSize The size to use for clipping the bloom effect. If not specified the bloom effect will not be clipped. * @param layerConfiguration The configuration for the bloom layers. If not specified the default layers configuration will be used. + * @param bottomSoftEdgeColor The color to use for the bottom soft edge. If not specified the [background] color will be used. * @param bottomSoftEdgeHeight The height of the bottom soft edge. If not specified the bottom soft edge will not be drawn. * @param bottomSoftEdgeAlpha The alpha value to apply to the bottom soft edge. * @param alpha The alpha value to apply to the bloom effect. @@ -170,6 +176,7 @@ fun Modifier.bloom( offset: DpOffset = DpOffset.Unspecified, clipToSize: DpSize = DpSize.Unspecified, layerConfiguration: ImmutableList? = null, + bottomSoftEdgeColor: Color = background, bottomSoftEdgeHeight: Dp = 40.dp, @FloatRange(from = 0.0, to = 1.0) bottomSoftEdgeAlpha: Float = 1.0f, @@ -238,7 +245,7 @@ fun Modifier.bloom( val bottomEdgeGradient = LinearGradientShader( from = IntOffset(0, clipToPixelSize.height - bottomSoftEdgeHeightPixels).toOffset(), to = IntOffset(0, clipToPixelSize.height).toOffset(), - listOf(Color.Transparent, background), + listOf(Color.Transparent, bottomSoftEdgeColor), listOf(0f, 1f) ) val bottomEdgeGradientBrush = ShaderBrush(bottomEdgeGradient) @@ -297,6 +304,7 @@ fun Modifier.bloom( * @param blurSize The size of the bloom effect. If not specified the bloom effect will be the size of the component. * @param offset The offset to use for the bloom effect. If not specified the bloom effect will be centered on the component. * @param clipToSize The size to use for clipping the bloom effect. If not specified the bloom effect will not be clipped. + * @param bottomSoftEdgeColor The color to use for the bottom soft edge. If not specified the [background] color will be used. * @param bottomSoftEdgeHeight The height of the bottom soft edge. If not specified the bottom soft edge will not be drawn. * @param bottomSoftEdgeAlpha The alpha value to apply to the bottom soft edge. * @param alpha The alpha value to apply to the bloom effect. @@ -307,6 +315,7 @@ fun Modifier.avatarBloom( blurSize: DpSize = DpSize.Unspecified, offset: DpOffset = DpOffset.Unspecified, clipToSize: DpSize = DpSize.Unspecified, + bottomSoftEdgeColor: Color = background, bottomSoftEdgeHeight: Dp = 40.dp, @FloatRange(from = 0.0, to = 1.0) bottomSoftEdgeAlpha: Float = 1.0f, @@ -317,21 +326,35 @@ fun Modifier.avatarBloom( if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return@composed this avatarData ?: return@composed this + // Request the avatar contents to use as the bloom source + val context = LocalContext.current + val density = LocalDensity.current if (avatarData.url != null) { - // Request the avatar contents to use as the bloom source - val painter = rememberAsyncImagePainter( - ImageRequest.Builder(LocalContext.current) + val painterRequest = remember(avatarData) { + ImageRequest.Builder(context) .data(avatarData) + // Allow cache and default dispatchers + .defaults(DefaultRequestOptions()) // Needed to be able to read pixels from the Bitmap for the hash .allowHardware(false) + // Reduce size so it loads faster for large avatars + .size(with(density) { Size(64.dp.roundToPx(), 64.dp.roundToPx()) }) .build() - ) - var blurHash by remember { mutableStateOf(null) } + } + // By making it saveable, we'll 'cache' the previous bloom effect until a new one is loaded + var blurHash by rememberSaveable(avatarData) { mutableStateOf(null) } LaunchedEffect(avatarData) { - val drawable = painter.imageLoader.execute(painter.request).drawable ?: return@LaunchedEffect - val bitmap = (drawable as? BitmapDrawable)?.bitmap ?: return@LaunchedEffect - blurHash = BlurHash.encode(bitmap, BloomDefaults.HASH_COMPONENTS, BloomDefaults.HASH_COMPONENTS) + withContext(Dispatchers.IO) { + val drawable = + context.imageLoader.execute(painterRequest).drawable ?: return@withContext + val bitmap = (drawable as? BitmapDrawable)?.bitmap ?: return@withContext + blurHash = BlurHash.encode( + bitmap, + BloomDefaults.HASH_COMPONENTS, + BloomDefaults.HASH_COMPONENTS + ) + } } bloom( @@ -363,6 +386,7 @@ fun Modifier.avatarBloom( blurSize = blurSize, offset = offset, clipToSize = clipToSize, + bottomSoftEdgeColor = bottomSoftEdgeColor, bottomSoftEdgeHeight = bottomSoftEdgeHeight, bottomSoftEdgeAlpha = bottomSoftEdgeAlpha, alpha = alpha, @@ -517,7 +541,13 @@ internal fun BloomInitialsPreview(@PreviewParameter(InitialsColorStateProvider:: modifier = Modifier.size(256.dp) .bloom( hash = hash, - background = ElementTheme.materialColors.background, + background = if (ElementTheme.isLightTheme) { + // Workaround to display a very subtle bloom for avatars with very soft colors + Color(0xFFF9F9F9) + } else { + ElementTheme.materialColors.background + }, + bottomSoftEdgeColor = ElementTheme.materialColors.background, blurSize = DpSize(256.dp, 256.dp), ), contentAlignment = Alignment.Center diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_3,NEXUS_5,1.0,en].png index 540f71b5a7..1f851222f4 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-D-0_1_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ee62a7f77e591d238878e72e3f2fbe489e8c4e8c6a5c121b16e120ad5c43836d -size 44185 +oid sha256:8421be9fe6518a4a610e561692352c28c63b1e588fae4f7617f6be94439852f2 +size 45078 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_3,NEXUS_5,1.0,en].png index cf7a8a2c81..8fae4446ea 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.actionlist_null_SheetContent-N-0_2_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d4bdf3944d30980e9bfd7cfffbabe2dac9861748cc3006e751bfd5cbf59c86db -size 42475 +oid sha256:4c30a6c0c7169044216a02dde5605d59fba9307499855ffc1fa0d3fcd1650f5e +size 43291 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_0,NEXUS_5,1.0,en].png index 7ff6d4dec6..affcb49660 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6c0485788c8776536a01613058ab001bad02a67519cf0cb4892505c7c3715fea -size 144681 +oid sha256:c40273c36eb1479f284e75fa91d4a75b1ae97edd0242dda37a2d4a8f10394928 +size 138700 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_1,NEXUS_5,1.0,en].png index 7dae7dddb0..cb4b57910b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b4a259f036e555fdc52ecc8f0c9578dae70ed677235fbfd344bc31cbabc76be5 -size 181478 +oid sha256:d7c47c713c74766c39d3b349d9e421ea588261e043105a5475cd8e68af782806 +size 185325 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_2,NEXUS_5,1.0,en].png index 00c4b05824..db705106e0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d5966cae164fed6a3a12c1e1dd940ae7b0601e4ba69d11f49d18740bdab8c520 -size 130130 +oid sha256:5d5479f3a6ea138b00c8f6a376cc4a67984385a087fb32bcdb764b2996e89402 +size 137137 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_0,NEXUS_5,1.0,en].png index 7ff6d4dec6..affcb49660 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6c0485788c8776536a01613058ab001bad02a67519cf0cb4892505c7c3715fea -size 144681 +oid sha256:c40273c36eb1479f284e75fa91d4a75b1ae97edd0242dda37a2d4a8f10394928 +size 138700 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_1,NEXUS_5,1.0,en].png index 7dae7dddb0..cb4b57910b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b4a259f036e555fdc52ecc8f0c9578dae70ed677235fbfd344bc31cbabc76be5 -size 181478 +oid sha256:d7c47c713c74766c39d3b349d9e421ea588261e043105a5475cd8e68af782806 +size 185325 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_2,NEXUS_5,1.0,en].png index a603a6cc61..db705106e0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemImageViewLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b8cb21e08faf31779111d78c2be1e4e68e6f3bc994b16c108bd654f13d39fa02 -size 130130 +oid sha256:5d5479f3a6ea138b00c8f6a376cc4a67984385a087fb32bcdb764b2996e89402 +size 137137 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_0,NEXUS_5,1.0,en].png index 0e6ff544a1..5361cd1a24 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f2782edd31f68b7aa27e0c35b29d7c84574326cb56c65394738357479d408f5f -size 144667 +oid sha256:06617cda0f93ce0ea26b2a77a243371cdaf4f9a2956d8159ecb7196f7f6fe082 +size 139282 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_1,NEXUS_5,1.0,en].png index b8b527778b..0e14867b04 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cd352f748e3fd08225aa714181fdc18d53e91a8c62f8e5e860b67ff5aaeb7b8e -size 181969 +oid sha256:55d2d11ba729a68b1b62e9a69c3308594839fdb3612ff3db59850f0b346c28da +size 186118 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_2,NEXUS_5,1.0,en].png index 6ee90c4b3a..da8a3d6499 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:43da903ec671dd1cb591396306ce8c057432ffa8c1bfce7a509f28576e82b530 -size 130337 +oid sha256:62c57a45c2cb1aac23fa0c3af44f90a5d7b9a1e1626ec49eb94a2c126f53f96d +size 137535 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_0,NEXUS_5,1.0,en].png index 0e6ff544a1..5361cd1a24 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f2782edd31f68b7aa27e0c35b29d7c84574326cb56c65394738357479d408f5f -size 144667 +oid sha256:06617cda0f93ce0ea26b2a77a243371cdaf4f9a2956d8159ecb7196f7f6fe082 +size 139282 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_1,NEXUS_5,1.0,en].png index b8b527778b..0e14867b04 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cd352f748e3fd08225aa714181fdc18d53e91a8c62f8e5e860b67ff5aaeb7b8e -size 181969 +oid sha256:55d2d11ba729a68b1b62e9a69c3308594839fdb3612ff3db59850f0b346c28da +size 186118 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_2,NEXUS_5,1.0,en].png index c4150178a1..da8a3d6499 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemVideoViewLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8141eaa257454258d2926df5ee970daf5ee165b774e4b948256b90e22a388d4c -size 130337 +oid sha256:62c57a45c2cb1aac23fa0c3af44f90a5d7b9a1e1626ec49eb94a2c126f53f96d +size 137535 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowDark_0_null,NEXUS_5,1.0,en].png index 5fd48ba7e6..722bd8c6a5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f95fbf1b51966c1c6b7b149c771f33400455d3c999b505e1aa65f0e3eb41c0ef -size 140928 +oid sha256:f0ad6895582183b697732ef032f89a6a0cad32106c9bbf30925c390dcab65ee6 +size 151752 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowLight_0_null,NEXUS_5,1.0,en].png index 3798fc1bc8..fb9457779e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowLight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowLight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e8d522eb99079792d010e053d488f78a95e91f5a1b614b9d512bd005f0df81cf -size 146976 +oid sha256:676b62ab782652c45a7267aac5df12943fd181bea48964d28dce664884ae4182 +size 156619 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyDark_0_null,NEXUS_5,1.0,en].png index 5bc3b72bec..c39b41db87 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eebf95f938f483da9b087eda86ae4a1baac594bc4b6f1f893d869b759679526c -size 123267 +oid sha256:b991a34a137d82ff4dedf48316a05ebbc008233984b11af70e64889a5fb5eda8 +size 127438 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyLight_0_null,NEXUS_5,1.0,en].png index 6e52c4b6d3..a6500ca748 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyLight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyLight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4875df98092a8ef8bd1c2fda8c4a038ae2830b9ffa57e4ab71859523f97c26c9 -size 128062 +oid sha256:43b6514716d18382c8962520928d9d2ff6d0f665b2471e8a24e5d2e44a25c88c +size 132295 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_2,NEXUS_5,1.0,en].png index 18e6545be9..307e6a7acf 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:30119e8fcb65e8cbf058191268f0d70633a62b160b9f49f71879272d0d076537 -size 241818 +oid sha256:0d7bc773e70c57226840b30675f14a7fd99026100d61f48eeab64fb55d43f7c6 +size 230426 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_3,NEXUS_5,1.0,en].png index cc3ad6b40e..4d97155b83 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-D-2_3_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:73ca2b85c0f1f8f13cd3a0aae9d394116a460aa2c511ca1f2672a356eee496d2 -size 241553 +oid sha256:87f93b06f658352e7d97617c28dc0a4bd7454263fd402abfc2676f548c41d6b2 +size 231314 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_2,NEXUS_5,1.0,en].png index 7fa7a38d87..946096b37e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ff7953fabf75b346e61bd4335f3753331b498dbe5f17f9af3aad8a6a1ce051cd -size 239490 +oid sha256:f13fbb9bc776fa230b69c41e3faab659c52083d4e4f737f84b472c966f42c8dd +size 229746 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_3,NEXUS_5,1.0,en].png index 45eafc5baa..419a96a180 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline_null_TimelineView-N-2_4_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e262b1128df681c9a98bbefe426a891d02e0500646319f2e1756c1b5c93f2d23 -size 239303 +oid sha256:d312c80758e940b368e0b9eb2d41efb55c158691164bfde3456d7540080e46a9 +size 230651 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarDark_0_null,NEXUS_5,1.0,en].png index 434058e988..3c87d03c4f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:51931b01aa27677c8d29a79bf92f4e8b48fc2be05e80fdabedfb9026dcbd8899 -size 31634 +oid sha256:b967a0dc3bd9a466790503dd49c2fff6ce70156b51603022916aa9db3fc5c372 +size 29976 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarLight_0_null,NEXUS_5,1.0,en].png index 70b7534b8c..0d8fd2c681 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarLight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_DefaultRoomListTopBarLight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5441c89fc077720b52479d4daf1ebd5fe5b98b63f35141a550dac228fe1c649f -size 10617 +oid sha256:8ec89c6b12c4eb1f8059d9d0d183f6635f5647393134c858720f3ef72b8c4c36 +size 36837 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_0,NEXUS_5,1.0,en].png index c6ce4ced6b..dc92a3a311 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9156202a9f621b75cff3ca45aac33d72a938620049948828fc34aab3b9e0980d -size 55382 +oid sha256:71c2ac04d7fb904b648fc383f430e3b8a4003e93e5964b60eb545248186cd8dc +size 53912 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_1,NEXUS_5,1.0,en].png index 21a3ec4a13..b8c2394645 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0c7ee3acbf4653e49633e68f896fe0f5f73591c2cbc889204cc244b319996e0d -size 78348 +oid sha256:3277b51e1a7153487e2d9764d5c495419f8df7fa635574302237ebf3549a4b3c +size 76821 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_2,NEXUS_5,1.0,en].png index c6ce4ced6b..dc92a3a311 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9156202a9f621b75cff3ca45aac33d72a938620049948828fc34aab3b9e0980d -size 55382 +oid sha256:71c2ac04d7fb904b648fc383f430e3b8a4003e93e5964b60eb545248186cd8dc +size 53912 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_3,NEXUS_5,1.0,en].png index 3cc44b882b..d6981eb457 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:55800431dfe4453fa3c11f97bfae53ceaf95f1c18b72bcc8620b8c3295b26b27 -size 56388 +oid sha256:0104fa9aca0b3d25f06225f54529e88d78f7d42aabd102b2c065c774427bbf3b +size 55038 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_4,NEXUS_5,1.0,en].png index 0f8a496726..efe91c2960 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b2d288f46eb76b8a71a8c1a2ec60ba7c3b8b1bf2a92be9d8daf33c06b3a0f126 -size 56593 +oid sha256:c2bf9d1733fc7230816cbcfbcef6780d34e687a064c289f2f9d651cf3047a1bd +size 55107 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_5,NEXUS_5,1.0,en].png index 0306387553..f280592154 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewDark_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c0e5bc6abe96bff50960c5ace2c4eccd5aabdd9f3ccd015fae867b4c3bc2b423 -size 56902 +oid sha256:a3cdb5de68791a0e5425ff9a29eaa8c1dc09aea9448211b9ad32f136bf11ace7 +size 55418 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_0,NEXUS_5,1.0,en].png index 6b5e25ce2f..aa486dbf8e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1f385e70f3a8bda7c0c2f7c090ba665575239299472c0fbd62f2821783ceb065 -size 39016 +oid sha256:3a9958e430c07445b9dcdc31a483c7925e2bd2a0d3fbbaf1ee5482051e2afe51 +size 65488 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_1,NEXUS_5,1.0,en].png index c0b73d2764..4ae4e14d2e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4bdb22d629e4bc3273aac4944802d1c91b43065858f4f4cc90052bd78ae6dd89 -size 62998 +oid sha256:c238218a16f7dc5c25125177434a8397821d5881971dd0404b9d79b7b181a592 +size 89294 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_2,NEXUS_5,1.0,en].png index 6b5e25ce2f..aa486dbf8e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1f385e70f3a8bda7c0c2f7c090ba665575239299472c0fbd62f2821783ceb065 -size 39016 +oid sha256:3a9958e430c07445b9dcdc31a483c7925e2bd2a0d3fbbaf1ee5482051e2afe51 +size 65488 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_3,NEXUS_5,1.0,en].png index 8fe1fefb5d..b12ac33325 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8ec1d951c96737ff8c5b401ef7c3af944f76be69348559401e40a12f60d5d459 -size 40807 +oid sha256:8176884d48589815521a35465f564858b4082b523f905e8d4cf7cbc96e25ac5e +size 65496 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_4,NEXUS_5,1.0,en].png index c0550bff56..1f5a18bf95 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ef7d9c31a72334294e93c67af1ca068ddff0062ae909ee8b682f0117c5c0ab6c -size 40331 +oid sha256:86f43007158129ed8e4a637df2db4044bdeb9d504e2a5c40da957bedea9ff395 +size 66618 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_5,NEXUS_5,1.0,en].png index 340f3d07c3..f8847daf13 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_null_RoomListViewLight_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:54ebfc606c04f37ed72edf5e9168a55628b59e69ea8a03cc3925cf25ca807195 -size 40695 +oid sha256:4543927c7e26cd464d28d3fe4dffda79479bcc8835d82088863031775bf6262e +size 67004 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom-N_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom-N_1_null,NEXUS_5,1.0,en].png index 42af4e3ccb..2c9be4925e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom-N_1_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom-N_1_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3bd86a694456603dce070a7bef0646e553cefdb365f81c9d835b28d6b2521950 -size 71026 +oid sha256:0a2f25931e9de2edbcc29d149fcb656683d1ff30757b9acde43e058f214d8afc +size 70873 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_0,NEXUS_5,1.0,en].png index 622b4080c5..a6024a3965 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:67be26f120cbce266651737206a5f444b9a0605a4528cea30971f4629b340501 -size 85653 +oid sha256:52d6fc6f88ce1e80dfe48ad83476e70afa5b5499ec24e8a94bbbc4b0e611e16d +size 76231 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_1,NEXUS_5,1.0,en].png index 2006811bc7..51aed9c9e7 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7142834262eb7db1909a5a48621979cb1a2ee00bc3b70de08e90523f53083e2d -size 85294 +oid sha256:4611148bcc9140bf40a63859ec88bac212a9774d81a5fe5abcfea9afec4192bf +size 75130 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_2,NEXUS_5,1.0,en].png index 637c2b6594..0860041efc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3424334cf7831701633ebe3b865a5696d6843c41acc372a6dcddadaaa371160f -size 83088 +oid sha256:39473b8fb90fcef316df257c4b3a45aa9c441199ef169b275e660d58d7fae52b +size 72606 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_3,NEXUS_5,1.0,en].png index 474bb5ca7a..b5b50230ac 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0e5583fd71bfe7ae518b4b90c3d3b00f1a65829dc015c6384ddd1a560ca77bdb -size 88567 +oid sha256:572db9d4c1796ec37e113907d5c13728cb87ce9959d94bb9396d7ea38914e52b +size 76355 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_4,NEXUS_5,1.0,en].png index a69eca99b4..c7f31854cb 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:88902f2d5512e22e1f5cd50d0628c7f968a0ee9e88b16a9d0d55fd2e11aefcba -size 85255 +oid sha256:6ca9d811ba70d8642e4831a1d62b94960c79fb28f93a3c36d67d2d67c1b376fc +size 74706 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_5,NEXUS_5,1.0,en].png index 07783dd2d7..81a543bd06 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a55cef72cf73e76104b74d55fe0abe92efa60e094116d871686fc4f525ca3649 -size 84298 +oid sha256:2319d9245e6f218f0b77d419d99ba101eda112184fc70729633006da0a4ee03d +size 74372 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_6,NEXUS_5,1.0,en].png index 97b62022c8..781cf6f3a6 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:70919d061d76126b09642e2d0f1b41b3d0b6a4cff68f68c6bd2e43d141732dd3 -size 87805 +oid sha256:6131175dabf7e1835856d37c37f8cdacaaa7294b44d4676a0bd4d32d4d2a1337 +size 79118 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_7,NEXUS_5,1.0,en].png index 8c93c67eb8..9f56ea678a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_BloomInitials-N_1_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1b62cd8043e21bed0a323d657f79605aa9a0ad3fae632387d175fdd764baf8ce -size 81507 +oid sha256:ce7f7219bd9027f0e6f3d8b44a4170b1e058c549cc143fbf63d67eab3e0eee2b +size 69351 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_0,NEXUS_5,1.0,en].png index 5df89eca37..d06c97ace6 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aafacbe3b1d14fdb11144d65148a24400fe964c4cd880796f8cc829abf37ae05 -size 5294 +oid sha256:3bf9d2e16fa86ec87e38fd82ecde90176542057d58729837d8aee73eb4828d12 +size 63936 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_1,NEXUS_5,1.0,en].png index c40dfa4088..f0e507f655 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:30bb9d0a709868ff29803e45265069aad6e75ea2e65cdd8524b83a490a666831 -size 5272 +oid sha256:e6575825152b070f8c2f6abe5ab89f5d1426d76df908638f3934c217193f1aac +size 58297 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_2,NEXUS_5,1.0,en].png index 553e8c904c..4f5be56d3f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3c56746d71fa25bf610f041b6c72e4559282407808bedbcdcc3c71a4497b3244 -size 5417 +oid sha256:17d225fbb3e9d7f1a954c0bc94b94cc1d7f131d226347b32c30940ba03991154 +size 67928 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_3,NEXUS_5,1.0,en].png index 29ceb833be..cd121a5eb5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8be31e6a338f76e28550062911766dab5e4744e3e514f1348636100885ac1fe7 -size 5310 +oid sha256:1f05a11dcd4174a1784d6c7fcd32154a1064d0a3369b18c857f051ef72c09943 +size 64470 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_4,NEXUS_5,1.0,en].png index 9cb6b0bb87..053b94e8a0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:813856d48fdb7b168b5cd662113a54dad9286b5f4191379471866ef6eda55e84 -size 5336 +oid sha256:1e6b22c6a7acbdbc77ebad06831318467ad40bdfbe8c56a0a81e8e9d69de4ff0 +size 66145 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_5,NEXUS_5,1.0,en].png index 7faff66c03..a51c3b1758 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:83adb2ece84370f3f7249765b391ca30dcb5ba9a2ceb04872bbb7f66101890a7 -size 5340 +oid sha256:29fd768d347c14c0e9f99de9e2c4e341f76850b8447ccd30fb240590bc8cd706 +size 68885 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_6,NEXUS_5,1.0,en].png index 888d88b06c..5328ba5fe0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a71d6d556b72e3be69f0a9902771066259123f002f7fd35652a64aa8c26c9eea -size 5256 +oid sha256:8e18c010bfd1cf93b5b30cf38b58b3cc24d3e1fdb992050786e35004d112563f +size 61822 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_7,NEXUS_5,1.0,en].png index 3d3e4db08f..46e82926c4 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_BloomInitials_0_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:667ecdc1069d2111044ca8f55f2fe12ff7aff84529b65c89e1c0223d841fb455 -size 5465 +oid sha256:21465f36c39930d08edbe2b099ff0cd2765292ee29a724720f75760066845440 +size 67954 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_Bloom_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_Bloom_0_null,NEXUS_5,1.0,en].png index 24f73f516c..17ad5a90a2 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_Bloom_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_Bloom_Bloom_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9c452593117cb003aca6d7d3c547b96a879c1bb10a169926c507c57a2abdc9b1 +oid sha256:b06bbc06573f8b25cb97e6de6c621c2580a29a2b0c688a5e5135e886af524eb8 size 77557 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png index 6d92ba07bc..37e8a8561f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:700c12595cb3df0b342b36816dd336424ae1a94245874cb1e989528e89964336 -size 79384 +oid sha256:e65e15c721a939ed700719cacbdee57e1ccb89d984e88bdb5ed772c4b583472a +size 81494 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png index d51e1ad32f..466f321959 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9f562083dcd0746eab20db445fce2836628faf5b57077dbb63ddbc32a479a9a0 -size 76138 +oid sha256:49f6d3b7f93008640abf30a5a65ddca6845e16343ef97c3450faf9dd6d9b9cec +size 78788 From c0b5084c625cd7a8f832b9f21fb86a6e200f040b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 12 Sep 2023 14:28:49 +0200 Subject: [PATCH 112/234] Fix overlapping issue - still not perfect when text is on several lines. --- .../impl/timeline/components/html/HtmlDocument.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/html/HtmlDocument.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/html/HtmlDocument.kt index 11eb1f421f..9df5399727 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/html/HtmlDocument.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/html/HtmlDocument.kt @@ -28,7 +28,7 @@ import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.InlineTextContent import androidx.compose.foundation.text.appendInlineContent @@ -61,10 +61,12 @@ import io.element.android.features.messages.impl.timeline.components.event.noExt import io.element.android.libraries.designsystem.components.ClickableLinkText import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewLight +import io.element.android.libraries.designsystem.text.toDp import io.element.android.libraries.designsystem.theme.components.Surface import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.matrix.api.permalink.PermalinkData import io.element.android.libraries.matrix.api.permalink.PermalinkParser +import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.LinkColor import kotlinx.collections.immutable.persistentMapOf import org.jsoup.nodes.Document @@ -92,7 +94,12 @@ fun HtmlDocument( onTextClicked = onTextClicked, onTextLongClicked = onTextLongClicked, ) - Spacer(modifier = Modifier.width(extraPadding.getDpSize())) + Spacer( + modifier = Modifier.size( + width = extraPadding.getDpSize(), + height = ElementTheme.typography.fontBodyXsRegular.fontSize.toDp() * 1.25f + ) + ) } } From d48577d79210bf2841ee53bdb094c57303804a78 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 12 Sep 2023 12:37:51 +0000 Subject: [PATCH 113/234] Update screenshots --- ...lineItemEventRowTimestampDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...lineItemEventRowTimestampDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...lineItemEventRowTimestampDark_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...lineItemEventRowTimestampDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...ineItemEventRowTimestampLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ineItemEventRowTimestampLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...ineItemEventRowTimestampLight_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...ineItemEventRowTimestampLight_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_0,NEXUS_5,1.0,en].png index 5ff17ba18a..5bb87f7b39 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d1a1361432b343ef1bacc7e95bf1c4b50f9eab2e1bd3ab80024db4994f62508 -size 63028 +oid sha256:f6010f8c84263cad47587a20c9d7da64aef2a8520c01765ee4966e4b6bdd8327 +size 63371 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_1,NEXUS_5,1.0,en].png index b7c334bef0..27e6956a21 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d573380414ffbabcb509bc9ae8e34f155daae61edf5c3c406d20eec929cc91a9 -size 65158 +oid sha256:6e12464ce600a1cd6ca6ea9dd930c2235e033896b336109e094b84dcf2d4e624 +size 65459 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_2,NEXUS_5,1.0,en].png index d07e5c3c1f..21092833ec 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:be16428b678680bf888d33beb07377faba36515c2d9aa0632c089f32330185ce -size 69640 +oid sha256:e74d57cb6f5cda78086989289d0f0543cfd3747e1cebec0bd656bd5be2d8bac1 +size 69944 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_3,NEXUS_5,1.0,en].png index 784f05fd57..4bf217a2e5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d220bc3af69c6e576b639bb98c9696cee71232caae5e164cc2b306821a2cd4c1 -size 71603 +oid sha256:9baf1ea5fca980be4744655283bd61de650c9f8399a9f3441a9a3f9c5f43566e +size 71852 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_0,NEXUS_5,1.0,en].png index 372883de77..31b384c132 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c6dd7c3eff7191c6ca0232fa467ac2ac723c81d7c8fdc60653ec49e2427990e3 -size 62067 +oid sha256:343d84dc714bb672084362155362b04936ae491f437e492332bff553d7776078 +size 62478 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_1,NEXUS_5,1.0,en].png index 6bc82b809c..7fedf5139d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6dc81ed6a87958bd35754941d3a767b40f331822402db88fc21058bafae23628 -size 64681 +oid sha256:daee8f18d24bcc07cf8edd9b902b03c3fb406199a925606b1caf34cee08ff9a1 +size 65076 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_2,NEXUS_5,1.0,en].png index b280c416b8..7bf4f6f57b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c3169984328bc0ff82f602b6b136bbafbe8361df269bbb6169ffffd803086d8e -size 69016 +oid sha256:f0cb7b8bd23784f2323ab61baad1a910b343fc498ea61f7364edeff9111992d0 +size 69478 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_3,NEXUS_5,1.0,en].png index 4415a6052e..ab0a440978 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowTimestampLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3e5905aabbe47b08864e6f6f3992b9e3a42d5b36bc101b53835ad91e7d7fd5f5 -size 71691 +oid sha256:54a52c6de5fd501e5c4f260343dd9ec582b0a1dd094a18f43f2fc4aa2c8acfcc +size 72145 From 664caf3041f74ac21a98d4d60a09466eb537ebf3 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 12 Sep 2023 15:13:19 +0200 Subject: [PATCH 114/234] Renane fun. --- .../android/features/messages/impl/timeline/TimelineView.kt | 4 ++-- .../impl/timeline/model/event/TimelineItemEventContent.kt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index b5187b4b30..e48eb4f72b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -63,7 +63,7 @@ import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContentProvider import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent -import io.element.android.features.messages.impl.timeline.model.event.canBeReplied +import io.element.android.features.messages.impl.timeline.model.event.canBeRepliedTo import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.theme.components.FloatingActionButton @@ -190,7 +190,7 @@ fun TimelineItemRow( TimelineItemEventRow( event = timelineItem, isHighlighted = highlightedItem == timelineItem.identifier(), - canReply = userHasPermissionToSendMessage && timelineItem.content.canBeReplied(), + canReply = userHasPermissionToSendMessage && timelineItem.content.canBeRepliedTo(), onClick = { onClick(timelineItem) }, onLongClick = { onLongClick(timelineItem) }, onUserDataClick = onUserDataClick, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt index 4501e98e79..ef31d6249c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContent.kt @@ -38,7 +38,7 @@ fun TimelineItemEventContent.canBeCopied(): Boolean = * Determine if the event content can be replied to. * Note: it should match the logic in [io.element.android.features.messages.impl.actionlist.ActionListPresenter]. */ -fun TimelineItemEventContent.canBeReplied(): Boolean = +fun TimelineItemEventContent.canBeRepliedTo(): Boolean = when (this) { is TimelineItemRedactedContent, is TimelineItemStateContent, From 8abaee870805a5ccf24c9058d114c6403e67009e Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Tue, 12 Sep 2023 16:03:40 +0200 Subject: [PATCH 115/234] Polls analytics (#1285) Send poll analytics event (creation, vote, end) where appropriate. --- .../messages/impl/MessagesPresenter.kt | 9 +++++-- .../impl/timeline/TimelinePresenter.kt | 5 +++- .../messages/MessagesPresenterTest.kt | 17 +++++++++--- .../timeline/TimelinePresenterTest.kt | 18 ++++++++++--- features/poll/impl/build.gradle.kts | 2 ++ .../poll/impl/create/CreatePollNode.kt | 7 ++--- .../poll/impl/create/CreatePollPresenter.kt | 26 ++++++++++++++++--- .../impl/create/CreatePollPresenterTest.kt | 26 +++++++++++++++++-- 8 files changed, 90 insertions(+), 20 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index b0ff403984..0831afb699 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -30,6 +30,7 @@ import androidx.compose.runtime.setValue import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject +import im.vector.app.features.analytics.plan.PollEnd import io.element.android.features.messages.impl.actionlist.ActionListEvents import io.element.android.features.messages.impl.actionlist.ActionListPresenter import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction @@ -74,6 +75,7 @@ import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType import io.element.android.libraries.matrix.ui.room.canRedactAsState import io.element.android.libraries.matrix.ui.room.canSendMessageAsState import io.element.android.libraries.textcomposer.MessageComposerMode +import io.element.android.services.analytics.api.AnalyticsService import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -92,6 +94,7 @@ class MessagesPresenter @AssistedInject constructor( private val messageSummaryFormatter: MessageSummaryFormatter, private val dispatchers: CoroutineDispatchers, private val clipboardHelper: ClipboardHelper, + private val analyticsService: AnalyticsService, @Assisted private val navigator: MessagesNavigator, ) : Presenter { @@ -321,8 +324,10 @@ class MessagesPresenter @AssistedInject constructor( } private suspend fun handleEndPollAction(event: TimelineItem.Event) { - event.eventId?.let { room.endPoll(it, "The poll with event id: $it has ended.") } - // TODO Polls: Send poll end analytic + event.eventId?.let { + room.endPoll(it, "The poll with event id: $it has ended.") + analyticsService.capture(PollEnd()) + } } private suspend fun handleCopyContents(event: TimelineItem.Event) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt index bf0f61e258..a7e86d341f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt @@ -26,6 +26,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable +import im.vector.app.features.analytics.plan.PollVote import io.element.android.features.messages.impl.timeline.factories.TimelineItemsFactory import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.libraries.architecture.Presenter @@ -35,6 +36,7 @@ import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MessageEventType import io.element.android.libraries.matrix.api.timeline.item.event.TimelineItemEventOrigin import io.element.android.libraries.matrix.ui.room.canSendMessageAsState +import io.element.android.services.analytics.api.AnalyticsService import kotlinx.collections.immutable.ImmutableList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.launchIn @@ -51,6 +53,7 @@ class TimelinePresenter @Inject constructor( private val room: MatrixRoom, private val dispatchers: CoroutineDispatchers, private val appScope: CoroutineScope, + private val analyticsService: AnalyticsService, ) : Presenter { private val timeline = room.timeline @@ -93,7 +96,7 @@ class TimelinePresenter @Inject constructor( pollStartId = event.pollStartId, answers = listOf(event.answerId), ) - // TODO Polls: Send poll vote analytic + analyticsService.capture(PollVote()) } } } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt index ed7c4a8064..2a601fbb90 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt @@ -21,6 +21,7 @@ import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat +import im.vector.app.features.analytics.plan.PollEnd import io.element.android.features.messages.fixtures.aMessageEvent import io.element.android.features.messages.fixtures.aTimelineItemsFactory import io.element.android.features.messages.impl.InviteDialogAction @@ -575,7 +576,11 @@ class MessagesPresenterTest { @Test fun `present - handle poll end`() = runTest { val room = FakeMatrixRoom() - val presenter = createMessagePresenter(matrixRoom = room) + val analyticsService = FakeAnalyticsService() + val presenter = createMessagePresenter( + matrixRoom = room, + analyticsService = analyticsService, + ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -586,7 +591,8 @@ class MessagesPresenterTest { assertThat(room.endPollInvocations.size).isEqualTo(1) assertThat(room.endPollInvocations.first().pollStartId).isEqualTo(AN_EVENT_ID) assertThat(room.endPollInvocations.first().text).isEqualTo("The poll with event id: \$anEventId has ended.") - // TODO Polls: Test poll end analytic + assertThat(analyticsService.capturedEvents.size).isEqualTo(1) + assertThat(analyticsService.capturedEvents.last()).isEqualTo(PollEnd()) } } @@ -595,6 +601,7 @@ class MessagesPresenterTest { matrixRoom: MatrixRoom = FakeMatrixRoom(), navigator: FakeMessagesNavigator = FakeMessagesNavigator(), clipboardHelper: FakeClipboardHelper = FakeClipboardHelper(), + analyticsService: FakeAnalyticsService = FakeAnalyticsService(), ): MessagesPresenter { val messageComposerPresenter = MessageComposerPresenter( appCoroutineScope = this, @@ -604,7 +611,7 @@ class MessagesPresenterTest { localMediaFactory = FakeLocalMediaFactory(mockMediaUrl), mediaSender = MediaSender(FakeMediaPreProcessor(), matrixRoom), snackbarDispatcher = SnackbarDispatcher(), - analyticsService = FakeAnalyticsService(), + analyticsService = analyticsService, messageComposerContext = MessageComposerContextImpl(), richTextEditorStateFactory = TestRichTextEditorStateFactory(), @@ -613,7 +620,8 @@ class MessagesPresenterTest { timelineItemsFactory = aTimelineItemsFactory(), room = matrixRoom, dispatchers = coroutineDispatchers, - appScope = this + appScope = this, + analyticsService = analyticsService, ) val buildMeta = aBuildMeta() val actionListPresenter = ActionListPresenter(buildMeta = buildMeta) @@ -633,6 +641,7 @@ class MessagesPresenterTest { messageSummaryFormatter = FakeMessageSummaryFormatter(), navigator = navigator, clipboardHelper = clipboardHelper, + analyticsService = analyticsService, dispatchers = coroutineDispatchers, ) } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/TimelinePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/TimelinePresenterTest.kt index 4e8ab07d95..eb5a7b72e1 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/TimelinePresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/TimelinePresenterTest.kt @@ -20,6 +20,7 @@ import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat +import im.vector.app.features.analytics.plan.PollVote import io.element.android.features.messages.fixtures.aTimelineItemsFactory import io.element.android.features.messages.impl.timeline.TimelineEvents import io.element.android.features.messages.impl.timeline.TimelinePresenter @@ -37,6 +38,7 @@ import io.element.android.libraries.matrix.test.room.aMessageContent import io.element.android.libraries.matrix.test.room.anEventTimelineItem import io.element.android.libraries.matrix.test.timeline.FakeMatrixTimeline import io.element.android.libraries.matrix.ui.components.aMatrixUserList +import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.awaitWithLatch import io.element.android.tests.testutils.testCoroutineDispatchers @@ -260,7 +262,11 @@ class TimelinePresenterTest { @Test fun `present - PollAnswerSelected event calls into rust room api and analytics`() = runTest { val room = FakeMatrixRoom() - val presenter = createTimelinePresenter(room) + val analyticsService = FakeAnalyticsService() + val presenter = createTimelinePresenter( + room = room, + analyticsService = analyticsService, + ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -271,7 +277,8 @@ class TimelinePresenterTest { assertThat(room.sendPollResponseInvocations.size).isEqualTo(1) assertThat(room.sendPollResponseInvocations.first().answers).isEqualTo(listOf("anAnswerId")) assertThat(room.sendPollResponseInvocations.first().pollStartId).isEqualTo(AN_EVENT_ID) - // TODO Polls: Test poll vote analytic + assertThat(analyticsService.capturedEvents.size).isEqualTo(1) + assertThat(analyticsService.capturedEvents.last()).isEqualTo(PollVote()) } private fun TestScope.createTimelinePresenter( @@ -282,18 +289,21 @@ class TimelinePresenterTest { timelineItemsFactory = timelineItemsFactory, room = FakeMatrixRoom(matrixTimeline = timeline), dispatchers = testCoroutineDispatchers(), - appScope = this + appScope = this, + analyticsService = FakeAnalyticsService(), ) } private fun TestScope.createTimelinePresenter( room: MatrixRoom, + analyticsService: FakeAnalyticsService = FakeAnalyticsService(), ): TimelinePresenter { return TimelinePresenter( timelineItemsFactory = aTimelineItemsFactory(), room = room, dispatchers = testCoroutineDispatchers(), - appScope = this + appScope = this, + analyticsService = analyticsService, ) } } diff --git a/features/poll/impl/build.gradle.kts b/features/poll/impl/build.gradle.kts index e2139424e1..5ff9025aae 100644 --- a/features/poll/impl/build.gradle.kts +++ b/features/poll/impl/build.gradle.kts @@ -39,6 +39,7 @@ dependencies { implementation(projects.libraries.matrixui) implementation(projects.libraries.designsystem) implementation(projects.services.analytics.api) + implementation(projects.features.messages.api) implementation(projects.libraries.uiStrings) testImplementation(libs.test.junit) @@ -48,6 +49,7 @@ dependencies { testImplementation(libs.test.turbine) testImplementation(projects.libraries.matrix.test) testImplementation(projects.services.analytics.test) + testImplementation(projects.features.messages.test) testImplementation(projects.tests.testutils) ksp(libs.showkase.processor) diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollNode.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollNode.kt index 387f57a597..506c39c177 100644 --- a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollNode.kt +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollNode.kt @@ -24,15 +24,17 @@ import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin import dagger.assisted.Assisted import dagger.assisted.AssistedInject +import im.vector.app.features.analytics.plan.MobileScreen import io.element.android.anvilannotations.ContributesNode import io.element.android.libraries.di.RoomScope +import io.element.android.services.analytics.api.AnalyticsService @ContributesNode(RoomScope::class) class CreatePollNode @AssistedInject constructor( @Assisted buildContext: BuildContext, @Assisted plugins: List, presenterFactory: CreatePollPresenter.Factory, - // analyticsService: AnalyticsService, // TODO Polls: add analytics + analyticsService: AnalyticsService, ) : Node(buildContext, plugins = plugins) { private val presenter = presenterFactory.create(backNavigator = ::navigateUp) @@ -40,8 +42,7 @@ class CreatePollNode @AssistedInject constructor( init { lifecycle.subscribe( onResume = { - // TODO Polls: add analytics - // analyticsService.screen(MobileScreen(screenName = MobileScreen.ScreenName.PollView)) + analyticsService.screen(MobileScreen(screenName = MobileScreen.ScreenName.CreatePollView)) } ) } diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenter.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenter.kt index b44afae9d1..44cc54a100 100644 --- a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenter.kt +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenter.kt @@ -29,9 +29,13 @@ import androidx.compose.runtime.setValue import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject +import im.vector.app.features.analytics.plan.Composer +import im.vector.app.features.analytics.plan.PollCreation +import io.element.android.features.messages.api.MessageComposerContext import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.services.analytics.api.AnalyticsService import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.launch @@ -44,9 +48,9 @@ private const val MAX_SELECTIONS = 1 class CreatePollPresenter @AssistedInject constructor( private val room: MatrixRoom, - // private val analyticsService: AnalyticsService, // TODO Polls: add analytics + private val analyticsService: AnalyticsService, + private val messageComposerContext: MessageComposerContext, @Assisted private val navigateUp: () -> Unit, - // private val messageComposerContext: MessageComposerContext, // TODO Polls: add analytics ) : Presenter { @AssistedFactory @@ -78,7 +82,21 @@ class CreatePollPresenter @AssistedInject constructor( maxSelections = MAX_SELECTIONS, pollKind = pollKind, ) - // analyticsService.capture(PollCreate()) // TODO Polls: add analytics + analyticsService.capture( + Composer( + inThread = messageComposerContext.composerMode.inThread, + isEditing = messageComposerContext.composerMode.isEditing, + isReply = messageComposerContext.composerMode.isReply, + messageType = Composer.MessageType.Poll, + ) + ) + analyticsService.capture( + PollCreation( + action = PollCreation.Action.Create, + isUndisclosed = pollKind == PollKind.Undisclosed, + numberOfAnswers = answers.size, + ) + ) navigateUp() } else { Timber.d("Cannot create poll") @@ -153,7 +171,7 @@ private val pollKindSaver: Saver, Boolean> = Saver( }, restore = { mutableStateOf( - when(it) { + when (it) { true -> PollKind.Undisclosed else -> PollKind.Disclosed } diff --git a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenterTest.kt b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenterTest.kt index c54972e9d1..a58fb5476b 100644 --- a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenterTest.kt +++ b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenterTest.kt @@ -20,9 +20,13 @@ import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth +import im.vector.app.features.analytics.plan.Composer +import im.vector.app.features.analytics.plan.PollCreation +import io.element.android.features.messages.test.MessageComposerContextFake import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.matrix.test.room.CreatePollInvocation import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.delay import kotlinx.coroutines.test.runTest @@ -37,11 +41,13 @@ class CreatePollPresenterTest { private var navUpInvocationsCount = 0 private val fakeMatrixRoom = FakeMatrixRoom() - // private val fakeAnalyticsService = FakeAnalyticsService() // TODO Polls: add analytics + private val fakeAnalyticsService = FakeAnalyticsService() + private val messageComposerContextFake = MessageComposerContextFake() private val presenter = CreatePollPresenter( room = fakeMatrixRoom, - // analyticsService = fakeAnalyticsService, // TODO Polls: add analytics + analyticsService = fakeAnalyticsService, + messageComposerContext = messageComposerContextFake, navigateUp = { navUpInvocationsCount++ }, ) @@ -104,6 +110,22 @@ class CreatePollPresenterTest { pollKind = PollKind.Disclosed ) ) + Truth.assertThat(fakeAnalyticsService.capturedEvents.size).isEqualTo(2) + Truth.assertThat(fakeAnalyticsService.capturedEvents[0]).isEqualTo( + Composer( + inThread = false, + isEditing = false, + isReply = false, + messageType = Composer.MessageType.Poll, + ) + ) + Truth.assertThat(fakeAnalyticsService.capturedEvents[1]).isEqualTo( + PollCreation( + action = PollCreation.Action.Create, + isUndisclosed = false, + numberOfAnswers = 2, + ) + ) } } From d4e141aad831f4a47949a7d74ef3dadd47295f39 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 12 Sep 2023 16:42:48 +0000 Subject: [PATCH 116/234] Update dependency org.matrix.rustcomponents:sdk-android to v0.1.51 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d172bc120d..e2b27adc6a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -149,7 +149,7 @@ jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" } appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = { module = "app.cash.molecule:molecule-runtime", version.ref = "molecule" } timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.50" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.51" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "com.squareup.sqldelight:android-driver", version.ref = "sqldelight" } From d6a2020bd90babc9e242703ae94a33514e2bf2c6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 12 Sep 2023 21:04:57 +0200 Subject: [PATCH 117/234] Add contact to OidcConfiguration (#1250) --- .../android/libraries/matrix/impl/auth/OidcConfiguration.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OidcConfiguration.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OidcConfiguration.kt index f49ee65208..ad848ef95a 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OidcConfiguration.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/OidcConfiguration.kt @@ -26,6 +26,9 @@ val oidcConfiguration: OidcConfiguration = OidcConfiguration( logoUri = "https://element.io/mobile-icon.png", tosUri = "https://element.io/acceptable-use-policy-terms", policyUri = "https://element.io/privacy", + contacts = listOf( + "support@element.io", + ), /** * Some homeservers/auth issuers don't support dynamic client registration, and have to be registered manually */ From f327726f53310387255e21bc23f8a2a83550b27d Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Wed, 13 Sep 2023 07:59:57 +0200 Subject: [PATCH 118/234] Send composer analytics when sending a message (#1288) Composer event are not sent to posthog when sending messages. After investigation I've found that in `MessageComposerPresenter` the `analyticsService.capture()` call is invoked in the `SetMode` event handler rather than in the `SendMessage` event handler. This change should result in the desired behavior. --- .../messagecomposer/MessageComposerPresenter.kt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt index 215826dade..a7728c2a00 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt @@ -148,14 +148,6 @@ class MessageComposerPresenter @Inject constructor( ) is MessageComposerEvents.SetMode -> { messageComposerContext.composerMode = event.composerMode - analyticsService.capture( - Composer( - inThread = messageComposerContext.composerMode.inThread, - isEditing = messageComposerContext.composerMode.isEditing, - isReply = messageComposerContext.composerMode.isReply, - messageType = Composer.MessageType.Text, - ) - ) } MessageComposerEvents.AddAttachment -> localCoroutineScope.launch { showAttachmentSourcePicker = true @@ -238,6 +230,14 @@ class MessageComposerPresenter @Inject constructor( message.html, ) } + analyticsService.capture( + Composer( + inThread = capturedMode.inThread, + isEditing = capturedMode.isEditing, + isReply = capturedMode.isReply, + messageType = Composer.MessageType.Text, // Set proper type when we'll be sending other types of messages. + ) + ) } private fun CoroutineScope.sendAttachment( From 8ab391f61597577d8be785aa4f4d9b881fe0da26 Mon Sep 17 00:00:00 2001 From: jonnyandrew Date: Wed, 13 Sep 2023 09:17:02 +0100 Subject: [PATCH 119/234] [Rich text editor] Add feature flag for rich text editor (#1289) --- changelog.d/1289.feature | 1 + .../messages/impl/MessagesPresenter.kt | 17 ++++++++++++-- .../features/messages/impl/MessagesState.kt | 1 + .../messages/impl/MessagesStateProvider.kt | 1 + .../features/messages/impl/MessagesView.kt | 1 + .../messagecomposer/AttachmentsBottomSheet.kt | 16 +++++++++---- .../messagecomposer/MessageComposerView.kt | 4 ++++ .../messages/MessagesPresenterTest.kt | 2 ++ gradle/libs.versions.toml | 2 +- .../libraries/featureflag/api/FeatureFlags.kt | 5 ++++ .../impl/StaticFeatureFlagProvider.kt | 1 + .../libraries/matrix/api/room/MatrixRoom.kt | 6 ++--- .../matrix/impl/room/RustMatrixRoom.kt | 23 +++++++++++++------ .../matrix/test/room/FakeMatrixRoom.kt | 10 ++++---- .../android/libraries/textcomposer/Message.kt | 2 +- .../libraries/textcomposer/TextComposer.kt | 17 +++++++++++++- 16 files changed, 84 insertions(+), 25 deletions(-) create mode 100644 changelog.d/1289.feature diff --git a/changelog.d/1289.feature b/changelog.d/1289.feature new file mode 100644 index 0000000000..33e8042f51 --- /dev/null +++ b/changelog.d/1289.feature @@ -0,0 +1 @@ +[Rich text editor] Add feature flag for rich text editor. Markdown support can now be enabled by disabling the rich text editor. diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index 0831afb699..50b3dca2d1 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -66,6 +66,8 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.utils.SnackbarDispatcher import io.element.android.libraries.designsystem.utils.SnackbarMessage import io.element.android.libraries.designsystem.utils.collectSnackbarMessageAsState +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState @@ -95,6 +97,7 @@ class MessagesPresenter @AssistedInject constructor( private val dispatchers: CoroutineDispatchers, private val clipboardHelper: ClipboardHelper, private val analyticsService: AnalyticsService, + private val featureFlagService: FeatureFlagService, @Assisted private val navigator: MessagesNavigator, ) : Presenter { @@ -143,6 +146,11 @@ class MessagesPresenter @AssistedInject constructor( timelineState.eventSink(TimelineEvents.SetHighlightedEvent(composerState.mode.relatedEventId)) } + var enableTextFormatting by remember { mutableStateOf(true) } + LaunchedEffect(Unit) { + enableTextFormatting = featureFlagService.isFeatureEnabled(FeatureFlags.RichTextEditor) + } + fun handleEvents(event: MessagesEvents) { when (event) { is MessagesEvents.HandleAction -> { @@ -178,6 +186,7 @@ class MessagesPresenter @AssistedInject constructor( snackbarMessage = snackbarMessage, showReinvitePrompt = showReinvitePrompt, inviteProgress = inviteProgress.value, + enableTextFormatting = enableTextFormatting, eventSink = { handleEvents(it) } ) } @@ -250,11 +259,15 @@ class MessagesPresenter @AssistedInject constructor( } } - private fun handleActionEdit(targetEvent: TimelineItem.Event, composerState: MessageComposerState) { + private suspend fun handleActionEdit(targetEvent: TimelineItem.Event, composerState: MessageComposerState) { val composerMode = MessageComposerMode.Edit( targetEvent.eventId, (targetEvent.content as? TimelineItemTextBasedContent)?.let { - it.htmlBody ?: it.body + if (featureFlagService.isFeatureEnabled(FeatureFlags.RichTextEditor)) { + it.htmlBody ?: it.body + } else { + it.body + } }.orEmpty(), targetEvent.transactionId, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt index d22d54e7f3..46aad1e191 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt @@ -45,5 +45,6 @@ data class MessagesState( val snackbarMessage: SnackbarMessage?, val inviteProgress: Async, val showReinvitePrompt: Boolean, + val enableTextFormatting: Boolean, val eventSink: (MessagesEvents) -> Unit ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt index 6ca799dc84..a88ebcbcd8 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt @@ -82,5 +82,6 @@ fun aMessagesState() = MessagesState( snackbarMessage = null, inviteProgress = Async.Uninitialized, showReinvitePrompt = false, + enableTextFormatting = true, eventSink = {} ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt index ab11ca05d7..1b4b8f7e19 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt @@ -304,6 +304,7 @@ private fun MessagesViewContent( state = state.composerState, onSendLocationClicked = onSendLocationClicked, onCreatePollClicked = onCreatePollClicked, + enableTextFormatting = state.enableTextFormatting, modifier = Modifier .fillMaxWidth() .wrapContentHeight(Alignment.Bottom) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt index 38ef458bd9..8332018385 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt @@ -55,6 +55,7 @@ internal fun AttachmentsBottomSheet( state: MessageComposerState, onSendLocationClicked: () -> Unit, onCreatePollClicked: () -> Unit, + enableTextFormatting: Boolean, modifier: Modifier = Modifier, ) { val localView = LocalView.current @@ -87,6 +88,7 @@ internal fun AttachmentsBottomSheet( ) { AttachmentSourcePickerMenu( state = state, + enableTextFormatting = enableTextFormatting, onSendLocationClicked = onSendLocationClicked, onCreatePollClicked = onCreatePollClicked, ) @@ -100,6 +102,7 @@ internal fun AttachmentSourcePickerMenu( state: MessageComposerState, onSendLocationClicked: () -> Unit, onCreatePollClicked: () -> Unit, + enableTextFormatting: Boolean, modifier: Modifier = Modifier, ) { Column( @@ -146,11 +149,13 @@ internal fun AttachmentSourcePickerMenu( text = { Text(stringResource(R.string.screen_room_attachment_source_poll)) }, ) } - ListItem( - modifier = Modifier.clickable { state.eventSink(MessageComposerEvents.ToggleTextFormatting(enabled = true)) }, - icon = { Icon(Icons.Default.FormatColorText, null) }, - text = { Text(stringResource(R.string.screen_room_attachment_text_formatting)) }, - ) + if (enableTextFormatting) { + ListItem( + modifier = Modifier.clickable { state.eventSink(MessageComposerEvents.ToggleTextFormatting(enabled = true)) }, + icon = { Icon(Icons.Default.FormatColorText, null) }, + text = { Text(stringResource(R.string.screen_room_attachment_text_formatting)) }, + ) + } } } @@ -163,5 +168,6 @@ internal fun AttachmentSourcePickerMenuPreview() = ElementPreview { ), onSendLocationClicked = {}, onCreatePollClicked = {}, + enableTextFormatting = true, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerView.kt index 4ea5a7cf76..3413dda107 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerView.kt @@ -31,6 +31,7 @@ fun MessageComposerView( state: MessageComposerState, onSendLocationClicked: () -> Unit, onCreatePollClicked: () -> Unit, + enableTextFormatting: Boolean, modifier: Modifier = Modifier, ) { fun onFullscreenToggle() { @@ -62,6 +63,7 @@ fun MessageComposerView( state = state, onSendLocationClicked = onSendLocationClicked, onCreatePollClicked = onCreatePollClicked, + enableTextFormatting = enableTextFormatting, ) TextComposer( @@ -74,6 +76,7 @@ fun MessageComposerView( onResetComposerMode = ::onCloseSpecialMode, onAddAttachment = ::onAddAttachment, onDismissTextFormatting = ::onDismissTextFormatting, + enableTextFormatting = enableTextFormatting, onError = ::onError, ) } @@ -95,5 +98,6 @@ private fun ContentToPreview(state: MessageComposerState) { state = state, onSendLocationClicked = {}, onCreatePollClicked = {}, + enableTextFormatting = true, ) } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt index 2a601fbb90..c1c7e1c993 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt @@ -628,6 +628,7 @@ class MessagesPresenterTest { val customReactionPresenter = CustomReactionPresenter(emojibaseProvider = FakeEmojibaseProvider()) val reactionSummaryPresenter = ReactionSummaryPresenter(room = matrixRoom) val retrySendMenuPresenter = RetrySendMenuPresenter(room = matrixRoom) + val featureFlagsService = FakeFeatureFlagService(mapOf(FeatureFlags.RichTextEditor.key to true)) return MessagesPresenter( room = matrixRoom, composerPresenter = messageComposerPresenter, @@ -642,6 +643,7 @@ class MessagesPresenterTest { navigator = navigator, clipboardHelper = clipboardHelper, analyticsService = analyticsService, + featureFlagService = featureFlagsService, dispatchers = coroutineDispatchers, ) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e2b27adc6a..cc0e9454ab 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -46,7 +46,7 @@ dependencyanalysis = "1.21.0" stem = "2.3.0" sqldelight = "1.5.5" telephoto = "0.6.0" -wysiwyg = "2.9.0" +wysiwyg = "2.10.0" # DI dagger = "2.48" diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt index c7744f486d..0f27a94a2d 100644 --- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt +++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt @@ -44,4 +44,9 @@ enum class FeatureFlags( // Do not forget to edit StaticFeatureFlagProvider when enabling the feature. defaultValue = false, ), + RichTextEditor( + key = "feature.richtexteditor", + title = "Enable rich text editor", + defaultValue = true, + ), } diff --git a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/StaticFeatureFlagProvider.kt b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/StaticFeatureFlagProvider.kt index 50efdb9fc3..c9b24f08e6 100644 --- a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/StaticFeatureFlagProvider.kt +++ b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/StaticFeatureFlagProvider.kt @@ -35,6 +35,7 @@ class StaticFeatureFlagProvider @Inject constructor() : FeatureFlags.LocationSharing -> true FeatureFlags.Polls -> true FeatureFlags.NotificationSettings -> false + FeatureFlags.RichTextEditor -> true } } else { false diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt index 169381f25e..142e86dcd9 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt @@ -79,11 +79,11 @@ interface MatrixRoom : Closeable { suspend fun userAvatarUrl(userId: UserId): Result - suspend fun sendMessage(body: String, htmlBody: String): Result + suspend fun sendMessage(body: String, htmlBody: String?): Result - suspend fun editMessage(originalEventId: EventId?, transactionId: TransactionId?, body: String, htmlBody: String): Result + suspend fun editMessage(originalEventId: EventId?, transactionId: TransactionId?, body: String, htmlBody: String?): Result - suspend fun replyMessage(eventId: EventId, body: String, htmlBody: String): Result + suspend fun replyMessage(eventId: EventId, body: String, htmlBody: String?): Result suspend fun redactEvent(eventId: EventId, reason: String? = null): Result diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt index 9e75d10aad..eb456588ee 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt @@ -63,10 +63,12 @@ import org.matrix.rustcomponents.sdk.RequiredState import org.matrix.rustcomponents.sdk.Room import org.matrix.rustcomponents.sdk.RoomListItem import org.matrix.rustcomponents.sdk.RoomMember +import org.matrix.rustcomponents.sdk.RoomMessageEventContentWithoutRelation import org.matrix.rustcomponents.sdk.RoomSubscription import org.matrix.rustcomponents.sdk.SendAttachmentJoinHandle import org.matrix.rustcomponents.sdk.genTransactionId import org.matrix.rustcomponents.sdk.messageEventContentFromHtml +import org.matrix.rustcomponents.sdk.messageEventContentFromMarkdown import timber.log.Timber import java.io.File @@ -227,32 +229,32 @@ class RustMatrixRoom( } } - override suspend fun sendMessage(body: String, htmlBody: String): Result = withContext(roomDispatcher) { + override suspend fun sendMessage(body: String, htmlBody: String?): Result = withContext(roomDispatcher) { val transactionId = genTransactionId() - messageEventContentFromHtml(body, htmlBody).use { content -> + messageEventContentFromParts(body, htmlBody).use { content -> runCatching { innerRoom.send(content, transactionId) } } } - override suspend fun editMessage(originalEventId: EventId?, transactionId: TransactionId?, body: String, htmlBody: String): Result = + override suspend fun editMessage(originalEventId: EventId?, transactionId: TransactionId?, body: String, htmlBody: String?): Result = withContext(roomDispatcher) { if (originalEventId != null) { runCatching { - innerRoom.edit(messageEventContentFromHtml(body, htmlBody), originalEventId.value, transactionId?.value) + innerRoom.edit(messageEventContentFromParts(body, htmlBody), originalEventId.value, transactionId?.value) } } else { runCatching { transactionId?.let { cancelSend(it) } - innerRoom.send(messageEventContentFromHtml(body, htmlBody), genTransactionId()) + innerRoom.send(messageEventContentFromParts(body, htmlBody), genTransactionId()) } } } - override suspend fun replyMessage(eventId: EventId, body: String, htmlBody: String): Result = withContext(roomDispatcher) { + override suspend fun replyMessage(eventId: EventId, body: String, htmlBody: String?): Result = withContext(roomDispatcher) { runCatching { - innerRoom.sendReply(messageEventContentFromHtml(body, htmlBody), eventId.value, genTransactionId()) + innerRoom.sendReply(messageEventContentFromParts(body, htmlBody), eventId.value, genTransactionId()) } } @@ -456,4 +458,11 @@ class RustMatrixRoom( MediaUploadHandlerImpl(files, handle()) } } + + private fun messageEventContentFromParts(body: String, htmlBody: String?): RoomMessageEventContentWithoutRelation = + if(htmlBody != null) { + messageEventContentFromHtml(body, htmlBody) + } else { + messageEventContentFromMarkdown(body) + } } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index 24f0e68d10..638b935000 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -92,7 +92,7 @@ class FakeMatrixRoom( private var sendPollResponseResult = Result.success(Unit) private var endPollResult = Result.success(Unit) private var progressCallbackValues = emptyList>() - val editMessageCalls = mutableListOf>() + val editMessageCalls = mutableListOf>() var sendMediaCount = 0 private set @@ -171,7 +171,7 @@ class FakeMatrixRoom( userAvatarUrlResult } - override suspend fun sendMessage(body: String, htmlBody: String) = simulateLongTask { + override suspend fun sendMessage(body: String, htmlBody: String?) = simulateLongTask { Result.success(Unit) } @@ -200,15 +200,15 @@ class FakeMatrixRoom( return cancelSendResult } - override suspend fun editMessage(originalEventId: EventId?, transactionId: TransactionId?, body: String, htmlBody: String): Result { + override suspend fun editMessage(originalEventId: EventId?, transactionId: TransactionId?, body: String, htmlBody: String?): Result { editMessageCalls += body to htmlBody return Result.success(Unit) } - var replyMessageParameter: Pair? = null + var replyMessageParameter: Pair? = null private set - override suspend fun replyMessage(eventId: EventId, body: String, htmlBody: String): Result { + override suspend fun replyMessage(eventId: EventId, body: String, htmlBody: String?): Result { replyMessageParameter = body to htmlBody return Result.success(Unit) } diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/Message.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/Message.kt index 0f3a213427..ebc066188a 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/Message.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/Message.kt @@ -17,6 +17,6 @@ package io.element.android.libraries.textcomposer data class Message( - val html: String, + val html: String?, val markdown: String, ) diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt index d137af18bb..3cc09ce09f 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt @@ -91,6 +91,7 @@ fun TextComposer( state: RichTextEditorState, composerMode: MessageComposerMode, canSendMessage: Boolean, + enableTextFormatting: Boolean, modifier: Modifier = Modifier, showTextFormatting: Boolean = false, onRequestFocus: () -> Unit = {}, @@ -101,7 +102,8 @@ fun TextComposer( onError: (Throwable) -> Unit = {}, ) { val onSendClicked = { - onSendMessage(Message(html = state.messageHtml, markdown = state.messageMarkdown)) + val html = if (enableTextFormatting) state.messageHtml else null + onSendMessage(Message(html = html, markdown = state.messageMarkdown)) } Column( @@ -600,6 +602,7 @@ internal fun TextComposerSimplePreview() = ElementPreview { onSendMessage = {}, composerMode = MessageComposerMode.Normal(""), onResetComposerMode = {}, + enableTextFormatting = true, ) TextComposer( RichTextEditorState("A message", fake = true).apply { requestFocus() }, @@ -607,6 +610,7 @@ internal fun TextComposerSimplePreview() = ElementPreview { onSendMessage = {}, composerMode = MessageComposerMode.Normal(""), onResetComposerMode = {}, + enableTextFormatting = true, ) TextComposer( RichTextEditorState( @@ -619,6 +623,7 @@ internal fun TextComposerSimplePreview() = ElementPreview { onSendMessage = {}, composerMode = MessageComposerMode.Normal(""), onResetComposerMode = {}, + enableTextFormatting = true, ) TextComposer( RichTextEditorState("A message without focus", fake = true), @@ -626,6 +631,7 @@ internal fun TextComposerSimplePreview() = ElementPreview { onSendMessage = {}, composerMode = MessageComposerMode.Normal(""), onResetComposerMode = {}, + enableTextFormatting = true, ) } } @@ -639,18 +645,21 @@ internal fun TextComposerFormattingPreview() = ElementPreview { canSendMessage = false, showTextFormatting = true, composerMode = MessageComposerMode.Normal(""), + enableTextFormatting = true, ) TextComposer( RichTextEditorState("A message", fake = true), canSendMessage = true, showTextFormatting = true, composerMode = MessageComposerMode.Normal(""), + enableTextFormatting = true, ) TextComposer( RichTextEditorState("A message\nWith several lines\nTo preview larger textfields and long lines with overflow", fake = true), canSendMessage = true, showTextFormatting = true, composerMode = MessageComposerMode.Normal(""), + enableTextFormatting = true, ) } } @@ -664,6 +673,7 @@ internal fun TextComposerEditPreview() = ElementPreview { onSendMessage = {}, composerMode = MessageComposerMode.Edit(EventId("$1234"), "Some text", TransactionId("1234")), onResetComposerMode = {}, + enableTextFormatting = true, ) } @@ -684,6 +694,7 @@ internal fun TextComposerReplyPreview() = ElementPreview { "To preview larger textfields and long lines with overflow" ), onResetComposerMode = {}, + enableTextFormatting = true, ) TextComposer( RichTextEditorState("A message", fake = true), @@ -701,6 +712,7 @@ internal fun TextComposerReplyPreview() = ElementPreview { defaultContent = "image.jpg" ), onResetComposerMode = {}, + enableTextFormatting = true, ) TextComposer( RichTextEditorState("A message", fake = true), @@ -718,6 +730,7 @@ internal fun TextComposerReplyPreview() = ElementPreview { defaultContent = "video.mp4" ), onResetComposerMode = {}, + enableTextFormatting = true, ) TextComposer( RichTextEditorState("A message", fake = true), @@ -735,6 +748,7 @@ internal fun TextComposerReplyPreview() = ElementPreview { defaultContent = "logs.txt" ), onResetComposerMode = {}, + enableTextFormatting = true, ) TextComposer( RichTextEditorState("A message", fake = true).apply { requestFocus() }, @@ -752,6 +766,7 @@ internal fun TextComposerReplyPreview() = ElementPreview { defaultContent = "Shared location" ), onResetComposerMode = {}, + enableTextFormatting = true, ) } } From 9f5666ac0c66f4bcfe847e9ea2a0cbd8c51ee517 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 13 Sep 2023 11:40:07 +0200 Subject: [PATCH 120/234] Thread decoration: create the ThreadDecoration ui --- .../components/TimelineItemEventRow.kt | 108 ++++++++++++------ .../res/drawable/ic_thread_decoration.xml | 15 +++ 2 files changed, 87 insertions(+), 36 deletions(-) create mode 100644 libraries/designsystem/src/main/res/drawable/ic_thread_decoration.xml diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index 7e21ff649d..122fa03b25 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -75,6 +75,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemPollContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent +import io.element.android.libraries.designsystem.R import io.element.android.libraries.designsystem.colors.AvatarColorsProvider import io.element.android.libraries.designsystem.components.EqualWidthColumn import io.element.android.libraries.designsystem.components.avatar.Avatar @@ -84,6 +85,7 @@ import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.swipe.SwipeableActionsState import io.element.android.libraries.designsystem.swipe.rememberSwipeableActionsState import io.element.android.libraries.designsystem.text.toPx +import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.UserId @@ -370,14 +372,6 @@ private fun MessageEventBubbleContent( onPollAnswerSelected: (pollStartId: EventId, answerId: String) -> Unit, @SuppressLint("ModifierParameter") bubbleModifier: Modifier = Modifier, // need to rename this modifier to distinguish it from the following ones ) { - val timestampPosition = when (event.content) { - is TimelineItemImageContent, - is TimelineItemVideoContent, - is TimelineItemLocationContent -> TimestampPosition.Overlay - is TimelineItemPollContent -> TimestampPosition.Below - else -> TimestampPosition.Default - } - val replyToDetails = event.inReplyTo as? InReplyTo.Ready // Long clicks are not not automatically propagated from a `clickable` // to its `combinedClickable` parent so we do it manually @@ -398,6 +392,21 @@ private fun MessageEventBubbleContent( ) } + @Composable + fun ThreadDecoration( + modifier: Modifier = Modifier + ) { + Row(modifier, verticalAlignment = Alignment.CenterVertically) { + Icon(resourceId = R.drawable.ic_thread_decoration, contentDescription = null, tint = ElementTheme.colors.iconSecondary) + Spacer(modifier = Modifier.width(4.dp)) + Text( + text = "Thread", + style = ElementTheme.typography.fontBodyXsRegular, + color = ElementTheme.colors.textPrimary, + ) + } + } + @Composable fun ContentAndTimestampView( timestampPosition: TimestampPosition, @@ -450,47 +459,74 @@ private fun MessageEventBubbleContent( /** Groups the different components in a Column with some space between them. */ @Composable fun CommonLayout( + timestampPosition: TimestampPosition, + showThreadDecoration: Boolean, inReplyToDetails: InReplyTo.Ready?, modifier: Modifier = Modifier ) { - var modifierWithPadding: Modifier = Modifier - var contentModifier: Modifier = Modifier - EqualWidthColumn(modifier = modifier, spacing = 8.dp) { - when { - inReplyToDetails != null -> { - val senderName = inReplyToDetails.senderDisplayName ?: inReplyToDetails.senderId.value - val attachmentThumbnailInfo = attachmentThumbnailInfoForInReplyTo(inReplyToDetails) - val text = textForInReplyTo(inReplyToDetails) - ReplyToContent( - senderName = senderName, - text = text, - attachmentThumbnailInfo = attachmentThumbnailInfo, - modifier = Modifier - .padding(top = 8.dp, start = 8.dp, end = 8.dp) - .clip(RoundedCornerShape(6.dp)) - .clickable(enabled = true, onClick = inReplyToClick), - ) - if (timestampPosition == TimestampPosition.Overlay) { - modifierWithPadding = Modifier.padding(start = 8.dp, end = 8.dp, bottom = 8.dp) - contentModifier = Modifier.clip(RoundedCornerShape(12.dp)) - } else { - contentModifier = Modifier.padding(start = 12.dp, end = 12.dp, top = 0.dp, bottom = 8.dp) - } - } - timestampPosition != TimestampPosition.Overlay -> { - contentModifier = Modifier.padding(start = 12.dp, end = 12.dp, top = 8.dp, bottom = 8.dp) + val modifierWithPadding: Modifier + val contentModifier: Modifier + when { + inReplyToDetails != null -> { + if (timestampPosition == TimestampPosition.Overlay) { + modifierWithPadding = Modifier.padding(start = 8.dp, end = 8.dp, bottom = 8.dp) + contentModifier = Modifier.clip(RoundedCornerShape(12.dp)) + } else { + contentModifier = Modifier.padding(start = 12.dp, end = 12.dp, top = 0.dp, bottom = 8.dp) + modifierWithPadding = Modifier } } + timestampPosition != TimestampPosition.Overlay -> { + modifierWithPadding = Modifier + contentModifier = Modifier.padding(start = 12.dp, end = 12.dp, top = 8.dp, bottom = 8.dp) + } + else -> { + modifierWithPadding = Modifier + contentModifier = Modifier + } + } + EqualWidthColumn(modifier = modifier, spacing = 8.dp) { + if (showThreadDecoration) { + ThreadDecoration(modifier = Modifier.padding(top = 8.dp, start = 12.dp, end = 12.dp)) + } + if (inReplyToDetails != null) { + val senderName = inReplyToDetails.senderDisplayName ?: inReplyToDetails.senderId.value + val attachmentThumbnailInfo = attachmentThumbnailInfoForInReplyTo(inReplyToDetails) + val text = textForInReplyTo(inReplyToDetails) + val topPadding = if (showThreadDecoration) 0.dp else 8.dp + ReplyToContent( + senderName = senderName, + text = text, + attachmentThumbnailInfo = attachmentThumbnailInfo, + modifier = Modifier + .padding(top = topPadding, start = 8.dp, end = 8.dp) + .clip(RoundedCornerShape(6.dp)) + .clickable(enabled = true, onClick = inReplyToClick), + ) + } ContentAndTimestampView( timestampPosition = timestampPosition, - contentModifier = contentModifier, modifier = modifierWithPadding, + contentModifier = contentModifier, ) } } - CommonLayout(inReplyToDetails = replyToDetails, modifier = bubbleModifier) + val timestampPosition = when (event.content) { + is TimelineItemImageContent, + is TimelineItemVideoContent, + is TimelineItemLocationContent -> TimestampPosition.Overlay + is TimelineItemPollContent -> TimestampPosition.Below + else -> TimestampPosition.Default + } + val replyToDetails = event.inReplyTo as? InReplyTo.Ready + CommonLayout( + showThreadDecoration = false, + timestampPosition = timestampPosition, + inReplyToDetails = replyToDetails, + modifier = bubbleModifier + ) } @Composable diff --git a/libraries/designsystem/src/main/res/drawable/ic_thread_decoration.xml b/libraries/designsystem/src/main/res/drawable/ic_thread_decoration.xml new file mode 100644 index 0000000000..09d4ad4ace --- /dev/null +++ b/libraries/designsystem/src/main/res/drawable/ic_thread_decoration.xml @@ -0,0 +1,15 @@ + + + + + From b960892f09a6600eacd3adf724633cbe2ae36b79 Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Wed, 13 Sep 2023 11:51:29 +0200 Subject: [PATCH 121/234] Set proper progress indicator track color on polls (#1295) Not yet a semantic color, so hardcoding it. --- .../android/features/poll/api/PollAnswerView.kt | 2 ++ .../libraries/designsystem/theme/ColorAliases.kt | 10 ++++++++++ ...lineItemPollView-D-13_14_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...lineItemPollView-D-13_14_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...lineItemPollView-N-13_15_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...lineItemPollView-N-13_15_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...eItemEventTimestampBelow_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...swerDisclosedNotSelected_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...lAnswerDisclosedSelected_0_null,NEXUS_5,1.0,en].png | 4 ++-- ..._PollAnswerEndedSelected_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...erEndedWinnerNotSelected_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...nswerEndedWinnerSelected_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...erUndisclosedNotSelected_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...nswerUndisclosedSelected_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...PollContentDisclosed-D-1_1_null,NEXUS_5,1.0,en].png | 4 ++-- ...PollContentDisclosed-N-1_2_null,NEXUS_5,1.0,en].png | 4 ++-- ...ull_PollContentEnded-D-2_2_null,NEXUS_5,1.0,en].png | 4 ++-- ...ull_PollContentEnded-N-2_3_null,NEXUS_5,1.0,en].png | 4 ++-- ...llContentUndisclosed-D-0_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...llContentUndisclosed-N-0_1_null,NEXUS_5,1.0,en].png | 4 ++-- 20 files changed, 48 insertions(+), 36 deletions(-) diff --git a/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollAnswerView.kt b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollAnswerView.kt index 3e52cc5fc7..4e7a23094b 100644 --- a/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollAnswerView.kt +++ b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollAnswerView.kt @@ -41,6 +41,7 @@ import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.IconToggleButton import io.element.android.libraries.designsystem.theme.components.LinearProgressIndicator import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.progressIndicatorTrackColor import io.element.android.libraries.designsystem.toEnabledColor import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.ui.strings.CommonPlurals @@ -111,6 +112,7 @@ fun PollAnswerView( answerItem.isSelected -> 1f else -> 0f }, + trackColor = ElementTheme.colors.progressIndicatorTrackColor, strokeCap = StrokeCap.Round, ) } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ColorAliases.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ColorAliases.kt index b9e0893836..52e0a69430 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ColorAliases.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ColorAliases.kt @@ -65,6 +65,16 @@ val SemanticColors.messageFromOtherBackground Color(0xFF26282D) } +// This color is not present in Semantic color, so put hard-coded value for now +val SemanticColors.progressIndicatorTrackColor + get() = if (isLight) { + // We want LightDesignTokens.colorAlphaGray500 + Color(0x33052448) + } else { + // We want DarkDesignTokens.colorAlphaGray500 + Color(0x25F4F7FA) + } + // Temporary color, which is not in the token right now val SemanticColors.temporaryColorBgSpecial get() = if (isLight) Color(0xFFE4E8F0) else Color(0xFF3A4048) diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_0,NEXUS_5,1.0,en].png index 84f2abf39d..8ba3fa59a7 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:339e5f22a47e29b6f681ac169be3b65568b7fa5d1197b0e81fb68bef639ae5c2 -size 49033 +oid sha256:801f832469346524fdce0b5ad8654c3405daf0f21ae0601c62dc7f148b576ce8 +size 49074 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_1,NEXUS_5,1.0,en].png index 0fbe7c6581..2af13b5df7 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c439f506df4eaed4ad35148d1734630a89b0de3ccb097864b7ff853c679772c1 -size 50964 +oid sha256:944eb2ef8abf2e8f1715d063020767940c80b40690aae1129f69d02ddafac9d0 +size 51029 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_0,NEXUS_5,1.0,en].png index dacffc90ea..0e2fb91a11 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f85799360092c7e2d02f64f32668279c4e0c39bca3d45c9db13d503ddb7bf753 -size 46162 +oid sha256:adf6f3f79b9d8f62172171dd8a172bff1958bc4698df4586bf83c73fe4c6c6f3 +size 46198 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_1,NEXUS_5,1.0,en].png index 40e0174919..c06bfdad7b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b05475d6509b15fcffeae54bdebf434a529a99af5173c48992677a88b654f3eb -size 48336 +oid sha256:38183d1d69e36c2570259c987be079d09ecfc0a0cba7508fc43d33e95c574121 +size 48368 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventTimestampBelow_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventTimestampBelow_0_null,NEXUS_5,1.0,en].png index 4ba636ed5c..ea0825524c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventTimestampBelow_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventTimestampBelow_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bdcc950b0ce924a73ae742f0bb3fc7279de46f36ba01d377822a2a14b6f90343 -size 56239 +oid sha256:54a4fe8e7f968bf487168a517baa0d9c9f6fc5b2354f4eff45f56de77b043f8f +size 56535 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedNotSelected_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedNotSelected_0_null,NEXUS_5,1.0,en].png index a3e90a69fe..7a81cb7428 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedNotSelected_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedNotSelected_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:74508ef7f77a9c8713c75586ae4d34a9daab2608dbbd2f20de3e4d4a9a9be7e9 -size 39225 +oid sha256:9f97a2f591619aa2dd914f79a2bdfabea3e4e8239e6d80f29400e2c02c6ae21d +size 39250 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedSelected_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedSelected_0_null,NEXUS_5,1.0,en].png index 7be79c2135..5e990f7141 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedSelected_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedSelected_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4ac9e0523fc99d472a1fe8f21719e64dbb7d1ec01059dd4183aa4a152f8ead55 -size 38673 +oid sha256:03b4bfab1cbbbedd9219423834f3bdf47f40e20c0da791be2c892cb2af86cf7d +size 38694 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedSelected_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedSelected_0_null,NEXUS_5,1.0,en].png index 7ee39de1a4..7ebe08ccd8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedSelected_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedSelected_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ed68d9ebe67d5dad938a3efcd8c2b680444c650e635bdc04cfd140ba694d9f1d -size 38928 +oid sha256:1672ff3a807b387b1f780920111c19484261b36884f1f68d72e108c90a4104d2 +size 38948 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerNotSelected_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerNotSelected_0_null,NEXUS_5,1.0,en].png index b2d901dc0d..96596d6000 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerNotSelected_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerNotSelected_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1d5c9d2042dad75b48b61cdbae5b2425d7c935eb860df5d5c6fa3bcb327d13d1 -size 38842 +oid sha256:43da602c904210df0112a1af831cd2a2f7a7c5109d26605efad464a3c5b58995 +size 38864 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerSelected_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerSelected_0_null,NEXUS_5,1.0,en].png index 4998418006..5396c8592b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerSelected_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerSelected_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d4ab648f5651b7457635be3eabb914be1c976154d12a163f1c1bb2cd92168824 -size 38730 +oid sha256:bf806b2490fc8a1df278bde94535cb1b5d38f66531df85d6fd1251e6671d9f56 +size 38756 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedNotSelected_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedNotSelected_0_null,NEXUS_5,1.0,en].png index a2cd64d048..a9c192a685 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedNotSelected_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedNotSelected_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fbb713d36f8b36ce6b55f38c10323e784a80f6187e6613ded91dc531b23a7cb7 -size 36444 +oid sha256:eeaa924482fa2fc29079f7f0d4bddacb96567a2133808bed8b49be2ad7afe80f +size 36481 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedSelected_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedSelected_0_null,NEXUS_5,1.0,en].png index 2d973414d1..b16b55dc1c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedSelected_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedSelected_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:31735c42ea83974595544a0f03636a2337210f23e60d4b7f8e41d46ba21d483f -size 35920 +oid sha256:de340de9f0f07a44c9d2c1af196abc059d32f62fc857214cdf2c1d1e1951d267 +size 35915 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-D-1_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-D-1_1_null,NEXUS_5,1.0,en].png index 84f2abf39d..8ba3fa59a7 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-D-1_1_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-D-1_1_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:339e5f22a47e29b6f681ac169be3b65568b7fa5d1197b0e81fb68bef639ae5c2 -size 49033 +oid sha256:801f832469346524fdce0b5ad8654c3405daf0f21ae0601c62dc7f148b576ce8 +size 49074 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-N-1_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-N-1_2_null,NEXUS_5,1.0,en].png index dacffc90ea..0e2fb91a11 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-N-1_2_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-N-1_2_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f85799360092c7e2d02f64f32668279c4e0c39bca3d45c9db13d503ddb7bf753 -size 46162 +oid sha256:adf6f3f79b9d8f62172171dd8a172bff1958bc4698df4586bf83c73fe4c6c6f3 +size 46198 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-D-2_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-D-2_2_null,NEXUS_5,1.0,en].png index e700e58b7e..e54dcafe51 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-D-2_2_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-D-2_2_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:85fbaa916a38c9b75a527dc3fddded9e9d06a98ab20f9f3eb74596c24ba4b5b7 -size 49105 +oid sha256:7d0674f2bac8e4912bb1faec069be0e86e3b796f61e6217494cfe42cce89dca2 +size 49143 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-N-2_3_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-N-2_3_null,NEXUS_5,1.0,en].png index 26b2576508..2a9c20d9c2 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-N-2_3_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-N-2_3_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cee9e96cfefa6f84fb924857a92fd4ba04bbd196d94a6345bb821ff769fbd56d -size 45889 +oid sha256:f54d112dc90c4e2402eeab5fe8e649ffc397e208c395a19f37889038206c8179 +size 45927 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-D-0_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-D-0_0_null,NEXUS_5,1.0,en].png index 41f7fba3e5..05fb3ba861 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-D-0_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-D-0_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:53cffdc5ea12b16db3f87ab12c28fede82ce5a744c222c9f19e5c35ef751c583 -size 47179 +oid sha256:4fe5ffa68f8ea13ae4343a4fd915c58c1ff9157433248ac93ffa8ab6d8ecbbdf +size 47223 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-N-0_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-N-0_1_null,NEXUS_5,1.0,en].png index cb51eea54a..59cc1e7ce4 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-N-0_1_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-N-0_1_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:96d696014b24a2a222ba331d754d6048063a9ec573158edc41ded92ed588b60d -size 43593 +oid sha256:137bce4fc589d2275239c84ebea5a3fc07f90a31a8dbb0a5efb830a9433aa437 +size 43650 From 36fdf243ccd0ad54e8a9053a12dd96476290f982 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 13 Sep 2023 12:05:50 +0200 Subject: [PATCH 122/234] Thread decoration: add and branch isThreaded method --- .../messages/impl/timeline/TimelineStateProvider.kt | 2 ++ .../impl/timeline/components/TimelineItemEventRow.kt | 11 ++++++----- .../factories/event/TimelineItemEventFactory.kt | 2 ++ .../messages/impl/timeline/model/TimelineItem.kt | 1 + .../features/messages/fixtures/aMessageEvent.kt | 2 ++ .../timeline/groups/TimelineItemGrouperTest.kt | 1 + .../matrix/api/timeline/item/event/EventContent.kt | 1 + .../api/timeline/item/event/EventTimelineItem.kt | 5 +++++ .../impl/timeline/item/event/EventMessageMapper.kt | 1 + .../libraries/matrix/test/room/RoomSummaryFixture.kt | 2 ++ 10 files changed, 23 insertions(+), 5 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt index 8a4d45e40c..1374f4aef4 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt @@ -111,6 +111,7 @@ internal fun aTimelineItemEvent( groupPosition: TimelineItemGroupPosition = TimelineItemGroupPosition.None, sendState: LocalEventSendState = LocalEventSendState.Sent(eventId), inReplyTo: InReplyTo? = null, + isThreaded: Boolean = false, debugInfo: TimelineItemDebugInfo = aTimelineItemDebugInfo(), timelineItemReactions: TimelineItemReactions = aTimelineItemReactions(), ): TimelineItem.Event { @@ -129,6 +130,7 @@ internal fun aTimelineItemEvent( localSendState = sendState, inReplyTo = inReplyTo, debugInfo = debugInfo, + isThreaded = isThreaded, origin = null ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index 122fa03b25..befb576696 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -522,7 +522,7 @@ private fun MessageEventBubbleContent( } val replyToDetails = event.inReplyTo as? InReplyTo.Ready CommonLayout( - showThreadDecoration = false, + showThreadDecoration = event.isThreaded, timestampPosition = timestampPosition, inReplyToDetails = replyToDetails, modifier = bubbleModifier @@ -707,7 +707,7 @@ private fun ContentToPreviewWithReply() { body = "A long text which will be displayed on several lines and" + " hopefully can be manually adjusted to test different behaviors." ), - inReplyTo = aInReplyToReady(replyContent), + inReplyTo = aInReplyToReady(replyContent, true), groupPosition = TimelineItemGroupPosition.First, ), isHighlighted = false, @@ -729,7 +729,7 @@ private fun ContentToPreviewWithReply() { content = aTimelineItemImageContent().copy( aspectRatio = 5f ), - inReplyTo = aInReplyToReady(replyContent), + inReplyTo = aInReplyToReady(replyContent, false), groupPosition = TimelineItemGroupPosition.Last, ), isHighlighted = false, @@ -750,11 +750,12 @@ private fun ContentToPreviewWithReply() { } private fun aInReplyToReady( - replyContent: String + replyContent: String, + isThreaded: Boolean, ): InReplyTo.Ready { return InReplyTo.Ready( eventId = EventId("\$event"), - content = MessageContent(replyContent, null, false, TextMessageType(replyContent, null)), + content = MessageContent(replyContent, null, false, isThreaded, TextMessageType(replyContent, null)), senderId = UserId("@Sender:domain"), senderDisplayName = "Sender", senderAvatarUrl = null, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt index 4cb249af72..14f8429c85 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemEventFactory.kt @@ -71,6 +71,7 @@ class TimelineItemEventFactory @Inject constructor( url = senderAvatarUrl, size = AvatarSize.TimelineSender ) + currentTimelineItem.event return TimelineItem.Event( id = currentTimelineItem.uniqueId.toString(), eventId = currentTimelineItem.eventId, @@ -85,6 +86,7 @@ class TimelineItemEventFactory @Inject constructor( reactionsState = currentTimelineItem.computeReactionsState(), localSendState = currentTimelineItem.event.localSendState, inReplyTo = currentTimelineItem.event.inReplyTo(), + isThreaded = currentTimelineItem.event.isThreaded(), debugInfo = currentTimelineItem.event.debugInfo, origin = currentTimelineItem.event.origin, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt index b1a5c245b9..8f00dfb0dd 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/TimelineItem.kt @@ -66,6 +66,7 @@ sealed interface TimelineItem { val reactionsState: TimelineItemReactions, val localSendState: LocalEventSendState?, val inReplyTo: InReplyTo?, + val isThreaded: Boolean, val debugInfo: TimelineItemDebugInfo, val origin: TimelineItemEventOrigin?, ) : TimelineItem { diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/fixtures/aMessageEvent.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/fixtures/aMessageEvent.kt index 4f1edcb64f..6d944075d1 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/fixtures/aMessageEvent.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/fixtures/aMessageEvent.kt @@ -37,6 +37,7 @@ internal fun aMessageEvent( isMine: Boolean = true, content: TimelineItemEventContent = TimelineItemTextContent(body = A_MESSAGE, htmlDocument = null, isEdited = false), inReplyTo: InReplyTo? = null, + isThreaded: Boolean = false, debugInfo: TimelineItemDebugInfo = aTimelineItemDebugInfo(), sendState: LocalEventSendState = LocalEventSendState.Sent(AN_EVENT_ID), ) = TimelineItem.Event( @@ -52,5 +53,6 @@ internal fun aMessageEvent( localSendState = sendState, inReplyTo = inReplyTo, debugInfo = debugInfo, + isThreaded = isThreaded, origin = null ) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/groups/TimelineItemGrouperTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/groups/TimelineItemGrouperTest.kt index d5ce31f87a..4c43a8552f 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/groups/TimelineItemGrouperTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/groups/TimelineItemGrouperTest.kt @@ -44,6 +44,7 @@ class TimelineItemGrouperTest { reactionsState = aTimelineItemReactions(count = 0), localSendState = LocalEventSendState.Sent(AN_EVENT_ID), inReplyTo = null, + isThreaded = false, debugInfo = aTimelineItemDebugInfo(), origin = null ) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventContent.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventContent.kt index b16e8d2694..a3edf80bee 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventContent.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventContent.kt @@ -32,6 +32,7 @@ data class MessageContent( val body: String, val inReplyTo: InReplyTo?, val isEdited: Boolean, + val isThreaded: Boolean, val type: MessageType? ) : EventContent diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventTimelineItem.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventTimelineItem.kt index 50bf5f8ce5..49108f8d54 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventTimelineItem.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventTimelineItem.kt @@ -40,6 +40,11 @@ data class EventTimelineItem( fun inReplyTo(): InReplyTo? { return (content as? MessageContent)?.inReplyTo } + + fun isThreaded(): Boolean { + return (content as? MessageContent)?.isThreaded ?: false + } + fun hasNotLoadedInReplyTo(): Boolean { val details = inReplyTo() return details is InReplyTo.NotLoaded diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventMessageMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventMessageMapper.kt index 330a06da62..d7df699a57 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventMessageMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventMessageMapper.kt @@ -68,6 +68,7 @@ class EventMessageMapper { body = it.body(), inReplyTo = inReplyToEvent, isEdited = it.isEdited(), + isThreaded = it.isThreaded(), type = type ) } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt index 59bac7ad40..12b0325da5 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt @@ -147,6 +147,7 @@ fun aMessageContent( body: String = "body", inReplyTo: InReplyTo? = null, isEdited: Boolean = false, + isThreaded: Boolean = false, messageType: MessageType = TextMessageType( body = body, formatted = null @@ -155,6 +156,7 @@ fun aMessageContent( body = body, inReplyTo = inReplyTo, isEdited = isEdited, + isThreaded = isThreaded, type = messageType ) From e2ce6a28b6534d033a5371c1b827b35e12cc2921 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 13 Sep 2023 12:11:09 +0200 Subject: [PATCH 123/234] Thread decoration : add changelog --- changelog.d/1236.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/1236.feature diff --git a/changelog.d/1236.feature b/changelog.d/1236.feature new file mode 100644 index 0000000000..8ad652361a --- /dev/null +++ b/changelog.d/1236.feature @@ -0,0 +1 @@ +Display a thread decorator in timeline so we know when a message is coming from a thread. From b4260844157419771030ff2b7ad79208e5f6363d Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Wed, 13 Sep 2023 13:43:17 +0200 Subject: [PATCH 124/234] Test analytics when sending messages (#1296) Covers changes in https://github.com/vector-im/element-x-android/pull/1288 --- .../MessageComposerPresenterTest.kt | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt index d1d4a54073..4025dc3bee 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt @@ -24,6 +24,7 @@ import app.cash.molecule.moleculeFlow import app.cash.turbine.ReceiveTurbine import app.cash.turbine.test import com.google.common.truth.Truth.assertThat +import im.vector.app.features.analytics.plan.Composer import io.element.android.features.messages.impl.messagecomposer.AttachmentsState import io.element.android.features.messages.impl.messagecomposer.MessageComposerContextImpl import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents @@ -57,6 +58,7 @@ import io.element.android.libraries.textcomposer.Message import io.element.android.libraries.textcomposer.MessageComposerMode import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.waitForPredicate import io.mockk.mockk import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -208,6 +210,15 @@ class MessageComposerPresenterTest { val messageSentState = awaitItem() assertThat(messageSentState.richTextEditorState.messageHtml).isEqualTo("") assertThat(messageSentState.canSendMessage).isFalse() + waitForPredicate { analyticsService.capturedEvents.size == 1 } + assertThat(analyticsService.capturedEvents).containsExactly( + Composer( + inThread = false, + isEditing = false, + isReply = false, + messageType = Composer.MessageType.Text, + ) + ) } } @@ -240,6 +251,14 @@ class MessageComposerPresenterTest { assertThat(messageSentState.richTextEditorState.messageHtml).isEqualTo("") assertThat(messageSentState.canSendMessage).isFalse() assertThat(fakeMatrixRoom.editMessageCalls.first()).isEqualTo(ANOTHER_MESSAGE to ANOTHER_MESSAGE) + assertThat(analyticsService.capturedEvents).containsExactly( + Composer( + inThread = false, + isEditing = true, + isReply = false, + messageType = Composer.MessageType.Text, + ) + ) } } @@ -272,6 +291,14 @@ class MessageComposerPresenterTest { assertThat(messageSentState.richTextEditorState.messageHtml).isEqualTo("") assertThat(messageSentState.canSendMessage).isFalse() assertThat(fakeMatrixRoom.editMessageCalls.first()).isEqualTo(ANOTHER_MESSAGE to ANOTHER_MESSAGE) + assertThat(analyticsService.capturedEvents).containsExactly( + Composer( + inThread = false, + isEditing = true, + isReply = false, + messageType = Composer.MessageType.Text, + ) + ) } } @@ -304,6 +331,14 @@ class MessageComposerPresenterTest { assertThat(messageSentState.richTextEditorState.messageHtml).isEqualTo("") assertThat(messageSentState.canSendMessage).isFalse() assertThat(fakeMatrixRoom.replyMessageParameter).isEqualTo(A_REPLY to A_REPLY) + assertThat(analyticsService.capturedEvents).containsExactly( + Composer( + inThread = false, + isEditing = false, + isReply = true, + messageType = Composer.MessageType.Text, + ) + ) } } From 9932bc7ed3932a7b44149cae7fa4fb8520d245f0 Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Wed, 13 Sep 2023 10:25:30 +0200 Subject: [PATCH 125/234] Improve ListItem logical item grouping --- .../poll/impl/create/CreatePollView.kt | 71 ++++++++++--------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollView.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollView.kt index 8e3de07574..e69d23fd32 100644 --- a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollView.kt +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollView.kt @@ -18,6 +18,7 @@ package io.element.android.features.poll.impl.create import androidx.activity.compose.BackHandler import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -110,30 +111,30 @@ fun CreatePollView( .fillMaxSize(), ) { item { - Text( - text = stringResource(id = R.string.screen_create_poll_question_desc), - modifier = Modifier.padding(start = 32.dp), - style = ElementTheme.typography.fontBodyMdRegular, - ) - } - item { - ListItem( - headlineContent = { - OutlinedTextField( - value = state.question, - onValueChange = { - state.eventSink(CreatePollEvents.SetQuestion(it)) - }, - modifier = Modifier - .focusRequester(questionFocusRequester) - .fillMaxWidth(), - placeholder = { - Text(text = stringResource(id = R.string.screen_create_poll_question_hint)) - }, - keyboardOptions = keyboardOptions, - ) - } - ) + Column { + Text( + text = stringResource(id = R.string.screen_create_poll_question_desc), + modifier = Modifier.padding(start = 32.dp), + style = ElementTheme.typography.fontBodyMdRegular, + ) + ListItem( + headlineContent = { + OutlinedTextField( + value = state.question, + onValueChange = { + state.eventSink(CreatePollEvents.SetQuestion(it)) + }, + modifier = Modifier + .focusRequester(questionFocusRequester) + .fillMaxWidth(), + placeholder = { + Text(text = stringResource(id = R.string.screen_create_poll_question_hint)) + }, + keyboardOptions = keyboardOptions, + ) + } + ) + } } itemsIndexed(state.answers) { index, answer -> ListItem( @@ -175,17 +176,17 @@ fun CreatePollView( } } item { - HorizontalDivider() - } - item { - ListItem( - headlineContent = { Text(text = stringResource(id = R.string.screen_create_poll_anonymous_headline)) }, - supportingContent = { Text(text = stringResource(id = R.string.screen_create_poll_anonymous_desc)) }, - trailingContent = ListItemContent.Switch( - checked = state.pollKind == PollKind.Undisclosed, - onChange = { state.eventSink(CreatePollEvents.SetPollKind(if (it) PollKind.Undisclosed else PollKind.Disclosed)) }, - ), - ) + Column { + HorizontalDivider() + ListItem( + headlineContent = { Text(text = stringResource(id = R.string.screen_create_poll_anonymous_headline)) }, + supportingContent = { Text(text = stringResource(id = R.string.screen_create_poll_anonymous_desc)) }, + trailingContent = ListItemContent.Switch( + checked = state.pollKind == PollKind.Undisclosed, + onChange = { state.eventSink(CreatePollEvents.SetPollKind(if (it) PollKind.Undisclosed else PollKind.Disclosed)) }, + ), + ) + } } } } From 1260272c33a2b0383c5b3d081d80efc7501c0f1f Mon Sep 17 00:00:00 2001 From: David Langley Date: Wed, 13 Sep 2023 12:44:22 +0100 Subject: [PATCH 126/234] Add tests, mocks and lint --- features/preferences/impl/build.gradle.kts | 1 + .../preferences/impl/PreferencesFlowNode.kt | 1 - .../NotificationSettingsEvents.kt | 4 - .../notifications/NotificationSettingsNode.kt | 1 - .../NotificationSettingsPresenter.kt | 50 ++--- .../NotificationSettingsState.kt | 18 +- .../NotificationSettingsStateProvider.kt | 4 +- .../notifications/NotificationSettingsView.kt | 30 ++- ...EditDefaultNotificationSettingPresenter.kt | 1 - .../EditDefaultNotificationSettingView.kt | 2 +- ...faultNotificationSettingsPresenterTests.kt | 64 ++++++ .../FakeSystemNotificationsEnabledProvider.kt | 23 ++ .../NotificationSettingsPresenterTests.kt | 201 ++++++++++++++++++ .../impl/root/PreferencesRootPresenterTest.kt | 2 + .../RoomNotificationSettingsPresenter.kt | 1 - .../roomdetails/RoomDetailsPresenterTests.kt | 6 +- .../RoomNotificationSettingsPresenterTests.kt | 5 +- .../NotificationSettingsService.kt | 1 - .../RustNotificationSettingsService.kt | 6 +- .../FakeNotificationSettingsService.kt | 77 +++++-- .../matrix/test/room/FakeMatrixRoom.kt | 3 +- libraries/pushstore/test/build.gradle.kts | 31 +++ .../test/userpushstore/FakeUserPushStore.kt | 59 +++++ .../userpushstore/FakeUserPushStoreFactory.kt | 28 +++ 24 files changed, 523 insertions(+), 96 deletions(-) create mode 100644 features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/EditDefaultNotificationSettingsPresenterTests.kt create mode 100644 features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/FakeSystemNotificationsEnabledProvider.kt create mode 100644 features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTests.kt create mode 100644 libraries/pushstore/test/build.gradle.kts create mode 100644 libraries/pushstore/test/src/main/kotlin/com/element/android/libraries/pushstore/test/userpushstore/FakeUserPushStore.kt create mode 100644 libraries/pushstore/test/src/main/kotlin/com/element/android/libraries/pushstore/test/userpushstore/FakeUserPushStoreFactory.kt diff --git a/features/preferences/impl/build.gradle.kts b/features/preferences/impl/build.gradle.kts index b868dd6b81..e2df4cfa9a 100644 --- a/features/preferences/impl/build.gradle.kts +++ b/features/preferences/impl/build.gradle.kts @@ -41,6 +41,7 @@ dependencies { implementation(projects.libraries.featureflag.ui) implementation(projects.libraries.network) implementation(projects.libraries.pushstore.api) + implementation(projects.libraries.pushstore.test) implementation(projects.libraries.testtags) implementation(projects.libraries.uiStrings) implementation(projects.features.rageshake.api) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt index 4f38a26d93..1f3c24108b 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt @@ -41,7 +41,6 @@ import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.createNode import io.element.android.libraries.di.SessionScope -import io.element.android.libraries.matrix.api.core.UserId import kotlinx.parcelize.Parcelize @ContributesNode(SessionScope::class) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsEvents.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsEvents.kt index f1ee07f6b1..374b8078ca 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsEvents.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsEvents.kt @@ -16,16 +16,12 @@ package io.element.android.features.preferences.impl.notifications -import io.element.android.libraries.matrix.api.room.RoomNotificationMode - sealed interface NotificationSettingsEvents { data object RefreshSystemNotificationsEnabled : NotificationSettingsEvents data class SetNotificationsEnabled(val enabled: Boolean) : NotificationSettingsEvents data class SetAtRoomNotificationsEnabled(val enabled: Boolean) : NotificationSettingsEvents data class SetCallNotificationsEnabled(val enabled: Boolean) : NotificationSettingsEvents - data class SetDefaultGroupNotificationMode(val mode: RoomNotificationMode) : NotificationSettingsEvents - data class SetDefaultOneToOneNotificationMode(val mode: RoomNotificationMode) : NotificationSettingsEvents data object FixConfigurationMismatch : NotificationSettingsEvents data object ClearConfigurationMismatchError : NotificationSettingsEvents } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsNode.kt index d7a9532219..14ffe2868f 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsNode.kt @@ -26,7 +26,6 @@ import dagger.assisted.Assisted import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode import io.element.android.libraries.di.SessionScope -import io.element.android.libraries.matrix.api.core.UserId @ContributesNode(SessionScope::class) class NotificationSettingsNode @AssistedInject constructor( diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt index 84d140b470..923415b339 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt @@ -56,8 +56,8 @@ class NotificationSettingsPresenter @Inject constructor( .getNotificationEnabledForDevice() .collectAsState(initial = false) - val matrixSettings: MutableState = remember { - mutableStateOf(NotificationSettingsState.MatrixNotificationSettings.Uninitialized) + val matrixSettings: MutableState = remember { + mutableStateOf(NotificationSettingsState.MatrixSettings.Uninitialized) } LaunchedEffect(Unit) { @@ -69,18 +69,20 @@ class NotificationSettingsPresenter @Inject constructor( when (event) { is NotificationSettingsEvents.SetAtRoomNotificationsEnabled -> localCoroutineScope.setAtRoomNotificationsEnabled(event.enabled) is NotificationSettingsEvents.SetCallNotificationsEnabled -> localCoroutineScope.setCallNotificationsEnabled(event.enabled) - is NotificationSettingsEvents.SetDefaultGroupNotificationMode -> localCoroutineScope.setDefaultGroupNotificationMode(event.mode) - is NotificationSettingsEvents.SetDefaultOneToOneNotificationMode -> localCoroutineScope.setDefaultOneToOneNotificationMode(event.mode) is NotificationSettingsEvents.SetNotificationsEnabled -> localCoroutineScope.setNotificationsEnabled(userPushStore, event.enabled) - NotificationSettingsEvents.ClearConfigurationMismatchError -> matrixSettings.value = NotificationSettingsState.MatrixNotificationSettings.InvalidNotificationSettingsState(fixFailed = false) + NotificationSettingsEvents.ClearConfigurationMismatchError -> { + matrixSettings.value = NotificationSettingsState.MatrixSettings.Invalid(fixFailed = false) + } NotificationSettingsEvents.FixConfigurationMismatch -> localCoroutineScope.fixConfigurationMismatch(matrixSettings) - NotificationSettingsEvents.RefreshSystemNotificationsEnabled -> systemNotificationsEnabled.value = systemNotificationsEnabledProvider.notificationsEnabled() + NotificationSettingsEvents.RefreshSystemNotificationsEnabled -> { + systemNotificationsEnabled.value = systemNotificationsEnabledProvider.notificationsEnabled() + } } } return NotificationSettingsState( - matrixNotificationSettings = matrixSettings.value, - appNotificationSettings = NotificationSettingsState.AppNotificationSettings( + matrixSettings = matrixSettings.value, + appSettings = NotificationSettingsState.AppSettings( systemNotificationsEnabled = systemNotificationsEnabled.value, appNotificationsEnabled = appNotificationsEnabled.value ), @@ -89,7 +91,7 @@ class NotificationSettingsPresenter @Inject constructor( } @OptIn(FlowPreview::class) - private fun CoroutineScope.observeNotificationSettings(target: MutableState) { + private fun CoroutineScope.observeNotificationSettings(target: MutableState) { notificationSettingsService.notificationSettingsChangeFlow .debounce(0.5.seconds) .onEach { @@ -98,7 +100,7 @@ class NotificationSettingsPresenter @Inject constructor( .launchIn(this) } - private fun CoroutineScope.fetchSettings(target: MutableState) = launch { + private fun CoroutineScope.fetchSettings(target: MutableState) = launch { val groupDefaultMode = notificationSettingsService.getDefaultRoomNotificationMode(isEncrypted = false, isOneToOne = false).getOrThrow() val encryptedGroupDefaultMode = notificationSettingsService.getDefaultRoomNotificationMode(isEncrypted = true, isOneToOne = false).getOrThrow() @@ -106,14 +108,14 @@ class NotificationSettingsPresenter @Inject constructor( val encryptedOneToOneDefaultMode = notificationSettingsService.getDefaultRoomNotificationMode(isEncrypted = true, isOneToOne = true).getOrThrow() if(groupDefaultMode != encryptedGroupDefaultMode || oneToOneDefaultMode != encryptedOneToOneDefaultMode) { - target.value = NotificationSettingsState.MatrixNotificationSettings.InvalidNotificationSettingsState(fixFailed = false) + target.value = NotificationSettingsState.MatrixSettings.Invalid(fixFailed = false) return@launch } val callNotificationsEnabled = notificationSettingsService.isCallEnabled().getOrThrow() val atRoomNotificationsEnabled = notificationSettingsService.isRoomMentionEnabled().getOrThrow() - target.value = NotificationSettingsState.MatrixNotificationSettings.ValidNotificationSettingsState( + target.value = NotificationSettingsState.MatrixSettings.Valid( atRoomNotificationsEnabled = atRoomNotificationsEnabled, callNotificationsEnabled = callNotificationsEnabled, defaultGroupNotificationMode = encryptedGroupDefaultMode, @@ -121,7 +123,7 @@ class NotificationSettingsPresenter @Inject constructor( ) } - private fun CoroutineScope.fixConfigurationMismatch(target: MutableState) = launch { + private fun CoroutineScope.fixConfigurationMismatch(target: MutableState) = launch { runCatching { val groupDefaultMode = notificationSettingsService.getDefaultRoomNotificationMode(isEncrypted = false, isOneToOne = false).getOrThrow() val encryptedGroupDefaultMode = notificationSettingsService.getDefaultRoomNotificationMode(isEncrypted = true, isOneToOne = false).getOrThrow() @@ -147,7 +149,7 @@ class NotificationSettingsPresenter @Inject constructor( }.fold( onSuccess = {}, onFailure = { - target.value = NotificationSettingsState.MatrixNotificationSettings.InvalidNotificationSettingsState(fixFailed = true) + target.value = NotificationSettingsState.MatrixSettings.Invalid(fixFailed = true) } ) } @@ -160,27 +162,7 @@ class NotificationSettingsPresenter @Inject constructor( notificationSettingsService.setCallEnabled(enabled) } - private fun CoroutineScope.setDefaultGroupNotificationMode(mode: RoomNotificationMode) = launch { - notificationSettingsService.setDefaultRoomNotificationMode(false, mode, false) - notificationSettingsService.setDefaultRoomNotificationMode(true, mode, false) - } - - private fun CoroutineScope.setDefaultOneToOneNotificationMode(mode: RoomNotificationMode) = launch { - notificationSettingsService.setDefaultRoomNotificationMode(false, mode, true) - notificationSettingsService.setDefaultRoomNotificationMode(true, mode, true) - } - private fun CoroutineScope.setNotificationsEnabled(userPushStore: UserPushStore, enabled: Boolean) = launch { userPushStore.setNotificationEnabledForDevice(enabled) } - - private fun CoroutineScope.getDefaultRoomNotificationMode(isOneToOne: Boolean, defaultRoomNotificationMode: MutableState) = launch { - val encryptedMode = notificationSettingsService.getDefaultRoomNotificationMode(true, isOneToOne).getOrThrow() - val unencryptedMode = notificationSettingsService.getDefaultRoomNotificationMode(false, isOneToOne).getOrThrow() - if (encryptedMode == unencryptedMode) { - defaultRoomNotificationMode.value - } else { - defaultRoomNotificationMode.value = null - } - } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsState.kt index ac3502b89b..cf3cf6e3d0 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsState.kt @@ -21,25 +21,25 @@ import io.element.android.libraries.matrix.api.room.RoomNotificationMode @Immutable data class NotificationSettingsState( - val matrixNotificationSettings: MatrixNotificationSettings, - val appNotificationSettings: AppNotificationSettings, + val matrixSettings: MatrixSettings, + val appSettings: AppSettings, val eventSink: (NotificationSettingsEvents) -> Unit, ) { - sealed interface MatrixNotificationSettings { - data object Uninitialized : MatrixNotificationSettings - data class ValidNotificationSettingsState( + sealed interface MatrixSettings { + data object Uninitialized : MatrixSettings + data class Valid( val atRoomNotificationsEnabled: Boolean, val callNotificationsEnabled: Boolean, val defaultGroupNotificationMode: RoomNotificationMode?, val defaultOneToOneNotificationMode: RoomNotificationMode?, - ) : MatrixNotificationSettings + ) : MatrixSettings - data class InvalidNotificationSettingsState( + data class Invalid( val fixFailed: Boolean - ) : MatrixNotificationSettings + ) : MatrixSettings } - data class AppNotificationSettings( + data class AppSettings( val systemNotificationsEnabled: Boolean, val appNotificationsEnabled: Boolean, ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsStateProvider.kt index a4b9014b0c..1e653c47e0 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsStateProvider.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsStateProvider.kt @@ -27,13 +27,13 @@ open class NotificationSettingsStateProvider : PreviewParameterProvider InvalidNotificationSettingsView( - showError = state.matrixNotificationSettings.fixFailed, + when (state.matrixSettings) { + is NotificationSettingsState.MatrixSettings.Invalid -> InvalidNotificationSettingsView( + showError = state.matrixSettings.fixFailed, onContinueClicked = { state.eventSink(NotificationSettingsEvents.FixConfigurationMismatch) }, onDismissError = { state.eventSink(NotificationSettingsEvents.ClearConfigurationMismatchError) }, - modifier = modifier, ) - NotificationSettingsState.MatrixNotificationSettings.Uninitialized -> return@PreferenceView - is NotificationSettingsState.MatrixNotificationSettings.ValidNotificationSettingsState -> NotificationSettingsContentView( - matrixSettings = state.matrixNotificationSettings, - systemSettings = state.appNotificationSettings, + NotificationSettingsState.MatrixSettings.Uninitialized -> return@PreferenceView + is NotificationSettingsState.MatrixSettings.Valid -> NotificationSettingsContentView( + matrixSettings = state.matrixSettings, + systemSettings = state.appSettings, onNotificationsEnabledChanged = { state.eventSink(NotificationSettingsEvents.SetNotificationsEnabled(it))}, onGroupChatsClicked = { onOpenEditDefault(false) }, onDirectChatsClicked = { onOpenEditDefault(true) }, onMentionNotificationsChanged = { state.eventSink(NotificationSettingsEvents.SetAtRoomNotificationsEnabled(it)) }, onCallsNotificationsChanged = { state.eventSink(NotificationSettingsEvents.SetCallNotificationsEnabled(it)) }, - modifier = modifier, ) } } @@ -98,8 +96,8 @@ fun NotificationSettingsView( @Composable private fun NotificationSettingsContentView( - matrixSettings: NotificationSettingsState.MatrixNotificationSettings.ValidNotificationSettingsState, - systemSettings: NotificationSettingsState.AppNotificationSettings, + matrixSettings: NotificationSettingsState.MatrixSettings.Valid, + systemSettings: NotificationSettingsState.AppSettings, onNotificationsEnabledChanged: (Boolean) -> Unit, onGroupChatsClicked: () -> Unit, onDirectChatsClicked: () -> Unit, @@ -252,16 +250,16 @@ private fun ContentToPreview(state: NotificationSettingsState) { @Preview @Composable -internal fun InvalidNotificationSettingsViewightPreview(@PreviewParameter(NotificationSettingsStateProvider::class) state: NotificationSettingsState) = - ElementPreviewLight { InvalidNotificationSettingsContentToPreview(state) } +internal fun InvalidNotificationSettingsViewightPreview() = + ElementPreviewLight { InvalidNotificationSettingsContentToPreview() } @Preview @Composable -internal fun InvalidNotificationSettingsViewDarkPreview(@PreviewParameter(NotificationSettingsStateProvider::class) state: NotificationSettingsState) = - ElementPreviewDark { InvalidNotificationSettingsContentToPreview(state) } +internal fun InvalidNotificationSettingsViewDarkPreview() = + ElementPreviewDark { InvalidNotificationSettingsContentToPreview() } @Composable -private fun InvalidNotificationSettingsContentToPreview(state: NotificationSettingsState) { +private fun InvalidNotificationSettingsContentToPreview() { InvalidNotificationSettingsView( showError = false, onContinueClicked = {}, diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingPresenter.kt index b146155486..cc15e5bdd8 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingPresenter.kt @@ -26,7 +26,6 @@ import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.room.RoomNotificationMode import kotlinx.coroutines.CoroutineScope diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt index 5c00cd49cb..777f07b9c7 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt @@ -55,7 +55,7 @@ fun EditDefaultNotificationSettingView( PreferenceCategory(title = stringResource(id = categoryTitle)) { if (state.mode != null) { - Column(modifier = modifier.selectableGroup()) { + Column(modifier = Modifier.selectableGroup()) { validModes.forEach { item -> DefaultNotificationSettingOption( mode = item, diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/EditDefaultNotificationSettingsPresenterTests.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/EditDefaultNotificationSettingsPresenterTests.kt new file mode 100644 index 0000000000..e8c9ff4fe5 --- /dev/null +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/EditDefaultNotificationSettingsPresenterTests.kt @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.notifications + +import app.cash.molecule.RecompositionMode +import app.cash.molecule.moleculeFlow +import app.cash.turbine.test +import com.google.common.truth.Truth +import io.element.android.features.preferences.impl.notifications.edit.EditDefaultNotificationSettingPresenter +import io.element.android.features.preferences.impl.notifications.edit.EditDefaultNotificationSettingStateEvents +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService +import io.element.android.tests.testutils.consumeItemsUntilPredicate +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class EditDefaultNotificationSettingsPresenterTests { + @Test + fun `present - ensures initial state is correct`() = runTest { + val notificationSettingsService = FakeNotificationSettingsService() + val presenter = EditDefaultNotificationSettingPresenter(notificationSettingsService = notificationSettingsService, isOneToOne = false) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + Truth.assertThat(initialState.mode).isNull() + Truth.assertThat(initialState.isOneToOne).isFalse() + + val loadedState = consumeItemsUntilPredicate { + it.mode == RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY + }.last() + Truth.assertThat(loadedState.mode).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY) + } + } + + @Test + fun `present - edit default notification setting`() = runTest { + val notificationSettingsService = FakeNotificationSettingsService() + val presenter = EditDefaultNotificationSettingPresenter(notificationSettingsService = notificationSettingsService, isOneToOne = false) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem().eventSink(EditDefaultNotificationSettingStateEvents.SetNotificationMode(RoomNotificationMode.ALL_MESSAGES)) + val loadedState = consumeItemsUntilPredicate { + it.mode == RoomNotificationMode.ALL_MESSAGES + }.last() + Truth.assertThat(loadedState.mode).isEqualTo(RoomNotificationMode.ALL_MESSAGES) + } + } +} diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/FakeSystemNotificationsEnabledProvider.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/FakeSystemNotificationsEnabledProvider.kt new file mode 100644 index 0000000000..1a7c1b5004 --- /dev/null +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/FakeSystemNotificationsEnabledProvider.kt @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.notifications + +class FakeSystemNotificationsEnabledProvider: SystemNotificationsEnabledProvider { + override fun notificationsEnabled(): Boolean { + return true + } +} diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTests.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTests.kt new file mode 100644 index 0000000000..70d15c7a71 --- /dev/null +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTests.kt @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.notifications + +import app.cash.molecule.RecompositionMode +import app.cash.molecule.moleculeFlow +import app.cash.turbine.test +import com.element.android.libraries.pushstore.test.userpushstore.FakeUserPushStoreFactory +import com.google.common.truth.Truth +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService +import io.element.android.tests.testutils.consumeItemsUntilPredicate +import kotlinx.coroutines.test.runTest +import org.junit.Test +import kotlin.time.Duration.Companion.milliseconds + +class NotificationSettingsPresenterTests { + @Test + fun `present - ensures initial state is correct`() = runTest { + val presenter = aNotificationPresenter() + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + Truth.assertThat(initialState.appSettings.appNotificationsEnabled).isFalse() + Truth.assertThat(initialState.appSettings.systemNotificationsEnabled).isTrue() + Truth.assertThat(initialState.matrixSettings).isEqualTo(NotificationSettingsState.MatrixSettings.Uninitialized) + + val loadedState = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid + }.last() + Truth.assertThat(loadedState.appSettings.appNotificationsEnabled).isTrue() + Truth.assertThat(loadedState.appSettings.systemNotificationsEnabled).isTrue() + val valid = loadedState.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid + Truth.assertThat(valid?.atRoomNotificationsEnabled).isFalse() + Truth.assertThat(valid?.callNotificationsEnabled).isFalse() + Truth.assertThat(valid?.defaultGroupNotificationMode).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY) + Truth.assertThat(valid?.defaultOneToOneNotificationMode).isEqualTo(RoomNotificationMode.ALL_MESSAGES) + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - default group notification mode changed`() = runTest { + val notificationSettingsService = FakeNotificationSettingsService() + val presenter = aNotificationPresenter(notificationSettingsService) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + + notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = true, isOneToOne = false, mode = RoomNotificationMode.ALL_MESSAGES) + notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = false, isOneToOne = false, mode = RoomNotificationMode.ALL_MESSAGES) + val updatedState = consumeItemsUntilPredicate { + (it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid) + ?.defaultGroupNotificationMode == RoomNotificationMode.ALL_MESSAGES + }.last() + val valid = updatedState.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid + Truth.assertThat(valid?.defaultGroupNotificationMode).isEqualTo(RoomNotificationMode.ALL_MESSAGES) + } + } + + @Test + fun `present - notification settings mismatched`() = runTest { + val notificationSettingsService = FakeNotificationSettingsService() + val presenter = aNotificationPresenter(notificationSettingsService) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + + notificationSettingsService.setDefaultRoomNotificationMode( + isEncrypted = true, + isOneToOne = false, + mode = RoomNotificationMode.ALL_MESSAGES + ) + notificationSettingsService.setDefaultRoomNotificationMode( + isEncrypted = false, + isOneToOne = false, + mode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY + ) + val updatedState = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Invalid + }.last() + Truth.assertThat(updatedState.matrixSettings).isEqualTo(NotificationSettingsState.MatrixSettings.Invalid(fixFailed = false)) + } + } + + @Test + fun `present - fix notification settings mismatched`() = runTest { + // Start with a mismatched configuration + val notificationSettingsService = FakeNotificationSettingsService( + initialEncryptedGroupDefaultMode = RoomNotificationMode.ALL_MESSAGES, + initialGroupDefaultMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY, + initialEncryptedOneToOneDefaultMode = RoomNotificationMode.ALL_MESSAGES, + initialOneToOneDefaultMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY + ) + val presenter = aNotificationPresenter(notificationSettingsService) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink(NotificationSettingsEvents.FixConfigurationMismatch) + val fixedState = consumeItemsUntilPredicate(timeout = 2000.milliseconds) { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid + }.last() + + val fixedMatrixState = fixedState.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid + Truth.assertThat(fixedMatrixState?.defaultGroupNotificationMode).isEqualTo(RoomNotificationMode.ALL_MESSAGES) + } + } + + @Test + fun `present - set notifications enabled`() = runTest { + val presenter = aNotificationPresenter() + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val loadedState = consumeItemsUntilPredicate { + it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid + }.last() + Truth.assertThat(loadedState.appSettings.appNotificationsEnabled).isTrue() + + loadedState.eventSink(NotificationSettingsEvents.SetNotificationsEnabled(false)) + val updatedState = consumeItemsUntilPredicate { + !it.appSettings.appNotificationsEnabled + }.last() + Truth.assertThat(updatedState.appSettings.appNotificationsEnabled).isFalse() + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - set call notifications enabled`() = runTest { + val presenter = aNotificationPresenter() + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val loadedState = consumeItemsUntilPredicate { + (it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid)?.callNotificationsEnabled == false + }.last() + val validMatrixState = loadedState.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid + Truth.assertThat(validMatrixState?.callNotificationsEnabled).isFalse() + + loadedState.eventSink(NotificationSettingsEvents.SetCallNotificationsEnabled(true)) + val updatedState = consumeItemsUntilPredicate { + (it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid)?.callNotificationsEnabled == true + }.last() + val updatedMatrixState = updatedState.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid + Truth.assertThat(updatedMatrixState?.callNotificationsEnabled).isTrue() + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - set atRoom notifications enabled`() = runTest { + val presenter = aNotificationPresenter() + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val loadedState = consumeItemsUntilPredicate { + (it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid)?.atRoomNotificationsEnabled == false + }.last() + val validMatrixState = loadedState.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid + Truth.assertThat(validMatrixState?.atRoomNotificationsEnabled).isFalse() + + loadedState.eventSink(NotificationSettingsEvents.SetAtRoomNotificationsEnabled(true)) + val updatedState = consumeItemsUntilPredicate { + (it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid)?.atRoomNotificationsEnabled == true + }.last() + val updatedMatrixState = updatedState.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid + Truth.assertThat(updatedMatrixState?.atRoomNotificationsEnabled).isTrue() + cancelAndIgnoreRemainingEvents() + } + } + + private fun aNotificationPresenter( + notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService() + ) : NotificationSettingsPresenter { + val matrixClient = FakeMatrixClient(notificationSettingsService = notificationSettingsService) + return NotificationSettingsPresenter( + notificationSettingsService = notificationSettingsService, + userPushStoreFactory = FakeUserPushStoreFactory(), + matrixClient = matrixClient, + systemNotificationsEnabledProvider = FakeSystemNotificationsEnabledProvider(), + ) + } +} 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 5217519071..99f7fc06a2 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 @@ -24,6 +24,7 @@ import io.element.android.features.logout.impl.DefaultLogoutPreferencePresenter import io.element.android.libraries.architecture.Async import io.element.android.libraries.core.meta.BuildType import io.element.android.libraries.designsystem.utils.SnackbarDispatcher +import io.element.android.libraries.featureflag.test.FakeFeatureFlagService 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_USER_NAME @@ -53,6 +54,7 @@ class PreferencesRootPresenterTest { BuildType.DEBUG, FakeVersionFormatter(), SnackbarDispatcher(), + FakeFeatureFlagService() ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt index f1993d27b1..a6e2477bcc 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt @@ -35,7 +35,6 @@ import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch -import timber.log.Timber import javax.inject.Inject import kotlin.time.Duration.Companion.seconds diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt index bbd67bd11a..010a335267 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt @@ -385,7 +385,7 @@ class RoomDetailsPresenterTests { @Test fun `present - mute room notifications`() = runTest { val leaveRoomPresenter = LeaveRoomPresenterFake() - val notificationSettingsService = FakeNotificationSettingsService(initialMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY) + val notificationSettingsService = FakeNotificationSettingsService(initialRoomMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY) val room = aMatrixRoom(notificationSettingsService = notificationSettingsService) val presenter = aRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers(), notificationSettingsService) moleculeFlow(RecompositionMode.Immediate) { @@ -404,8 +404,8 @@ class RoomDetailsPresenterTests { fun `present - unmute room notifications`() = runTest { val leaveRoomPresenter = LeaveRoomPresenterFake() val notificationSettingsService = FakeNotificationSettingsService( - initialMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY, - initialDefaultMode = RoomNotificationMode.ALL_MESSAGES + initialRoomMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY, + initialEncryptedGroupDefaultMode = RoomNotificationMode.ALL_MESSAGES ) val room = aMatrixRoom(notificationSettingsService = notificationSettingsService) val presenter = aRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers(), notificationSettingsService) diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/notificationsettings/RoomNotificationSettingsPresenterTests.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/notificationsettings/RoomNotificationSettingsPresenterTests.kt index 29bec7f622..a1b7831ce2 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/notificationsettings/RoomNotificationSettingsPresenterTests.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/notificationsettings/RoomNotificationSettingsPresenterTests.kt @@ -24,7 +24,6 @@ import io.element.android.features.roomdetails.aMatrixRoom import io.element.android.features.roomdetails.impl.notificationsettings.RoomNotificationSettingsEvents import io.element.android.features.roomdetails.impl.notificationsettings.RoomNotificationSettingsPresenter import io.element.android.libraries.matrix.api.room.RoomNotificationMode -import io.element.android.libraries.matrix.test.A_ROOM_NOTIFICATION_MODE import io.element.android.tests.testutils.consumeItemsUntilPredicate import kotlinx.coroutines.test.runTest import org.junit.Test @@ -67,9 +66,9 @@ class RoomNotificationSettingsPresenterTests { initialState.eventSink(RoomNotificationSettingsEvents.RoomNotificationModeChanged(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)) initialState.eventSink(RoomNotificationSettingsEvents.SetNotificationMode(true)) val defaultState = consumeItemsUntilPredicate { - it.roomNotificationSettings?.mode == A_ROOM_NOTIFICATION_MODE + it.roomNotificationSettings?.mode == RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY }.last() - Truth.assertThat(defaultState.roomNotificationSettings?.mode).isEqualTo(A_ROOM_NOTIFICATION_MODE) + Truth.assertThat(defaultState.roomNotificationSettings?.mode).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY) } } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt index 3e62b0c97f..5a81edb052 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt @@ -21,7 +21,6 @@ import io.element.android.libraries.matrix.api.room.MatrixRoomNotificationSettin import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.RoomNotificationSettings import kotlinx.coroutines.flow.SharedFlow -import kotlinx.coroutines.withContext interface NotificationSettingsService { /** diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt index 7dea15a809..a2fffdbdfb 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt @@ -57,7 +57,11 @@ class RustNotificationSettingsService( notificationSettings.getDefaultRoomNotificationMode(isEncrypted, isOneToOne).let(RoomNotificationSettingsMapper::mapMode) } - override suspend fun setDefaultRoomNotificationMode(isEncrypted: Boolean, mode: RoomNotificationMode, isOneToOne: Boolean): Result = withContext(dispatchers.io) { + override suspend fun setDefaultRoomNotificationMode( + isEncrypted: Boolean, + mode: RoomNotificationMode, + isOneToOne: Boolean + ): Result = withContext(dispatchers.io) { runCatching { notificationSettings.setDefaultRoomNotificationMode(isEncrypted, isOneToOne, mode.let(RoomNotificationSettingsMapper::mapMode)) } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt index 18c9f00e38..77592d6d1f 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt @@ -25,32 +25,75 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharedFlow class FakeNotificationSettingsService( - initialMode: RoomNotificationMode = A_ROOM_NOTIFICATION_MODE, - initialDefaultMode: RoomNotificationMode = A_ROOM_NOTIFICATION_MODE + initialRoomMode: RoomNotificationMode = A_ROOM_NOTIFICATION_MODE, + initialGroupDefaultMode: RoomNotificationMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY, + initialEncryptedGroupDefaultMode: RoomNotificationMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY, + initialOneToOneDefaultMode: RoomNotificationMode = RoomNotificationMode.ALL_MESSAGES, + initialEncryptedOneToOneDefaultMode: RoomNotificationMode = RoomNotificationMode.ALL_MESSAGES, ) : NotificationSettingsService { - private var _roomNotificationSettingsStateFlow = MutableStateFlow(Unit) - private var defaultRoomNotificationMode: RoomNotificationMode = initialDefaultMode - private var roomNotificationMode: RoomNotificationMode = initialMode + private var _notificationSettingsStateFlow = MutableStateFlow(Unit) + private var defaultGroupRoomNotificationMode: RoomNotificationMode = initialGroupDefaultMode + private var defaultEncryptedGroupRoomNotificationMode: RoomNotificationMode = initialEncryptedGroupDefaultMode + private var defaultOneToOneRoomNotificationMode: RoomNotificationMode = initialOneToOneDefaultMode + private var defaultEncryptedOneToOneRoomNotificationMode: RoomNotificationMode = initialEncryptedOneToOneDefaultMode + private var roomNotificationMode: RoomNotificationMode = initialRoomMode + private var callNotificationsEnabled = false + private var atRoomNotificationsEnabled = false override val notificationSettingsChangeFlow: SharedFlow - get() = _roomNotificationSettingsStateFlow + get() = _notificationSettingsStateFlow - override suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, membersCount: Long): Result { - return Result.success(RoomNotificationSettings(mode = roomNotificationMode, isDefault = roomNotificationMode == defaultRoomNotificationMode)) + override suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, isOneToOne: Boolean): Result { + return Result.success( + RoomNotificationSettings( + mode = roomNotificationMode, + isDefault = roomNotificationMode == defaultEncryptedGroupRoomNotificationMode + ) + ) } - override suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, membersCount: Long): Result { - return Result.success(defaultRoomNotificationMode) + override suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, isOneToOne: Boolean): Result { + return if (isOneToOne) { + if (isEncrypted) { + Result.success(defaultEncryptedOneToOneRoomNotificationMode) + } else { + Result.success(defaultOneToOneRoomNotificationMode) + } + } else { + if (isEncrypted) { + Result.success(defaultEncryptedGroupRoomNotificationMode) + } else { + Result.success(defaultGroupRoomNotificationMode) + } + } + } + + override suspend fun setDefaultRoomNotificationMode(isEncrypted: Boolean, mode: RoomNotificationMode, isOneToOne: Boolean): Result { + if (isOneToOne) { + if (isEncrypted) { + defaultEncryptedOneToOneRoomNotificationMode = mode + } else { + defaultOneToOneRoomNotificationMode = mode + } + } else { + if (isEncrypted) { + defaultEncryptedGroupRoomNotificationMode = mode + } else { + defaultGroupRoomNotificationMode = mode + } + } + _notificationSettingsStateFlow.emit(Unit) + return Result.success(Unit) } override suspend fun setRoomNotificationMode(roomId: RoomId, mode: RoomNotificationMode): Result { roomNotificationMode = mode - _roomNotificationSettingsStateFlow.emit(Unit) + _notificationSettingsStateFlow.emit(Unit) return Result.success(Unit) } override suspend fun restoreDefaultRoomNotificationMode(roomId: RoomId): Result { - roomNotificationMode = defaultRoomNotificationMode - _roomNotificationSettingsStateFlow.emit(Unit) + roomNotificationMode = defaultEncryptedGroupRoomNotificationMode + _notificationSettingsStateFlow.emit(Unit) return Result.success(Unit) } @@ -58,23 +101,25 @@ class FakeNotificationSettingsService( return setRoomNotificationMode(roomId, RoomNotificationMode.MUTE) } - override suspend fun unmuteRoom(roomId: RoomId, isEncrypted: Boolean, membersCount: Long): Result { + override suspend fun unmuteRoom(roomId: RoomId, isEncrypted: Boolean, isOneToOne: Boolean): Result { return restoreDefaultRoomNotificationMode(roomId) } override suspend fun isRoomMentionEnabled(): Result { - return Result.success(false) + return Result.success(atRoomNotificationsEnabled) } override suspend fun setRoomMentionEnabled(enabled: Boolean): Result { + atRoomNotificationsEnabled = enabled return Result.success(Unit) } override suspend fun isCallEnabled(): Result { - return Result.success(false) + return Result.success(callNotificationsEnabled) } override suspend fun setCallEnabled(enabled: Boolean): Result { + callNotificationsEnabled = enabled return Result.success(Unit) } } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index d53b8e2c92..f551a33225 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -72,7 +72,6 @@ class FakeMatrixRoom( private var userAvatarUrlResult = Result.success(null) private var updateMembersResult: Result = Result.success(Unit) private var joinRoomResult = Result.success(Unit) - private var updateRoomNotificationSettingsResult: Result = Result.success(Unit) private var inviteUserResult = Result.success(Unit) private var canInviteResult = Result.success(true) private var canRedactResult = Result.success(canRedact) @@ -149,7 +148,7 @@ class FakeMatrixRoom( } override suspend fun updateRoomNotificationSettings(): Result = simulateLongTask { - val notificationSettings = notificationSettingsService.getRoomNotificationSettings(roomId, isEncrypted, activeMemberCount).getOrThrow() + val notificationSettings = notificationSettingsService.getRoomNotificationSettings(roomId, isEncrypted, isOneToOne).getOrThrow() roomNotificationSettingsStateFlow.value = MatrixRoomNotificationSettingsState.Ready(notificationSettings) return Result.success(Unit) } diff --git a/libraries/pushstore/test/build.gradle.kts b/libraries/pushstore/test/build.gradle.kts new file mode 100644 index 0000000000..a100c40f7d --- /dev/null +++ b/libraries/pushstore/test/build.gradle.kts @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + id("io.element.android-library") +} + +android { + namespace = "io.element.android.libraries.pushstore.test" +} + +dependencies { + api(projects.libraries.matrix.api) + api(libs.coroutines.core) + implementation(libs.coroutines.test) + implementation(projects.tests.testutils) + implementation(projects.libraries.pushstore.api) +} diff --git a/libraries/pushstore/test/src/main/kotlin/com/element/android/libraries/pushstore/test/userpushstore/FakeUserPushStore.kt b/libraries/pushstore/test/src/main/kotlin/com/element/android/libraries/pushstore/test/userpushstore/FakeUserPushStore.kt new file mode 100644 index 0000000000..c697e0d3c9 --- /dev/null +++ b/libraries/pushstore/test/src/main/kotlin/com/element/android/libraries/pushstore/test/userpushstore/FakeUserPushStore.kt @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.element.android.libraries.pushstore.test.userpushstore + +import io.element.android.libraries.pushstore.api.UserPushStore +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow + +class FakeUserPushStore: UserPushStore { + + private var pushProviderName: String? = null + private var currentRegisteredPushKey: String? = null + private val notificationEnabledForDevice = MutableStateFlow(true) + override suspend fun getPushProviderName(): String? { + return pushProviderName + } + + override suspend fun setPushProviderName(value: String) { + pushProviderName = value + } + + override suspend fun getCurrentRegisteredPushKey(): String? { + return currentRegisteredPushKey + } + + override suspend fun setCurrentRegisteredPushKey(value: String) { + currentRegisteredPushKey = value + } + + override fun getNotificationEnabledForDevice(): Flow { + return notificationEnabledForDevice + } + + override suspend fun setNotificationEnabledForDevice(enabled: Boolean) { + notificationEnabledForDevice.value = enabled + } + + override fun useCompleteNotificationFormat(): Boolean { + return true + } + + override suspend fun reset() { + + } +} diff --git a/libraries/pushstore/test/src/main/kotlin/com/element/android/libraries/pushstore/test/userpushstore/FakeUserPushStoreFactory.kt b/libraries/pushstore/test/src/main/kotlin/com/element/android/libraries/pushstore/test/userpushstore/FakeUserPushStoreFactory.kt new file mode 100644 index 0000000000..f51893b00a --- /dev/null +++ b/libraries/pushstore/test/src/main/kotlin/com/element/android/libraries/pushstore/test/userpushstore/FakeUserPushStoreFactory.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.element.android.libraries.pushstore.test.userpushstore + +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.pushstore.api.UserPushStore +import io.element.android.libraries.pushstore.api.UserPushStoreFactory + +class FakeUserPushStoreFactory: UserPushStoreFactory { + override fun create(userId: SessionId): UserPushStore { + return FakeUserPushStore() + } +} + From c6d68e8392304e1e6118e26dee2970ae627c3972 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 13 Sep 2023 13:49:08 +0200 Subject: [PATCH 127/234] Maestro cli 1.32.0 does not like integer with this format :/ --- .maestro/tests/account/changeServer.yaml | 2 +- .maestro/tests/assertions/assertAnalyticsDisplayed.yaml | 2 +- .maestro/tests/assertions/assertHomeDisplayed.yaml | 2 +- .maestro/tests/assertions/assertInitDisplayed.yaml | 2 +- .maestro/tests/assertions/assertLoginDisplayed.yaml | 2 +- .maestro/tests/assertions/assertRoomListSynced.yaml | 2 +- .maestro/tests/assertions/assertWelcomeScreenDisplayed.yaml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.maestro/tests/account/changeServer.yaml b/.maestro/tests/account/changeServer.yaml index e503589f5c..c6b092e018 100644 --- a/.maestro/tests/account/changeServer.yaml +++ b/.maestro/tests/account/changeServer.yaml @@ -15,7 +15,7 @@ appId: ${APP_ID} - tapOn: "gnuradio.org" - extendedWaitUntil: visible: "This server currently doesn’t support sliding sync." - timeout: 10_000 + timeout: 10000 - tapOn: "Cancel" - back - back diff --git a/.maestro/tests/assertions/assertAnalyticsDisplayed.yaml b/.maestro/tests/assertions/assertAnalyticsDisplayed.yaml index 96a91a24af..9c63c99ffc 100644 --- a/.maestro/tests/assertions/assertAnalyticsDisplayed.yaml +++ b/.maestro/tests/assertions/assertAnalyticsDisplayed.yaml @@ -2,4 +2,4 @@ appId: ${APP_ID} --- - extendedWaitUntil: visible: "Help improve Element X dbg" - timeout: 10_000 + timeout: 10000 diff --git a/.maestro/tests/assertions/assertHomeDisplayed.yaml b/.maestro/tests/assertions/assertHomeDisplayed.yaml index 6e9eec50db..ca409705e1 100644 --- a/.maestro/tests/assertions/assertHomeDisplayed.yaml +++ b/.maestro/tests/assertions/assertHomeDisplayed.yaml @@ -2,4 +2,4 @@ appId: ${APP_ID} --- - extendedWaitUntil: visible: "All Chats" - timeout: 10_000 + timeout: 10000 diff --git a/.maestro/tests/assertions/assertInitDisplayed.yaml b/.maestro/tests/assertions/assertInitDisplayed.yaml index 417ac87711..9424f382c1 100644 --- a/.maestro/tests/assertions/assertInitDisplayed.yaml +++ b/.maestro/tests/assertions/assertInitDisplayed.yaml @@ -2,4 +2,4 @@ appId: ${APP_ID} --- - extendedWaitUntil: visible: "Be in your element" - timeout: 10_000 + timeout: 10000 diff --git a/.maestro/tests/assertions/assertLoginDisplayed.yaml b/.maestro/tests/assertions/assertLoginDisplayed.yaml index 3abd86ceef..b18078f916 100644 --- a/.maestro/tests/assertions/assertLoginDisplayed.yaml +++ b/.maestro/tests/assertions/assertLoginDisplayed.yaml @@ -2,4 +2,4 @@ appId: ${APP_ID} --- - extendedWaitUntil: visible: "Change account provider" - timeout: 10_000 + timeout: 10000 diff --git a/.maestro/tests/assertions/assertRoomListSynced.yaml b/.maestro/tests/assertions/assertRoomListSynced.yaml index 2d13c17df9..5fcd6e093e 100644 --- a/.maestro/tests/assertions/assertRoomListSynced.yaml +++ b/.maestro/tests/assertions/assertRoomListSynced.yaml @@ -2,4 +2,4 @@ appId: ${APP_ID} --- - extendedWaitUntil: visible: ${ROOM_NAME} - timeout: 10_000 + timeout: 10000 diff --git a/.maestro/tests/assertions/assertWelcomeScreenDisplayed.yaml b/.maestro/tests/assertions/assertWelcomeScreenDisplayed.yaml index 73e8e78ef5..3fbd9d2513 100644 --- a/.maestro/tests/assertions/assertWelcomeScreenDisplayed.yaml +++ b/.maestro/tests/assertions/assertWelcomeScreenDisplayed.yaml @@ -3,4 +3,4 @@ appId: ${APP_ID} - extendedWaitUntil: visible: id: "welcome_screen-title" - timeout: 10_000 + timeout: 10000 From 21e25e93e1b619a7eee33d598ddd62201eeb514c Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Wed, 13 Sep 2023 11:02:25 +0200 Subject: [PATCH 128/234] Poll Creation: Switch focus to newly added option field when clicking "Add option". - Also scrolls the list to make the "Add option" button visible for further additions. --- .../features/poll/impl/create/CreatePollView.kt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollView.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollView.kt index e69d23fd32..462ff4e48a 100644 --- a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollView.kt +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollView.kt @@ -26,6 +26,7 @@ import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Add @@ -77,6 +78,7 @@ fun CreatePollView( onDismiss = { state.eventSink(CreatePollEvents.HideConfirmation) } ) val questionFocusRequester = remember { FocusRequester() } + val answerFocusRequester = remember { FocusRequester() } LaunchedEffect(Unit) { questionFocusRequester.requestFocus() } @@ -103,12 +105,14 @@ fun CreatePollView( ) }, ) { paddingValues -> + val lazyListState = rememberLazyListState() LazyColumn( modifier = Modifier .padding(paddingValues) .consumeWindowInsets(paddingValues) .imePadding() .fillMaxSize(), + state = lazyListState, ) { item { Column { @@ -137,6 +141,8 @@ fun CreatePollView( } } itemsIndexed(state.answers) { index, answer -> + val isLastItem = index == state.answers.size - 1 + val hasAdditionalOptions = state.answers.size > 2 ListItem( headlineContent = { OutlinedTextField( @@ -144,7 +150,9 @@ fun CreatePollView( onValueChange = { state.eventSink(CreatePollEvents.SetAnswer(index, it)) }, - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .then(if (isLastItem) Modifier.focusRequester(answerFocusRequester) else Modifier) + .fillMaxWidth(), placeholder = { Text(text = stringResource(id = R.string.screen_create_poll_answer_hint, index + 1)) }, @@ -162,6 +170,10 @@ fun CreatePollView( }, style = if (answer.canDelete) ListItemStyle.Destructive else ListItemStyle.Default, ) + LaunchedEffect(isLastItem, hasAdditionalOptions) { + lazyListState.animateScrollToItem(state.answers.size + 1) + if (isLastItem && hasAdditionalOptions) answerFocusRequester.requestFocus() + } } if (state.canAddAnswer) { item { From 27ecec763b3c714cfc24cc3a15c7b2aad9be3cb1 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 13 Sep 2023 14:13:51 +0200 Subject: [PATCH 129/234] Thread decoration : fix test compilation --- .../eventformatter/impl/DefaultRoomLastMessageFormatterTests.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTests.kt b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTests.kt index 494c63784d..0f22105635 100644 --- a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTests.kt +++ b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLastMessageFormatterTests.kt @@ -153,7 +153,7 @@ class DefaultRoomLastMessageFormatterTests { fun `Message contents`() { val body = "Shared body" fun createMessageContent(type: MessageType): MessageContent { - return MessageContent(body, null, false, type) + return MessageContent(body, null, false, false,type) } val sharedContentMessagesTypes = arrayOf( From 18f401684256699e065889fc164b408366f4078d Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 13 Sep 2023 12:14:40 +0000 Subject: [PATCH 130/234] Update screenshots --- ...ificationSettingOptionLight-D-1_2_null,NEXUS_5,1.0,en].png | 3 +++ ...ificationSettingOptionLight-N-1_3_null,NEXUS_5,1.0,en].png | 3 +++ ...lidNotificationSettingsViewDark_0_null,NEXUS_5,1.0,en].png | 3 +++ ...lidNotificationSettingsViewight_0_null,NEXUS_5,1.0,en].png | 3 +++ ..._NotificationSettingsViewDark_0_null_0,NEXUS_5,1.0,en].png | 3 +++ ...NotificationSettingsViewLight_0_null_0,NEXUS_5,1.0,en].png | 3 +++ ...ll_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ll_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...l_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...l_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png | 4 ++-- ....impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png | 4 ++-- ...impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png | 4 ++-- 28 files changed, 62 insertions(+), 44 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOptionLight-D-1_2_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOptionLight-N-1_3_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_InvalidNotificationSettingsViewDark_0_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_InvalidNotificationSettingsViewight_0_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_NotificationSettingsViewDark_0_null_0,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_NotificationSettingsViewLight_0_null_0,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOptionLight-D-1_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOptionLight-D-1_2_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..2d9578c3c2 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOptionLight-D-1_2_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:954c763c082f8e4016247643408a61a038a221bb84643ba7e80f3389818528ba +size 15587 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOptionLight-N-1_3_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOptionLight-N-1_3_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..8a32c8d742 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOptionLight-N-1_3_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:30886fbb00695077a80e046cd6c6c134375be8ecb8c3962e72fdc0dff60d7069 +size 14194 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_InvalidNotificationSettingsViewDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_InvalidNotificationSettingsViewDark_0_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..f7d27ba4c0 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_InvalidNotificationSettingsViewDark_0_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fbece1a3764a140e2e8218d34517461809acf67ea87715140fa22b81ffa9d7c0 +size 42771 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_InvalidNotificationSettingsViewight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_InvalidNotificationSettingsViewight_0_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..eee59588f1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_InvalidNotificationSettingsViewight_0_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a6c2719db95641bd6c2b613c65008ebecb8f8989d74d76c8070da0d741be3e7d +size 43506 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_NotificationSettingsViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_NotificationSettingsViewDark_0_null_0,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..324dabeb34 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_NotificationSettingsViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fdab0618a9188ced6ad4c3124aa7ce4a467615564bd1484bbf9f035c2a9037ff +size 57523 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_NotificationSettingsViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_NotificationSettingsViewLight_0_null_0,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..c9a0b8219f --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_NotificationSettingsViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5edd3646866f2c76ad28fe6c77079cdac41da30aaa77f8f4c6f7f2b2d12a7d37 +size 62384 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png index 70697459fb..ee4debea8d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1e047b2d8c1e780b6b5b17d697ef68329e82965359168c02acab59a641f7c3d8 -size 287 +oid sha256:a99b724ff8e90a48557c38909fe62d3fb1b260c3b5f6a57ac9f3b25879aad1ef +size 41532 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png index 8f7840e99f..6d6798e98a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4415059f5b3bea2d68cb19bba725004b5ee987ef3480d0b92bb8616df143fe2e -size 287 +oid sha256:1b87a3743ebe1fc4c5df49180b94652543c58d250184787ae3f32c0c713ffad8 +size 40858 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png index 0cbf4da1f2..e57be18284 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9bf4008fe7567a29bdc56054d66a2e46f44d4219d7ac4405898dc28844987b4a -size 287 +oid sha256:d4dd79afac67e5d7ada5b32dc2d9d21d7b56ae53a19d34775058df77d4abce30 +size 44169 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png index 800d8b2efa..632a80ee03 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1939e8ed90c936c52ec73abecc6da3c879d42097aa9463c780bb42cd337d78db -size 287 +oid sha256:53b465eddb29226425e68f50de870d85477fb847fa5bb83b6294da11f682e2d0 +size 44036 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png index 19c44f9bfd..ae23a77cbc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e7767c8e93ea26db11a587befb060db13cb437019fb4c78a41d1da392631c322 -size 287 +oid sha256:470a655997e6cd489a74d31e6db8641b48fd7974db87547f2d2efc9a4c8901bf +size 52503 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png index 6fe16e5227..1f23fa479a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1db1cd829102bb50c4310340574d0c2f77decc5e8ae6ba65ca0bad8a0208ff19 -size 287 +oid sha256:70b8a0df5f3184e54b372a07bba99381ddc107e6dea58eee96dcfd4f0d04c022 +size 50857 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png index ea7e406b74..00c3f8d140 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:11980e20c7f8d12239a5d0b70228a94210d2ce36237568a47557dac023869122 -size 287 +oid sha256:fc70f4008e918612b15ce7d55d26092c632a08f3179c98452bd3acc9111dbb9f +size 43979 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png index 530f986564..ab80b1cf18 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c041251d76ced4b502bb67ad0948c22d7ccdfa21418c19608c57da0d22b2f677 -size 287 +oid sha256:dd9f45108f2ec9739cb414bd11751e9ed41044948d5ddd70e9afaf7d75b52b3a +size 53305 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png index 3a813fbda8..40942f08a9 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f399a87338988677a7e7036cbaa9b13772cae80d51b08a1c2aa6c55968ae909c -size 287 +oid sha256:c01f60be5fdd30d9f75de6dc8a272954123e14a05eca2dc3fe643fe8769ff218 +size 50239 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png index c494f78fd7..0efa94ce47 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6a72f7d9deff8576d0a748d3793d4f7abbbb6341372bf9c2645914adb279cecf -size 287 +oid sha256:275e0112aeed3097ef7eb295ef6dc7aedf6bccb0add1167c823b78953c887e33 +size 51963 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png index c494f78fd7..0efa94ce47 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6a72f7d9deff8576d0a748d3793d4f7abbbb6341372bf9c2645914adb279cecf -size 287 +oid sha256:275e0112aeed3097ef7eb295ef6dc7aedf6bccb0add1167c823b78953c887e33 +size 51963 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png index ac19b3c914..1b87302d36 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cb02dc32e5340e25f928e5c24c2f4975ac439662582842193f40eb37ce9a1baf -size 287 +oid sha256:eb9e612cc985121de0a8a506066dfecad22eb283232a6815e7a50197c1af5a1c +size 53640 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png index 78e138e2e9..5914da7d56 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsDark--1_1_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ef2d4fc3e58ca6e0d25d7936f6a318eb54698f476e73f616a0e652f464a8afd2 -size 287 +oid sha256:2efcf4a4db75ffdf8f2a2bcc841eb8c27b5497f8724754360256dec83b494f5b +size 52747 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png index 7e3bcfbe2f..cd275d2b96 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9026859eae0ea32b49a0f5c58729de98fe3ccdfead6f541231c81aeb2fee3d59 -size 287 +oid sha256:b845bb8d92a35424cd81a5355c0eb69cd069bdf327d28caf69326355e4c33e93 +size 53658 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png index 3d31181d34..4f5d817402 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e9e752cec376724d4cf0cebebdf627c19f6d253317b08e860d500764771fd0c7 -size 287 +oid sha256:6825637037556cf9440d0cc2303f73e88e29385d1fce9e7670106c96ea3143f6 +size 53597 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png index f5165db0f4..53423131be 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e815c6aa5b0f7ed10ee3d04e8dbb2714475ca3868133a31d6b24e6966e03b813 -size 287 +oid sha256:6cca72e75685d2dbc6eb1b2025f8c487c443006d077cc560e6abafd16e06e6c9 +size 46510 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png index aea58df185..8425c5405e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7770e0eb1a181de8f9005d248b4e26d4397987343021d397ccef2f2a09c71f5a -size 287 +oid sha256:6a4c6e92b895251c2c075f3679f7d31480bf1eacfa3592ef17e7d11c79120397 +size 54529 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png index 9a8c454cc4..7b04c98e13 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f38f6787a926fa879e83eea7469fc03f237d629e21df7f4796c815fec24a558c -size 287 +oid sha256:2072ec79ee1aad73cd20eaf0d87106b8757223a2499fff67c5c806223a705c66 +size 51626 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png index 9a323c65cf..e54b8591f4 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ab8bba0ea41d78157dcc8202223af3a3d2a14d78b0d3200b84d33ea61fb5e60 -size 287 +oid sha256:537e9ab994b8a6c6589b03e9c4231cd9b984cad4f233d106425d3d0e65af8864 +size 53852 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png index 9a323c65cf..e54b8591f4 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ab8bba0ea41d78157dcc8202223af3a3d2a14d78b0d3200b84d33ea61fb5e60 -size 287 +oid sha256:537e9ab994b8a6c6589b03e9c4231cd9b984cad4f233d106425d3d0e65af8864 +size 53852 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png index 59fec2a703..dc6c756bd1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_7,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e97b101b64b15b884e232520d4adbe3a44f4149538f51e08b86c0d9d2b581f81 -size 287 +oid sha256:183145910ec9cd8a5c19e30bcdf0995dcfc70c7a9a176fe28f6106b2dd5b21d3 +size 54827 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png index 38e7a89396..185288adb1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl_null_RoomDetailsLight--0_0_null_8,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:70914a3502f1bf0edf5a210192fe19215645a1260ce27ff8224194861890613e -size 287 +oid sha256:3202fed8c4344f427442905d4088441ea97446b4ef9350e588df26d5497192e4 +size 53932 From ebde39055ccb64380e59e69b5c4b1a611206884a Mon Sep 17 00:00:00 2001 From: David Langley Date: Wed, 13 Sep 2023 13:22:05 +0100 Subject: [PATCH 131/234] Use CommonStirngs --- .../impl/notifications/NotificationSettingsView.kt | 9 ++++----- .../edit/DefaultNotificationSettingOption.kt | 6 +++--- .../edit/EditDefaultNotificationSettingView.kt | 5 ++--- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt index 66e5ec470e..144821906c 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt @@ -54,7 +54,6 @@ import io.element.android.libraries.designsystem.utils.OnLifecycleEvent import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.ui.strings.CommonStrings -import io.element.android.libraries.ui.strings.R @Composable fun NotificationSettingsView( state: NotificationSettingsState, @@ -171,8 +170,8 @@ private fun NotificationSettingsContentView( @Composable private fun getTitleForRoomNotificationMode(mode: RoomNotificationMode?) = when(mode) { - RoomNotificationMode.ALL_MESSAGES -> stringResource(id = R.string.screen_notification_settings_edit_mode_all_messages) - RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> stringResource(id = R.string.screen_notification_settings_edit_mode_mentions_and_keywords) + RoomNotificationMode.ALL_MESSAGES -> stringResource(id = CommonStrings.screen_notification_settings_edit_mode_all_messages) + RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> stringResource(id = CommonStrings.screen_notification_settings_edit_mode_mentions_and_keywords) RoomNotificationMode.MUTE -> stringResource(id = CommonStrings.common_mute) null -> "" } @@ -197,7 +196,7 @@ private fun InvalidNotificationSettingsView( ) { Row { Text( - stringResource(R.string.screen_notification_settings_configuration_mismatch), + stringResource(CommonStrings.screen_notification_settings_configuration_mismatch), modifier = Modifier.weight(1f), style = ElementTheme.typography.fontBodyLgMedium, color = MaterialTheme.colorScheme.primary, @@ -206,7 +205,7 @@ private fun InvalidNotificationSettingsView( } Spacer(modifier = Modifier.height(4.dp)) Text( - stringResource(R.string.screen_notification_settings_configuration_mismatch_description), + stringResource(CommonStrings.screen_notification_settings_configuration_mismatch_description), style = ElementTheme.typography.fontBodyMdRegular, ) Spacer(modifier = Modifier.height(12.dp)) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/DefaultNotificationSettingOption.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/DefaultNotificationSettingOption.kt index b06df90d30..7ece6cc737 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/DefaultNotificationSettingOption.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/DefaultNotificationSettingOption.kt @@ -33,7 +33,7 @@ import io.element.android.libraries.designsystem.theme.components.RadioButton import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.theme.ElementTheme -import io.element.android.libraries.ui.strings.R +import io.element.android.libraries.ui.strings.CommonStrings @Composable fun DefaultNotificationSettingOption( @@ -43,8 +43,8 @@ fun DefaultNotificationSettingOption( onOptionSelected: (RoomNotificationMode) -> Unit = {}, ) { val subtitle = when(mode) { - RoomNotificationMode.ALL_MESSAGES -> stringResource(id = R.string.screen_notification_settings_edit_mode_all_messages) - RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> stringResource(id = R.string.screen_notification_settings_edit_mode_mentions_and_keywords) + RoomNotificationMode.ALL_MESSAGES -> stringResource(id = CommonStrings.screen_notification_settings_edit_mode_all_messages) + RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> stringResource(id = CommonStrings.screen_notification_settings_edit_mode_mentions_and_keywords) else -> "" } Row( diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt index 777f07b9c7..d67b789cc9 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt @@ -21,7 +21,6 @@ import androidx.compose.foundation.selection.selectableGroup import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource -import io.element.android.libraries.ui.strings.R import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory import io.element.android.libraries.designsystem.components.preferences.PreferenceView import io.element.android.libraries.matrix.api.room.RoomNotificationMode @@ -48,9 +47,9 @@ fun EditDefaultNotificationSettingView( val validModes = listOf(RoomNotificationMode.ALL_MESSAGES, RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY) val categoryTitle = if(state.isOneToOne) { - R.string.screen_notification_settings_edit_screen_direct_section_header + CommonStrings.screen_notification_settings_edit_screen_direct_section_header } else { - R.string.screen_notification_settings_edit_screen_group_section_header + CommonStrings.screen_notification_settings_edit_screen_group_section_header } PreferenceCategory(title = stringResource(id = categoryTitle)) { From aedfed3be9b5c6c548c264771c79bc8a1238a7bc Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 13 Sep 2023 14:33:32 +0200 Subject: [PATCH 132/234] Maestro: ensure the Rich Text Editor can be clicked by Maestro. We cannot click on the hint "Message" anymore, since it's now a separate Text. --- .maestro/tests/roomList/timeline/messages/text.yaml | 3 ++- .../kotlin/io/element/android/libraries/testtags/TestTags.kt | 5 +++++ libraries/textcomposer/impl/build.gradle.kts | 1 + .../element/android/libraries/textcomposer/TextComposer.kt | 5 ++++- 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.maestro/tests/roomList/timeline/messages/text.yaml b/.maestro/tests/roomList/timeline/messages/text.yaml index 4e3b7bbd45..963b2cf9e9 100644 --- a/.maestro/tests/roomList/timeline/messages/text.yaml +++ b/.maestro/tests/roomList/timeline/messages/text.yaml @@ -1,7 +1,8 @@ appId: ${APP_ID} --- - takeScreenshot: build/maestro/510-Timeline -- tapOn: "Message" +- tapOn: + id: "rich_text_editor" - inputText: "Hello world!" - tapOn: "Send" - hideKeyboard diff --git a/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt b/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt index d832a6168d..d90be0c25c 100644 --- a/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt +++ b/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt @@ -47,6 +47,11 @@ object TestTags { * Welcome screen. */ val welcomeScreenTitle = TestTag("welcome_screen-title") + + /** + * RichTextEditor. + */ + val richTextEditor = TestTag("rich_text_editor") } diff --git a/libraries/textcomposer/impl/build.gradle.kts b/libraries/textcomposer/impl/build.gradle.kts index 633491d3b3..86e911ca3e 100644 --- a/libraries/textcomposer/impl/build.gradle.kts +++ b/libraries/textcomposer/impl/build.gradle.kts @@ -31,6 +31,7 @@ dependencies { implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrixui) implementation(projects.libraries.designsystem) + implementation(projects.libraries.testtags) implementation(libs.androidx.constraintlayout) implementation(libs.androidx.constraintlayout.compose) diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt index 3cc09ce09f..983c84c45b 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt @@ -74,6 +74,8 @@ import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.ui.components.AttachmentThumbnail import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType +import io.element.android.libraries.testtags.TestTags +import io.element.android.libraries.testtags.testTag import io.element.android.libraries.textcomposer.components.FormattingOption import io.element.android.libraries.textcomposer.components.FormattingOptionState import io.element.android.libraries.theme.ElementTheme @@ -255,7 +257,8 @@ private fun TextInput( start = 12.dp.applyScaleUp(), end = 42.dp.applyScaleUp() ) - ), + ) + .testTag(TestTags.richTextEditor), contentAlignment = Alignment.CenterStart, ) { From 5e8cb958f84a631288a71d315e2cbd36cbd17c69 Mon Sep 17 00:00:00 2001 From: David Langley Date: Wed, 13 Sep 2023 14:18:28 +0100 Subject: [PATCH 133/234] Enabled NotificationSettings by default, Fix spacing, use activeMemberCount for isOneToOne. - Enabled Notification Settings by default - Fix spacing - Use activeMemberCount for isOneToOne --- .../android/features/preferences/impl/PreferencesFlowNode.kt | 1 - .../preferences/impl/notifications/NotificationSettingsView.kt | 3 +-- .../element/android/libraries/featureflag/api/FeatureFlags.kt | 3 +-- .../libraries/featureflag/impl/StaticFeatureFlagProvider.kt | 2 +- .../io/element/android/libraries/matrix/api/room/MatrixRoom.kt | 2 +- 5 files changed, 4 insertions(+), 7 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt index 1f3c24108b..85ae3ac55f 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt @@ -70,7 +70,6 @@ class PreferencesFlowNode @AssistedInject constructor( data object AnalyticsSettings : NavTarget @Parcelize - data object About : NavTarget @Parcelize diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt index 144821906c..9bb0f1cd66 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt @@ -54,6 +54,7 @@ import io.element.android.libraries.designsystem.utils.OnLifecycleEvent import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.ui.strings.CommonStrings + @Composable fun NotificationSettingsView( state: NotificationSettingsState, @@ -166,7 +167,6 @@ private fun NotificationSettingsContentView( } } - @Composable private fun getTitleForRoomNotificationMode(mode: RoomNotificationMode?) = when(mode) { @@ -246,7 +246,6 @@ private fun ContentToPreview(state: NotificationSettingsState) { ) } - @Preview @Composable internal fun InvalidNotificationSettingsViewightPreview() = diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt index 0f27a94a2d..ca68b0cbd1 100644 --- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt +++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt @@ -41,8 +41,7 @@ enum class FeatureFlags( NotificationSettings( key = "feature.notificationsettings", title = "Show notification settings", - // Do not forget to edit StaticFeatureFlagProvider when enabling the feature. - defaultValue = false, + defaultValue = true, ), RichTextEditor( key = "feature.richtexteditor", diff --git a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/StaticFeatureFlagProvider.kt b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/StaticFeatureFlagProvider.kt index c9b24f08e6..d7759ac474 100644 --- a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/StaticFeatureFlagProvider.kt +++ b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/StaticFeatureFlagProvider.kt @@ -34,7 +34,7 @@ class StaticFeatureFlagProvider @Inject constructor() : when(feature) { FeatureFlags.LocationSharing -> true FeatureFlags.Polls -> true - FeatureFlags.NotificationSettings -> false + FeatureFlags.NotificationSettings -> true FeatureFlags.RichTextEditor -> true } } else { diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt index d122aca495..1dd6101354 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt @@ -53,7 +53,7 @@ interface MatrixRoom : Closeable { * A one-to-one is a room with exactly 2 members. * See [the Matrix spec](https://spec.matrix.org/latest/client-server-api/#default-underride-rules). */ - val isOneToOne: Boolean get() = joinedMemberCount == 2L + val isOneToOne: Boolean get() = activeMemberCount == 2L /** * The current loaded members as a StateFlow. From 7fdd83bf91282ef49db9289fa0976b0aa97c0a9b Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Wed, 13 Sep 2023 15:19:26 +0200 Subject: [PATCH 134/234] GRemove the @JvmField annotation whenever using `WarmUpRule`. --- .../test/kotlin/io/element/android/appnav/RootPresenterTest.kt | 3 +-- .../element/android/appnav/loggedin/LoggedInPresenterTest.kt | 3 +-- .../features/analytics/impl/AnalyticsOptInPresenterTest.kt | 3 +-- .../impl/preferences/AnalyticsPreferencesPresenterTest.kt | 3 +-- .../createroom/impl/addpeople/AddPeoplePresenterTests.kt | 3 +-- .../impl/configureroom/ConfigureRoomPresenterTests.kt | 3 +-- .../createroom/impl/root/CreateRoomRootPresenterTests.kt | 3 +-- .../createroom/impl/userlist/DefaultUserListPresenterTests.kt | 3 +-- .../ftue/impl/migration/MigrationScreenPresenterTest.kt | 3 +-- .../impl/notifications/NotificationsOptInPresenterTests.kt | 3 +-- .../features/invitelist/impl/InviteListPresenterTests.kt | 3 +-- .../features/leaveroom/impl/LeaveRoomPresenterImplTest.kt | 3 +-- .../features/location/impl/send/SendLocationPresenterTest.kt | 3 +-- .../features/location/impl/show/ShowLocationPresenterTest.kt | 3 +-- .../login/impl/changeserver/ChangeServerPresenterTest.kt | 3 +-- .../features/login/impl/oidc/webview/OidcPresenterTest.kt | 3 +-- .../ChangeAccountProviderPresenterTest.kt | 3 +-- .../ConfirmAccountProviderPresenterTest.kt | 3 +-- .../impl/screens/loginpassword/LoginPasswordPresenterTest.kt | 3 +-- .../SearchAccountProviderPresenterTest.kt | 3 +-- .../login/impl/screens/waitlistscreen/WaitListPresenterTest.kt | 3 +-- .../features/logout/impl/LogoutPreferencePresenterTest.kt | 3 +-- .../element/android/features/messages/MessagesPresenterTest.kt | 3 +-- .../features/messages/actionlist/ActionListPresenterTest.kt | 3 +-- .../messages/attachments/AttachmentsPreviewPresenterTest.kt | 3 +-- .../features/messages/forward/ForwardMessagesPresenterTests.kt | 3 +-- .../features/messages/media/viewer/MediaViewerPresenterTest.kt | 3 +-- .../features/messages/report/ReportMessagePresenterTests.kt | 3 +-- .../messages/textcomposer/MessageComposerPresenterTest.kt | 3 +-- .../features/messages/timeline/TimelinePresenterTest.kt | 3 +-- .../components/customreaction/CustomReactionPresenterTests.kt | 3 +-- .../reactionsummary/ReactionSummaryPresenterTests.kt | 3 +-- .../components/retrysendmenu/RetrySendMenuPresenterTests.kt | 3 +-- .../features/onboarding/impl/OnBoardingPresenterTest.kt | 3 +-- .../features/poll/impl/create/CreatePollPresenterTest.kt | 3 +-- .../features/preferences/impl/about/AboutPresenterTest.kt | 3 +-- .../impl/analytics/AnalyticsSettingsPresenterTest.kt | 3 +-- .../impl/developer/DeveloperSettingsPresenterTest.kt | 3 +-- .../impl/developer/tracing/ConfigureTracingPresenterTest.kt | 3 +-- .../preferences/impl/root/PreferencesRootPresenterTest.kt | 3 +-- .../rageshake/impl/bugreport/BugReportPresenterTest.kt | 3 +-- .../rageshake/impl/crash/ui/CrashDetectionPresenterTest.kt | 3 +-- .../impl/detection/RageshakeDetectionPresenterTest.kt | 3 +-- .../impl/preferences/RageshakePreferencesPresenterTest.kt | 3 +-- .../android/features/roomdetails/RoomDetailsPresenterTests.kt | 3 +-- .../features/roomdetails/edit/RoomDetailsEditPresenterTest.kt | 3 +-- .../roomdetails/impl/invite/RoomInviteMembersPresenterTest.kt | 3 +-- .../roomdetails/members/RoomMemberListPresenterTests.kt | 3 +-- .../members/details/RoomMemberDetailsPresenterTests.kt | 3 +-- .../android/features/roomlist/impl/RoomListPresenterTests.kt | 3 +-- .../verifysession/impl/VerifySelfSessionPresenterTests.kt | 3 +-- .../permissions/impl/DefaultPermissionsPresenterTest.kt | 3 +-- .../libraries/permissions/noop/NoopPermissionsPresenterTest.kt | 3 +-- 53 files changed, 53 insertions(+), 106 deletions(-) diff --git a/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt b/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt index 703e59c7f1..6771718d81 100644 --- a/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt +++ b/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt @@ -37,8 +37,7 @@ import org.junit.Rule import org.junit.Test class RootPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test 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 f0a9642f4f..efada670b0 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 @@ -37,8 +37,7 @@ import org.junit.Test class LoggedInPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInPresenterTest.kt b/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInPresenterTest.kt index aad9973282..3dcb4674df 100644 --- a/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInPresenterTest.kt +++ b/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInPresenterTest.kt @@ -31,8 +31,7 @@ import org.junit.Test class AnalyticsOptInPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/preferences/AnalyticsPreferencesPresenterTest.kt b/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/preferences/AnalyticsPreferencesPresenterTest.kt index 3a2812b72e..494468c530 100644 --- a/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/preferences/AnalyticsPreferencesPresenterTest.kt +++ b/features/analytics/impl/src/test/kotlin/io/element/android/features/analytics/impl/preferences/AnalyticsPreferencesPresenterTest.kt @@ -30,8 +30,7 @@ import org.junit.Test class AnalyticsPreferencesPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeoplePresenterTests.kt b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeoplePresenterTests.kt index af68f0dd57..968b2a1b57 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeoplePresenterTests.kt +++ b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeoplePresenterTests.kt @@ -32,8 +32,7 @@ import org.junit.Test class AddPeoplePresenterTests { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() private lateinit var presenter: AddPeoplePresenter diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenterTests.kt b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenterTests.kt index bc5bafa843..a330384f60 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenterTests.kt +++ b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenterTests.kt @@ -60,8 +60,7 @@ private const val AN_URI_FROM_GALLERY = "content://uri_from_gallery" @RunWith(RobolectricTestRunner::class) class ConfigureRoomPresenterTests { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() private lateinit var presenter: ConfigureRoomPresenter diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenterTests.kt b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenterTests.kt index 1809df135b..bf4593bdbb 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenterTests.kt +++ b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenterTests.kt @@ -44,8 +44,7 @@ import org.junit.Test class CreateRoomRootPresenterTests { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() private lateinit var userRepository: FakeUserRepository diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/userlist/DefaultUserListPresenterTests.kt b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/userlist/DefaultUserListPresenterTests.kt index 12e9f2fc90..a591a7a8e9 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/userlist/DefaultUserListPresenterTests.kt +++ b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/userlist/DefaultUserListPresenterTests.kt @@ -33,8 +33,7 @@ import org.junit.Test class DefaultUserListPresenterTests { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() private val userRepository = FakeUserRepository() diff --git a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/migration/MigrationScreenPresenterTest.kt b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/migration/MigrationScreenPresenterTest.kt index 1a9a33130d..ac56718e06 100644 --- a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/migration/MigrationScreenPresenterTest.kt +++ b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/migration/MigrationScreenPresenterTest.kt @@ -32,8 +32,7 @@ import org.junit.Test class MigrationScreenPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenterTests.kt b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenterTests.kt index 74a867a0fc..9bfa1cf33c 100644 --- a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenterTests.kt +++ b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInPresenterTests.kt @@ -39,8 +39,7 @@ import org.junit.Test class NotificationsOptInPresenterTests { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() private var isFinished = false diff --git a/features/invitelist/impl/src/test/kotlin/io/element/android/features/invitelist/impl/InviteListPresenterTests.kt b/features/invitelist/impl/src/test/kotlin/io/element/android/features/invitelist/impl/InviteListPresenterTests.kt index 9ba26b5e2d..ca0c73d53e 100644 --- a/features/invitelist/impl/src/test/kotlin/io/element/android/features/invitelist/impl/InviteListPresenterTests.kt +++ b/features/invitelist/impl/src/test/kotlin/io/element/android/features/invitelist/impl/InviteListPresenterTests.kt @@ -50,8 +50,7 @@ import org.junit.Rule import org.junit.Test class InviteListPresenterTests { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt b/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt index 7bbab71a8d..fff7c00410 100644 --- a/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt +++ b/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt @@ -39,8 +39,7 @@ import org.junit.Test class LeaveRoomPresenterImplTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/SendLocationPresenterTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/SendLocationPresenterTest.kt index af31f1bfeb..c0b4cb7d35 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/SendLocationPresenterTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/SendLocationPresenterTest.kt @@ -42,8 +42,7 @@ import org.junit.Test class SendLocationPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() private val permissionsPresenterFake = PermissionsPresenterFake() diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt index ebb146ca57..9eb0c3e1e2 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt @@ -35,8 +35,7 @@ import org.junit.Test class ShowLocationPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() private val permissionsPresenterFake = PermissionsPresenterFake() diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt index 4a2fcc397c..f94ce4e65d 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt @@ -33,8 +33,7 @@ import org.junit.Test class ChangeServerPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/oidc/webview/OidcPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/oidc/webview/OidcPresenterTest.kt index 60cc1285e3..70d6da7783 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/oidc/webview/OidcPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/oidc/webview/OidcPresenterTest.kt @@ -35,8 +35,7 @@ import org.junit.Test class OidcPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderPresenterTest.kt index 6fe3248ec3..edf198fe35 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderPresenterTest.kt @@ -31,8 +31,7 @@ import org.junit.Test class ChangeAccountProviderPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt index 0ec396694b..f348839c97 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt @@ -39,8 +39,7 @@ import org.junit.Test class ConfirmAccountProviderPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenterTest.kt index 1848940966..a2b0fae449 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenterTest.kt @@ -38,8 +38,7 @@ import org.junit.Test class LoginPasswordPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderPresenterTest.kt index 89d1a22b0c..84bd6925db 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderPresenterTest.kt @@ -38,8 +38,7 @@ import org.junit.Test class SearchAccountProviderPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/waitlistscreen/WaitListPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/waitlistscreen/WaitListPresenterTest.kt index dadcbe186a..590fa8efc0 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/waitlistscreen/WaitListPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/waitlistscreen/WaitListPresenterTest.kt @@ -37,8 +37,7 @@ import org.junit.Test class WaitListPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPreferencePresenterTest.kt b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPreferencePresenterTest.kt index 9527012e28..52e673cba6 100644 --- a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPreferencePresenterTest.kt +++ b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPreferencePresenterTest.kt @@ -32,8 +32,7 @@ import org.junit.Test class LogoutPreferencePresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt index c1c7e1c993..c9ef88f18c 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt @@ -86,8 +86,7 @@ import kotlin.time.Duration.Companion.milliseconds class MessagesPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() private val mockMediaUrl: Uri = mockk("localMediaUri") diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt index 5e68906216..2682a71207 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt @@ -41,8 +41,7 @@ import org.junit.Test class ActionListPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/attachments/AttachmentsPreviewPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/attachments/AttachmentsPreviewPresenterTest.kt index 5a66fe13b8..30c8d761b3 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/attachments/AttachmentsPreviewPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/attachments/AttachmentsPreviewPresenterTest.kt @@ -43,8 +43,7 @@ import org.junit.Test class AttachmentsPreviewPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() private val mediaPreProcessor = FakeMediaPreProcessor() diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/forward/ForwardMessagesPresenterTests.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/forward/ForwardMessagesPresenterTests.kt index 7b6f48403f..c3a70deac6 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/forward/ForwardMessagesPresenterTests.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/forward/ForwardMessagesPresenterTests.kt @@ -39,8 +39,7 @@ import org.junit.Test class ForwardMessagesPresenterTests { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/media/viewer/MediaViewerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/media/viewer/MediaViewerPresenterTest.kt index 97ee81bcb6..6401f60f47 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/media/viewer/MediaViewerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/media/viewer/MediaViewerPresenterTest.kt @@ -44,8 +44,7 @@ private val TESTED_MEDIA_INFO = aFileInfo() class MediaViewerPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/report/ReportMessagePresenterTests.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/report/ReportMessagePresenterTests.kt index 97b0227def..8244562622 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/report/ReportMessagePresenterTests.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/report/ReportMessagePresenterTests.kt @@ -35,8 +35,7 @@ import org.junit.Test class ReportMessagePresenterTests { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt index 4025dc3bee..a842162b26 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt @@ -69,8 +69,7 @@ import java.io.File class MessageComposerPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() private val pickerProvider = FakePickerProvider().apply { diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/TimelinePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/TimelinePresenterTest.kt index eb5a7b72e1..0435be3cb1 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/TimelinePresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/TimelinePresenterTest.kt @@ -51,8 +51,7 @@ import java.util.Date class TimelinePresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/customreaction/CustomReactionPresenterTests.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/customreaction/CustomReactionPresenterTests.kt index 9f9b7358d8..40912c0cc0 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/customreaction/CustomReactionPresenterTests.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/customreaction/CustomReactionPresenterTests.kt @@ -33,8 +33,7 @@ import org.junit.Test class CustomReactionPresenterTests { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() private val presenter = CustomReactionPresenter(emojibaseProvider = FakeEmojibaseProvider()) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/reactionsummary/ReactionSummaryPresenterTests.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/reactionsummary/ReactionSummaryPresenterTests.kt index c2a415ea44..7b18d890df 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/reactionsummary/ReactionSummaryPresenterTests.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/reactionsummary/ReactionSummaryPresenterTests.kt @@ -37,8 +37,7 @@ import org.junit.Test class ReactionSummaryPresenterTests { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() private val aggregatedReaction = anAggregatedReaction(userId = A_USER_ID, key = "👍", isHighlighted = true) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/retrysendmenu/RetrySendMenuPresenterTests.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/retrysendmenu/RetrySendMenuPresenterTests.kt index 5a23eba6da..011db1f038 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/retrysendmenu/RetrySendMenuPresenterTests.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/timeline/components/retrysendmenu/RetrySendMenuPresenterTests.kt @@ -32,8 +32,7 @@ import org.junit.Test class RetrySendMenuPresenterTests { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() private val room = FakeMatrixRoom() diff --git a/features/onboarding/impl/src/test/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenterTest.kt b/features/onboarding/impl/src/test/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenterTest.kt index 538fba98d5..9a356aa488 100644 --- a/features/onboarding/impl/src/test/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenterTest.kt +++ b/features/onboarding/impl/src/test/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenterTest.kt @@ -29,8 +29,7 @@ import org.junit.Test class OnBoardingPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenterTest.kt b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenterTest.kt index a58fb5476b..8e16084a59 100644 --- a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenterTest.kt +++ b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenterTest.kt @@ -35,8 +35,7 @@ import org.junit.Test class CreatePollPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() private var navUpInvocationsCount = 0 diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/about/AboutPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/about/AboutPresenterTest.kt index ad98756992..2cfd73b614 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/about/AboutPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/about/AboutPresenterTest.kt @@ -27,8 +27,7 @@ import org.junit.Test class AboutPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/analytics/AnalyticsSettingsPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/analytics/AnalyticsSettingsPresenterTest.kt index 775ad1b183..9570258092 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/analytics/AnalyticsSettingsPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/analytics/AnalyticsSettingsPresenterTest.kt @@ -30,8 +30,7 @@ import org.junit.Test class AnalyticsSettingsPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenterTest.kt index 17ffa2fe73..88778d4227 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsPresenterTest.kt @@ -35,8 +35,7 @@ import org.junit.Test class DeveloperSettingsPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/tracing/ConfigureTracingPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/tracing/ConfigureTracingPresenterTest.kt index 5388e97e9e..5ca874b6d6 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/tracing/ConfigureTracingPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/tracing/ConfigureTracingPresenterTest.kt @@ -30,8 +30,7 @@ import org.junit.Test class ConfigureTracingPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test fun `present - initial state`() = runTest { 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 5217519071..085ec95c0e 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,8 +37,7 @@ import org.junit.Test class PreferencesRootPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt index 204cd4aea1..3360ce3dd3 100644 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt @@ -36,8 +36,7 @@ const val A_LONG_DESCRIPTION = "I have seen a bug!" class BugReportPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/crash/ui/CrashDetectionPresenterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/crash/ui/CrashDetectionPresenterTest.kt index e77c1fd7e2..716f424ce3 100644 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/crash/ui/CrashDetectionPresenterTest.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/crash/ui/CrashDetectionPresenterTest.kt @@ -31,8 +31,7 @@ import org.junit.Test class CrashDetectionPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/detection/RageshakeDetectionPresenterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/detection/RageshakeDetectionPresenterTest.kt index d1d09131ad..a8a80fdc25 100644 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/detection/RageshakeDetectionPresenterTest.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/detection/RageshakeDetectionPresenterTest.kt @@ -38,8 +38,7 @@ import org.junit.Test class RageshakeDetectionPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() companion object { diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/preferences/RageshakePreferencesPresenterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/preferences/RageshakePreferencesPresenterTest.kt index 74cd1906a9..c639adb98f 100644 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/preferences/RageshakePreferencesPresenterTest.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/preferences/RageshakePreferencesPresenterTest.kt @@ -31,8 +31,7 @@ import org.junit.Test class RageshakePreferencesPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt index 71695094b3..6c383ac70a 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt @@ -57,8 +57,7 @@ import kotlin.time.Duration.Companion.milliseconds @ExperimentalCoroutinesApi class RoomDetailsPresenterTests { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() private fun aRoomDetailsPresenter( room: MatrixRoom, diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/edit/RoomDetailsEditPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/edit/RoomDetailsEditPresenterTest.kt index 587cc34429..aeaefeab6e 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/edit/RoomDetailsEditPresenterTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/edit/RoomDetailsEditPresenterTest.kt @@ -48,8 +48,7 @@ import java.io.File @ExperimentalCoroutinesApi class RoomDetailsEditPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() private lateinit var fakePickerProvider: FakePickerProvider diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersPresenterTest.kt index 175e4ec48c..4033038b69 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersPresenterTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersPresenterTest.kt @@ -46,8 +46,7 @@ import org.junit.Test internal class RoomInviteMembersPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/RoomMemberListPresenterTests.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/RoomMemberListPresenterTests.kt index 6dd8e5bf56..c7e4c6d8b5 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/RoomMemberListPresenterTests.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/RoomMemberListPresenterTests.kt @@ -43,8 +43,7 @@ import org.junit.Test @ExperimentalCoroutinesApi class RoomMemberListPresenterTests { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/details/RoomMemberDetailsPresenterTests.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/details/RoomMemberDetailsPresenterTests.kt index 2fd240237f..a249e38823 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/details/RoomMemberDetailsPresenterTests.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/members/details/RoomMemberDetailsPresenterTests.kt @@ -38,8 +38,7 @@ import org.junit.Test @ExperimentalCoroutinesApi class RoomMemberDetailsPresenterTests { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt index 1a2f32e54d..b7bfd3ecb4 100644 --- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt @@ -61,8 +61,7 @@ import org.junit.Test class RoomListPresenterTests { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenterTests.kt b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenterTests.kt index ced2c48e9b..eee6c51a07 100644 --- a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenterTests.kt +++ b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenterTests.kt @@ -35,8 +35,7 @@ import org.junit.Test @ExperimentalCoroutinesApi class VerifySelfSessionPresenterTests { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt index c25e8072e7..316ce7bc67 100644 --- a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt +++ b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenterTest.kt @@ -35,8 +35,7 @@ const val A_PERMISSION = "A_PERMISSION" class DefaultPermissionsPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test diff --git a/libraries/permissions/noop/src/test/kotlin/io/element/android/libraries/permissions/noop/NoopPermissionsPresenterTest.kt b/libraries/permissions/noop/src/test/kotlin/io/element/android/libraries/permissions/noop/NoopPermissionsPresenterTest.kt index f837529515..828610a6fb 100644 --- a/libraries/permissions/noop/src/test/kotlin/io/element/android/libraries/permissions/noop/NoopPermissionsPresenterTest.kt +++ b/libraries/permissions/noop/src/test/kotlin/io/element/android/libraries/permissions/noop/NoopPermissionsPresenterTest.kt @@ -27,8 +27,7 @@ import org.junit.Test class NoopPermissionsPresenterTest { - @Rule - @JvmField + @get:Rule val warmUpRule = WarmUpRule() @Test From 8881f9732f0c30c8565f91ed16b265319942490c Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Wed, 13 Sep 2023 15:42:48 +0200 Subject: [PATCH 135/234] Warmup molecule only once. --- .../android/tests/testutils/WarmUpRule.kt | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/WarmUpRule.kt b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/WarmUpRule.kt index a192cfbd63..4eeef468ff 100644 --- a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/WarmUpRule.kt +++ b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/WarmUpRule.kt @@ -32,17 +32,22 @@ import kotlin.time.Duration.Companion.seconds * Applying this test rule ensures that the slow initialisation is not done * inside runTest which has a short default timeout. */ -class WarmUpRule: TestRule { - override fun apply(base: Statement, description: Description): Statement = object: Statement() { - override fun evaluate() { - runTest(timeout = 60.seconds) { - moleculeFlow(RecompositionMode.Immediate) { - // Do nothing - }.test { - awaitItem() // Await a Unit composition - } - } - base.evaluate() +class WarmUpRule : TestRule { + companion object { + init { + warmUpMolecule() + } + } + + override fun apply(base: Statement, description: Description): Statement = base +} + +private fun warmUpMolecule() { + runTest(timeout = 60.seconds) { + moleculeFlow(RecompositionMode.Immediate) { + // Do nothing + }.test { + awaitItem() // Await a Unit composition } } } From b36ea5cedf8ff1205ab3f048f58a9aafdff3e4c6 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 13 Sep 2023 16:00:44 +0200 Subject: [PATCH 136/234] Thread decoration: add "Reply in thread" context --- .../features/messages/impl/MessagesPresenter.kt | 4 +++- .../impl/actionlist/ActionListPresenter.kt | 6 +++++- .../impl/actionlist/model/TimelineItemAction.kt | 1 + .../timeline/components/TimelineItemEventRow.kt | 2 +- .../MessageComposerPresenterTest.kt | 2 +- .../impl/src/main/res/values/localazy.xml | 2 ++ .../textcomposer/MessageComposerMode.kt | 3 ++- .../libraries/textcomposer/TextComposer.kt | 14 ++++++++++++-- .../ui-strings/src/main/res/values/localazy.xml | 17 +++++++++++------ 9 files changed, 38 insertions(+), 13 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index 50b3dca2d1..8c985d45d9 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -209,7 +209,8 @@ class MessagesPresenter @AssistedInject constructor( TimelineItemAction.Copy -> handleCopyContents(targetEvent) TimelineItemAction.Redact -> handleActionRedact(targetEvent) TimelineItemAction.Edit -> handleActionEdit(targetEvent, composerState) - TimelineItemAction.Reply -> handleActionReply(targetEvent, composerState) + TimelineItemAction.Reply, + TimelineItemAction.ReplyInThread -> handleActionReply(targetEvent, composerState) TimelineItemAction.Developer -> handleShowDebugInfoAction(targetEvent) TimelineItemAction.Forward -> handleForwardAction(targetEvent) TimelineItemAction.ReportContent -> handleReportAction(targetEvent) @@ -312,6 +313,7 @@ class MessagesPresenter @AssistedInject constructor( is TimelineItemUnknownContent -> null } val composerMode = MessageComposerMode.Reply( + isThreaded = targetEvent.isThreaded, senderName = targetEvent.safeSenderName, eventId = targetEvent.eventId, attachmentThumbnailInfo = attachmentThumbnailInfo, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt index b179261c72..e87523d702 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt @@ -130,7 +130,11 @@ class ActionListPresenter @Inject constructor( if (timelineItem.isRemote) { // Can only reply or forward messages already uploaded to the server if (userCanSendMessage) { - add(TimelineItemAction.Reply) + if (timelineItem.isThreaded) { + add(TimelineItemAction.ReplyInThread) + } else { + add(TimelineItemAction.Reply) + } } add(TimelineItemAction.Forward) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt index 7a8a1fa1db..331edfa1a5 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt @@ -32,6 +32,7 @@ sealed class TimelineItemAction( data object Copy : TimelineItemAction(CommonStrings.action_copy, VectorIcons.Copy) data object Redact : TimelineItemAction(CommonStrings.action_remove, VectorIcons.Delete, destructive = true) data object Reply : TimelineItemAction(CommonStrings.action_reply, VectorIcons.Reply) + data object ReplyInThread : TimelineItemAction(CommonStrings.action_reply_in_thread, VectorIcons.Reply) data object Edit : TimelineItemAction(CommonStrings.action_edit, VectorIcons.Edit) data object Developer : TimelineItemAction(CommonStrings.action_view_source, VectorIcons.DeveloperMode) data object ReportContent : TimelineItemAction(CommonStrings.action_report_content, VectorIcons.ReportContent, destructive = true) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index befb576696..0158372c79 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -400,7 +400,7 @@ private fun MessageEventBubbleContent( Icon(resourceId = R.drawable.ic_thread_decoration, contentDescription = null, tint = ElementTheme.colors.iconSecondary) Spacer(modifier = Modifier.width(4.dp)) Text( - text = "Thread", + text = stringResource(CommonStrings.common_thread), style = ElementTheme.typography.fontBodyXsRegular, color = ElementTheme.colors.textPrimary, ) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt index d1d4a54073..07a4800ffb 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt @@ -598,7 +598,7 @@ fun anEditMode( transactionId: TransactionId? = null, ) = MessageComposerMode.Edit(eventId, message, transactionId) -fun aReplyMode() = MessageComposerMode.Reply(A_USER_NAME, null, AN_EVENT_ID, A_MESSAGE) +fun aReplyMode() = MessageComposerMode.Reply(A_USER_NAME, null, false, AN_EVENT_ID, A_MESSAGE) fun aQuoteMode() = MessageComposerMode.Quote(AN_EVENT_ID, A_MESSAGE) private fun String.toMessage() = Message( diff --git a/features/roomdetails/impl/src/main/res/values/localazy.xml b/features/roomdetails/impl/src/main/res/values/localazy.xml index 717f503e22..7f0f4ddc30 100644 --- a/features/roomdetails/impl/src/main/res/values/localazy.xml +++ b/features/roomdetails/impl/src/main/res/values/localazy.xml @@ -30,11 +30,13 @@ "You can change it in your %1$s." "global settings" "Default setting" + "Remove custom setting" "An error occurred while loading notification settings." "Failed restoring the default mode, please try again." "Failed setting the mode, please try again." "All messages" "Mentions and Keywords only" + "In this room, notify me for" "Block" "Blocked users won\'t be able to send you messages and all their messages will be hidden. You can unblock them anytime." "Block user" diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/MessageComposerMode.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/MessageComposerMode.kt index aa3e745ea2..3dbc652aaf 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/MessageComposerMode.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/MessageComposerMode.kt @@ -41,6 +41,7 @@ sealed interface MessageComposerMode : Parcelable { class Reply( val senderName: String, val attachmentThumbnailInfo: AttachmentThumbnailInfo?, + val isThreaded: Boolean, override val eventId: EventId, override val defaultContent: String ) : Special(eventId, defaultContent) @@ -60,5 +61,5 @@ sealed interface MessageComposerMode : Parcelable { get() = this is Reply val inThread: Boolean - get() = false // TODO + get() = this is Reply && isThreaded } diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt index 3cc09ce09f..c407e678dd 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt @@ -183,9 +183,13 @@ fun TextComposer( if (composerMode is MessageComposerMode.Special) { ComposerModeView(composerMode = composerMode, onResetComposerMode = onResetComposerMode) } - TextInput( state = state, + placeholder = if (composerMode.inThread) { + stringResource(id = CommonStrings.action_reply_in_thread) + } else { + stringResource(id = CommonStrings.rich_text_editor_composer_placeholder) + }, roundedCorners = roundedCorners, bgColor = bgColor, onError = onError, @@ -237,6 +241,7 @@ fun TextComposer( @Composable private fun TextInput( state: RichTextEditorState, + placeholder: String, roundedCorners: RoundedCornerShape, bgColor: Color, modifier: Modifier = Modifier, @@ -262,7 +267,7 @@ private fun TextInput( // Placeholder if (state.messageHtml.isEmpty()) { Text( - stringResource(CommonStrings.common_message), + placeholder, style = defaultTypography.copy( color = ElementTheme.colors.textDisabled, ), @@ -686,6 +691,7 @@ internal fun TextComposerReplyPreview() = ElementPreview { canSendMessage = false, onSendMessage = {}, composerMode = MessageComposerMode.Reply( + isThreaded = false, senderName = "Alice", eventId = EventId("$1234"), attachmentThumbnailInfo = null, @@ -701,6 +707,7 @@ internal fun TextComposerReplyPreview() = ElementPreview { canSendMessage = true, onSendMessage = {}, composerMode = MessageComposerMode.Reply( + isThreaded = true, senderName = "Alice", eventId = EventId("$1234"), attachmentThumbnailInfo = AttachmentThumbnailInfo( @@ -719,6 +726,7 @@ internal fun TextComposerReplyPreview() = ElementPreview { canSendMessage = true, onSendMessage = {}, composerMode = MessageComposerMode.Reply( + isThreaded = false, senderName = "Alice", eventId = EventId("$1234"), attachmentThumbnailInfo = AttachmentThumbnailInfo( @@ -737,6 +745,7 @@ internal fun TextComposerReplyPreview() = ElementPreview { canSendMessage = true, onSendMessage = {}, composerMode = MessageComposerMode.Reply( + isThreaded = false, senderName = "Alice", eventId = EventId("$1234"), attachmentThumbnailInfo = AttachmentThumbnailInfo( @@ -755,6 +764,7 @@ internal fun TextComposerReplyPreview() = ElementPreview { canSendMessage = true, onSendMessage = {}, composerMode = MessageComposerMode.Reply( + isThreaded = false, senderName = "Alice", eventId = EventId("$1234"), attachmentThumbnailInfo = AttachmentThumbnailInfo( diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index d6f9f2cbaf..3098b9b5b3 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -1,6 +1,5 @@ - "Use an identity server to invite by email. ""Use the default (%(defaultIdentityServerName)s)"" or manage in ""Settings""." "Hide password" "Mentions only" "Muted" @@ -37,6 +36,8 @@ "Learn more" "Leave" "Leave room" + "Manage account" + "Manage devices" "Next" "No" "Not now" @@ -47,6 +48,7 @@ "React" "Remove" "Reply" + "Reply in thread" "Report bug" "Report Content" "Retry" @@ -65,8 +67,12 @@ "Take photo" "View Source" "Yes" + "Ongoing call" + "Tap to return to the call" + "☎️ Call in progress" "About" "Acceptable use policy" + "Advanced settings" "Analytics" "Audio" "Bubbles" @@ -85,6 +91,7 @@ "Forward message" "GIF" "Image" + "In reply to %1$s" "This Matrix ID can\'t be found, so the invite might not be received." "Leaving room" "Link copied to clipboard" @@ -99,15 +106,16 @@ "Password" "People" "Permalink" - "Final votes: %1$s" "Total votes: %1$s" "Results will show after the poll has ended" "Privacy policy" + "Reaction" "Reactions" "Refreshing…" "Replying to %1$s" "Report a bug" "Report submitted" + "Rich text editor" "Room name" "e.g. your project name" "Search for someone" @@ -126,6 +134,7 @@ "Syncing" "Text" "Third-party notices" + "Thread" "Topic" "What is this room about?" "Unable to decrypt" @@ -162,10 +171,6 @@ "Are you sure that you want to leave this room? This room is not public and you won\'t be able to rejoin without an invite." "Are you sure that you want to leave the room?" "%1$s Android" - - "%(count)s room" - "%(count)s rooms" - "%1$d member" "%1$d members" From 74c2d6a9d62f34d71d9cc2f8959ff72e65f02a3b Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 13 Sep 2023 14:14:25 +0000 Subject: [PATCH 137/234] Update screenshots --- ..._null_MessageComposerViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...null_MessageComposerViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...es.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...s.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...null_TextComposerFormatting-D-1_2_null,NEXUS_5,1.0,en].png | 4 ++-- ...null_TextComposerFormatting-N-1_3_null,NEXUS_5,1.0,en].png | 4 ++-- ...oser_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png | 4 ++-- ...oser_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png | 4 ++-- ...ser_null_TextComposerSimple-D-0_1_null,NEXUS_5,1.0,en].png | 4 ++-- ...ser_null_TextComposerSimple-N-0_2_null,NEXUS_5,1.0,en].png | 4 ++-- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewDark_0_null_0,NEXUS_5,1.0,en].png index ee0937d439..67b7525ddc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f3ea303577f655368800debe9c40e1292dc08a20da7f2ea6ddddb87f8407b112 -size 10431 +oid sha256:6bf428927e9a3493284d9fa7ba307b51315ed52b317a60ac345e87ba70849d0f +size 10523 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewLight_0_null_0,NEXUS_5,1.0,en].png index e537e910e3..8007500f81 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b646c06e55b50b64eb7b566fbc0bcafa7f7e348398f87152d008a47e7448f4e0 -size 10736 +oid sha256:6eced1d7173c2d0100351f5bb9cd14c649a826b2e355e426b9c6d4add90015d9 +size 10833 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png index eb75a98270..8d7e2dcf95 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd991a67e7d6c1169e08e62cb74ed6fa7d12ad7f91d69bbfa778e0053efebfec -size 52284 +oid sha256:c329165fa341a2130b43a448b8bba465f1e5f458136efa6da80f2cdeee9d6caa +size 52369 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png index 9603a65588..ec09599aca 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d421656ae8ad316e65f406c74dffa2ceb4e47b868b7f033f9cc4139e3e6be788 -size 53909 +oid sha256:2b4e5e9d920ea2a7733453e030bb365c9e2af7263de8fe216ab56088e0861fa5 +size 53997 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-D-1_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-D-1_2_null,NEXUS_5,1.0,en].png index 760cf75800..f9dc3f8b9a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-D-1_2_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-D-1_2_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d0e4c8da669ee5383a7d0f828a3300b923ec38ab5e04bc388da0e83f1cf1ccf3 -size 38291 +oid sha256:1f065f63fb37fa9a5441cfaeca04e867e4e8f6f744dd02a83c459fc128ee353d +size 38384 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-N-1_3_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-N-1_3_null,NEXUS_5,1.0,en].png index 0b9f9f3ab7..ca3a85e52c 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-N-1_3_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-N-1_3_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1f26aa7b13403cfaa864778a6ec5c26edde5932f3d887c7148d3a2b9f60f6e6a -size 36392 +oid sha256:a5ded1cbc536c544b0cb188ba0a333a541157eaf1772cd0e06c7338307549adc +size 36483 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png index 37e8a8561f..3c7754c726 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e65e15c721a939ed700719cacbdee57e1ccb89d984e88bdb5ed772c4b583472a -size 81494 +oid sha256:dd9b6fc48c755f51edaff00131b864a0c95bedc5d29133e010b885054cf7c954 +size 81601 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png index 466f321959..77acf98598 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:49f6d3b7f93008640abf30a5a65ddca6845e16343ef97c3450faf9dd6d9b9cec -size 78788 +oid sha256:b6b4ad7b6549da6c449827498b14057df0ea3990ecf1d05fa82b1247d218834e +size 78890 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-D-0_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-D-0_1_null,NEXUS_5,1.0,en].png index d6beb7c22c..06fbfc6c7f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-D-0_1_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-D-0_1_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2a998d3db9e4454fe74f31028b1dc61e4d6c07c824192f5e75563234dedf0b26 -size 44108 +oid sha256:267f482ceddeadea4c3b580d6783fed1048015fa05a11e385dd547e60f72e1e8 +size 44206 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-N-0_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-N-0_2_null,NEXUS_5,1.0,en].png index 863e8b8628..a237bcce80 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-N-0_2_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-N-0_2_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:97ab0a0b64ea7704a1557fc34b24d7caea34f9951948f5f5637f0bda596288dd -size 41455 +oid sha256:9f5e7ab52469b406509964d71f12475df546973f1382944ce7f2e1a437e4f880 +size 41536 From f456eea0e4b405364327ceca010779380ea6b73d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 13 Sep 2023 16:35:32 +0200 Subject: [PATCH 138/234] Request focus after adding an answer --- .../poll/impl/create/CreatePollView.kt | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollView.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollView.kt index 462ff4e48a..0355b34375 100644 --- a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollView.kt +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollView.kt @@ -34,6 +34,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester @@ -63,6 +64,8 @@ import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.ui.strings.CommonStrings +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -70,6 +73,8 @@ fun CreatePollView( state: CreatePollState, modifier: Modifier = Modifier, ) { + val coroutineScope = rememberCoroutineScope() + val navBack = { state.eventSink(CreatePollEvents.ConfirmNavBack) } BackHandler(onBack = navBack) if (state.showConfirmation) ConfirmationDialog( @@ -142,7 +147,6 @@ fun CreatePollView( } itemsIndexed(state.answers) { index, answer -> val isLastItem = index == state.answers.size - 1 - val hasAdditionalOptions = state.answers.size > 2 ListItem( headlineContent = { OutlinedTextField( @@ -170,10 +174,6 @@ fun CreatePollView( }, style = if (answer.canDelete) ListItemStyle.Destructive else ListItemStyle.Default, ) - LaunchedEffect(isLastItem, hasAdditionalOptions) { - lazyListState.animateScrollToItem(state.answers.size + 1) - if (isLastItem && hasAdditionalOptions) answerFocusRequester.requestFocus() - } } if (state.canAddAnswer) { item { @@ -183,7 +183,13 @@ fun CreatePollView( iconSource = IconSource.Vector(Icons.Default.Add), ), style = ListItemStyle.Primary, - onClick = { state.eventSink(CreatePollEvents.AddAnswer) }, + onClick = { + state.eventSink(CreatePollEvents.AddAnswer) + coroutineScope.launch(Dispatchers.Main) { + lazyListState.animateScrollToItem(state.answers.size + 1) + answerFocusRequester.requestFocus() + } + }, ) } } From 0fb93d1cca98a6d4fb1b803d40ec0e83cd0ef1c3 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 13 Sep 2023 16:36:35 +0200 Subject: [PATCH 139/234] Thread decoration: update preview with new changes --- .../timeline/components/TimelineItemEventRow.kt | 8 ++++---- .../libraries/textcomposer/TextComposer.kt | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index 0158372c79..95a28131d3 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -707,7 +707,7 @@ private fun ContentToPreviewWithReply() { body = "A long text which will be displayed on several lines and" + " hopefully can be manually adjusted to test different behaviors." ), - inReplyTo = aInReplyToReady(replyContent, true), + inReplyTo = aInReplyToReady(replyContent), groupPosition = TimelineItemGroupPosition.First, ), isHighlighted = false, @@ -729,7 +729,8 @@ private fun ContentToPreviewWithReply() { content = aTimelineItemImageContent().copy( aspectRatio = 5f ), - inReplyTo = aInReplyToReady(replyContent, false), + inReplyTo = aInReplyToReady(replyContent), + isThreaded = true, groupPosition = TimelineItemGroupPosition.Last, ), isHighlighted = false, @@ -751,11 +752,10 @@ private fun ContentToPreviewWithReply() { private fun aInReplyToReady( replyContent: String, - isThreaded: Boolean, ): InReplyTo.Ready { return InReplyTo.Ready( eventId = EventId("\$event"), - content = MessageContent(replyContent, null, false, isThreaded, TextMessageType(replyContent, null)), + content = MessageContent(replyContent, null, false, false, TextMessageType(replyContent, null)), senderId = UserId("@Sender:domain"), senderDisplayName = "Sender", senderAvatarUrl = null, diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt index c407e678dd..de43424aae 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt @@ -702,6 +702,22 @@ internal fun TextComposerReplyPreview() = ElementPreview { onResetComposerMode = {}, enableTextFormatting = true, ) + TextComposer( + RichTextEditorState("", fake = true), + canSendMessage = false, + onSendMessage = {}, + composerMode = MessageComposerMode.Reply( + isThreaded = true, + senderName = "Alice", + eventId = EventId("$1234"), + attachmentThumbnailInfo = null, + defaultContent = "A message\n" + + "With several lines\n" + + "To preview larger textfields and long lines with overflow" + ), + onResetComposerMode = {}, + enableTextFormatting = true, + ) TextComposer( RichTextEditorState("A message", fake = true), canSendMessage = true, From 3c81f12f932f53ece0066078673c1ab30b0db33c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 13 Sep 2023 16:39:24 +0200 Subject: [PATCH 140/234] Ensure testTag does not resize the Composable. --- .../io/element/android/libraries/testtags/Compose.kt | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/Compose.kt b/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/Compose.kt index 966c88fa06..7d467dc5a4 100644 --- a/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/Compose.kt +++ b/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/Compose.kt @@ -26,9 +26,7 @@ import androidx.compose.ui.semantics.testTagsAsResourceId * Add a testTag to a Modifier, to be used by external tool, like TrafficLight for instance. */ @OptIn(ExperimentalComposeUiApi::class) -fun Modifier.testTag(id: TestTag) = this.then( - semantics { - testTag = id.value - testTagsAsResourceId = true - } -) +fun Modifier.testTag(id: TestTag) = semantics { + testTag = id.value + testTagsAsResourceId = true +} From a94fe980049adb2c7f927cad5e3e98b7819599eb Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 13 Sep 2023 14:55:57 +0000 Subject: [PATCH 141/234] Update screenshots --- ...melineItemEventRowWithReplyDark_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...elineItemEventRowWithReplyLight_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...oser_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png | 4 ++-- ...oser_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyDark_0_null,NEXUS_5,1.0,en].png index c39b41db87..a41e57eecc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b991a34a137d82ff4dedf48316a05ebbc008233984b11af70e64889a5fb5eda8 -size 127438 +oid sha256:2bf08003a076d8a206782888cc2fc3df297e53478cd4c0e0aa5c8a26069bb7fa +size 128065 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyLight_0_null,NEXUS_5,1.0,en].png index a6500ca748..9c01abd666 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyLight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventRowWithReplyLight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:43b6514716d18382c8962520928d9d2ff6d0f665b2471e8a24e5d2e44a25c88c -size 132295 +oid sha256:8f5f950fce40c10710eb7fe4b193b4623633acdedfcf9029d6e0920e0c8d43d6 +size 133043 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png index 3c7754c726..0d9c311dcc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dd9b6fc48c755f51edaff00131b864a0c95bedc5d29133e010b885054cf7c954 -size 81601 +oid sha256:69e98a3521ae6545700e395bff211b06bb02095b01d9c254b3e0d2d0b8b88d26 +size 80484 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png index 77acf98598..ef035d6cd5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b6b4ad7b6549da6c449827498b14057df0ea3990ecf1d05fa82b1247d218834e -size 78890 +oid sha256:27dee9eaae6736a128107c9fd93048a677287a40d24c334223243b3c55f1cf69 +size 77686 From 4bf439d5ecbc0829f287fb576bfac20bd6cd9031 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 13 Sep 2023 17:13:15 +0200 Subject: [PATCH 142/234] Fix top padding in room list when app is opened in offline mode (#1299) * Fix top padding in room list when app is opened in offline mode * Fix `avatarBloom` not passing the `bottomSoftEdgeColor` to `bloom` --- changelog.d/1297.bugfix | 1 + .../networkmonitor/api/ui/ConnectivityIndicatorView.kt | 4 +++- .../android/libraries/designsystem/components/Bloom.kt | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 changelog.d/1297.bugfix diff --git a/changelog.d/1297.bugfix b/changelog.d/1297.bugfix new file mode 100644 index 0000000000..3b7d61fd8d --- /dev/null +++ b/changelog.d/1297.bugfix @@ -0,0 +1 @@ +Fix top padding in room list when app is opened in offline mode. diff --git a/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/ConnectivityIndicatorView.kt b/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/ConnectivityIndicatorView.kt index 7c03be6a41..dd586d4576 100644 --- a/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/ConnectivityIndicatorView.kt +++ b/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/ConnectivityIndicatorView.kt @@ -109,7 +109,9 @@ fun ConnectivityIndicatorContainer( } else { WindowInsets.statusBars.asPaddingValues().calculateTopPadding() + 6.dp } - val target = remember(isOnline) { if (isOnline) 0.dp else statusBarTopPadding } + val target = remember(isIndicatorVisible.targetState, statusBarTopPadding) { + if (!isIndicatorVisible.targetState) 0.dp else statusBarTopPadding + } val animationStateOffset by animateDpAsState( targetValue = target, animationSpec = spring( diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/Bloom.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/Bloom.kt index 2a178af000..b23c0cc2bb 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/Bloom.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/Bloom.kt @@ -363,6 +363,7 @@ fun Modifier.avatarBloom( blurSize = blurSize, offset = offset, clipToSize = clipToSize, + bottomSoftEdgeColor = bottomSoftEdgeColor, bottomSoftEdgeHeight = bottomSoftEdgeHeight, bottomSoftEdgeAlpha = bottomSoftEdgeAlpha, alpha = alpha, From 517f54ca2f2dceea2c1116ef1cca8d18979d2d5e Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 13 Sep 2023 15:48:14 +0000 Subject: [PATCH 143/234] Update screenshots --- ...SearchAccountProviderViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...SearchAccountProviderViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...earchAccountProviderViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...earchAccountProviderViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.login.impl.screens.searchaccountprovider_null_SearchAccountProviderViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.login.impl.screens.searchaccountprovider_null_SearchAccountProviderViewDark_0_null_0,NEXUS_5,1.0,en].png index f7ed356451..bc70d900bc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.login.impl.screens.searchaccountprovider_null_SearchAccountProviderViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.login.impl.screens.searchaccountprovider_null_SearchAccountProviderViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c8a6aa5c7bdddcb18453efc47f90dd0301173bcfa5622abc0821eb09cb2579d8 -size 25149 +oid sha256:856fc14eb010048f355c902419d7d346f77bfb26e79bbba7e966363a39f503f5 +size 24884 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.login.impl.screens.searchaccountprovider_null_SearchAccountProviderViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.login.impl.screens.searchaccountprovider_null_SearchAccountProviderViewDark_0_null_1,NEXUS_5,1.0,en].png index 3b68e95447..ebb99ef2c6 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.login.impl.screens.searchaccountprovider_null_SearchAccountProviderViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.login.impl.screens.searchaccountprovider_null_SearchAccountProviderViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b6344d9976849f1e56782a463fcca625943a7c6adf74c598c7a58245809b9db5 -size 53642 +oid sha256:d4329c822e128dcfa495df0c81126d929fa5f787e28f3c144009aaaaafae4dc6 +size 53371 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.login.impl.screens.searchaccountprovider_null_SearchAccountProviderViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.login.impl.screens.searchaccountprovider_null_SearchAccountProviderViewLight_0_null_0,NEXUS_5,1.0,en].png index cad7ad3f59..54d60d6642 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.login.impl.screens.searchaccountprovider_null_SearchAccountProviderViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.login.impl.screens.searchaccountprovider_null_SearchAccountProviderViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:602d7585b9693d08b1a4e3e620f2cecbbbde2a9b0e6b2beeb77f244520c5e4eb -size 25827 +oid sha256:8222670d7b08fc9f5e446e86a31fad4fa773bbac03742df9bb5dfb35189571aa +size 25617 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.login.impl.screens.searchaccountprovider_null_SearchAccountProviderViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.login.impl.screens.searchaccountprovider_null_SearchAccountProviderViewLight_0_null_1,NEXUS_5,1.0,en].png index 2e35a8461c..79b7a23804 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.login.impl.screens.searchaccountprovider_null_SearchAccountProviderViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.login.impl.screens.searchaccountprovider_null_SearchAccountProviderViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd7e6fc09011429e0fe19bff73d3c48124b1f3bed74d3cb12c9f3f0405f53980 -size 55728 +oid sha256:a4830db08b7e09971e299c31f18ce45dfa500c59a056b407c7df397b679e23d3 +size 55455 From 40da08fcbaf50e0c04316d008a7ab41817da6007 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 13 Sep 2023 18:31:17 +0000 Subject: [PATCH 144/234] Update dependency com.autonomousapps.dependency-analysis to v1.22.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cc0e9454ab..a48094ae9b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -42,7 +42,7 @@ showkase = "1.0.0-beta18" jsoup = "1.16.1" appyx = "1.3.0" dependencycheck = "8.4.0" -dependencyanalysis = "1.21.0" +dependencyanalysis = "1.22.0" stem = "2.3.0" sqldelight = "1.5.5" telephoto = "0.6.0" From 004abd16dc90073587ef5ad56fa1a541f40b432f Mon Sep 17 00:00:00 2001 From: David Langley Date: Wed, 13 Sep 2023 21:03:52 +0100 Subject: [PATCH 145/234] Address PR review comments. - use util startNotificationSettingsIntent. - add documentation. - use remember with userPushStoreFactory for recomposition. --- .../impl/notifications/NotificationSettingsNode.kt | 2 +- .../notifications/NotificationSettingsPresenter.kt | 2 +- .../impl/notifications/NotificationSettingsView.kt | 12 ++++++------ .../edit/DefaultNotificationSettingOption.kt | 2 +- .../edit/EditDefaultNotificationSettingPresenter.kt | 1 + .../edit/EditDefaultNotificationSettingView.kt | 5 +++++ .../libraries/androidutils/system/SystemUtils.kt | 9 +++++++-- 7 files changed, 22 insertions(+), 11 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsNode.kt index 14ffe2868f..0e3861c5ec 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsNode.kt @@ -49,7 +49,7 @@ class NotificationSettingsNode @AssistedInject constructor( val state = presenter.present() NotificationSettingsView( state = state, - onOpenEditDefault = { openEditDefault(it) }, + onOpenEditDefault = { openEditDefault(isOneToOne = it) }, onBackPressed = ::navigateUp, modifier = modifier, ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt index 923415b339..697d5887f0 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt @@ -46,7 +46,7 @@ class NotificationSettingsPresenter @Inject constructor( ) : Presenter { @Composable override fun present(): NotificationSettingsState { - val userPushStore = userPushStoreFactory.create(matrixClient.sessionId) + val userPushStore = remember { userPushStoreFactory.create(matrixClient.sessionId) } val systemNotificationsEnabled: MutableState = remember { mutableStateOf(systemNotificationsEnabledProvider.notificationsEnabled()) } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt index 9bb0f1cd66..b5aa7db9f6 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt @@ -39,6 +39,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import androidx.lifecycle.Lifecycle +import io.element.android.libraries.androidutils.system.startNotificationSettingsIntent import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch @@ -55,10 +56,13 @@ import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.ui.strings.CommonStrings +/** + * A view that allows a user edit their global notification settings. + */ @Composable fun NotificationSettingsView( state: NotificationSettingsState, - onOpenEditDefault: (Boolean) -> Unit, + onOpenEditDefault: (isOneToOne: Boolean) -> Unit, onBackPressed: () -> Unit, modifier: Modifier = Modifier, ) { @@ -113,11 +117,7 @@ private fun NotificationSettingsContentView( subtitle = stringResource(id = CommonStrings.screen_notification_settings_system_notifications_action_required, stringResource(id = CommonStrings.screen_notification_settings_system_notifications_action_required_content_link)), onClick = { - val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - val uri: Uri = Uri.fromParts("package", context.packageName, null) - intent.data = uri - context.startActivity(intent) + context.startNotificationSettingsIntent() } ) } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/DefaultNotificationSettingOption.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/DefaultNotificationSettingOption.kt index 7ece6cc737..e60b2bc8dc 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/DefaultNotificationSettingOption.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/DefaultNotificationSettingOption.kt @@ -80,7 +80,7 @@ fun DefaultNotificationSettingOption( } @DayNightPreviews @Composable -internal fun DefaultNotificationSettingOptionLightPreview() = ElementPreview { ContentToPreview() } +internal fun DefaultNotificationSettingOptionPreview() = ElementPreview { ContentToPreview() } @Composable private fun ContentToPreview() { diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingPresenter.kt index cc15e5bdd8..764b37c52d 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingPresenter.kt @@ -84,6 +84,7 @@ class EditDefaultNotificationSettingPresenter @AssistedInject constructor( } private fun CoroutineScope.setDefaultNotificationMode(mode: RoomNotificationMode) = launch { + // On modern clients, we don't have different settings for encrypted and non-encrypted rooms (Legacy clients did). notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = true, mode = mode, isOneToOne = isOneToOne) notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = false, mode = mode, isOneToOne = isOneToOne) } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt index d67b789cc9..4cc95af71f 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt @@ -26,6 +26,10 @@ import io.element.android.libraries.designsystem.components.preferences.Preferen import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.ui.strings.CommonStrings +/** + * A view that allows a user to edit the default notification setting for rooms. This can be set separately + * for one-to-one and group rooms, indicated by [EditDefaultNotificationSettingState.isOneToOne]. + */ @Composable fun EditDefaultNotificationSettingView( state: EditDefaultNotificationSettingState, @@ -44,6 +48,7 @@ fun EditDefaultNotificationSettingView( title = stringResource(id = title) ) { + // Only ALL_MESSAGES and MENTIONS_AND_KEYWORDS_ONLY are valid global defaults. val validModes = listOf(RoomNotificationMode.ALL_MESSAGES, RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY) val categoryTitle = if(state.isOneToOne) { diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/SystemUtils.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/SystemUtils.kt index a9a17dcceb..1aee986d32 100644 --- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/SystemUtils.kt +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/system/SystemUtils.kt @@ -122,7 +122,7 @@ fun Context.copyToClipboard( * Shows notification settings for the current app. * In android O will directly opens the notification settings, in lower version it will show the App settings */ -fun Context.startNotificationSettingsIntent(activityResultLauncher: ActivityResultLauncher) { +fun Context.startNotificationSettingsIntent(activityResultLauncher: ActivityResultLauncher? = null) { val intent = Intent() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS @@ -132,7 +132,12 @@ fun Context.startNotificationSettingsIntent(activityResultLauncher: ActivityResu intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) intent.data = Uri.fromParts("package", packageName, null) } - activityResultLauncher.launch(intent) + + if (activityResultLauncher != null) { + activityResultLauncher.launch(intent) + } else { + startActivity(intent) + } } fun Context.openAppSettingsPage( From 79c70d68c9583b3fd20c652b54cd769195705971 Mon Sep 17 00:00:00 2001 From: David Langley Date: Wed, 13 Sep 2023 21:12:16 +0100 Subject: [PATCH 146/234] - Remove call notification toggle --- .../notifications/NotificationSettingsView.kt | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt index b5aa7db9f6..e29cef9ede 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt @@ -154,16 +154,16 @@ private fun NotificationSettingsContentView( onCheckedChange = onMentionNotificationsChanged ) } - - PreferenceCategory(title = stringResource(id = CommonStrings.screen_notification_settings_additional_settings_section_title)) { - PreferenceSwitch( - modifier = Modifier, - title = stringResource(id = CommonStrings.screen_notification_settings_calls_label), - isChecked = matrixSettings.callNotificationsEnabled, - switchAlignment = Alignment.Top, - onCheckedChange = onCallsNotificationsChanged - ) - } + // We are removing the call notification toggle until call support has been added +// PreferenceCategory(title = stringResource(id = CommonStrings.screen_notification_settings_additional_settings_section_title)) { +// PreferenceSwitch( +// modifier = Modifier, +// title = stringResource(id = CommonStrings.screen_notification_settings_calls_label), +// isChecked = matrixSettings.callNotificationsEnabled, +// switchAlignment = Alignment.Top, +// onCheckedChange = onCallsNotificationsChanged +// ) +// } } } From 3907067b7f9b408a0905d556642c4dcc54a227c7 Mon Sep 17 00:00:00 2001 From: David Langley Date: Wed, 13 Sep 2023 21:14:37 +0100 Subject: [PATCH 147/234] lint --- .../preferences/impl/notifications/NotificationSettingsView.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt index e29cef9ede..c148d2dea5 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt @@ -16,9 +16,6 @@ package io.element.android.features.preferences.impl.notifications -import android.content.Intent -import android.net.Uri -import android.provider.Settings import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row From 255a71ef2ece4e97184965380694a69210d63d6a Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 13 Sep 2023 20:28:48 +0000 Subject: [PATCH 148/234] Update screenshots --- ...tNotificationSettingOption-D-1_2_null,NEXUS_5,1.0,en].png} | 0 ...tNotificationSettingOption-N-1_3_null,NEXUS_5,1.0,en].png} | 0 ..._NotificationSettingsViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...NotificationSettingsViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- 4 files changed, 4 insertions(+), 4 deletions(-) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOptionLight-D-1_2_null,NEXUS_5,1.0,en].png => ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOption-D-1_2_null,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOptionLight-N-1_3_null,NEXUS_5,1.0,en].png => ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOption-N-1_3_null,NEXUS_5,1.0,en].png} (100%) diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOptionLight-D-1_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOption-D-1_2_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOptionLight-D-1_2_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOption-D-1_2_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOptionLight-N-1_3_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOption-N-1_3_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOptionLight-N-1_3_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOption-N-1_3_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_NotificationSettingsViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_NotificationSettingsViewDark_0_null_0,NEXUS_5,1.0,en].png index 324dabeb34..926b1b641a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_NotificationSettingsViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_NotificationSettingsViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fdab0618a9188ced6ad4c3124aa7ce4a467615564bd1484bbf9f035c2a9037ff -size 57523 +oid sha256:c100e53723c6ed01ed1d82bba61e355bfc89ef45152f1490f664cf056beb95ce +size 49228 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_NotificationSettingsViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_NotificationSettingsViewLight_0_null_0,NEXUS_5,1.0,en].png index c9a0b8219f..dc08c6b74b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_NotificationSettingsViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_NotificationSettingsViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5edd3646866f2c76ad28fe6c77079cdac41da30aaa77f8f4c6f7f2b2d12a7d37 -size 62384 +oid sha256:3d3ebc3196c825b08f7622ad370bb69f2989e57a0fc69058f41877163b43fd1a +size 52756 From 97bbb8296f8cd597d65d2923fdd9a4f5fdf89222 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Thu, 14 Sep 2023 08:30:41 +0200 Subject: [PATCH 149/234] Fix possible memory leak in `EventMessageMapper`. (#1326) --- .../timeline/item/event/EventMessageMapper.kt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventMessageMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventMessageMapper.kt index 330a06da62..6e6efc67f5 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventMessageMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventMessageMapper.kt @@ -46,22 +46,22 @@ class EventMessageMapper { fun map(message: Message): MessageContent = message.use { val type = it.msgtype().use(this::mapMessageType) - val inReplyToId = it.inReplyTo()?.eventId?.let(::EventId) - val inReplyToEvent: InReplyTo? = it.inReplyTo()?.event?.use { details -> - when (details) { + val inReplyToEvent: InReplyTo? = it.inReplyTo()?.use { details -> + val inReplyToId = EventId(details.eventId) + when (val event = details.event) { is RepliedToEventDetails.Ready -> { - val senderProfile = details.senderProfile as? ProfileDetails.Ready + val senderProfile = event.senderProfile as? ProfileDetails.Ready InReplyTo.Ready( - eventId = inReplyToId!!, - content = timelineEventContentMapper.map(details.content), - senderId = UserId(details.sender), + eventId = inReplyToId, + content = timelineEventContentMapper.map(event.content), + senderId = UserId(event.sender), senderDisplayName = senderProfile?.displayName, senderAvatarUrl = senderProfile?.avatarUrl, ) } is RepliedToEventDetails.Error -> InReplyTo.Error is RepliedToEventDetails.Pending -> InReplyTo.Pending - is RepliedToEventDetails.Unavailable -> InReplyTo.NotLoaded(inReplyToId!!) + is RepliedToEventDetails.Unavailable -> InReplyTo.NotLoaded(inReplyToId) } } MessageContent( From f6b6a0a1e253852b1ff532cd4fbbd70e325a4eb6 Mon Sep 17 00:00:00 2001 From: David Langley Date: Thu, 14 Sep 2023 09:51:45 +0100 Subject: [PATCH 150/234] Fix warning for removed call notification setting code. --- .../impl/notifications/NotificationSettingsView.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt index c148d2dea5..4b17eba4ca 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt @@ -89,7 +89,7 @@ fun NotificationSettingsView( onGroupChatsClicked = { onOpenEditDefault(false) }, onDirectChatsClicked = { onOpenEditDefault(true) }, onMentionNotificationsChanged = { state.eventSink(NotificationSettingsEvents.SetAtRoomNotificationsEnabled(it)) }, - onCallsNotificationsChanged = { state.eventSink(NotificationSettingsEvents.SetCallNotificationsEnabled(it)) }, +// onCallsNotificationsChanged = { state.eventSink(NotificationSettingsEvents.SetCallNotificationsEnabled(it)) }, ) } } @@ -103,7 +103,7 @@ private fun NotificationSettingsContentView( onGroupChatsClicked: () -> Unit, onDirectChatsClicked: () -> Unit, onMentionNotificationsChanged: (Boolean) -> Unit, - onCallsNotificationsChanged: (Boolean) -> Unit, +// onCallsNotificationsChanged: (Boolean) -> Unit, modifier: Modifier = Modifier, ) { val context = LocalContext.current From 754671303a36c18f3035e55e1161cb3b703523d5 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Thu, 14 Sep 2023 11:51:10 +0200 Subject: [PATCH 151/234] Fix long click on simple formatted messages (#1327) --- changelog.d/1232.bugfix | 1 + .../messages/impl/timeline/components/html/HtmlDocument.kt | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 changelog.d/1232.bugfix diff --git a/changelog.d/1232.bugfix b/changelog.d/1232.bugfix new file mode 100644 index 0000000000..ab540beeab --- /dev/null +++ b/changelog.d/1232.bugfix @@ -0,0 +1 @@ +Fix long click on simple formatted messages diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/html/HtmlDocument.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/html/HtmlDocument.kt index 9df5399727..1febdd6092 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/html/HtmlDocument.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/html/HtmlDocument.kt @@ -126,7 +126,12 @@ private fun HtmlBody( when (val node = nodes.next()) { is TextNode -> { if (!node.isBlank) { - ClickableLinkText(text = node.text(), interactionSource = interactionSource) + ClickableLinkText( + text = node.text(), + interactionSource = interactionSource, + onClick = onTextClicked, + onLongClick = onTextLongClicked, + ) } } is Element -> { From 819b82533de564bfc6ec4768c434293c49eec478 Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Thu, 14 Sep 2023 12:12:49 +0200 Subject: [PATCH 152/234] Change "anonymous" copy in the create poll screen (#1325) --- features/poll/impl/src/main/res/values/localazy.xml | 2 +- ...reate_null_CreatePollView-D-0_1_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...reate_null_CreatePollView-D-0_1_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...reate_null_CreatePollView-D-0_1_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...reate_null_CreatePollView-D-0_1_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...reate_null_CreatePollView-N-0_2_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...reate_null_CreatePollView-N-0_2_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...reate_null_CreatePollView-N-0_2_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...reate_null_CreatePollView-N-0_2_null_3,NEXUS_5,1.0,en].png | 4 ++-- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/features/poll/impl/src/main/res/values/localazy.xml b/features/poll/impl/src/main/res/values/localazy.xml index 4c80a4ce45..3c5006d0af 100644 --- a/features/poll/impl/src/main/res/values/localazy.xml +++ b/features/poll/impl/src/main/res/values/localazy.xml @@ -2,7 +2,7 @@ "Add option" "Show results only after poll ends" - "Anonymous Poll" + "Hide votes" "Option %1$d" "Are you sure you want to discard this poll?" "Discard Poll" diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-D-0_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-D-0_1_null_0,NEXUS_5,1.0,en].png index f60c0c7a4d..175d444754 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-D-0_1_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-D-0_1_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6b06ec4a259dfccec114689bff7d53089bb7fc64758af23372938fd83c422071 -size 35374 +oid sha256:32651c4e32cea6891c8695b468db30dd3b6eefe72b1d441c3a5fbacfa08276a9 +size 34493 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-D-0_1_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-D-0_1_null_1,NEXUS_5,1.0,en].png index c53d96b0e5..43bdd9bee7 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-D-0_1_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-D-0_1_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:72bb304299954abac15f9487feab06649c0151c41cbcbcbf9c887417224d499b -size 39756 +oid sha256:95a8fd37e77521464a4af078b1e5b4113872fe875f6de90c6218d77b0168467b +size 38913 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-D-0_1_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-D-0_1_null_2,NEXUS_5,1.0,en].png index 8e47757aa3..9e63cc654a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-D-0_1_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-D-0_1_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:636e6c2494e69d7f1383e0c2ef178db484cfa6802c6714ee20a66aad10f4421f -size 40500 +oid sha256:0087805cdddb75fdb34775264949ce5974d8679c752b1eea87cfc44563e57de4 +size 40202 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-D-0_1_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-D-0_1_null_3,NEXUS_5,1.0,en].png index 9de6f34f78..f36ed1b6ee 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-D-0_1_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-D-0_1_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1bb6afbfd69bf254a2d222deb72d80c7f0bb4fc44bc5010a7e34f2b82420a423 -size 47529 +oid sha256:15f481a983765a5aeffff837aa0b7727e0fe87e69cba189ec78d56928630ff63 +size 46634 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-N-0_2_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-N-0_2_null_0,NEXUS_5,1.0,en].png index ce95adf2e9..e31b3b4ce2 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-N-0_2_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-N-0_2_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5f7fbf51ee1d86b1fc7cce949f88bfcb1c7ff7f700304e5a74242c4aa4965fcb -size 33455 +oid sha256:9ea6ba41fb57c9353ffe26014852ab8517a634e09106168cf9352391bee45270 +size 32643 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-N-0_2_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-N-0_2_null_1,NEXUS_5,1.0,en].png index 8e11aa2691..995416c8df 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-N-0_2_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-N-0_2_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2c7ca3daff99c6086f114d15dbf0649a4be7ff99a5afdeb6d0e8effda383bfec -size 36968 +oid sha256:91680df981504bad5d82760ffe38ee3aca9a7b34adf9ab4ab1b204e4381ce855 +size 36189 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-N-0_2_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-N-0_2_null_2,NEXUS_5,1.0,en].png index 96707cb507..ad4b412b67 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-N-0_2_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-N-0_2_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58ced9ebe2a161167f5515efa18b87eb02c340b75db47af84f91eab0866b113f -size 36370 +oid sha256:5b2bfcc5e61adb3b41d79bc25e4a5c159b0a729da4026bf4347f9ac0a7966b5d +size 36097 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-N-0_2_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-N-0_2_null_3,NEXUS_5,1.0,en].png index 79faef2ce6..3839132e39 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-N-0_2_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.impl.create_null_CreatePollView-N-0_2_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0680506590290c4ab5ae299abc51e0806b9a1e06a647971eae7b6a2227b0aba9 -size 44631 +oid sha256:71420ae88ea8d3e71a7799597f8132514bab5757cdf644d157bbb527248a4c4e +size 43862 From 96fbdb91c74988f68e11aa652ea8ec262c211439 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 14 Sep 2023 12:35:20 +0200 Subject: [PATCH 153/234] Thread decoration : pr review --- .../impl/timeline/components/TimelineItemEventRow.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index 95a28131d3..51711db0ae 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -24,6 +24,7 @@ import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.gestures.draggable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Arrangement.spacedBy import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues @@ -396,9 +397,12 @@ private fun MessageEventBubbleContent( fun ThreadDecoration( modifier: Modifier = Modifier ) { - Row(modifier, verticalAlignment = Alignment.CenterVertically) { + Row( + modifier = modifier, + horizontalArrangement = spacedBy(4.dp, Alignment.Start), + verticalAlignment = Alignment.CenterVertically, + ) { Icon(resourceId = R.drawable.ic_thread_decoration, contentDescription = null, tint = ElementTheme.colors.iconSecondary) - Spacer(modifier = Modifier.width(4.dp)) Text( text = stringResource(CommonStrings.common_thread), style = ElementTheme.typography.fontBodyXsRegular, From ed1949aa5106383cceedbe063785b291d412c634 Mon Sep 17 00:00:00 2001 From: David Langley Date: Thu, 14 Sep 2023 14:24:13 +0100 Subject: [PATCH 154/234] Show a room list decoration for notification setting applied - Add the UI - Rebuild room summaries when push rules change or when user disables notifications(hide them all) --- features/roomlist/impl/build.gradle.kts | 1 + .../impl/components/RoomSummaryRow.kt | 46 +++++++++++++++-- .../impl/datasource/RoomListDataSource.kt | 50 ++++++++++++++++--- .../impl/model/RoomListRoomSummary.kt | 2 + .../impl/model/RoomListRoomSummaryProvider.kt | 6 ++- .../libraries/designsystem/VectorIcons.kt | 2 + .../src/main/res/drawable/ic_mention.xml | 13 +++++ .../src/main/res/drawable/ic_mute.xml | 10 ++++ .../matrix/api/roomlist/RoomListService.kt | 5 ++ .../matrix/api/roomlist/RoomSummary.kt | 2 + .../roomlist/RoomSummaryDetailsFactory.kt | 2 + .../impl/roomlist/RoomSummaryListProcessor.kt | 12 +++++ .../impl/roomlist/RustRoomListService.kt | 6 +++ 13 files changed, 145 insertions(+), 12 deletions(-) create mode 100644 libraries/designsystem/src/main/res/drawable/ic_mention.xml create mode 100644 libraries/designsystem/src/main/res/drawable/ic_mute.xml diff --git a/features/roomlist/impl/build.gradle.kts b/features/roomlist/impl/build.gradle.kts index f5a08ba860..3a3639de98 100644 --- a/features/roomlist/impl/build.gradle.kts +++ b/features/roomlist/impl/build.gradle.kts @@ -49,6 +49,7 @@ dependencies { implementation(projects.libraries.dateformatter.api) implementation(projects.libraries.eventformatter.api) implementation(projects.libraries.deeplink) + implementation(projects.libraries.pushstore.api) implementation(projects.features.invitelist.api) implementation(projects.features.networkmonitor.api) implementation(projects.features.leaveroom.api) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt index aab174c6a4..61826dc2b2 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt @@ -19,14 +19,17 @@ package io.element.android.features.roomlist.impl.components import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.material.ripple.rememberRipple import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable @@ -38,6 +41,9 @@ import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Outline import androidx.compose.ui.graphics.Path import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.res.vectorResource import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview @@ -48,16 +54,20 @@ import androidx.compose.ui.unit.dp import io.element.android.features.roomlist.impl.model.RoomListRoomSummary import io.element.android.features.roomlist.impl.model.RoomListRoomSummaryProvider import io.element.android.libraries.core.extensions.orEmpty +import io.element.android.libraries.designsystem.VectorIcons import io.element.android.libraries.designsystem.atomic.atoms.UnreadIndicatorAtom import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewLight +import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.roomListRoomMessage import io.element.android.libraries.designsystem.theme.roomListRoomMessageDate import io.element.android.libraries.designsystem.theme.roomListRoomName import io.element.android.libraries.designsystem.theme.unreadIndicator +import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.theme.ElementTheme +import io.element.android.libraries.ui.strings.CommonStrings internal val minHeight = 84.dp @@ -168,11 +178,39 @@ private fun RowScope.LastMessageAndIndicatorRow(room: RoomListRoomSummary) { maxLines = 2, overflow = TextOverflow.Ellipsis ) + // Unread - UnreadIndicatorAtom( - modifier = Modifier.padding(top = 3.dp), - isVisible = room.hasUnread, - ) + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + NotificationIcon(room) + if (room.hasUnread) { + UnreadIndicatorAtom( + modifier = Modifier.padding(top = 3.dp), + ) + } + } + +} + +@Composable +private fun NotificationIcon(room: RoomListRoomSummary) { + val tint = if(room.hasUnread) ElementTheme.colors.unreadIndicator else ElementTheme.colors.iconQuaternary + when(room.notificationMode) { + null, RoomNotificationMode.ALL_MESSAGES -> return + RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> + Icon( + contentDescription = stringResource(CommonStrings.screen_notification_settings_mode_mentions), + imageVector = ImageVector.vectorResource(VectorIcons.Mention), + tint = tint, + ) + RoomNotificationMode.MUTE -> + Icon( + contentDescription = stringResource(CommonStrings.common_mute), + imageVector = ImageVector.vectorResource(VectorIcons.Mute), + tint = tint, + ) + } } val TextPlaceholderShape = PercentRectangleSizeShape(0.5f) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt index e44bcd6b6b..e0b20aada9 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt @@ -26,30 +26,57 @@ import io.element.android.libraries.dateformatter.api.LastMessageTimestampFormat import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter +import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService +import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.api.roomlist.RoomSummary +import io.element.android.libraries.pushstore.api.UserPushStoreFactory import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.debounce +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext import javax.inject.Inject +import kotlin.time.Duration.Companion.seconds class RoomListDataSource @Inject constructor( private val roomListService: RoomListService, private val lastMessageTimestampFormatter: LastMessageTimestampFormatter, private val roomLastMessageFormatter: RoomLastMessageFormatter, private val coroutineDispatchers: CoroutineDispatchers, + notificationSettingsService: NotificationSettingsService, + appScope: CoroutineScope, + userPushStoreFactory: UserPushStoreFactory, + matrixClient: MatrixClient, ) { + init { + notificationSettingsService.notificationSettingsChangeFlow + .debounce(0.5.seconds) + .onEach { + roomListService.rebuildRoomSummaries() + } + .launchIn(appScope) + val userPushStore = userPushStoreFactory.create(matrixClient.sessionId) + userPushStore.getNotificationEnabledForDevice().distinctUntilChanged() + .onEach { + roomListService.rebuildRoomSummaries() + } + .launchIn(appScope) + } private val _filter = MutableStateFlow("") private val _allRooms = MutableStateFlow>(persistentListOf()) private val _filteredRooms = MutableStateFlow>(persistentListOf()) @@ -59,13 +86,15 @@ class RoomListDataSource @Inject constructor( private val diffCacheUpdater = DiffCacheUpdater(diffCache = diffCache, detectMoves = true) { old, new -> old?.identifier() == new?.identifier() } + private val userPushStore = userPushStoreFactory.create(matrixClient.sessionId) fun launchIn(coroutineScope: CoroutineScope) { + roomListService .allRooms() .summaries .onEach { roomSummaries -> - replaceWith(roomSummaries) + replaceWith(roomSummaries, userPushStore.getNotificationEnabledForDevice().first()) } .launchIn(coroutineScope) @@ -92,14 +121,14 @@ class RoomListDataSource @Inject constructor( val allRooms: StateFlow> = _allRooms val filteredRooms: StateFlow> = _filteredRooms - private suspend fun replaceWith(roomSummaries: List) = withContext(coroutineDispatchers.computation) { + private suspend fun replaceWith(roomSummaries: List, notificationsEnabled: Boolean) = withContext(coroutineDispatchers.computation) { lock.withLock { diffCacheUpdater.updateWith(roomSummaries) - buildAndEmitAllRooms(roomSummaries) + buildAndEmitAllRooms(roomSummaries, notificationsEnabled) } } - private suspend fun buildAndEmitAllRooms(roomSummaries: List) { + private suspend fun buildAndEmitAllRooms(roomSummaries: List, notificationsEnabled: Boolean) { if (diffCache.isEmpty()) { _allRooms.emit( RoomListRoomSummaryPlaceholders.createFakeList(16).toImmutableList() @@ -109,7 +138,7 @@ class RoomListDataSource @Inject constructor( for (index in diffCache.indices()) { val cacheItem = diffCache.get(index) if (cacheItem == null) { - buildAndCacheItem(roomSummaries, index)?.also { timelineItemState -> + buildAndCacheItem(roomSummaries, index, notificationsEnabled)?.also { timelineItemState -> roomListRoomSummaries.add(timelineItemState) } } else { @@ -122,11 +151,18 @@ class RoomListDataSource @Inject constructor( private fun buildAndCacheItem( roomSummaries: List, - index: Int + index: Int, + notificationsEnabled: Boolean, ): RoomListRoomSummary? { val roomListRoomSummary = when (val roomSummary = roomSummaries.getOrNull(index)) { is RoomSummary.Empty -> RoomListRoomSummaryPlaceholders.create(roomSummary.identifier) is RoomSummary.Filled -> { + // Only show a decoration if notifications are enabled and the mode is not ALL_MESSAGES + val notificationMode = if (roomSummary.details.notificationMode == RoomNotificationMode.ALL_MESSAGES || !notificationsEnabled) { + null + } else { + roomSummary.details.notificationMode + } val avatarData = AvatarData( id = roomSummary.identifier(), name = roomSummary.details.name, @@ -144,10 +180,12 @@ class RoomListDataSource @Inject constructor( roomLastMessageFormatter.format(message.event, roomSummary.details.isDirect) }.orEmpty(), avatarData = avatarData, + notificationMode = notificationMode ) } null -> null } + diffCache[index] = roomListRoomSummary return roomListRoomSummary } diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/model/RoomListRoomSummary.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/model/RoomListRoomSummary.kt index 8ba6c26c0f..bb3405c2d3 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/model/RoomListRoomSummary.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/model/RoomListRoomSummary.kt @@ -20,6 +20,7 @@ import androidx.compose.runtime.Immutable import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.room.RoomNotificationMode @Immutable data class RoomListRoomSummary constructor( @@ -31,4 +32,5 @@ data class RoomListRoomSummary constructor( val lastMessage: CharSequence? = null, val avatarData: AvatarData = AvatarData(id, name, size = AvatarSize.RoomListItem), val isPlaceholder: Boolean = false, + val notificationMode: RoomNotificationMode? = null, ) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/model/RoomListRoomSummaryProvider.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/model/RoomListRoomSummaryProvider.kt index cd6ca21106..f2db8a376c 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/model/RoomListRoomSummaryProvider.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/model/RoomListRoomSummaryProvider.kt @@ -20,14 +20,16 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.room.RoomNotificationMode open class RoomListRoomSummaryProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( aRoomListRoomSummary(), aRoomListRoomSummary().copy(lastMessage = null), - aRoomListRoomSummary().copy(hasUnread = true), - aRoomListRoomSummary().copy(timestamp = "88:88"), + aRoomListRoomSummary().copy(hasUnread = true, notificationMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY), + aRoomListRoomSummary().copy(timestamp = "88:88", notificationMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY), + aRoomListRoomSummary().copy(timestamp = "88:88", notificationMode = RoomNotificationMode.MUTE), aRoomListRoomSummary().copy(timestamp = "88:88", hasUnread = true), aRoomListRoomSummary().copy(isPlaceholder = true, timestamp = "88:88"), aRoomListRoomSummary().copy( diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt index 20ebb85615..229605e3ea 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt @@ -41,4 +41,6 @@ object VectorIcons { val Quote = R.drawable.ic_quote val Strikethrough = R.drawable.ic_strikethrough val Underline = R.drawable.ic_underline + val Mention = R.drawable.ic_mention + val Mute = R.drawable.ic_mute } diff --git a/libraries/designsystem/src/main/res/drawable/ic_mention.xml b/libraries/designsystem/src/main/res/drawable/ic_mention.xml new file mode 100644 index 0000000000..37f70481e5 --- /dev/null +++ b/libraries/designsystem/src/main/res/drawable/ic_mention.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/libraries/designsystem/src/main/res/drawable/ic_mute.xml b/libraries/designsystem/src/main/res/drawable/ic_mute.xml new file mode 100644 index 0000000000..ea6f842696 --- /dev/null +++ b/libraries/designsystem/src/main/res/drawable/ic_mute.xml @@ -0,0 +1,10 @@ + + + diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt index de7f1f3918..8b85b3fe38 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt @@ -54,6 +54,11 @@ interface RoomListService { */ fun updateAllRoomsVisibleRange(range: IntRange) + /** + * Rebuild the room summaries, required when we know some data may have changed. (E.g. room notification settings) + */ + fun rebuildRoomSummaries() + /** * The sync indicator as a flow. */ diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt index 87cf2139d6..4638fc6e03 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt @@ -18,6 +18,7 @@ package io.element.android.libraries.matrix.api.roomlist import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.RoomMember +import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.message.RoomMessage sealed interface RoomSummary { @@ -42,4 +43,5 @@ data class RoomSummaryDetails( val lastMessageTimestamp: Long?, val unreadNotificationCount: Int, val inviter: RoomMember? = null, + val notificationMode: RoomNotificationMode? = null, ) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt index d33e2f58fc..f9f63ab271 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt @@ -18,6 +18,7 @@ package io.element.android.libraries.matrix.impl.roomlist import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails +import io.element.android.libraries.matrix.impl.notificationsettings.RoomNotificationSettingsMapper import io.element.android.libraries.matrix.impl.room.RoomMemberMapper import io.element.android.libraries.matrix.impl.room.message.RoomMessageFactory import org.matrix.rustcomponents.sdk.RoomInfo @@ -39,6 +40,7 @@ class RoomSummaryDetailsFactory(private val roomMessageFactory: RoomMessageFacto lastMessage = latestRoomMessage, lastMessageTimestamp = latestRoomMessage?.originServerTs, inviter = roomInfo.inviter?.let(RoomMemberMapper::map), + notificationMode = roomInfo.notificationMode?.let(RoomNotificationSettingsMapper::mapMode), ) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt index 03b58ed2ce..9ae10db12d 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt @@ -20,6 +20,7 @@ import io.element.android.libraries.core.coroutine.parallelMap import io.element.android.libraries.matrix.api.roomlist.RoomSummary import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.map import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate @@ -59,6 +60,17 @@ class RoomSummaryListProcessor( } } + suspend fun rebuildRoomSummaries() { + updateRoomSummaries { + forEachIndexed { i, summary -> + this[i] = when(summary) { + is RoomSummary.Empty -> summary + is RoomSummary.Filled -> buildAndCacheRoomSummaryForIdentifier(summary.identifier()) + } + } + } + } + private suspend fun MutableList.applyUpdate(update: RoomListEntriesUpdate) { when (update) { is RoomListEntriesUpdate.Append -> { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt index a2de2be89b..347e53aa0c 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt @@ -107,6 +107,12 @@ class RustRoomListService( } } + override fun rebuildRoomSummaries() { + sessionCoroutineScope.launch { + allRoomsListProcessor.rebuildRoomSummaries() + } + } + override val syncIndicator: StateFlow = innerRoomListService.syncIndicator() .map { it.toSyncIndicator() } From f91f75457dc503331953f122082c9eb56ed53124 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 14 Sep 2023 14:04:12 +0000 Subject: [PATCH 155/234] Update dependency org.matrix.rustcomponents:sdk-android to v0.1.52 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a48094ae9b..cdc80fbd1b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -149,7 +149,7 @@ jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" } appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = { module = "app.cash.molecule:molecule-runtime", version.ref = "molecule" } timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.51" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.52" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "com.squareup.sqldelight:android-driver", version.ref = "sqldelight" } From 1e0665c3e9a9637e5a5e63e6bb171e30b9f8bce8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 13 Sep 2023 15:01:12 +0200 Subject: [PATCH 156/234] Import English strings from Localazy --- .../impl/src/main/res/values/localazy.xml | 2 ++ .../ui-strings/src/main/res/values/localazy.xml | 15 +++++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/features/roomdetails/impl/src/main/res/values/localazy.xml b/features/roomdetails/impl/src/main/res/values/localazy.xml index 717f503e22..7f0f4ddc30 100644 --- a/features/roomdetails/impl/src/main/res/values/localazy.xml +++ b/features/roomdetails/impl/src/main/res/values/localazy.xml @@ -30,11 +30,13 @@ "You can change it in your %1$s." "global settings" "Default setting" + "Remove custom setting" "An error occurred while loading notification settings." "Failed restoring the default mode, please try again." "Failed setting the mode, please try again." "All messages" "Mentions and Keywords only" + "In this room, notify me for" "Block" "Blocked users won\'t be able to send you messages and all their messages will be hidden. You can unblock them anytime." "Block user" diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index d6f9f2cbaf..8d692d4dfc 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -1,6 +1,5 @@ - "Use an identity server to invite by email. ""Use the default (%(defaultIdentityServerName)s)"" or manage in ""Settings""." "Hide password" "Mentions only" "Muted" @@ -37,6 +36,8 @@ "Learn more" "Leave" "Leave room" + "Manage account" + "Manage devices" "Next" "No" "Not now" @@ -65,8 +66,12 @@ "Take photo" "View Source" "Yes" + "Ongoing call" + "Tap to return to the call" + "☎️ Call in progress" "About" "Acceptable use policy" + "Advanced settings" "Analytics" "Audio" "Bubbles" @@ -85,6 +90,7 @@ "Forward message" "GIF" "Image" + "In reply to %1$s" "This Matrix ID can\'t be found, so the invite might not be received." "Leaving room" "Link copied to clipboard" @@ -99,15 +105,16 @@ "Password" "People" "Permalink" - "Final votes: %1$s" "Total votes: %1$s" "Results will show after the poll has ended" "Privacy policy" + "Reaction" "Reactions" "Refreshing…" "Replying to %1$s" "Report a bug" "Report submitted" + "Rich text editor" "Room name" "e.g. your project name" "Search for someone" @@ -162,10 +169,6 @@ "Are you sure that you want to leave this room? This room is not public and you won\'t be able to rejoin without an invite." "Are you sure that you want to leave the room?" "%1$s Android" - - "%(count)s room" - "%(count)s rooms" - "%1$d member" "%1$d members" From b4546118f92ad3d045d1b095f28353bd51d1c3f8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 14 Sep 2023 16:34:58 +0200 Subject: [PATCH 157/234] Account management with OIDC: split account and session management. #1303 --- .../impl/root/PreferencesRootNode.kt | 18 +++++++++--- .../impl/root/PreferencesRootPresenter.kt | 15 ++++++++-- .../impl/root/PreferencesRootState.kt | 1 + .../impl/root/PreferencesRootStateProvider.kt | 1 + .../impl/root/PreferencesRootView.kt | 24 ++++++++++----- .../impl/root/PreferencesRootPresenterTest.kt | 1 + .../libraries/matrix/api/MatrixClient.kt | 3 +- .../api/oidc/AccountManagementAction.kt | 24 +++++++++++++++ .../libraries/matrix/impl/RustMatrixClient.kt | 7 +++-- .../impl/oidc/AccountManagementAction.kt | 29 +++++++++++++++++++ .../libraries/matrix/test/FakeMatrixClient.kt | 3 +- 11 files changed, 108 insertions(+), 18 deletions(-) create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/oidc/AccountManagementAction.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/oidc/AccountManagementAction.kt diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt index 0f297d14dd..5226d55b6b 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt @@ -29,6 +29,7 @@ import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode import io.element.android.libraries.androidutils.browser.openUrlInChromeCustomTab import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.theme.ElementTheme import timber.log.Timber @ContributesNode(SessionScope::class) @@ -67,9 +68,17 @@ class PreferencesRootNode @AssistedInject constructor( plugins().forEach { it.onOpenAbout() } } - private fun onManageAccountClicked(activity: Activity, accountManagementUrl: String?) { - accountManagementUrl?.let { - activity.openUrlInChromeCustomTab(null, false, it) + private fun onManageAccountClicked( + activity: Activity, + url: String?, + isDark: Boolean, + ) { + url?.let { + activity.openUrlInChromeCustomTab( + null, + darkTheme = isDark, + url = it + ) } } @@ -81,6 +90,7 @@ class PreferencesRootNode @AssistedInject constructor( override fun View(modifier: Modifier) { val state = presenter.present() val activity = LocalContext.current as Activity + val isDark = ElementTheme.isLightTheme.not() PreferencesRootView( state = state, modifier = modifier, @@ -91,7 +101,7 @@ class PreferencesRootNode @AssistedInject constructor( onVerifyClicked = this::onVerifyClicked, onOpenDeveloperSettings = this::onOpenDeveloperSettings, onSuccessLogout = { onSuccessLogout(activity, it) }, - onManageAccountClicked = { onManageAccountClicked(activity, state.accountManagementUrl) }, + onManageAccountClicked = { onManageAccountClicked(activity, it, isDark) }, onOpenNotificationSettings = this::onOpenNotificationSettings ) } 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 37ea66b31f..dac7ae3204 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 @@ -32,6 +32,7 @@ import io.element.android.libraries.designsystem.utils.collectSnackbarMessageAsS import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.MatrixClient +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.user.getCurrentUser import io.element.android.libraries.matrix.api.verification.SessionVerificationService @@ -74,9 +75,12 @@ class PreferencesRootPresenter @Inject constructor( val accountManagementUrl: MutableState = remember { mutableStateOf(null) } + val devicesManagementUrl: MutableState = remember { + mutableStateOf(null) + } LaunchedEffect(Unit) { - initAccountManagementUrl(accountManagementUrl) + initAccountManagementUrl(accountManagementUrl, devicesManagementUrl) } val logoutState = logoutPresenter.present() @@ -87,6 +91,7 @@ class PreferencesRootPresenter @Inject constructor( version = versionFormatter.get(), showCompleteVerification = showCompleteVerification, accountManagementUrl = accountManagementUrl.value, + devicesManagementUrl = devicesManagementUrl.value, showAnalyticsSettings = hasAnalyticsProviders, showDeveloperSettings = showDeveloperSettings, showNotificationSettings = showNotificationSettings.value, @@ -98,7 +103,11 @@ class PreferencesRootPresenter @Inject constructor( matrixUser.value = matrixClient.getCurrentUser() } - private fun CoroutineScope.initAccountManagementUrl(accountManagementUrl: MutableState) = launch { - accountManagementUrl.value = matrixClient.getAccountManagementUrl().getOrNull() + private fun CoroutineScope.initAccountManagementUrl( + accountManagementUrl: MutableState, + devicesManagementUrl: MutableState, + ) = launch { + accountManagementUrl.value = matrixClient.getAccountManagementUrl(AccountManagementAction.Profile).getOrNull() + devicesManagementUrl.value = matrixClient.getAccountManagementUrl(AccountManagementAction.SessionsList).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 967450031a..accede5d6d 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 @@ -26,6 +26,7 @@ data class PreferencesRootState( val version: String, val showCompleteVerification: Boolean, val accountManagementUrl: String?, + val devicesManagementUrl: String?, val showAnalyticsSettings: Boolean, val showDeveloperSettings: Boolean, val showNotificationSettings: Boolean, diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt index 8dd6b807f8..860c738687 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 @@ -26,6 +26,7 @@ fun aPreferencesRootState() = PreferencesRootState( version = "Version 1.1 (1)", showCompleteVerification = true, accountManagementUrl = "aUrl", + devicesManagementUrl = "anOtherUrl", showAnalyticsSettings = true, showDeveloperSettings = true, showNotificationSettings = true, 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 a2449424e6..3d901c4617 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 @@ -23,8 +23,8 @@ import androidx.compose.material.icons.outlined.BugReport import androidx.compose.material.icons.outlined.DeveloperMode import androidx.compose.material.icons.outlined.Help import androidx.compose.material.icons.outlined.InsertChart -import androidx.compose.material.icons.outlined.ManageAccounts import androidx.compose.material.icons.outlined.Notifications +import androidx.compose.material.icons.outlined.OpenInNew import androidx.compose.material.icons.outlined.VerifiedUser import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -53,7 +53,7 @@ fun PreferencesRootView( state: PreferencesRootState, onBackPressed: () -> Unit, onVerifyClicked: () -> Unit, - onManageAccountClicked: () -> Unit, + onManageAccountClicked: (url: String) -> Unit, onOpenAnalytics: () -> Unit, onOpenRageShake: () -> Unit, onOpenAbout: () -> Unit, @@ -82,10 +82,11 @@ fun PreferencesRootView( } if (state.accountManagementUrl != null) { PreferenceText( - title = stringResource(id = CommonStrings.screen_settings_oidc_account), - icon = Icons.Outlined.ManageAccounts, - onClick = onManageAccountClicked, + title = stringResource(id = CommonStrings.action_manage_account), + icon = Icons.Outlined.OpenInNew, + onClick = { onManageAccountClicked(state.accountManagementUrl) }, ) + HorizontalDivider() } if (state.showAnalyticsSettings) { PreferenceText( @@ -94,7 +95,7 @@ fun PreferencesRootView( onClick = onOpenAnalytics, ) } - if(state.showNotificationSettings) { + if (state.showNotificationSettings) { PreferenceText( title = stringResource(id = CommonStrings.screen_notification_settings_title), icon = Icons.Outlined.Notifications, @@ -111,10 +112,19 @@ fun PreferencesRootView( icon = Icons.Outlined.Help, onClick = onOpenAbout, ) + HorizontalDivider() + if (state.devicesManagementUrl != null) { + PreferenceText( + title = stringResource(id = CommonStrings.action_manage_devices), + icon = Icons.Outlined.OpenInNew, + onClick = { onManageAccountClicked(state.devicesManagementUrl) }, + ) + HorizontalDivider() + } if (state.showDeveloperSettings) { DeveloperPreferencesView(onOpenDeveloperSettings) + HorizontalDivider() } - HorizontalDivider() LogoutPreferenceView( state = state.logoutState, onSuccessLogout = onSuccessLogout, 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 f246e8c852..2237f717bd 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 @@ -73,6 +73,7 @@ class PreferencesRootPresenterTest { assertThat(loadedState.showDeveloperSettings).isEqualTo(true) assertThat(loadedState.showAnalyticsSettings).isEqualTo(false) assertThat(loadedState.accountManagementUrl).isNull() + assertThat(loadedState.devicesManagementUrl).isNull() } } } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt index 63093064b6..611cb4303c 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt @@ -24,6 +24,7 @@ import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters import io.element.android.libraries.matrix.api.media.MatrixMediaLoader import io.element.android.libraries.matrix.api.notification.NotificationService import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService +import io.element.android.libraries.matrix.api.oidc.AccountManagementAction import io.element.android.libraries.matrix.api.pusher.PushersService import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.RoomMembershipObserver @@ -66,7 +67,7 @@ interface MatrixClient : Closeable { suspend fun logout(): String? suspend fun loadUserDisplayName(): Result suspend fun loadUserAvatarURLString(): Result - suspend fun getAccountManagementUrl(): Result + suspend fun getAccountManagementUrl(action: AccountManagementAction?): Result suspend fun uploadMedia(mimeType: String, data: ByteArray, progressCallback: ProgressCallback?): Result fun roomMembershipObserver(): RoomMembershipObserver diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/oidc/AccountManagementAction.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/oidc/AccountManagementAction.kt new file mode 100644 index 0000000000..ceb5f4fb71 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/oidc/AccountManagementAction.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.api.oidc + +sealed interface AccountManagementAction { + data object Profile : AccountManagementAction + data object SessionsList : AccountManagementAction + data class SessionView(val deviceId: String) : AccountManagementAction + data class SessionEnd(val deviceId: String) : AccountManagementAction +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index 090a0cf613..c4a3ab3ef2 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -30,6 +30,7 @@ import io.element.android.libraries.matrix.api.createroom.RoomVisibility import io.element.android.libraries.matrix.api.media.MatrixMediaLoader import io.element.android.libraries.matrix.api.notification.NotificationService import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService +import io.element.android.libraries.matrix.api.oidc.AccountManagementAction import io.element.android.libraries.matrix.api.pusher.PushersService import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.RoomMembershipObserver @@ -44,6 +45,7 @@ import io.element.android.libraries.matrix.impl.mapper.toSessionData import io.element.android.libraries.matrix.impl.media.RustMediaLoader import io.element.android.libraries.matrix.impl.notification.RustNotificationService import io.element.android.libraries.matrix.impl.notificationsettings.RustNotificationSettingsService +import io.element.android.libraries.matrix.impl.oidc.toRustAction import io.element.android.libraries.matrix.impl.pushers.RustPushersService import io.element.android.libraries.matrix.impl.room.RoomContentForwarder import io.element.android.libraries.matrix.impl.room.RustMatrixRoom @@ -326,9 +328,10 @@ class RustMatrixClient constructor( return result } - override suspend fun getAccountManagementUrl(): Result = withContext(sessionDispatcher) { + override suspend fun getAccountManagementUrl(action: AccountManagementAction?): Result = withContext(sessionDispatcher) { + val rustAction = action?.toRustAction() runCatching { - client.accountUrl() + client.accountUrl(rustAction) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/oidc/AccountManagementAction.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/oidc/AccountManagementAction.kt new file mode 100644 index 0000000000..2644ac0321 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/oidc/AccountManagementAction.kt @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.impl.oidc + +import io.element.android.libraries.matrix.api.oidc.AccountManagementAction +import org.matrix.rustcomponents.sdk.AccountManagementAction as RustAccountManagementAction + +fun AccountManagementAction.toRustAction(): RustAccountManagementAction { + return when (this) { + AccountManagementAction.Profile -> RustAccountManagementAction.Profile + is AccountManagementAction.SessionEnd -> RustAccountManagementAction.SessionEnd(deviceId) + is AccountManagementAction.SessionView -> RustAccountManagementAction.SessionView(deviceId) + AccountManagementAction.SessionsList -> RustAccountManagementAction.SessionsList + } +} diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt index 9ef50ecda5..660c1e268a 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt @@ -25,6 +25,7 @@ import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters import io.element.android.libraries.matrix.api.media.MatrixMediaLoader import io.element.android.libraries.matrix.api.notification.NotificationService import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService +import io.element.android.libraries.matrix.api.oidc.AccountManagementAction import io.element.android.libraries.matrix.api.pusher.PushersService import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.RoomMembershipObserver @@ -129,7 +130,7 @@ class FakeMatrixClient( return userAvatarURLString } - override suspend fun getAccountManagementUrl(): Result { + override suspend fun getAccountManagementUrl(action: AccountManagementAction?): Result { return accountManagementUrlString } override suspend fun uploadMedia( From b382993cbbf82cdc793b1461e89d8222274e85a2 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 14 Sep 2023 14:38:49 +0000 Subject: [PATCH 158/234] Sync Strings from Localazy --- .../src/main/res/values-de/translations.xml | 6 - .../src/main/res/values-fr/translations.xml | 8 +- .../main/res/values-zh-rTW/translations.xml | 5 + .../src/main/res/values-de/translations.xml | 11 - .../src/main/res/values-fr/translations.xml | 18 +- .../src/main/res/values-de/translations.xml | 10 +- .../src/main/res/values-fr/translations.xml | 15 +- .../src/main/res/values-sk/translations.xml | 2 + .../src/main/res/values-de/translations.xml | 9 - .../src/main/res/values-fr/translations.xml | 4 +- .../src/main/res/values-de/translations.xml | 39 ---- .../src/main/res/values-fr/translations.xml | 49 ++-- .../src/main/res/values-sk/translations.xml | 1 + .../main/res/values-zh-rTW/translations.xml | 3 +- .../src/main/res/values-de/translations.xml | 8 - .../src/main/res/values-fr/translations.xml | 4 +- .../src/main/res/values-de/translations.xml | 38 +-- .../src/main/res/values-fr/translations.xml | 46 ++-- .../src/main/res/values-sk/translations.xml | 1 + .../src/main/res/values-de/translations.xml | 10 - .../src/main/res/values-fr/translations.xml | 10 +- .../main/res/values-zh-rTW/translations.xml | 2 +- .../src/main/res/values-de/translations.xml | 11 + .../src/main/res/values-fr/translations.xml | 12 + .../src/main/res/values-sk/translations.xml | 12 + .../src/main/res/values-de/translations.xml | 5 - .../src/main/res/values-fr/translations.xml | 2 +- .../src/main/res/values-de/translations.xml | 15 -- .../src/main/res/values-fr/translations.xml | 6 +- .../src/main/res/values-cs/translations.xml | 13 ++ .../src/main/res/values-de/translations.xml | 33 +-- .../src/main/res/values-fr/translations.xml | 54 +++-- .../src/main/res/values-ro/translations.xml | 13 ++ .../src/main/res/values-ru/translations.xml | 2 + .../src/main/res/values-sk/translations.xml | 2 + .../impl/src/main/res/values/localazy.xml | 2 + .../src/main/res/values-de/translations.xml | 9 - .../src/main/res/values-fr/translations.xml | 6 +- .../src/main/res/values-de/translations.xml | 17 +- .../src/main/res/values-fr/translations.xml | 6 +- .../src/main/res/values-de/translations.xml | 4 - .../src/main/res/values-de/translations.xml | 52 ----- .../src/main/res/values-fr/translations.xml | 60 ++--- .../main/res/values-zh-rTW/translations.xml | 54 ++--- .../src/main/res/values-de/translations.xml | 47 +--- .../src/main/res/values-fr/translations.xml | 24 +- .../{values-de => values-fr}/translations.xml | 2 +- .../src/main/res/values-cs/translations.xml | 1 - .../src/main/res/values-de/translations.xml | 221 ++---------------- .../src/main/res/values-fr/translations.xml | 172 +++++++++----- .../src/main/res/values-ro/translations.xml | 1 - .../src/main/res/values-ru/translations.xml | 1 - .../src/main/res/values-sk/translations.xml | 10 +- .../main/res/values-zh-rTW/translations.xml | 12 +- .../src/main/res/values/localazy.xml | 18 +- 55 files changed, 445 insertions(+), 753 deletions(-) delete mode 100644 features/invitelist/impl/src/main/res/values-de/translations.xml delete mode 100644 features/logout/api/src/main/res/values-de/translations.xml delete mode 100644 features/onboarding/impl/src/main/res/values-de/translations.xml create mode 100644 features/poll/impl/src/main/res/values-de/translations.xml create mode 100644 features/poll/impl/src/main/res/values-fr/translations.xml create mode 100644 features/poll/impl/src/main/res/values-sk/translations.xml delete mode 100644 features/rageshake/api/src/main/res/values-de/translations.xml delete mode 100644 features/rageshake/impl/src/main/res/values-de/translations.xml delete mode 100644 features/roomlist/impl/src/main/res/values-de/translations.xml delete mode 100644 libraries/androidutils/src/main/res/values-de/translations.xml rename libraries/textcomposer/impl/src/main/res/{values-de => values-fr}/translations.xml (56%) diff --git a/features/analytics/impl/src/main/res/values-de/translations.xml b/features/analytics/impl/src/main/res/values-de/translations.xml index 7ef2ff2500..4282ead092 100644 --- a/features/analytics/impl/src/main/res/values-de/translations.xml +++ b/features/analytics/impl/src/main/res/values-de/translations.xml @@ -1,10 +1,4 @@ - "Wir werden keine personenbezogenen Daten aufzeichnen oder auswerten" - "Teile anonyme Nutzungsdaten, um uns bei der Identifizierung von Problemen zu helfen." - "Du kannst alle unsere Nutzerbedingungen %1$s lesen." "hier" - "Du kannst dies jederzeit deaktivieren" - "Wir geben deine Daten nicht an Dritte weiter" - "Hilf uns, %1$s zu verbessern" diff --git a/features/analytics/impl/src/main/res/values-fr/translations.xml b/features/analytics/impl/src/main/res/values-fr/translations.xml index 55231f7b6c..63a97dc905 100644 --- a/features/analytics/impl/src/main/res/values-fr/translations.xml +++ b/features/analytics/impl/src/main/res/values-fr/translations.xml @@ -1,10 +1,10 @@ - "Nous n\'enregistrerons ni ne traiterons aucune donnée personnelle" + "Nous n\'enregistrerons ni ne profilerons aucune donnée personnelle" "Partagez des données d\'utilisation anonymes pour nous aider à identifier les problèmes." - "Consultez nos conditions d\'utilisation %1$s." + "Vous pouvez lire toutes nos conditions %1$s." "ici" - "Vous pouvez désactiver cette fonction à tout moment" + "Vous pouvez le désactiver à tout moment" "Nous ne partagerons pas vos données avec des tiers" - "Aidez-nous à améliorer %1$s" + "Aidez à améliorer %1$s" diff --git a/features/analytics/impl/src/main/res/values-zh-rTW/translations.xml b/features/analytics/impl/src/main/res/values-zh-rTW/translations.xml index 35a607c95e..81349674b7 100644 --- a/features/analytics/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/analytics/impl/src/main/res/values-zh-rTW/translations.xml @@ -1,5 +1,10 @@ + "我們不會紀錄或剖繪您的個人資料" + "分享匿名的使用數據以協助我們釐清問題" + "您可以到 %1$s 閱讀我們的條款。" + "這裡" "您可以在任何時候關閉它" "我們不會和第三方分享您的資料" + "讓 %1$s 變得更好" diff --git a/features/createroom/impl/src/main/res/values-de/translations.xml b/features/createroom/impl/src/main/res/values-de/translations.xml index abc2ef9d71..f033df7792 100644 --- a/features/createroom/impl/src/main/res/values-de/translations.xml +++ b/features/createroom/impl/src/main/res/values-de/translations.xml @@ -1,15 +1,4 @@ - "Neuer Raum" - "Freunde zu Element einladen" - "Personen hinzufügen" - "Beim Erstellen des Raums ist ein Fehler aufgetreten" - "Die Nachrichten in diesem Raum sind verschlüsselt. Die Verschlüsselung kann nicht nachträglich deaktiviert werden." - "Privater Raum (nur auf Einladung)" - "Nachrichten sind nicht verschlüsselt und jeder kann sie lesen. Du kannst die Verschlüsselung zu einem späteren Zeitpunkt aktivieren." - "Öffentlicher Raum (jeder)" - "Raumname" - "Thema (optional)" - "Beim Versuch, einen Chat zu starten, ist ein Fehler aufgetreten" "Raum erstellen" diff --git a/features/createroom/impl/src/main/res/values-fr/translations.xml b/features/createroom/impl/src/main/res/values-fr/translations.xml index e37a30c457..289fb3f50d 100644 --- a/features/createroom/impl/src/main/res/values-fr/translations.xml +++ b/features/createroom/impl/src/main/res/values-fr/translations.xml @@ -1,15 +1,15 @@ - "Nouveau salon" + "Nouvelle salle" "Inviter des amis sur Element" "Inviter des personnes" - "Une erreur s\'est produite lors de la création du salon" - "Les messages dans ce salon sont chiffrés. Une fois activé, le chiffrement ne peut pas être désactivé." - "Salon privé (sur invitation uniquement)" - "Les messages ne sont pas chiffrés et n\'importe qui peut les lire. Vous pouvez activer le chiffrement ultérieurement." - "Salon public (n’importe qui)" - "Nom du salon" - "Sujet (optionnel)" + "Une erreur s\'est produite lors de la création de la salle" + "Les messages dans cette pièce sont cryptés. Le cryptage ne peut pas être désactivé par la suite." + "Salle privée (sur invitation seulement)" + "Les messages ne sont pas cryptés et n\'importe qui peut les lire. Vous pouvez activer le chiffrement ultérieurement." + "Salle publique (tout le monde)" + "Nom de la salle" + "Sujet (facultatif)" "Une erreur s\'est produite lors de la tentative de démarrage d\'une discussion" - "Créer un salon" + "Créer une salle" diff --git a/features/ftue/impl/src/main/res/values-de/translations.xml b/features/ftue/impl/src/main/res/values-de/translations.xml index 19b445bd50..36fc85fba5 100644 --- a/features/ftue/impl/src/main/res/values-de/translations.xml +++ b/features/ftue/impl/src/main/res/values-de/translations.xml @@ -1,11 +1,5 @@ - "Dies ist ein einmaliger Vorgang, danke fürs Warten." - "Dein Konto einrichten" - "Anrufe, Umfragen, Suche und mehr werden später in diesem Jahr hinzugefügt." - "Der Nachrichtenverlauf für verschlüsselte Räume wird in diesem Update nicht verfügbar sein." - "Wir würden uns freuen, wenn du uns über die Einstellungsseite deine Meinung mitteilst." - "Los geht\'s!" - "Folgendes musst du wissen:" - "Willkommen bei %1$s!" + "Du kannst deine Einstellungen später ändern." + "Erlaube Benachrichtigungen und verpasse keine Nachricht" diff --git a/features/ftue/impl/src/main/res/values-fr/translations.xml b/features/ftue/impl/src/main/res/values-fr/translations.xml index 9f431f545d..68345265d4 100644 --- a/features/ftue/impl/src/main/res/values-fr/translations.xml +++ b/features/ftue/impl/src/main/res/values-fr/translations.xml @@ -1,10 +1,13 @@ - "Ce processus n’a besoin d’être fait qu’une seule fois, merci de patienter." + "Il s\'agit d\'un processus unique, merci d\'avoir attendu." "Configuration de votre compte." - "L’historique des messages pour les salons chiffrés ne sera pas disponible dans cette mise à jour." - "Nous serions ravis d’avoir votre avis, n’hésitez pas à nous le partager via la page des paramètres." - "C’est parti !" - "Voici ce qu’il faut savoir :" - "Bienvenue sur %1$s !" + "Vous pourrez modifier vos paramètres ultérieurement." + "Autorisez les notifications et ne manquez aucun message" + "Les appels, les sondages, les recherches et plus encore seront ajoutés plus tard cette année." + "L\'historique des messages pour les salles cryptées ne sera pas disponible dans cette mise à jour." + "N\'hésitez pas à nous faire part de vos commentaires via la page des paramètres." + "C\'est parti !" + "Voici ce que vous devez savoir :" + "Bienvenue à %1$s !" diff --git a/features/ftue/impl/src/main/res/values-sk/translations.xml b/features/ftue/impl/src/main/res/values-sk/translations.xml index 5bbd2d386d..aa76053cea 100644 --- a/features/ftue/impl/src/main/res/values-sk/translations.xml +++ b/features/ftue/impl/src/main/res/values-sk/translations.xml @@ -2,6 +2,8 @@ "Ide o jednorazový proces, ďakujeme za trpezlivosť." "Nastavenie vášho účtu." + "Svoje nastavenia môžete neskôr zmeniť." + "Povoľte oznámenia a nikdy nezmeškajte žiadnu správu" "Hovory, ankety, vyhľadávanie a ďalšie funkcie pribudnú neskôr v tomto roku." "História správ pre zašifrované miestnosti nebude v tejto aktualizácii k dispozícii." "Radi by sme od vás počuli, dajte nám vedieť, čo si myslíte, prostredníctvom stránky nastavení." diff --git a/features/invitelist/impl/src/main/res/values-de/translations.xml b/features/invitelist/impl/src/main/res/values-de/translations.xml deleted file mode 100644 index 2cec59d6a0..0000000000 --- a/features/invitelist/impl/src/main/res/values-de/translations.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - "Möchtest du den Beitritt zu %1$s wirklich ablehnen?" - "Einladung ablehnen" - "Möchtest du den privaten Chat mit %1$s wirklich ablehnen?" - "Chat ablehnen" - "Keine Einladungen" - "%1$s (%2$s) hat dich eingeladen" - diff --git a/features/invitelist/impl/src/main/res/values-fr/translations.xml b/features/invitelist/impl/src/main/res/values-fr/translations.xml index 677fadd539..55606b100d 100644 --- a/features/invitelist/impl/src/main/res/values-fr/translations.xml +++ b/features/invitelist/impl/src/main/res/values-fr/translations.xml @@ -1,8 +1,8 @@ - "Voulez-vous vraiment refuser l‘invitation à rejoindre %1$s ?" + "Êtes-vous sûr de vouloir décliner l\'invitation à participer %1$s ?" "Refuser l\'invitation" - "Voulez-vous vraiment refuser ce chat privé avec %1$s ?" + "Êtes-vous sûr de vouloir refuser cette discussion privée avec %1$s ?" "Refuser le chat" "Aucune invitation" "%1$s (%2$s) vous a invité" diff --git a/features/login/impl/src/main/res/values-de/translations.xml b/features/login/impl/src/main/res/values-de/translations.xml index 7464e17f8d..8a69936ff8 100644 --- a/features/login/impl/src/main/res/values-de/translations.xml +++ b/features/login/impl/src/main/res/values-de/translations.xml @@ -1,47 +1,8 @@ - "Kontoanbieter wechseln" - "Adresse des Homeservers" - "Gib einen Suchbegriff oder eine Domainadresse ein." - "Suche nach einem Unternehmen, einer Community oder einem privaten Server." - "Finde einen Kontoanbieter" - "Hier werden deine Konversationen stattfinden — genauso wie du einen E-Mail-Anbieter verwenden würdest, um deine E-Mails aufzubewahren." - "Du bist dabei dich bei %s anzumelden" - "Hier werden deine Konversationen stattfinden — genauso wie du einen E-Mail-Anbieter verwenden würdest, um deine E-Mails aufzubewahren." - "Du bist dabei ein Konto auf %s zu erstellen" - "Matrix.org ist ein großer, kostenloser Server im öffentlichen Matrix-Netzwerk für sichere, dezentrale Kommunikation, der von der Matrix.org Foundation betrieben wird." - "Andere" - "Verwende einen anderen Kontoanbieter, z. B. deinen eigenen privaten Server oder ein Arbeitskonto." - "Kontoanbieter ändern" - "Wir konnten diesen Homeserver nicht erreichen. Bitte überprüfe, dass du die Homeserver-URL korrekt eingegeben hast. Wenn die URL korrekt ist, wende dich an deinen Homeserver-Administrator für weitere Hilfe." - "Dieser Server unterstützt derzeit keine Sliding Sync." - "Homeserver-URL" - "Du kannst dich nur mit einem existierenden Server verbinden, der Sliding Sync unterstützt. Dein Homeserver-Administrator muss es konfigurieren. %1$s" - "Wie lautet die Adresse deines Servers?" - "Dieses Konto wurde deaktiviert." - "Falscher Benutzername und/oder Passwort" - "Dies ist kein gültiger Benutzeridentifikator. Erwartetes Format: \'@user:homeserver.org\'" - "Der ausgewählte Homeserver unterstützt kein Passwort- oder OIDC-Login. Bitte kontaktiere deinen Admin oder wähle einen anderen Homeserver." - "Gib deine Daten ein" - "Willkommen zurück!" - "Bei %1$s anmelden" - "Kontoanbieter wechseln" - "Ein privater Server für Element-Mitarbeiter." - "Matrix ist ein offenes Netzwerk für sichere, dezentrale Kommunikation" - "Hier werden deine Konversationen stattfinden — genau so wie du einen E-Mail-Anbieter verwenden würdest, um deine E-Mails aufzubewahren." - "Du bist dabei dich bei %1$s anzumelden" - "Du bist dabei ein Konto auf %1$s zu erstellen" - "Im Moment besteht eine hohe Nachfrage nach %1$s auf %2$s. Besuche die App in ein paar Tagen wieder und versuche es erneut. - -Vielen Dank für deine Geduld!" - "Willkommen bei %1$s!" - "Du hast es fast geschafft!" - "Du bist dabei." "Weiter" "Weiter" - "Wählen deinen Server" "Passwort" "Weiter" - "Matrix ist ein offenes Netzwerk für sichere, dezentrale Kommunikation" "Benutzername" diff --git a/features/login/impl/src/main/res/values-fr/translations.xml b/features/login/impl/src/main/res/values-fr/translations.xml index 74f23cc5c9..41be63cb2c 100644 --- a/features/login/impl/src/main/res/values-fr/translations.xml +++ b/features/login/impl/src/main/res/values-fr/translations.xml @@ -1,39 +1,40 @@ - "Changer de fournisseur" + "Changer de fournisseur de compte" "Adresse du serveur d\'accueil" - "Entrez un mot clé de recherche ou un nom de domaine." - "Rechercher une entreprise, une communauté ou un serveur privé." - "Trouver un fournisseur de services" - "C\'est ici que vos conversations seront stockées - tout comme vous utiliseriez un fournisseur de messagerie pour conserver vos e-mails." + "Entrez un terme de recherche ou une adresse de domaine." + "Recherchez une entreprise, une communauté ou un serveur privé." + "Trouver un fournisseur de comptes" + "C\'est ici que vos conversations seront enregistrées, comme vous le feriez avec un fournisseur de messagerie pour conserver vos e-mails." "Vous êtes sur le point de vous connecter à %s" - "C\'est ici que vos conversations seront stockées - tout comme vous utiliseriez un fournisseur de messagerie pour conserver vos e-mails." + "C\'est ici que vos conversations seront enregistrées, comme vous le feriez avec un fournisseur de messagerie pour conserver vos e-mails." "Vous êtes sur le point de créer un compte sur %s" - "Autre" - "Utilisez un autre fournisseur de compte, tel que votre propre serveur ou un compte professionnel." - "Changer de fournisseur" - "Nous n\'avons pas pu atteindre ce serveur domestique. Vérifiez que vous avez correctement saisi l\'URL du serveur d\'accueil. Si l\'URL est correcte, contactez l\'administrateur de votre serveur domestique pour obtenir de l\'aide." + "Matrix.org est un grand serveur gratuit sur le réseau public Matrix pour une communication sécurisée et décentralisée, géré par la Fondation Matrix.org." + "Autres" + "Utilisez un autre fournisseur de compte, tel que votre propre serveur privé ou un compte professionnel." + "Changer de fournisseur de compte" + "Nous n\'avons pas pu atteindre ce serveur d\'accueil. Vérifiez que vous avez correctement saisi l\'URL du serveur d\'accueil. Si l\'URL est correcte, contactez l\'administrateur de votre serveur d\'accueil pour obtenir de l\'aide." "Ce serveur ne prend actuellement pas en charge la synchronisation glissante." "URL du serveur d\'accueil" - "Vous ne pouvez vous connecter qu\'à un serveur existant qui prend en charge la synchronisation glissante. L\'administrateur de votre serveur domestique devra la configurer. %1$s" + "Vous ne pouvez vous connecter qu\'à un serveur existant qui prend en charge la synchronisation par glissement. L\'administrateur de votre serveur d\'accueil devra le configurer. %1$s" "Quelle est l\'adresse de votre serveur ?" "Ce compte a été désactivé." - "Nom d\'utilisateur et/ou mot de passe incorrect" + "Nom d\'utilisateur et/ou mot de passe incorrects" "Il ne s\'agit pas d\'un identifiant utilisateur valide. Format attendu : « @user:homeserver.org »" - "Le serveur domestique sélectionné ne prend pas en charge le mot de passe ou la connexion OIDC. Contactez votre administrateur ou choisissez un autre serveur domestique." + "Le serveur d\'accueil sélectionné ne prend pas en charge le mot de passe ou la connexion OIDC. Contactez votre administrateur ou choisissez un autre serveur d\'accueil." "Saisir vos informations personnelles" - "Heureux de vous revoir!" - "Se connecter à %1$s" + "Bienvenue !" + "Connectez-vous à %1$s" "Changer de fournisseur de compte" - "Un serveur privé pour les employés d’Element." - "Matrix est un réseau ouvert de communication sécurisée et décentralisée." - "C\'est là que vos conversations seront conservées — de la même manière que votre service d’e-mail habituel conserverait vos e-mails." - "Vous allez vous connecter à %1$s" - "Vous allez créer un compte sur %1$s" - "Il y a une forte demande pour %1$s sur %2$s en ce moment. Rouvrez l’app dans quelques jours et réessayez. + "Un serveur privé pour les employés d\'Element." + "Matrix est un réseau ouvert pour une communication sécurisée et décentralisée." + "C\'est ici que vos conversations seront enregistrées, comme vous le feriez avec un fournisseur de messagerie pour conserver vos e-mails." + "Vous êtes sur le point de vous connecter à %1$s" + "Vous êtes sur le point de créer un compte sur %1$s" + "Il y a une forte demande pour %1$s sur %2$s à l\'heure actuelle. Revenez sur l\'application dans quelques jours et réessayez. -Merci de votre patience !" - "Bienvenue sur %1$s !" +Merci pour votre patience !" + "Bienvenue à %1$s !" "Vous y êtes presque." "Vous y êtes." "Continuer" @@ -41,6 +42,6 @@ Merci de votre patience !" "Sélectionnez votre serveur" "Mot de passe" "Continuer" - "Matrix est un réseau ouvert de communication sécurisée et décentralisée." + "Matrix est un réseau ouvert pour une communication sécurisée et décentralisée." "Nom d\'utilisateur" diff --git a/features/login/impl/src/main/res/values-sk/translations.xml b/features/login/impl/src/main/res/values-sk/translations.xml index 14a5407055..e94990554f 100644 --- a/features/login/impl/src/main/res/values-sk/translations.xml +++ b/features/login/impl/src/main/res/values-sk/translations.xml @@ -9,6 +9,7 @@ "Chystáte sa prihlásiť do %s" "Tu budú žiť vaše konverzácie — podobne ako používate poskytovateľa e-mailových služieb na uchovávanie e-mailov." "Chystáte sa vytvoriť účet na %s" + "Matrix.org je veľký bezplatný server vo verejnej sieti Matrix na bezpečnú, decentralizovanú komunikáciu, ktorý prevádzkuje nadácia Matrix.org." "Iný" "Použite iného poskytovateľa účtu, ako napríklad vlastný súkromný server alebo pracovný účet." "Zmeniť poskytovateľa účtu" diff --git a/features/login/impl/src/main/res/values-zh-rTW/translations.xml b/features/login/impl/src/main/res/values-zh-rTW/translations.xml index d3dca0942a..e4bfd61b35 100644 --- a/features/login/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/login/impl/src/main/res/values-zh-rTW/translations.xml @@ -1,10 +1,11 @@ - "您即將登入%s" + "您即將登入 %s" "您即將在 %s 建立帳號" "其他" "此伺服器目前不支援 sliding sync。" "家伺服器 URL" + "輸入您的詳細資料" "歡迎回來!" "登入 %1$s" "您即將登入 %1$s" diff --git a/features/logout/api/src/main/res/values-de/translations.xml b/features/logout/api/src/main/res/values-de/translations.xml deleted file mode 100644 index 0cd8ac389a..0000000000 --- a/features/logout/api/src/main/res/values-de/translations.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - "Möchtest du Dich wirklich abmelden?" - "Abmelden" - "Abmeldung läuft…" - "Abmelden" - "Abmelden" - diff --git a/features/logout/api/src/main/res/values-fr/translations.xml b/features/logout/api/src/main/res/values-fr/translations.xml index b6d5137072..d4d8b8477b 100644 --- a/features/logout/api/src/main/res/values-fr/translations.xml +++ b/features/logout/api/src/main/res/values-fr/translations.xml @@ -1,8 +1,8 @@ - "Êtes-vous sûr de vouloir vous déconnecter?" + "Êtes-vous sûr de vouloir vous déconnecter ?" "Se déconnecter" - "Déconnexion en cours…" + "Déconnexion…" "Se déconnecter" "Se déconnecter" diff --git a/features/messages/impl/src/main/res/values-de/translations.xml b/features/messages/impl/src/main/res/values-de/translations.xml index 482065c887..5d43a8167f 100644 --- a/features/messages/impl/src/main/res/values-de/translations.xml +++ b/features/messages/impl/src/main/res/values-de/translations.xml @@ -1,41 +1,5 @@ - - "%1$d Raumänderung" - "%1$d Raumänderungen" - - "Kamera" - "Foto aufnehmen" - "Video aufnehmen" - "Anhang" - "Foto- & Video-Bibliothek" - "Standort" - "Umfrage" - "Der Nachrichtenverlauf ist in diesem Raum derzeit nicht verfügbar" - "Benutzerdetails konnten nicht abgerufen werden" - "Möchtest du sie wieder einladen?" - "Du bist allein in diesem Chat" - "Nachricht kopiert" - "Du bist keine Berechtigung, um in diesem Raum zu posten" - "Benutzerdefinierte Einstellung zulassen" - "Das Aktivieren dieser Option wird die Standardeinstellungen überschreiben." - "Benachrichtige mich in diesem Chat für" - "Du kannst es in deinem %1$s ändern." - "Globale Einstellungen" - "Standardeinstellung" - "Benutzerdefinierte Einstellung entfernen" - "Beim Laden der Benachrichtigungseinstellungen ist ein Fehler aufgetreten." - "Wiederherstellung des Standardmodus fehlgeschlagen. Bitte versuche es erneut." - "Fehler beim Einstellen des Modus. Bitte versuche es erneut." - "Alle Nachrichten" - "Nur Erwähnungen und Schlüsselwörter" - "In diesem Raum, benachrichtige mich für" - "Weniger anzeigen" - "Mehr anzeigen" - "Erneut senden" - "Ihre Nachricht konnte nicht gesendet werden" - "Emoji hinzufügen" - "Weniger anzeigen" - "Fehler bei der Verarbeitung von Medien zum Hochladen, bitte versuche es erneut." + "Textformatierung" "Entfernen" diff --git a/features/messages/impl/src/main/res/values-fr/translations.xml b/features/messages/impl/src/main/res/values-fr/translations.xml index e88ddc43cb..5bbd8e85b8 100644 --- a/features/messages/impl/src/main/res/values-fr/translations.xml +++ b/features/messages/impl/src/main/res/values-fr/translations.xml @@ -1,36 +1,42 @@ - "%1$d changement dans la conversation" - "%1$d changements dans la conversation" + "%1$d changement de salle" + "%1$d changements de salle" "Appareil photo" "Prendre une photo" "Enregistrer une vidéo" - "Pièce-jointe" - "Gallerie photo et vidéo" - "L’historique des messages n’est pas disponible actuellement dans ce salon" - "Impossible de récupérer les détails de l’utilisateur" - "Souhaitez-vous les inviter à revenir ?" + "Pièce jointe" + "Photothèque et vidéothèque" + "Emplacement" + "Sondage" + "Formatage du texte" + "L\'historique des messages n\'est actuellement pas disponible dans cette salle" + "Impossible de récupérer les détails de l\'utilisateur" + "Aimeriez-vous les inviter à revenir ?" "Vous êtes seul dans ce chat" "Message copié" - "Vous n‘avez pas le droit de poster dans ce salon" + "Vous n\'êtes pas autorisé à publier dans cette salle" "Autoriser les paramètres personnalisés" - "Activer cette option remplacera votre paramètre par défaut" - "Me notifier dans ce chat pour" - "paramètres généraux" + "L\'activation de cette option annulera votre paramètre par défaut" + "Prévenez-moi dans ce chat pour" + "Vous pouvez le modifier dans votre %1$s." + "paramètres globaux" "Paramètre par défaut" - "Une erreur s’est produite lors du chargement des paramètres de notification." - "Impossible de restaurer le mode par défaut, veuillez réessayer." - "Impossible de régler le mode, veuillez réessayer." + "Supprimer le paramètre personnalisé" + "Une erreur s\'est produite lors du chargement des paramètres de notification." + "Échec de la restauration du mode par défaut, veuillez réessayer." + "Échec de la configuration du mode, veuillez réessayer." "Tous les messages" - "Mentions et mots-clés uniquement" + "Mentions et mots clés uniquement" + "Dans cette salle, prévenez-moi pour" "Afficher moins" "Afficher plus" - "Renvoyer" + "Envoyer à nouveau" "Votre message n\'a pas pu être envoyé" - "Ajouter un emoji" - "Montrer moins" - "Échec du traitement du média avant son envoi, veuillez réessayer." - "Supprimer" + "Ajouter un émoji" + "Afficher moins" + "Échec du traitement des médias à télécharger, veuillez réessayer." + "Enlever" diff --git a/features/messages/impl/src/main/res/values-sk/translations.xml b/features/messages/impl/src/main/res/values-sk/translations.xml index 2390e1e25e..2c98aab148 100644 --- a/features/messages/impl/src/main/res/values-sk/translations.xml +++ b/features/messages/impl/src/main/res/values-sk/translations.xml @@ -12,6 +12,7 @@ "Knižnica fotografií a videí" "Poloha" "Anketa" + "Formátovanie textu" "História správ v tejto miestnosti nie je momentálne k dispozícii" "Nepodarilo sa získať údaje o používateľovi" "Chceli by ste ich pozvať späť?" diff --git a/features/onboarding/impl/src/main/res/values-de/translations.xml b/features/onboarding/impl/src/main/res/values-de/translations.xml deleted file mode 100644 index 82e20c3509..0000000000 --- a/features/onboarding/impl/src/main/res/values-de/translations.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - "Manuell anmelden" - "Mit QR-Code anmelden" - "Konto erstellen" - "Sicher kommunizieren und zusammenarbeiten" - "Willkommen beim schnellsten Element aller Zeiten. Optimiert für Geschwindigkeit und Einfachheit." - "Willkommen zur %1$s. Verbessert, für Geschwindigkeit und Einfachheit." - "Sei in deinem Element" - diff --git a/features/onboarding/impl/src/main/res/values-fr/translations.xml b/features/onboarding/impl/src/main/res/values-fr/translations.xml index 5ed96ebf60..cbcfd477f0 100644 --- a/features/onboarding/impl/src/main/res/values-fr/translations.xml +++ b/features/onboarding/impl/src/main/res/values-fr/translations.xml @@ -1,10 +1,10 @@ - "Se connecter manuellement" - "Se connecter avec un code QR" + "Connectez-vous manuellement" + "Connectez-vous avec le code QR" "Créer un compte" - "Communiquer et collaborer en toute sécurité" - "Bienvenue dans l’Element le plus rapide de tous les temps. Surpuissant pour plus de vitesse et de simplicité." - "Bienvenue dans %1$s. Affiné pour plus de rapidité et de simplicité." + "Communiquez et collaborez en toute sécurité" + "Bienvenue dans l\'Element le plus rapide de tous les temps. Boosté pour plus de rapidité et de simplicité." + "Bienvenue sur %1$s. Boosté, pour rapidité et simplicité." "Soyez dans votre Element" diff --git a/features/onboarding/impl/src/main/res/values-zh-rTW/translations.xml b/features/onboarding/impl/src/main/res/values-zh-rTW/translations.xml index 5150b50c9a..22c9d70004 100644 --- a/features/onboarding/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/onboarding/impl/src/main/res/values-zh-rTW/translations.xml @@ -4,5 +4,5 @@ "使用 QR code 登入" "建立帳號" "歡迎使用有史以來最快的 Element。速度超快,操作簡便。" - "得心應手" + "Be in your element" diff --git a/features/poll/impl/src/main/res/values-de/translations.xml b/features/poll/impl/src/main/res/values-de/translations.xml new file mode 100644 index 0000000000..762afd5fd8 --- /dev/null +++ b/features/poll/impl/src/main/res/values-de/translations.xml @@ -0,0 +1,11 @@ + + + "Option hinzufügen" + "Ergebnisse erst nach Ende der Umfrage anzeigen" + "Anonyme Umfrage" + "Option %1$d" + "Bist du sicher, dass du diese Umfrage verwerfen willst?" + "Umfrage verwerfen" + "Frage oder Thema" + "Umfrage erstellen" + diff --git a/features/poll/impl/src/main/res/values-fr/translations.xml b/features/poll/impl/src/main/res/values-fr/translations.xml new file mode 100644 index 0000000000..adfcfd274d --- /dev/null +++ b/features/poll/impl/src/main/res/values-fr/translations.xml @@ -0,0 +1,12 @@ + + + "Ajouter une option" + "Afficher les résultats uniquement après la fin du sondage" + "Masquer les votes" + "Option %1$d" + "Êtes-vous sûr de vouloir supprimer ce sondage ?" + "Supprimer le sondage" + "Question ou sujet" + "Quel est le sujet du sondage ?" + "Créer un sondage" + diff --git a/features/poll/impl/src/main/res/values-sk/translations.xml b/features/poll/impl/src/main/res/values-sk/translations.xml new file mode 100644 index 0000000000..5e2d9ee7bc --- /dev/null +++ b/features/poll/impl/src/main/res/values-sk/translations.xml @@ -0,0 +1,12 @@ + + + "Pridať možnosť" + "Zobraziť výsledky až po skončení ankety" + "Anonymná anketa" + "Možnosť %1$d" + "Ste si istí, že chcete túto anketu zahodiť?" + "Odstrániť anketu" + "Otázka alebo téma" + "O čom je anketa?" + "Vytvoriť anketu" + diff --git a/features/rageshake/api/src/main/res/values-de/translations.xml b/features/rageshake/api/src/main/res/values-de/translations.xml deleted file mode 100644 index f2446a4028..0000000000 --- a/features/rageshake/api/src/main/res/values-de/translations.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - "%1$s ist bei der letzten Verwendung abgestürzt. Möchtest du uns einen Absturzbericht senden?" - "Du scheinst frustriert das Telefon zu schütteln. Möchtest du den Fehlerberichtsbildschirm öffnen?" - diff --git a/features/rageshake/api/src/main/res/values-fr/translations.xml b/features/rageshake/api/src/main/res/values-fr/translations.xml index 455ab1daef..8d57edb3e1 100644 --- a/features/rageshake/api/src/main/res/values-fr/translations.xml +++ b/features/rageshake/api/src/main/res/values-fr/translations.xml @@ -1,5 +1,5 @@ - "%1$s a planté la dernière fois qu\'il a été utilisé. Souhaitez-vous partager un rapport de crash avec nous ?" + "%1$s s\'est arrêté la dernière fois qu\'il a été utilisé. Souhaitez-vous partager un rapport d\'incident avec nous ?" "Vous semblez secouer le téléphone de frustration. Voulez-vous ouvrir le formulaire de rapport de problème ?" diff --git a/features/rageshake/impl/src/main/res/values-de/translations.xml b/features/rageshake/impl/src/main/res/values-de/translations.xml deleted file mode 100644 index 51b331a86f..0000000000 --- a/features/rageshake/impl/src/main/res/values-de/translations.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - "Bildschirmfoto anhängen" - "Ihr könnt mich kontaktieren, wenn ihr weitere Fragen habt" - "Kontaktiere mich" - "Bildschirmfoto bearbeiten" - "Beschreibe bitte den Fehler. Was hast du gemacht? Was hätte passieren sollen? Was ist passiert? Bitte beschreibe alles mit so vielen Details wie möglich." - "Beschreibe den Fehler…" - "Wenn möglich, verfasse die Beschreibung bitte auf Englisch." - "Absturzprotokolle senden" - "Logs zulassen" - "Bildschirmfoto senden" - "Deiner Nachricht werden Protokolle beigefügt, um sicherzustellen, dass alles ordnungsgemäß funktioniert. Um deine Nachricht ohne Logs zu senden, deaktiviere diese Einstellung." - "%1$s ist bei der letzten Verwendung abgestürzt. Möchtest du uns einen Absturzbericht senden?" - diff --git a/features/rageshake/impl/src/main/res/values-fr/translations.xml b/features/rageshake/impl/src/main/res/values-fr/translations.xml index 53b95af6be..cd800881dc 100644 --- a/features/rageshake/impl/src/main/res/values-fr/translations.xml +++ b/features/rageshake/impl/src/main/res/values-fr/translations.xml @@ -1,8 +1,8 @@ - "Joindre une capture d\'écran" + "Joindre une capture d’écran" "Vous pouvez me contacter si vous avez des questions complémentaires." - "Me contacter" + "Contactez-moi" "Modifier la capture d\'écran" "S\'il vous plait, veuillez décrire le bogue. Qu\'avez-vous fait ? À quoi vous attendiez-vous ? Que s\'est-il réellement passé. Veuillez ajouter le plus de détails possible." "Décrire le bogue" @@ -11,5 +11,5 @@ "Autoriser à inclure les journaux techniques" "Envoyer une capture d’écran" "Pour vérifier que les choses fonctionnent comme prévu, des journaux techniques seront envoyés avec votre message. Pour l’envoyer sans ces journaux, désactivez ce paramètre." - "%1$s a planté la dernière fois qu\'il a été utilisé. Souhaitez-vous partager un rapport de crash avec nous ?" + "%1$s s\'est arrêté la dernière fois qu\'il a été utilisé. Souhaitez-vous partager un rapport d\'incident avec nous ?" diff --git a/features/roomdetails/impl/src/main/res/values-cs/translations.xml b/features/roomdetails/impl/src/main/res/values-cs/translations.xml index 90a9bb0190..defedd3bfb 100644 --- a/features/roomdetails/impl/src/main/res/values-cs/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-cs/translations.xml @@ -25,6 +25,19 @@ "Aktualizace místnosti…" "Nevyřízeno" "Členové místnosti" + "Povolit vlastní nastavení" + "Zapnutím této funkce přepíšete výchozí nastavení" + "Upozornit mě v tomto chatu na" + "Můžete změnit ve vašem %1$s." + "globální nastavení" + "Výchozí nastavení" + "Odebrat vlastní nastavení" + "Při načítání nastavení oznámení došlo k chybě." + "Obnovení výchozího režimu se nezdařilo, zkuste to prosím znovu." + "Nastavení režimu se nezdařilo, zkuste to prosím znovu." + "Všechny zprávy" + "Pouze zmínky a klíčová slova" + "V této místnosti mě upozornit na" "Zablokovat" "Blokovaní uživatelé vám nebudou moci posílat zprávy a všechny jejich zprávy budou skryty. Můžete je kdykoli odblokovat." "Zablokovat uživatele" diff --git a/features/roomdetails/impl/src/main/res/values-de/translations.xml b/features/roomdetails/impl/src/main/res/values-de/translations.xml index 8ae23e8152..7e33583ffd 100644 --- a/features/roomdetails/impl/src/main/res/values-de/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-de/translations.xml @@ -1,37 +1,6 @@ - - "%1$d Person" - "%1$d Personen" - - "Thema hinzufügen" - "Bereits Mitglied" - "Bereits eingeladen" - "Raum bearbeiten" - "Es gab einen unbekannten Fehler und die Informationen konnten nicht geändert werden." - "Raum konnte nicht aktualisiert werden" - "Nachrichten sind mit Schlössern gesichert. Nur du und der Empfänger haben die eindeutigen Schlüssel, um sie zu entsperren." - "Nachrichtenverschlüsselung aktiviert" - "Beim Laden der Benachrichtigungseinstellungen ist ein Fehler aufgetreten." - "Das Stummschalten dieses Raums ist fehlgeschlagen. Bitte versuche es erneut." - "Die Stummschaltung dieses Raums konnte nicht aufgehoben werden. Bitte versuchen Sie es erneut." - "Personen einladen" - "Benutzerdefiniert" - "Standard" - "Benachrichtigungen" - "Raumname" - "Raum teilen" - "Aktualisiere Raum…" - "Ausstehend" - "Raummitglieder" - "Blockieren" - "Blockierte Benutzer können dir keine Nachrichten senden und alle ihre Nachrichten werden ausgeblendet. Du kannst sie jederzeit entsperren." - "Nutzer blockieren" - "Blockierung aufheben" - "Du wirst alle ihre Nachrichten wieder sehen." - "Nutzer entblockieren" "Raum verlassen" - "Personen" - "Sicherheit" + "Menschen" "Thema" diff --git a/features/roomdetails/impl/src/main/res/values-fr/translations.xml b/features/roomdetails/impl/src/main/res/values-fr/translations.xml index 34fae4fea9..d8dbd878d4 100644 --- a/features/roomdetails/impl/src/main/res/values-fr/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-fr/translations.xml @@ -1,45 +1,49 @@ - "%1$d membre" - "%1$d membres" + "%1$d personne" + "%1$d personnes" - "Définir un sujet" + "Ajouter un sujet" "Déjà membre" - "Déjà invité(e)" - "Modifier le salon" - "Une erreur inconnue s’est produite et les informations n’ont pas pu être modifiées." - "Impossible de mettre à jour le salon" - "Les messages sont sécurisés par des cadenas numériques. Seuls vous et les destinataires possédez les clés uniques pour les déverrouiller." - "Chiffrement des messages activé" - "Une erreur s’est produite lors du chargement des paramètres de notification." - "Impossible de désactiver les notifications de cette salle, veuillez réessayer." - "Impossible de réactiver les notifications de cette salle, veuillez réessayer." + "Déjà invité" + "Modifier la salle" + "Une erreur inconnue s\'est produite et les informations n\'ont pas pu être modifiées." + "Impossible de mettre à jour la salle" + "Les messages sont sécurisés par des verrous. Seuls vous et les destinataires possédez les clés uniques pour les déverrouiller." + "Cryptage des messages activé" + "Une erreur s\'est produite lors du chargement des paramètres de notification." + "Échec de la mise en sourdine de cette salle, veuillez réessayer." + "Échec de la désactivation de la mise en sourdine de cette salle, veuillez réessayer." "Inviter des personnes" "Personnalisé" - "Par défaut" + "Défaut" "Notifications" - "Nom du salon" - "Partager le salon" - "Mise à jour du salon…" + "Nom de la salle" + "Partager la salle" + "Mise à jour de la salle…" "En attente" + "Membres de la salle" "Autoriser les paramètres personnalisés" - "Activer cette option remplacera votre paramètre par défaut" - "Me notifier dans ce chat pour" - "paramètres généraux" + "L\'activation de cette option annulera votre paramètre par défaut" + "Prévenez-moi dans ce chat pour" + "Vous pouvez le modifier dans votre %1$s." + "paramètres globaux" "Paramètre par défaut" - "Une erreur s’est produite lors du chargement des paramètres de notification." - "Impossible de restaurer le mode par défaut, veuillez réessayer." - "Impossible de régler le mode, veuillez réessayer." + "Supprimer le paramètre personnalisé" + "Une erreur s\'est produite lors du chargement des paramètres de notification." + "Échec de la restauration du mode par défaut, veuillez réessayer." + "Échec de la configuration du mode, veuillez réessayer." "Tous les messages" - "Mentions et mots-clés uniquement" + "Mentions et mots clés uniquement" + "Dans cette salle, prévenez-moi pour" "Bloquer" "Les utilisateurs bloqués ne pourront pas vous envoyer de messages et tous leurs messages seront masqués. Vous pouvez les débloquer à tout moment." "Bloquer l\'utilisateur" "Débloquer" "Vous pourrez à nouveau voir tous leurs messages." - "Débloquer l\'utilisateur" - "Quitter le salon" + "Débloquer un utilisateur" + "Quitter la salle" "Personnes" "Sécurité" "Sujet" diff --git a/features/roomdetails/impl/src/main/res/values-ro/translations.xml b/features/roomdetails/impl/src/main/res/values-ro/translations.xml index a2be94aee9..f86fbb8bb5 100644 --- a/features/roomdetails/impl/src/main/res/values-ro/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ro/translations.xml @@ -24,6 +24,19 @@ "Se actualizează camera…" "În așteptare" "Membrii camerei" + "Permiteți setări personalizate" + "Activarea acestei opțiuni va anula setările implicite." + "Anunțați-mă în acestă cameră pentru" + "Îl puteți schimba în %1$s." + "Setări generale" + "Setare implicită" + "Stergeți setarea personalizată" + "A apărut o eroare la încărcarea setărilor pentry notificari." + "Nu s-a reușit restaurarea modului implicit, vă rugăm să încercați din nou." + "Nu s-a reușit setarea modului, vă rugăm să încercați din nou." + "Toate mesajele" + "Numai mențiuni și cuvinte cheie" + "În această cameră, anunțați-mă pentru" "Blocați" "Utilizatorii blocați nu vă vor putea trimite mesaje și toate mesajele lor vor fi ascunse. Puteți anula această acțiune oricând." "Blocați utilizatorul" diff --git a/features/roomdetails/impl/src/main/res/values-ru/translations.xml b/features/roomdetails/impl/src/main/res/values-ru/translations.xml index 4154f041ff..cff08460c1 100644 --- a/features/roomdetails/impl/src/main/res/values-ru/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ru/translations.xml @@ -31,11 +31,13 @@ "Вы можете изменить его в своем %1$s." "Основные Настройки" "Настройка по умолчанию" + "Удалить пользовательскую настройку" "Произошла ошибка при загрузке настроек уведомлений." "Не удалось восстановить режим по умолчанию, попробуйте еще раз." "Не удалось настроить режим, попробуйте еще раз." "Все сообщения" "Только упоминания и ключевые слова" + "В этой комнате уведомить меня о" "Заблокировать" "Заблокированные пользователи не смогут отправлять вам сообщения, а все их сообщения будут скрыты. Вы можете разблокировать их в любое время." "Заблокировать пользователя" diff --git a/features/roomdetails/impl/src/main/res/values-sk/translations.xml b/features/roomdetails/impl/src/main/res/values-sk/translations.xml index 687c495ce7..01e0f717e1 100644 --- a/features/roomdetails/impl/src/main/res/values-sk/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-sk/translations.xml @@ -31,11 +31,13 @@ "Môžete to zmeniť vo svojich %1$s." "všeobecných nastaveniach" "Predvolené nastavenie" + "Odstrániť vlastné nastavenie" "Pri načítavaní nastavení oznámení došlo k chybe." "Nepodarilo sa obnoviť predvolený režim, skúste to prosím znova." "Nepodarilo sa nastaviť režim, skúste to prosím znova." "Všetky správy" "Iba zmienky a kľúčové slová" + "V tejto miestnosti ma upozorniť na" "Zablokovať" "Blokovaní používatelia vám nebudú môcť posielať správy a všetky ich správy budú skryté. Môžete ich kedykoľvek odblokovať." "Zablokovať používateľa" diff --git a/features/roomdetails/impl/src/main/res/values/localazy.xml b/features/roomdetails/impl/src/main/res/values/localazy.xml index 717f503e22..7f0f4ddc30 100644 --- a/features/roomdetails/impl/src/main/res/values/localazy.xml +++ b/features/roomdetails/impl/src/main/res/values/localazy.xml @@ -30,11 +30,13 @@ "You can change it in your %1$s." "global settings" "Default setting" + "Remove custom setting" "An error occurred while loading notification settings." "Failed restoring the default mode, please try again." "Failed setting the mode, please try again." "All messages" "Mentions and Keywords only" + "In this room, notify me for" "Block" "Blocked users won\'t be able to send you messages and all their messages will be hidden. You can unblock them anytime." "Block user" diff --git a/features/roomlist/impl/src/main/res/values-de/translations.xml b/features/roomlist/impl/src/main/res/values-de/translations.xml deleted file mode 100644 index 49a400b138..0000000000 --- a/features/roomlist/impl/src/main/res/values-de/translations.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - "Ein neues Gespräch oder einen neuen Raum erstellen" - "Beginnen, indem du jemandem eine Nachricht sendest." - "Noch keine Chats." - "Alle Chats" - "Es sieht so aus, als ob du ein neues Gerät verwendest. Verifiziere, dass du es bist, um auf deine verschlüsselten Nachrichten zuzugreifen." - "Verifiziere, dass du es bist" - diff --git a/features/roomlist/impl/src/main/res/values-fr/translations.xml b/features/roomlist/impl/src/main/res/values-fr/translations.xml index a5217e1ad5..0380971724 100644 --- a/features/roomlist/impl/src/main/res/values-fr/translations.xml +++ b/features/roomlist/impl/src/main/res/values-fr/translations.xml @@ -1,7 +1,9 @@ - "Créer une nouvelle conversation ou un nouveau salon" + "Créer une nouvelle conversation ou une nouvelle salle" + "Commencez par envoyer un message à quelqu\'un." + "Aucune discussion pour le moment." "Tous les chats" - "Il semblerait que vous utilisiez un nouvel appareil. Lancez la vérification avec un autre appareil pour accéder à vos messages chiffrés à l’avenir." + "Il semblerait que vous utilisiez un nouvel appareil. Vérifiez que vous êtes bien autorisé à accéder à vos messages cryptés." "Vérifier que c’est bien vous" diff --git a/features/verifysession/impl/src/main/res/values-de/translations.xml b/features/verifysession/impl/src/main/res/values-de/translations.xml index f5f149cfd9..6699697e79 100644 --- a/features/verifysession/impl/src/main/res/values-de/translations.xml +++ b/features/verifysession/impl/src/main/res/values-de/translations.xml @@ -1,19 +1,4 @@ - "Etwas scheint nicht zu stimmen. Entweder ist die Antwortzeit für die Anfrage abgelaufen oder die Anfrage wurde abgelehnt." - "Bestätige, dass die folgenden Emojis mit denen deiner anderen Sitzung übereinstimmen." - "Emojis vergleichen" - "Deine neue Sitzung ist jetzt verifiziert. Sie hat Zugriff auf deine verschlüsselten Nachrichten und andere Benutzer werden sie als vertrauenswürdig sehen." - "Beweise, dass du es bist, um auf deinen verschlüsselten Nachrichtenverlauf zuzugreifen." - "Eine bestehende Sitzung öffnen" - "Verifizierung erneut versuchen" - "Ich bin bereit" - "Warten auf Übereinstimmung" - "Vergleiche die einzigartigen Emojis und achte darauf, dass sie in derselben Reihenfolge erscheinen." - "Sie stimmen nicht überein" - "Sie stimmen überein" - "Akzeptiere die Aufforderung zum Starten des Verifizierungsprozesses in deiner anderen Sitzung, um fortzufahren." - "Warten auf die Annahme der Anfrage" - "Verifizierung abgebrochen" - "Starten" + "Start" diff --git a/features/verifysession/impl/src/main/res/values-fr/translations.xml b/features/verifysession/impl/src/main/res/values-fr/translations.xml index dd0bb56708..83de83146f 100644 --- a/features/verifysession/impl/src/main/res/values-fr/translations.xml +++ b/features/verifysession/impl/src/main/res/values-fr/translations.xml @@ -1,10 +1,10 @@ - "Quelque chose ne semble pas normal. Soit la demande a dépassé le temps imparti, soit elle a été refusée." + "Quelque chose ne va pas. Soit la demande a expiré, soit elle a été refusée." "Confirmez que les emojis ci-dessous correspondent à ceux affichés sur votre autre session." "Comparez les émojis" - "Votre nouvelle session est désormais vérifiée. Elle a accès à vos messages chiffrés et les autres utilisateurs la verront identifiée comme fiable." - "Prouvez qu\'il s\'agit bien de vous pour accéder à l\'historique de vos messages chiffrés." + "Votre nouvelle session est désormais vérifiée. Elle a accès à vos messages cryptés et les autres utilisateurs la verront identifiée comme fiable." + "Prouvez qu\'il s\'agit bien de vous pour accéder à l\'historique de vos messages cryptés." "Ouvrir une session existante" "Réessayer la vérification" "Je suis prêt.e" diff --git a/libraries/androidutils/src/main/res/values-de/translations.xml b/libraries/androidutils/src/main/res/values-de/translations.xml deleted file mode 100644 index d30d83f831..0000000000 --- a/libraries/androidutils/src/main/res/values-de/translations.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - "Keine kompatible App für diese Aktion gefunden." - diff --git a/libraries/eventformatter/impl/src/main/res/values-de/translations.xml b/libraries/eventformatter/impl/src/main/res/values-de/translations.xml index 0ca17bc4fe..48d41bed39 100644 --- a/libraries/eventformatter/impl/src/main/res/values-de/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-de/translations.xml @@ -1,57 +1,5 @@ - "(Profilbild wurde auch geändert)" - "%1$s hat sein Profilbild geändert" - "Du hast deinen Avatar geändert" - "%1$s hat seinen Anzeigenamen von %2$s in %3$s geändert" - "Du hast deinen Anzeigenamen von %1$s in %2$s geändert" - "%1$s hat seinen Anzeigenamen entfernt (es war %2$s)" - "Du hast deinen Anzeigenamen entfernt (es war %1$s)" - "%1$s hat seinen Anzeigenamen zu %2$s geändert" - "Du hast deinen Anzeigenamen auf %1$s geändert" - "%1$s hat den Raum-Avatar geändert" - "Du hast den Raum-Avatar geändert" - "%1$s hat das Raumbild entfernt" - "Du hast das Raumbild entfernt" - "%1$s hat %2$s gebannt" - "Du hast %1$s gebannt" "%1$s hat den Raum erstellt" "Du hast den Raum erstellt" - "%1$s hat %2$s eingeladen" - "%1$s hat die Einladung angenommen" - "Du hast die Einladung angenommen" - "Du hast %1$s eingeladen" - "%1$s hat dich eingeladen" - "%1$s ist dem Raum beigetreten" - "Du bist dem Raum beigetreten" - "%1$s hat um Beitritt gebeten" - "%1$s hat %2$s erlaubt, beizutreten" - "%1$s hat dir erlaubt beizutreten" - "Du hast um Beitritt gebeten" - "%1$s hat die Beitrittsanfrage von %2$s abgelehnt" - "Du hast die Beitrittsanfrage von %1$s abgelehnt" - "%1$s hat deine Beitrittsanfrage abgelehnt" - "%1$s ist nicht mehr daran interessiert, beizutreten" - "Du hast deine Beitrittsanfrage zurückgezogen" - "%1$s hat den Raum verlassen" - "Du hast den Raum verlassen" - "%1$s hat den Raumnamen geändert in: %2$s" - "Du hast den Raumnamen geändert in: %1$s" - "%1$s hat den Raumnamen entfernt" - "Du hast den Raumnamen entfernt" - "%1$s hat die Einladung abgelehnt" - "Du hast die Einladung abgelehnt" - "%1$s hat %2$s entfernt" - "Du hast %1$s entfernt" - "%1$s hat eine Einladung an %2$s gesendet, um dem Raum beizutreten" - "Du hast eine Einladung an %1$s gesendet, um dem Raum beizutreten" - "%1$s hat die Einladung für %2$s widerrufen, dem Raum beizutreten" - "Du hast die Einladung für %1$s widerrufen, dem Raum beizutreten" - "%1$s hat das Thema geändert zu: %2$s" - "Du hast das Thema geändert zu: %1$s" - "%1$s hat das Raumthema entfernt" - "Du hast das Raumthema entfernt" - "%1$s hat %2$s entbannt" - "Du hast %1$s entbannt" - "%1$s hat eine unbekannte Änderung an seiner Mitgliedschaft vorgenommen" diff --git a/libraries/eventformatter/impl/src/main/res/values-fr/translations.xml b/libraries/eventformatter/impl/src/main/res/values-fr/translations.xml index e7e07c0852..b81dc80c0d 100644 --- a/libraries/eventformatter/impl/src/main/res/values-fr/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-fr/translations.xml @@ -5,53 +5,53 @@ "Vous avez changé d\'avatar" "%1$s a changé son nom d\'affichage de %2$s à %3$s" "Vous avez changé votre nom d\'affichage de %1$s à %2$s" - "%1$s a supprimé son nom d\'affichage (il s\'agissait de %2$s)" - "Vous avez supprimé votre nom d\'affichage (il s\'agissait de %1$s)" + "%1$s a supprimé leur nom d\'affichage (c\'était %2$s)" + "Vous avez supprimé votre nom d\'affichage (c\'était %1$s)" "%1$s a défini son nom d\'affichage en tant que %2$s" - "Vous avez défini votre nom d\'affichage en tant que %1$s" - "%1$s a changé l\'avatar du salon" - "Vous avez changé l\'avatar du salon" - "%1$s a supprimé l\'avatar du salon" - "Vous avez supprimé l\'avatar du salon" + "Vous avez défini votre nom d\'affichage comme %1$s" + "%1$s a changé l\'avatar de la salle" + "Vous avez changé l\'avatar de la salle" + "%1$s a supprimé l\'avatar de la salle" + "Vous avez supprimé l\'avatar de la salle" "%1$s a banni %2$s" "Vous avez banni %1$s" - "%1$s a créé le salon" - "Vous avez créé le salon" + "%1$s a créé la salle" + "Vous avez créé la salle" "%1$s a invité %2$s" "%1$s a accepté l\'invitation" "Vous avez accepté l\'invitation" "Vous avez invité %1$s" - "%1$s vous a invité." - "%1$s a rejoint le salon" - "Vous avez rejoint le salon" + "%1$s vous a invité" + "%1$s a rejoint la salle" + "Vous avez rejoint la salle" "%1$s a demandé à rejoindre" "%1$s a autorisé %2$s à rejoindre" "%1$s vous a autorisé à rejoindre" "Vous avez demandé à rejoindre" - "%1$s a rejeté la demande d\'adhésion de %2$s" - "Vous avez rejeté la demande d\'adhésion de %1$s" - "%1$s a rejeté votre demande d\'adhésion" + "%1$s a rejeté la demande de %2$s pour rejoindre" + "Vous avez rejeté la demande de %1$s pour rejoindre" + "%1$s a rejeté votre demande pour rejoindre" "%1$s n’est plus intéressé à rejoindre" "Vous avez annulé votre demande d\'adhésion" - "%1$s a quitté le salon" - "Vous avez quitté le salon" - "%1$s a changé le nom du salon en : %2$s" - "Vous avez changé le nom du salon en : %1$s" - "%1$s a supprimé le nom du salon" - "Vous avez supprimé le nom du salon" + "%1$s a quitté la salle" + "Vous avez quitté la salle" + "%1$s a changé le nom de la salle en : %2$s" + "Vous avez changé le nom de la salle en : %1$s" + "%1$s a supprimé le nom de la salle" + "Vous avez supprimé le nom de la salle" "%1$s a rejeté l\'invitation" "Vous avez refusé l\'invitation" "%1$s a supprimé %2$s" "Vous avez supprimé %1$s" - "%1$s a envoyé une invitation à %2$s à rejoindre le salon" - "Vous avez envoyé une invitation à %1$s pour rejoindre le salon" - "%1$s a révoqué l\'invitation de %2$s à rejoindre le salon" - "Vous avez révoqué l\'invitation de %1$s à rejoindre le salon" - "%1$s a changé le sujet en : %2$s" - "Vous avez changé le sujet en : %1$s" - "%1$s a supprimé le sujet du salon" - "Vous avez supprimé le sujet du salon" + "%1$s a envoyé une invitation à %2$s à rejoindre le salle" + "Vous avez envoyé une invitation à %1$s pour rejoindre la salle" + "%1$s a révoqué l\'invitation de %2$s à rejoindre la salle" + "Vous avez révoqué l\'invitation de %1$s à rejoindre la salle" + "%1$s a changé le sujet pour : %2$s" + "Vous avez changé le sujet pour : %1$s" + "%1$s a supprimé le sujet de la salle" + "Vous avez supprimé le sujet de la salle" "%1$s a débanni %2$s" "Vous avez débanni %1$s" - "%1$s a apporté une modification inconnue à son adhésion" + "%1$s a effectué un changement inconnu à son adhésion" diff --git a/libraries/eventformatter/impl/src/main/res/values-zh-rTW/translations.xml b/libraries/eventformatter/impl/src/main/res/values-zh-rTW/translations.xml index 45ab0acee1..2453e2d825 100644 --- a/libraries/eventformatter/impl/src/main/res/values-zh-rTW/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-zh-rTW/translations.xml @@ -1,37 +1,37 @@ - "%1$s將他的顯示名稱從%2$s變更為%3$s" - "您將您的顯示名稱從%1$s1變更為%2$s" - "%1$s的顯示名稱已被本人移除(原為%2$s)" - "您的顯示名稱已被您移除(原為%1$s)" - "%1$s將他的顯示名稱設為%2$s" - "您將您的顯示名稱設為%1$s" - "%1$s建立此聊天室" + "%1$s 將他的顯示名稱從 %2$s 變更為 %3$s" + "您將您的顯示名稱從 %1$s1 變更為 %2$s" + "%1$s 的顯示名稱已被本人移除(原為 %2$s)" + "您的顯示名稱已被您移除(原為 %1$s)" + "%1$s 將他的顯示名稱設為 %2$s" + "您將您的顯示名稱設為 %1$s" + "%1$s 建立此聊天室" "您建立此聊天室" - "%1$s邀請%2$s" - "%1$s接受邀請" + "%1$s 邀請 %2$s" + "%1$s 接受邀請" "您接受邀請" - "您邀請%1$s" - "%1$s邀請您" - "%1$s加入聊天室" + "您邀請 %1$s" + "%1$s 邀請您" + "%1$s 加入聊天室" "您加入聊天室" - "%1$s請求加入" + "%1$s 請求加入" "您請求加入" - "%1$s拒絕%2$s的加入請求" - "您拒絕%1$s的加入請求" - "%1$s拒絕您的加入請求" - "%1$s離開聊天室" + "%1$s 拒絕 %2$s 的加入請求" + "您拒絕 %1$s 的加入請求" + "%1$s 拒絕您的加入請求" + "%1$s 離開聊天室" "您離開聊天室" - "%1$s將聊天室名稱變更為%2$s" - "您將聊天室名稱變更為%1$s" - "聊天室名稱已被%1$s移除" + "%1$s 將聊天室名稱變更為 %2$s" + "您將聊天室名稱變更為 %1$s" + "聊天室名稱已被 %1$s 移除" "聊天室名稱已被您移除" - "%2$s已被%1$s移除" - "%1$s已被您移除" - "%1$s邀請%2$s加入聊天室" - "您邀請%1$s加入聊天室" - "%1$s將主題變更為%2$s" - "您將主題變更為%1$s" - "聊天室主題已被%1$s移除" + "%2$s 已被 %1$s 移除" + "%1$s 已被您移除" + "%1$s 邀請 %2$s 加入聊天室" + "您邀請 %1$s 加入聊天室" + "%1$s 將主題變更為 %2$s" + "您將主題變更為 %1$s" + "聊天室主題已被 %1$s 移除" "聊天室主題已被您移除" diff --git a/libraries/push/impl/src/main/res/values-de/translations.xml b/libraries/push/impl/src/main/res/values-de/translations.xml index 04c7521d9e..496071416d 100644 --- a/libraries/push/impl/src/main/res/values-de/translations.xml +++ b/libraries/push/impl/src/main/res/values-de/translations.xml @@ -1,52 +1,7 @@ - "Anruf" - "Warte auf Ereignisse" - "Laute Benachrichtigungen" - "Stumme Benachrichtigungen" - "** Senden fehlgeschlagen - bitte Raum öffnen" - "Beitreten" - "Ablehnen" - "Hat dich zum Chatten eingeladen" - "Neue Nachrichten" - "Reagierte mit %1$s" - "Als gelesen markieren" - "Hat dich eingeladen, dem Raum beizutreten" - "Ich" - "Du siehst die Benachrichtigung an! Klick mich an!" "%1$s: %2$s" "%1$s: %2$s %3$s" "%1$s und %2$s" - "%1$s in %2$s" - "%1$s in %2$s und %3$s" - - "%1$s: %2$d Nachricht" - "%1$s: %2$d Nachrichten" - - - "%d Mitteilung" - "%d Mitteilungen" - - - "%d Einladung" - "%d Einladungen" - - - "%d neue Nachricht" - "%d neue Nachrichten" - - - "%d ungelesene benachrichtigte Nachricht" - "%d ungelesene benachrichtigte Nachrichten" - - - "%d Raum" - "%d Räume" - - "Auswählen, wie Benachrichtigungen empfangen werden sollen" - "Hintergrundsynchronisation" - "Google-Dienste" - "Keine gültigen Google Play-Dienste gefunden. Benachrichtigungen funktionieren möglicherweise nicht richtig." - "Mitteilung" - "Schnellantwort" + "Schnelle Antwort" diff --git a/libraries/push/impl/src/main/res/values-fr/translations.xml b/libraries/push/impl/src/main/res/values-fr/translations.xml index 6e6374e8f2..67309cfc27 100644 --- a/libraries/push/impl/src/main/res/values-fr/translations.xml +++ b/libraries/push/impl/src/main/res/values-fr/translations.xml @@ -1,27 +1,27 @@ "Appel" - "À l\'écoute d\'événements" + "À l\'écoute des événements" "Notifications bruyantes" "Notifications silencieuses" - "** Échec d\'envoi - veuillez ouvrir le salon" + "** Échec de l\'envoi - veuillez ouvrir la salle" "Rejoindre" - "Refuser" + "Rejeter" "Vous a invité à discuter" "Nouveaux messages" "A réagi avec %1$s" "Marquer comme lu" - "Vous a invité à rejoindre le salon" + "Vous a invité à rejoindre la salle" "Moi" - "Vous êtes en train de consulter la notification ! Cliquez-moi !" - "%1$s: %2$s" - "%1$s: %2$s %3$s" + "Vous êtes en train de consulter la notification ! Cliquez sur moi !" + "%1$s : %2$s" + "%1$s : %2$s %3$s" "%1$s et %2$s" "%1$s dans %2$s" "%1$s dans %2$s et %3$s" - "%1$s: %2$d message" - "%1$s: %2$d messages" + "%1$s : %2$d message" + "%1$s : %2$d messages" "%d notification" @@ -40,10 +40,10 @@ "%d messages notifiés non lus" - "%d conversation" - "%d conversations" + "%d salle" + "%d salles" - "Choisissez comment recevoir les notifications" + "Choisissez le mode de réception des notifications" "Synchronisation en arrière-plan" "Services Google" "Aucun service Google Play valide n\'a été trouvé. Les notifications peuvent ne pas fonctionner correctement." diff --git a/libraries/textcomposer/impl/src/main/res/values-de/translations.xml b/libraries/textcomposer/impl/src/main/res/values-fr/translations.xml similarity index 56% rename from libraries/textcomposer/impl/src/main/res/values-de/translations.xml rename to libraries/textcomposer/impl/src/main/res/values-fr/translations.xml index 6b75a1c9a7..1a7539c8c6 100644 --- a/libraries/textcomposer/impl/src/main/res/values-de/translations.xml +++ b/libraries/textcomposer/impl/src/main/res/values-fr/translations.xml @@ -1,4 +1,4 @@ - "Anhang hinzufügen" + "Ajouter une pièce jointe" diff --git a/libraries/ui-strings/src/main/res/values-cs/translations.xml b/libraries/ui-strings/src/main/res/values-cs/translations.xml index bbb68b53e8..0ff43bceb7 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -96,7 +96,6 @@ "Heslo" "Lidé" "Trvalý odkaz" - "Konečné hlasy: %1$s" "Celkový počet hlasů: %1$s" "Výsledky se zobrazí po skončení hlasování" "Zásady ochrany osobních údajů" diff --git a/libraries/ui-strings/src/main/res/values-de/translations.xml b/libraries/ui-strings/src/main/res/values-de/translations.xml index 7aa02bddae..4028ece8ed 100644 --- a/libraries/ui-strings/src/main/res/values-de/translations.xml +++ b/libraries/ui-strings/src/main/res/values-de/translations.xml @@ -1,240 +1,65 @@ - "Passwort ausblenden" - "Dateien senden" - "Passwort anzeigen" - "Benutzermenü" - "Zustimmen" - "Zurück" + "Nur Erwähnungen" + "Stummgeschaltet" "Abbrechen" - "Foto auswählen" - "Zurücksetzen" - "Schließen" - "Verifizierung abschließen" "Bestätigen" "Weiter" "Kopieren" - "Link kopieren" - "Link zur Nachricht kopieren" - "Erstellen" "Raum erstellen" - "Ablehnen" - "Deaktivieren" - "Fertig" + "Erledigt" "Bearbeiten" "Aktivieren" - "Passwort vergessen?" - "Weiterleiten" + "Umfrage beenden" "Einladen" - "Freunde einladen" - "Freunde zu %1$s einladen" - "Personen zu %1$s einladen" - "Einladungen" "Mehr erfahren" "Verlassen" "Raum verlassen" "Weiter" - "Nein" "Nicht jetzt" "OK" - "Öffnen mit" - "Schnellantwort" - "Zitieren" - "Reagieren" + "Schnelle Antwort" + "Zitat" "Entfernen" - "Antworten" + "Antwort" "Fehler melden" "Inhalt melden" "Erneut versuchen" - "Entschlüsselung erneut versuchen" - "Speichern" - "Suchen" + "Entschlüsselung wiederholen" "Senden" - "Nachricht senden" - "Teilen" - "Link teilen" - "Überspringen" - "Starten" + "Start" "Chat starten" - "Verifizierung starten" - "Zum Karte laden tippen" - "Foto aufnehmen" - "Quelltext anzeigen" - "Ja" - "Über" - "Allgemeine Geschäftsbedingungen" - "Analyse" - "Audio" - "Blasen" - "Urheberrecht" - "Erstelle Raum…" - "Raum verlassen" - "Entschlüsselungsfehler" - "Entwickleroptionen" + "Überprüfung starten" + "Quelle anzeigen" + "Dekodierungsfehler" "(bearbeitet)" - "Bearbeiten" - "* %1$s %2$s" + "Bearbeitung" "Verschlüsselung aktiviert" "Fehler" "Datei" - "Datei gespeichert unter Downloads" - "Nachricht weiterleiten" "GIF" "Bild" - "Diese Matrix-ID kann nicht gefunden werden, daher wird die Einladung möglicherweise nicht empfangen." - "Verlasse Raum" - "Link in Zwischenablage kopiert" - "Lädt…" + "Link in die Zwischenablage kopiert" + "Laden…" "Nachricht" - "Nachrichtenlayout" "Nachricht entfernt" - "Modern" - "Stummschalten" - "Keine Ergebnisse" - "Offline" "Passwort" - "Personen" - "Dauerlink" - "Endgültige Stimmen: %1$s" - "Stimmen insgesamt: %1$s" - "Ergebnisse werden nach Ende der Umfrage angezeigt" - "Datenschutz­erklärung" + "Menschen" + "Permalink" "Reaktionen" - "Aktualisiere…" - "Auf %1$s antworten" - "Einen Fehler melden" - "Bericht gesendet" - "Raumname" - "z.B. dein Projektname" - "Suche nach jemandem" - "Suchergebnisse" - "Sicherheit" - "Wählen deinen Server" - "Sendet…" - "Server wird nicht unterstützt" - "Server-URL" "Einstellungen" - "Geteilter Standort" - "Starte Chat…" "Sticker" - "Erfolg" "Vorschläge" - "Synchronisiere…" - "Hinweise von Drittanbietern" + "Text" "Thema" - "Worum geht es in diesem Raum?" - "Entschlüsselung nicht möglich" - "Einladungen konnten nicht an einen oder mehrere Benutzer gesendet werden." - "Einladung(en) können nicht gesendet werden" - "Stummschaltung aufheben" "Nicht unterstütztes Ereignis" "Benutzername" - "Verifizierung abgebrochen" - "Verifizierung abgeschlossen" "Video" - "Warte…" - "Bestätigung" - "Warnung" - "Aktivitäten" - "Flaggen" - "Essen & Trinken" - "Tiere & Natur" - "Objekte" - "Smileys & Personen" - "Reisen & Orte" - "Symbole" - "Fehler beim Erstellen des Dauerlinks" - "%1$s konnte die Karte nicht laden. Bitte versuche es später erneut." - "Fehler beim Laden der Nachrichten" - "%1$s konnte nicht auf deinen Standort zugreifen. Bitte versuche es später erneut." - "%1$s hat keine Berechtigung, auf deinen Standort zuzugreifen. Du kannst den Zugriff in den Einstellungen aktivieren." - "%1$s hat keine Berechtigung, auf deinen Standort zuzugreifen. Aktiviere den Zugriff unten." - "Einige Nachrichten wurden nicht gesendet" - "Entschuldigung, ein Fehler ist aufgetreten." - "🔐️ Besuche mich auf %1$s" - "Hey, sprich mit mir auf %1$s: %2$s" - "Bist du sicher, dass du diesen Raum verlassen willst? Du bist die einzige Person hier. Wenn du gehst, kann in Zukunft niemand mehr beitreten, auch du nicht." - "Bist du dir sicher, dass du den Raum verlassen möchtest? Dieser Raum ist nicht öffentlich und du kannst ihm ohne eine Einladung nicht mehr beitreten." - "Bist du dir sicher, dass du den Raum verlassen möchtest?" - "%1$s Android" - - "%1$d Mitglied" - "%1$d Mitglieder" - - - "%d Stimme" - "%d Stimmen" - - "Schütteln zum Melden von Fehlern" - "Du scheinst frustriert das Telefon zu schütteln. Möchtest du den Fehlerberichtsbildschirm öffnen?" - "Diese Nachricht wird an deinen Heimserver-Admin gemeldet. Er wird nicht in der Lage sein, verschlüsselte Nachrichten zu lesen." - "Grund für die Meldung dieses Inhalts" - "Aufzählungsliste ein-/ausschalten" - "Codeblock umschalten" - "Nachricht…" - "Fettformatierung anwenden" - "Kursivformat anwenden" - "Durchgestrichenes Format anwenden" - "Unterstreichungsformat anwenden" - "Vollbildmodus umschalten" - "Einrücken" - "Inline-Codeformat anwenden" - "Link setzen" - "Nummerierte Liste ein-/ausschalten" - "Zitat umschalten" - "Einrücken aufheben" - "Dies ist der Anfang von %1$s." - "Dies ist der Beginn dieser Konversation." - "Neu" - "Teile Analyse-Daten" - "Medienauswahl fehlgeschlagen, bitte versuche es erneut." - "Fehler bei der Verarbeitung von Medien zum Hochladen, bitte versuche es erneut." - "Hochladen von Medien fehlgeschlagen, bitte versuchen Sie es erneut." - "Zusätzliche Einstellungen" - "Audio- und Videoanrufe" - "Konfigurationskonflikt" - "Wir haben die Benachrichtigungseinstellungen vereinfacht, damit Optionen leichter zu finden sind. - -Einige benutzerdefinierte Einstellungen, die du in der Vergangenheit ausgewählt hast, werden hier nicht angezeigt, sind aber immer noch aktiv. - -Wenn du fortfährst, ändern sich möglicherweise einige deine Einstellungen." - "Direkte Chats" - "Benutzerdefinierte Einstellung pro Chat" - "Beim Aktualisieren der Benachrichtigungseinstellung ist ein Fehler aufgetreten." - "Alle Nachrichten" - "Nur Erwähnungen und Schlüsselwörter" - "Bei direkten Chats, benachrichtigen mich für" - "Bei Gruppenchats, benachrichtigte mich für" - "Benachrichtigungen auf diesem Gerät aktivieren" - "Die Konfiguration wurde nicht korrigiert. Bitte versuche es erneut." - "Gruppenchats" - "Erwähnungen" - "Alle" - "Erwähnungen" - "Benachrichtige mich für" - "Benachrichtige mich bei @room" - "Um Benachrichtigungen zu erhalten, ändern bitte deine %1$s." - "Systemeinstellungen" - "Systembenachrichtigungen deaktiviert" - "Benachrichtigungen" - "Prüfe, ob du alle aktuellen und zukünftigen Nachrichten dieses Benutzers ausblenden möchtest" - "Konto und Geräte" - "Standort teilen" - "Meinen Standort teilen" - "In Apple Maps öffnen" - "In Google Maps öffnen" - "In OpenStreetMap öffnen" - "Diesen Ort teilen" - "Standort" - "Rageshake" - "Erkennungsschwelle" - "Allgemein" - "Version: %1$s (%2$s)" - "de" + "Warten…" + "Formatierungsoptionen schließen" + "Einen Link erstellen" + "Link bearbeiten" + "Link" "Fehler" - "Erfolg" - "Teile anonyme Nutzungsdaten, um uns bei der Identifizierung von Problemen zu helfen." - "Du kannst alle unsere Nutzerbedingungen %1$s lesen." "hier" - "Nutzer blockieren" diff --git a/libraries/ui-strings/src/main/res/values-fr/translations.xml b/libraries/ui-strings/src/main/res/values-fr/translations.xml index 745bde6497..67b738cc21 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -1,106 +1,122 @@ "Masquer le mot de passe" + "Mentions uniquement" + "En sourdine" "Envoyer des fichiers" "Afficher le mot de passe" "Menu utilisateur" "Accepter" "Retour" "Annuler" - "Choisir une photo" + "Choisissez une photo" "Effacer" "Fermer" - "Compléter la vérification" + "Terminer la vérification" "Confirmer" "Continuer" "Copier" "Copier le lien" "Copier le lien vers le message" "Créer" - "Créer un salon" + "Créer une salle" "Refuser" "Désactiver" "Terminé" "Modifier" "Activer" + "Terminer le sondage" "Mot de passe oublié ?" "Transférer" "Inviter" "Inviter des amis" "Inviter des amis à %1$s" - "Inviter des gens sur %1$s" + "Invitez des personnes à %1$s" "Invitations" "En savoir plus" "Quitter" - "Quitter le salon" + "Quitter la salle" + "Gérer le compte" + "Gérez les appareils" "Suivant" "Non" "Pas maintenant" "OK" - "Ouvrir avec" + "Ouvrez avec" "Réponse rapide" "Citer" - "Supprimer" + "Réagissez" + "Enlever" "Répondre" - "Signaler un bug" + "Répondre dans le fil de discussion" + "Signaler un bogue" "Signaler le contenu" "Réessayer" - "Réessayer le déchiffrement" + "Réessayer le décryptage" "Enregistrer" - "Chercher" + "Rechercher" "Envoyer" "Envoyer un message" "Partager" "Partager le lien" - "Passer" + "Sauter" "Démarrer" - "Commencer un chat" + "Démarrer la discussion" "Commencer la vérification" - "Touchez pour charger la carte" + "Appuyez pour charger la carte" "Prendre une photo" - "Voir la source" + "Afficher la source" "Oui" + "Appel en cours" + "Appuyez pour retourner à l\'appel." + "☎️ Appel en cours" "À propos" - "Politique d’utilisation" + "Politique d\'utilisation acceptable" + "Paramètres avancés" "Statistiques d\'utilisation" "Audio" "Bulles" - "Copyright" - "Création du salon…" - "Le salon a été quitté" - "Erreur de déchiffrement" - "Options de développement" + "Droits d\'auteur" + "Création de salle…" + "Quitter la salle" + "Erreur de décryptage" + "Options pour les développeurs" "(modifié)" - "Modification en cours" + "Édition" "* %1$s %2$s" - "Chiffrement activé" + "Cryptage activé" "Erreur" "Fichier" - "Fichier enregistré dans les Téléchargements" + "Fichier enregistré dans Téléchargements" "Transférer le message" "GIF" "Image" - "Nous ne pouvons pas vérifier le Matrix ID de cet utilisateur. Cette invitation pourrait être envoyée dans le vide." - "Quitter le salon" + "En réponse à %1$s" + "Cet identifiant Matrix est introuvable, il est donc possible que l\'invitation ne soit pas reçue." + "Quitter la salle" "Lien copié dans le presse-papiers" "Chargement…" "Message" "Mode d\'affichage des messages" "Message supprimé" "Moderne" - "Sourdine" + "Mettre en sourdine" "Aucun résultat" "Hors ligne" "Mot de passe" "Personnes" "Permalien" + "Nombre total de votes : %1$s" + "Les résultats s\'afficheront une fois le sondage terminé" "Politique de confidentialité" + "Réaction" "Réactions" "Actualisation…" "En réponse à %1$s" - "Signaler un problème" - "Rapport envoyé" - "Nom du salon" + "Signaler un bogue" + "Rapport soumis" + "Éditeur de texte enrichi" + "Nom de la salle" "par exemple, le nom de votre projet" "Rechercher quelqu\'un" "Résultats de la recherche" @@ -110,25 +126,27 @@ "Serveur non pris en charge" "URL du serveur" "Paramètres" - "Position partagée" - "Démarrage du chat…" + "Emplacement partagé" + "Démarrer le chat…" "Autocollant" "Succès" "Suggestions" "Synchronisation" - "Mentions tierces" + "Texte" + "Avis de tiers" + "Fil de discussion" "Sujet" - "De quoi parle ce salon ?" + "De quoi s\'agit-il dans cette salle ?" "Échec de déchiffrement" - "Nous n\'avons pas réussi à envoyer des invitations à un ou plusieurs utilisateurs." + "Les invitations n\'ont pas pu être envoyées à un ou plusieurs utilisateurs." "Impossible d\'envoyer une ou plusieurs invitations" - "Réactiver" + "Annuler la sourdine" "Événement non pris en charge" "Nom d\'utilisateur" "Vérification annulée" "Vérification terminée" "Vidéo" - "Patientez…" + "En attente…" "Confirmation" "Attention" "Activités" @@ -140,65 +158,103 @@ "Voyages & lieux" "Symboles" "Échec de la création du permalien" - "%1$s n’a pas pu charger la carte. Veuillez réessayer plus tard." + "%1$s n\'a pas pu charger la carte. Veuillez réessayer ultérieurement." "Échec du chargement des messages" + "%1$s n\'a pas pu accéder à votre emplacement. Veuillez réessayer ultérieurement." + "%1$s n\'est pas autorisé à accéder à votre position. Vous pouvez activer l\'accès dans les Paramètres." + "%1$s n\'est pas autorisé à accéder à votre position. Activez l\'accès ci-dessous." "Certains messages n\'ont pas été envoyés" - "Désolé, une erreur est survenue." + "Désolé, une erreur s\'est produite" "🔐️ Rejoignez-moi sur %1$s" "Salut, parle-moi sur %1$s : %2$s" - "Êtes-vous sûr de vouloir quitter ce salon ? Vous êtes la seule personne ici. Si vous partez, personne ne pourra plus rejoindre ce salon, y compris vous." - "Êtes-vous sûr de vouloir quitter ce salon ? Ce salon n\'est pas public et vous ne pourrez pas le rejoindre sans invitation." - "Êtes-vous sûr de vouloir quitter le salon ?" + "Êtes-vous sûr de vouloir quitter cette salle ? Vous êtes la seule personne ici. Si vous partez, personne ne pourra rejoindre la salle à l\'avenir, y compris vous." + "Êtes-vous sûr de vouloir quitter cette salle ? Cette salle n\'est pas publique et vous ne pourrez pas la rejoindre sans invitation." + "Êtes-vous sûr de vouloir quitter la salle ?" "%1$s Android" "%1$d membre" "%1$d membres" - "Rageshake pour signaler un bug" + + "%d vote" + "%d votes" + + "Rageshake pour signaler un bogue" "Vous semblez secouer le téléphone de frustration. Voulez-vous ouvrir le formulaire de rapport de problème ?" - "Ce message sera signalé à l’administrateur de votre serveur d\'accueil. Ils ne pourront lire aucun message chiffré." + "Ce message sera signalé à l’administrateur de votre serveur d\'accueil. Ils ne pourront lire aucun message crypté." "Raison du signalement de ce contenu" "Afficher une liste à puces" + "Fermer les options de formatage" "Afficher le bloc de code" - "Envoyer un message…" + "Message…" + "Créer un lien" + "Modifier le lien" "Appliquer le format gras" "Appliquer le format italique" "Appliquer le format barré" "Appliquer le format souligné" - "Afficher en mode plein écran" + "Activer/désactiver le mode plein écran" "Décaler vers la droite" "Appliquer le formatage de code en ligne" "Définir un lien" "Afficher une liste numérotée" - "Afficher une citation" + "Ouvrir les options de rédaction" + "Afficher/masquer la citation" + "Supprimer le lien" "Décaler vers la gauche" + "Lien" "Ceci est le début de %1$s." "Ceci est le début de cette conversation." "Nouveau" - "Partager les statistiques d\'utilisation" - "Impossible de sélectionner un média, veuillez réessayer." - "Échec du traitement du média avant son envoi, veuillez réessayer." - "Impossible d’envoyer le média, veuillez réessayer." + "Partagez des données de statistiques d\'utilisation" + "Échec de la sélection du média, veuillez réessayer." + "Échec du traitement des médias à télécharger, veuillez réessayer." + "Échec du téléchargement du média, veuillez réessayer." + "Réglages supplémentaires" + "Appels audio et vidéo" + "Incompatibilité de configuration" + "Nous avons simplifié les paramètres des notifications pour que les options soient plus faciles à trouver. + +Certains paramètres personnalisés que vous avez choisis par le passé ne sont pas affichés ici, mais ils sont toujours actifs. + +Si vous continuez, il est possible que certains de vos paramètres soient modifiés." + "Discussions directes" + "Paramétrage personnalisé par chat" + "Une erreur s\'est produite lors de la mise à jour du paramètre de notification." + "Tous les messages" + "Mentions et mots clés uniquement" + "Sur les chats directs, prévenez-moi pour" + "Lors de discussions de groupe, prévenez-moi pour" "Activer les notifications sur cet appareil" - "paramètres système" - "Notifications système désactivées" + "La configuration n\'a pas été corrigée, veuillez réessayer." + "Discussions de groupe" + "Mentions" + "Tous" + "Mentions" + "Prévenez-moi pour" + "Prévenez-moi sur @salle" + "Pour recevoir des notifications, veuillez modifier votre %1$s." + "paramètres du système" + "Les notifications du système sont désactivées" "Notifications" "Cochez si vous souhaitez masquer tous les messages actuels et futurs de cet utilisateur." - "Partage de position" - "Partager ma position" + "Compte et appareils" + "Emplacement partagé" + "Partager mon emplacement" "Ouvrir dans Apple Maps" "Ouvrir dans Google Maps" "Ouvrir dans OpenStreetMap" - "Partager cette position" + "Partager cet emplacement" + "Emplacement" "Rageshake" "Seuil de détection" "Général" - "Version: %1$s ( %2$s )" - "fr" + "Version : %1$s ( %2$s )" + "Ang." "Erreur" "Succès" "Partagez des données d\'utilisation anonymes pour nous aider à identifier les problèmes." - "Consultez nos conditions d\'utilisation %1$s." + "Vous pouvez lire toutes nos conditions %1$s." "ici" "Bloquer l\'utilisateur" diff --git a/libraries/ui-strings/src/main/res/values-ro/translations.xml b/libraries/ui-strings/src/main/res/values-ro/translations.xml index d96abca3cc..c122a37d96 100644 --- a/libraries/ui-strings/src/main/res/values-ro/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ro/translations.xml @@ -98,7 +98,6 @@ "Parola" "Persoane" "Permalink" - "Voturi finale: %1$s" "Total voturi: %1$s" "Rezultatele vor fi afișate după încheierea sondajului" "Politica de confidențialitate" diff --git a/libraries/ui-strings/src/main/res/values-ru/translations.xml b/libraries/ui-strings/src/main/res/values-ru/translations.xml index 28284f6347..798515fa6a 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -95,7 +95,6 @@ "Пароль" "Пользователи" "Постоянная ссылка" - "Итоговые голоса: %1$s" "Всего голосов: %1$s" "Результаты будут показаны после завершения опроса" "Политика конфиденциальности" diff --git a/libraries/ui-strings/src/main/res/values-sk/translations.xml b/libraries/ui-strings/src/main/res/values-sk/translations.xml index cad1b5a564..162ca8f9d8 100644 --- a/libraries/ui-strings/src/main/res/values-sk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml @@ -1,6 +1,8 @@ "Skryť heslo" + "Iba zmienky" + "Stlmené" "Odoslať súbory" "Zobraziť heslo" "Používateľské menu" @@ -23,6 +25,7 @@ "Hotovo" "Upraviť" "Povoliť" + "Ukončiť anketu" "Zabudnuté heslo?" "Preposlať" "Pozvať" @@ -95,7 +98,6 @@ "Heslo" "Ľudia" "Trvalý odkaz" - "Výsledné hlasovanie: %1$s" "Celkový počet hlasov: %1$s" "Výsledky sa zobrazia po ukončení ankety" "Zásady ochrany osobných údajov" @@ -120,6 +122,7 @@ "Úspech" "Návrhy" "Synchronizuje sa" + "Text" "Oznámenia tretích strán" "Téma" "O čom je táto miestnosť?" @@ -172,8 +175,11 @@ "Táto správa bude nahlásená správcovi vášho domovského servera. Nebude môcť prečítať žiadne šifrované správy." "Dôvod nahlásenia tohto obsahu" "Prepnúť zoznam odrážok" + "Zatvoriť možnosti formátovania" "Prepnúť blok kódu" "Správa…" + "Vytvoriť odkaz" + "Upraviť odkaz" "Použiť tučný formát" "Použiť formát kurzívy" "Použiť formát prečiarknutia" @@ -183,8 +189,10 @@ "Použiť formát riadkového kódu" "Nastaviť odkaz" "Prepnúť číslovaný zoznam" + "Otvoriť možnosti písania" "Prepnúť citáciu" "Zrušiť odsadenie" + "Odkaz" "Toto je začiatok %1$s." "Toto je začiatok tejto konverzácie." "Nové" diff --git a/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml b/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml index ddaaed0d33..b385e7c8a4 100644 --- a/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml @@ -31,6 +31,8 @@ "了解更多" "離開" "離開聊天室" + "管理帳號" + "管理裝置" "下一個" "否" "以後再說" @@ -144,6 +146,8 @@ "切換項目編號" "切換程式碼區塊" "訊息" + "建立連結" + "編輯連結" "套用粗體" "套用斜體" "套用刪除線" @@ -154,6 +158,7 @@ "切換數字編號" "切換引用" "減少縮排" + "連結" "新訊息" "分享分析數據" "無法上傳媒體檔案,請稍後再試。" @@ -168,8 +173,8 @@ "通知" "分享位置" "分享我的位置" - "在 Apple 地圖中開啟" - "在 Google 地圖中開啟" + "在 Apple Maps 中開啟" + "在 Google Maps 中開啟" "在開放街圖(OpenStreetMap) 中開啟" "分享這個位置" "位置" @@ -178,5 +183,8 @@ "zh-tw" "錯誤" "成功" + "分享匿名的使用數據以協助我們釐清問題" + "您可以到 %1$s 閱讀我們的條款。" + "這裡" "封鎖使用者" diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index d6f9f2cbaf..2355e4b603 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -1,6 +1,5 @@ - "Use an identity server to invite by email. ""Use the default (%(defaultIdentityServerName)s)"" or manage in ""Settings""." "Hide password" "Mentions only" "Muted" @@ -37,6 +36,8 @@ "Learn more" "Leave" "Leave room" + "Manage account" + "Manage devices" "Next" "No" "Not now" @@ -47,6 +48,7 @@ "React" "Remove" "Reply" + "Reply in thread" "Report bug" "Report Content" "Retry" @@ -65,8 +67,12 @@ "Take photo" "View Source" "Yes" + "Ongoing call" + "Tap to return to the call" + "☎️ Call in progress" "About" "Acceptable use policy" + "Advanced settings" "Analytics" "Audio" "Bubbles" @@ -85,6 +91,7 @@ "Forward message" "GIF" "Image" + "In reply to %1$s" "This Matrix ID can\'t be found, so the invite might not be received." "Leaving room" "Link copied to clipboard" @@ -99,15 +106,16 @@ "Password" "People" "Permalink" - "Final votes: %1$s" "Total votes: %1$s" "Results will show after the poll has ended" "Privacy policy" + "Reaction" "Reactions" "Refreshing…" "Replying to %1$s" "Report a bug" "Report submitted" + "Rich text editor" "Room name" "e.g. your project name" "Search for someone" @@ -126,6 +134,7 @@ "Syncing" "Text" "Third-party notices" + "Thread" "Topic" "What is this room about?" "Unable to decrypt" @@ -162,10 +171,6 @@ "Are you sure that you want to leave this room? This room is not public and you won\'t be able to rejoin without an invite." "Are you sure that you want to leave the room?" "%1$s Android" - - "%(count)s room" - "%(count)s rooms" - "%1$d member" "%1$d members" @@ -195,6 +200,7 @@ "Toggle numbered list" "Open compose options" "Toggle quote" + "Remove link" "Unindent" "Link" "This is the beginning of %1$s." From 4e750d9c5abdfee1b17d0261236417bc5b02bcb5 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 14 Sep 2023 14:50:29 +0000 Subject: [PATCH 159/234] Update screenshots --- ...ll_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ll_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...l_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...l_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png index ee4debea8d..05ac81ce49 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a99b724ff8e90a48557c38909fe62d3fb1b260c3b5f6a57ac9f3b25879aad1ef -size 41532 +oid sha256:aed6ab34c685d32aa77e926c416621716acedd586eea2e76e51f1c51867be6cf +size 43419 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png index 6d6798e98a..66bf07e1ce 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1b87a3743ebe1fc4c5df49180b94652543c58d250184787ae3f32c0c713ffad8 -size 40858 +oid sha256:d4dce8dec2408bcf8e1e8a547689cdac25145d2fef603b21ff20ba2a40e181b1 +size 42741 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png index e57be18284..793b31326f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d4dd79afac67e5d7ada5b32dc2d9d21d7b56ae53a19d34775058df77d4abce30 -size 44169 +oid sha256:b01d7dcb16041285c2915b7572c16e39d199ac930ed0f6a69b1219bdf5d0ccd5 +size 46362 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png index 632a80ee03..399417d8ac 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:53b465eddb29226425e68f50de870d85477fb847fa5bb83b6294da11f682e2d0 -size 44036 +oid sha256:a9667115ed339726a09e7917737a6aa5698f4f03249f2704f162461775ddc20b +size 46229 From dec32ac10cf3f7b5a40c6071df382ac443340fdc Mon Sep 17 00:00:00 2001 From: David Langley Date: Thu, 14 Sep 2023 16:39:11 +0100 Subject: [PATCH 160/234] Only show green indicator for "All Messages" - Only show green indicator for "All Messages" as mentions doesn't work and we should never see it for muted rooms. - Remove code that tried to reflect the notificationsEnabled setting I mis-undertood the requirements by reading the iOS code. --- features/roomlist/impl/build.gradle.kts | 1 - .../impl/components/RoomSummaryRow.kt | 17 +++++---- .../impl/datasource/RoomListDataSource.kt | 36 +++++-------------- 3 files changed, 18 insertions(+), 36 deletions(-) diff --git a/features/roomlist/impl/build.gradle.kts b/features/roomlist/impl/build.gradle.kts index 3a3639de98..f5a08ba860 100644 --- a/features/roomlist/impl/build.gradle.kts +++ b/features/roomlist/impl/build.gradle.kts @@ -49,7 +49,6 @@ dependencies { implementation(projects.libraries.dateformatter.api) implementation(projects.libraries.eventformatter.api) implementation(projects.libraries.deeplink) - implementation(projects.libraries.pushstore.api) implementation(projects.features.invitelist.api) implementation(projects.features.networkmonitor.api) implementation(projects.features.leaveroom.api) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt index 61826dc2b2..33a8564efb 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt @@ -24,12 +24,10 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.RowScope -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width import androidx.compose.material.ripple.rememberRipple import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable @@ -154,7 +152,7 @@ private fun RowScope.NameAndTimestampRow(room: RoomListRoomSummary) { Text( text = room.timestamp ?: "", style = ElementTheme.typography.fontBodySmRegular, - color = if (room.hasUnread) { + color = if (room.shouldDisplayNotificationAlertDecoration) { ElementTheme.colors.unreadIndicator } else { MaterialTheme.roomListRoomMessageDate() @@ -184,7 +182,7 @@ private fun RowScope.LastMessageAndIndicatorRow(room: RoomListRoomSummary) { horizontalArrangement = Arrangement.spacedBy(8.dp) ) { NotificationIcon(room) - if (room.hasUnread) { + if (room.shouldDisplayNotificationAlertDecoration) { UnreadIndicatorAtom( modifier = Modifier.padding(top = 3.dp), ) @@ -192,23 +190,28 @@ private fun RowScope.LastMessageAndIndicatorRow(room: RoomListRoomSummary) { } } +// We should never show a green dot/icon for mute. Also mentions is not yet supported by the mobile app. +// In some cases a green @ was incorrectly shown when we switch from ALL_MESSAGES to MENTIONS_AND_KEYWORDS_ONLY +// and we don't know whether the room has mentions, just that it has unread. +private val RoomListRoomSummary.shouldDisplayNotificationAlertDecoration get() = hasUnread + && notificationMode != RoomNotificationMode.MUTE + && notificationMode != RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY @Composable private fun NotificationIcon(room: RoomListRoomSummary) { - val tint = if(room.hasUnread) ElementTheme.colors.unreadIndicator else ElementTheme.colors.iconQuaternary when(room.notificationMode) { null, RoomNotificationMode.ALL_MESSAGES -> return RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> Icon( contentDescription = stringResource(CommonStrings.screen_notification_settings_mode_mentions), imageVector = ImageVector.vectorResource(VectorIcons.Mention), - tint = tint, + tint = ElementTheme.colors.iconQuaternary, ) RoomNotificationMode.MUTE -> Icon( contentDescription = stringResource(CommonStrings.common_mute), imageVector = ImageVector.vectorResource(VectorIcons.Mute), - tint = tint, + tint = ElementTheme.colors.iconQuaternary, ) } } diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt index e0b20aada9..2cf28a6913 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt @@ -26,24 +26,19 @@ import io.element.android.libraries.dateformatter.api.LastMessageTimestampFormat import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter -import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.api.roomlist.RoomSummary -import io.element.android.libraries.pushstore.api.UserPushStoreFactory import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.debounce -import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.sync.Mutex @@ -59,8 +54,6 @@ class RoomListDataSource @Inject constructor( private val coroutineDispatchers: CoroutineDispatchers, notificationSettingsService: NotificationSettingsService, appScope: CoroutineScope, - userPushStoreFactory: UserPushStoreFactory, - matrixClient: MatrixClient, ) { init { notificationSettingsService.notificationSettingsChangeFlow @@ -69,13 +62,6 @@ class RoomListDataSource @Inject constructor( roomListService.rebuildRoomSummaries() } .launchIn(appScope) - - val userPushStore = userPushStoreFactory.create(matrixClient.sessionId) - userPushStore.getNotificationEnabledForDevice().distinctUntilChanged() - .onEach { - roomListService.rebuildRoomSummaries() - } - .launchIn(appScope) } private val _filter = MutableStateFlow("") private val _allRooms = MutableStateFlow>(persistentListOf()) @@ -86,15 +72,13 @@ class RoomListDataSource @Inject constructor( private val diffCacheUpdater = DiffCacheUpdater(diffCache = diffCache, detectMoves = true) { old, new -> old?.identifier() == new?.identifier() } - private val userPushStore = userPushStoreFactory.create(matrixClient.sessionId) fun launchIn(coroutineScope: CoroutineScope) { - roomListService .allRooms() .summaries .onEach { roomSummaries -> - replaceWith(roomSummaries, userPushStore.getNotificationEnabledForDevice().first()) + replaceWith(roomSummaries) } .launchIn(coroutineScope) @@ -121,14 +105,14 @@ class RoomListDataSource @Inject constructor( val allRooms: StateFlow> = _allRooms val filteredRooms: StateFlow> = _filteredRooms - private suspend fun replaceWith(roomSummaries: List, notificationsEnabled: Boolean) = withContext(coroutineDispatchers.computation) { + private suspend fun replaceWith(roomSummaries: List) = withContext(coroutineDispatchers.computation) { lock.withLock { diffCacheUpdater.updateWith(roomSummaries) - buildAndEmitAllRooms(roomSummaries, notificationsEnabled) + buildAndEmitAllRooms(roomSummaries) } } - private suspend fun buildAndEmitAllRooms(roomSummaries: List, notificationsEnabled: Boolean) { + private suspend fun buildAndEmitAllRooms(roomSummaries: List) { if (diffCache.isEmpty()) { _allRooms.emit( RoomListRoomSummaryPlaceholders.createFakeList(16).toImmutableList() @@ -138,7 +122,7 @@ class RoomListDataSource @Inject constructor( for (index in diffCache.indices()) { val cacheItem = diffCache.get(index) if (cacheItem == null) { - buildAndCacheItem(roomSummaries, index, notificationsEnabled)?.also { timelineItemState -> + buildAndCacheItem(roomSummaries, index)?.also { timelineItemState -> roomListRoomSummaries.add(timelineItemState) } } else { @@ -149,16 +133,12 @@ class RoomListDataSource @Inject constructor( } } - private fun buildAndCacheItem( - roomSummaries: List, - index: Int, - notificationsEnabled: Boolean, - ): RoomListRoomSummary? { + private fun buildAndCacheItem(roomSummaries: List, index: Int, ): RoomListRoomSummary? { val roomListRoomSummary = when (val roomSummary = roomSummaries.getOrNull(index)) { is RoomSummary.Empty -> RoomListRoomSummaryPlaceholders.create(roomSummary.identifier) is RoomSummary.Filled -> { - // Only show a decoration if notifications are enabled and the mode is not ALL_MESSAGES - val notificationMode = if (roomSummary.details.notificationMode == RoomNotificationMode.ALL_MESSAGES || !notificationsEnabled) { + // Only show a decoration if the mode is not ALL_MESSAGES + val notificationMode = if (roomSummary.details.notificationMode == RoomNotificationMode.ALL_MESSAGES) { null } else { roomSummary.details.notificationMode From 0e2a5e38ccd099c2ce1a79a7769927599f70b2e2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 14 Sep 2023 15:39:32 +0000 Subject: [PATCH 161/234] Update codecov/codecov-action action to v4 --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f662e5352d..2fdaa2195e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -81,6 +81,6 @@ jobs: # https://github.com/codecov/codecov-action - name: ☂️ Upload coverage reports to codecov if: always() - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 # with: # files: build/reports/kover/merged/xml/report.xml From 4e5036f962828686a4f17bb6e96013fe7c29adf9 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 14 Sep 2023 18:16:10 +0200 Subject: [PATCH 162/234] Avoid lint false positive. --- .../messages/impl/timeline/components/TimelineItemEventRow.kt | 4 ++-- .../io/element/android/libraries/designsystem/VectorIcons.kt | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index 51711db0ae..f492407690 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -76,7 +76,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemPollContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent -import io.element.android.libraries.designsystem.R +import io.element.android.libraries.designsystem.VectorIcons import io.element.android.libraries.designsystem.colors.AvatarColorsProvider import io.element.android.libraries.designsystem.components.EqualWidthColumn import io.element.android.libraries.designsystem.components.avatar.Avatar @@ -402,7 +402,7 @@ private fun MessageEventBubbleContent( horizontalArrangement = spacedBy(4.dp, Alignment.Start), verticalAlignment = Alignment.CenterVertically, ) { - Icon(resourceId = R.drawable.ic_thread_decoration, contentDescription = null, tint = ElementTheme.colors.iconSecondary) + Icon(resourceId = VectorIcons.ThreadDecoration, contentDescription = null, tint = ElementTheme.colors.iconSecondary) Text( text = stringResource(CommonStrings.common_thread), style = ElementTheme.typography.fontBodyXsRegular, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt index 20ebb85615..0194e86518 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt @@ -41,4 +41,5 @@ object VectorIcons { val Quote = R.drawable.ic_quote val Strikethrough = R.drawable.ic_strikethrough val Underline = R.drawable.ic_underline + val ThreadDecoration = R.drawable.ic_thread_decoration } From 15eb976ffb84f8965d5bffcfc1a3ce2df1fa09d0 Mon Sep 17 00:00:00 2001 From: jonnyandrew Date: Thu, 14 Sep 2023 17:32:15 +0100 Subject: [PATCH 163/234] [Rich text editor] Fix 'text formatting' option only partially visible (#1335) --- changelog.d/1335.bugfix | 1 + .../messages/impl/messagecomposer/AttachmentsBottomSheet.kt | 4 ++++ 2 files changed, 5 insertions(+) create mode 100644 changelog.d/1335.bugfix diff --git a/changelog.d/1335.bugfix b/changelog.d/1335.bugfix new file mode 100644 index 0000000000..c58683c695 --- /dev/null +++ b/changelog.d/1335.bugfix @@ -0,0 +1 @@ +[Rich text editor] Fix 'text formatting' option only partially visible \ No newline at end of file diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt index 8332018385..f7108fe951 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt @@ -31,6 +31,7 @@ import androidx.compose.material.icons.filled.LocationOn import androidx.compose.material.icons.filled.PhotoCamera import androidx.compose.material.icons.filled.Videocam import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -84,6 +85,9 @@ internal fun AttachmentsBottomSheet( if (isVisible) { ModalBottomSheet( modifier = modifier, + sheetState = rememberModalBottomSheetState( + skipPartiallyExpanded = true + ), onDismissRequest = { isVisible = false } ) { AttachmentSourcePickerMenu( From 6ff9e802fcc4062c834548f93ea1564d64eeac24 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 14 Sep 2023 18:49:51 +0200 Subject: [PATCH 164/234] Change `implementation` to `testImplementation` on a test module. --- features/preferences/impl/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/preferences/impl/build.gradle.kts b/features/preferences/impl/build.gradle.kts index e2df4cfa9a..336388772c 100644 --- a/features/preferences/impl/build.gradle.kts +++ b/features/preferences/impl/build.gradle.kts @@ -41,7 +41,6 @@ dependencies { implementation(projects.libraries.featureflag.ui) implementation(projects.libraries.network) implementation(projects.libraries.pushstore.api) - implementation(projects.libraries.pushstore.test) implementation(projects.libraries.testtags) implementation(projects.libraries.uiStrings) implementation(projects.features.rageshake.api) @@ -65,6 +64,7 @@ dependencies { testImplementation(libs.test.turbine) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.featureflag.test) + testImplementation(projects.libraries.pushstore.test) testImplementation(projects.features.rageshake.test) testImplementation(projects.features.rageshake.impl) testImplementation(projects.features.logout.impl) From 2d9cdd1acfabcd11ea17cd7bb306b856a079af40 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 14 Sep 2023 10:25:39 +0200 Subject: [PATCH 165/234] Add Advanced Settings screen in the preferences. --- features/preferences/impl/build.gradle.kts | 2 + .../preferences/impl/PreferencesFlowNode.kt | 13 +++- .../impl/advanced/AdvancedSettingsEvents.kt | 22 ++++++ .../impl/advanced/AdvancedSettingsNode.kt | 45 +++++++++++ .../advanced/AdvancedSettingsPresenter.kt | 59 +++++++++++++++ .../impl/advanced/AdvancedSettingsState.kt | 23 ++++++ .../advanced/AdvancedSettingsStateProvider.kt | 37 +++++++++ .../impl/advanced/AdvancedSettingsView.kt | 63 ++++++++++++++++ .../impl/root/PreferencesRootNode.kt | 6 ++ .../impl/root/PreferencesRootView.kt | 10 +++ libraries/preferences/api/build.gradle.kts | 27 +++++++ .../preferences/api/store/PreferencesStore.kt | 29 +++++++ libraries/preferences/impl/build.gradle.kts | 36 +++++++++ .../impl/store/DefaultPreferencesStore.kt | 75 +++++++++++++++++++ libraries/preferences/test/build.gradle.kts | 28 +++++++ .../test/InMemoryPreferencesStore.kt | 49 ++++++++++++ .../kotlin/extension/DependencyHandleScope.kt | 1 + 17 files changed, 524 insertions(+), 1 deletion(-) create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsEvents.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsNode.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenter.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsState.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsStateProvider.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsView.kt create mode 100644 libraries/preferences/api/build.gradle.kts create mode 100644 libraries/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/store/PreferencesStore.kt create mode 100644 libraries/preferences/impl/build.gradle.kts create mode 100644 libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultPreferencesStore.kt create mode 100644 libraries/preferences/test/build.gradle.kts create mode 100644 libraries/preferences/test/src/main/kotlin/io/element/android/libraries/featureflag/test/InMemoryPreferencesStore.kt diff --git a/features/preferences/impl/build.gradle.kts b/features/preferences/impl/build.gradle.kts index e2df4cfa9a..447adb5fa3 100644 --- a/features/preferences/impl/build.gradle.kts +++ b/features/preferences/impl/build.gradle.kts @@ -42,6 +42,7 @@ dependencies { implementation(projects.libraries.network) implementation(projects.libraries.pushstore.api) implementation(projects.libraries.pushstore.test) + implementation(projects.libraries.preferences.api) implementation(projects.libraries.testtags) implementation(projects.libraries.uiStrings) implementation(projects.features.rageshake.api) @@ -55,6 +56,7 @@ dependencies { implementation(libs.accompanist.placeholder) implementation(libs.coil.compose) implementation(libs.androidx.browser) + implementation(libs.androidx.datastore.preferences) api(projects.features.preferences.api) ksp(libs.showkase.processor) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt index 85ae3ac55f..238b4006e7 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt @@ -31,11 +31,12 @@ import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode import io.element.android.features.preferences.api.PreferencesEntryPoint import io.element.android.features.preferences.impl.about.AboutNode +import io.element.android.features.preferences.impl.advanced.AdvancedSettingsNode import io.element.android.features.preferences.impl.analytics.AnalyticsSettingsNode import io.element.android.features.preferences.impl.developer.DeveloperSettingsNode +import io.element.android.features.preferences.impl.developer.tracing.ConfigureTracingNode import io.element.android.features.preferences.impl.notifications.NotificationSettingsNode import io.element.android.features.preferences.impl.notifications.edit.EditDefaultNotificationSettingNode -import io.element.android.features.preferences.impl.developer.tracing.ConfigureTracingNode import io.element.android.features.preferences.impl.root.PreferencesRootNode import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler @@ -63,6 +64,9 @@ class PreferencesFlowNode @AssistedInject constructor( @Parcelize data object DeveloperSettings : NavTarget + @Parcelize + data object AdvancedSettings : NavTarget + @Parcelize data object ConfigureTracing : NavTarget @@ -106,6 +110,10 @@ class PreferencesFlowNode @AssistedInject constructor( override fun onOpenNotificationSettings() { backstack.push(NavTarget.NotificationSettings) } + + override fun onOpenAdvancedSettings() { + backstack.push(NavTarget.AdvancedSettings) + } } createNode(buildContext, plugins = listOf(callback)) } @@ -138,6 +146,9 @@ class PreferencesFlowNode @AssistedInject constructor( val input = EditDefaultNotificationSettingNode.Inputs(navTarget.isOneToOne) createNode(buildContext, plugins = listOf(input)) } + NavTarget.AdvancedSettings -> { + createNode(buildContext) + } } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsEvents.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsEvents.kt new file mode 100644 index 0000000000..37641d684c --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsEvents.kt @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.advanced + +sealed interface AdvancedSettingsEvents { + data class SetRichTextEditorEnabled(val enabled: Boolean) : AdvancedSettingsEvents + data class SetDeveloperModeEnabled(val enabled: Boolean) : AdvancedSettingsEvents +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsNode.kt new file mode 100644 index 0000000000..f7f0fd2eb8 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsNode.kt @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.advanced + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode +import io.element.android.libraries.di.SessionScope + +@ContributesNode(SessionScope::class) +class AdvancedSettingsNode @AssistedInject constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + private val presenter: AdvancedSettingsPresenter, +) : Node(buildContext, plugins = plugins) { + + @Composable + override fun View(modifier: Modifier) { + val state = presenter.present() + AdvancedSettingsView( + state = state, + modifier = modifier, + onBackPressed = ::navigateUp + ) + } +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenter.kt new file mode 100644 index 0000000000..b30ca63dc8 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenter.kt @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.advanced + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.rememberCoroutineScope +import io.element.android.features.preferences.api.store.PreferencesStore +import io.element.android.libraries.architecture.Presenter +import kotlinx.coroutines.launch +import javax.inject.Inject + +class AdvancedSettingsPresenter @Inject constructor( + private val preferencesStore: PreferencesStore, +) : Presenter { + + @Composable + override fun present(): AdvancedSettingsState { + val localCoroutineScope = rememberCoroutineScope() + val isRichTextEditorEnabled by preferencesStore + .isRichTextEditorEnabledFlow() + .collectAsState(initial = false) + val isDeveloperModeEnabled by preferencesStore + .isDevelopModeEnabledFlow() + .collectAsState(initial = false) + + fun handleEvents(event: AdvancedSettingsEvents) { + when (event) { + is AdvancedSettingsEvents.SetRichTextEditorEnabled -> localCoroutineScope.launch { + preferencesStore.setRichTextEditorEnabled(event.enabled) + } + is AdvancedSettingsEvents.SetDeveloperModeEnabled -> localCoroutineScope.launch { + preferencesStore.setDevelopModeEnabled(event.enabled) + } + } + } + + return AdvancedSettingsState( + isRichTextEditorEnabled = isRichTextEditorEnabled, + isDeveloperModeEnabled = isDeveloperModeEnabled, + eventSink = ::handleEvents + ) + } +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsState.kt new file mode 100644 index 0000000000..19625b9ebc --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsState.kt @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.advanced + +data class AdvancedSettingsState constructor( + val isRichTextEditorEnabled: Boolean, + val isDeveloperModeEnabled: Boolean, + val eventSink: (AdvancedSettingsEvents) -> Unit +) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsStateProvider.kt new file mode 100644 index 0000000000..5ab50c8a16 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsStateProvider.kt @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.advanced + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider + +open class AdvancedSettingsStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + aAdvancedSettingsState(), + aAdvancedSettingsState(isRichTextEditorEnabled = true), + aAdvancedSettingsState(isDeveloperModeEnabled = true), + ) +} + +fun aAdvancedSettingsState( + isRichTextEditorEnabled: Boolean = false, + isDeveloperModeEnabled: Boolean = false, +) = AdvancedSettingsState( + isRichTextEditorEnabled = isRichTextEditorEnabled, + isDeveloperModeEnabled = isDeveloperModeEnabled, + eventSink = {} +) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsView.kt new file mode 100644 index 0000000000..cff1454594 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsView.kt @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.advanced + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.PreviewParameter +import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch +import io.element.android.libraries.designsystem.components.preferences.PreferenceView +import io.element.android.libraries.designsystem.preview.DayNightPreviews +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.ui.strings.CommonStrings + +@Composable +fun AdvancedSettingsView( + state: AdvancedSettingsState, + onBackPressed: () -> Unit, + modifier: Modifier = Modifier, +) { + PreferenceView( + modifier = modifier, + onBackPressed = onBackPressed, + title = stringResource(id = CommonStrings.common_advanced_settings) + ) { + PreferenceSwitch( + title = stringResource(id = CommonStrings.common_rich_text_editor), + // TODO i18n + subtitle = "Disable the rich text editor to type Markdown manually", + isChecked = state.isRichTextEditorEnabled, + onCheckedChange = { state.eventSink(AdvancedSettingsEvents.SetRichTextEditorEnabled(it)) }, + ) + PreferenceSwitch( + // TODO i18n + title = "Developer mode", + // TODO i18n + subtitle = "The developer mode activates hidden features. For developers only!", + isChecked = state.isDeveloperModeEnabled, + onCheckedChange = { state.eventSink(AdvancedSettingsEvents.SetDeveloperModeEnabled(it)) }, + ) + } +} + +@DayNightPreviews +@Composable +internal fun AdvancedSettingsViewPreview(@PreviewParameter(AdvancedSettingsStateProvider::class) state: AdvancedSettingsState) = + ElementPreview { + AdvancedSettingsView(state = state, onBackPressed = { }) + } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt index 5226d55b6b..b4495d8899 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt @@ -46,6 +46,7 @@ class PreferencesRootNode @AssistedInject constructor( fun onOpenAbout() fun onOpenDeveloperSettings() fun onOpenNotificationSettings() + fun onOpenAdvancedSettings() } private fun onOpenBugReport() { @@ -60,6 +61,10 @@ class PreferencesRootNode @AssistedInject constructor( plugins().forEach { it.onOpenDeveloperSettings() } } + private fun onOpenAdvancedSettings() { + plugins().forEach { it.onOpenAdvancedSettings() } + } + private fun onOpenAnalytics() { plugins().forEach { it.onOpenAnalytics() } } @@ -100,6 +105,7 @@ class PreferencesRootNode @AssistedInject constructor( onOpenAbout = this::onOpenAbout, onVerifyClicked = this::onVerifyClicked, onOpenDeveloperSettings = this::onOpenDeveloperSettings, + onOpenAdvancedSettings = this::onOpenAdvancedSettings, onSuccessLogout = { onSuccessLogout(activity, it) }, onManageAccountClicked = { onManageAccountClicked(activity, it, isDark) }, onOpenNotificationSettings = this::onOpenNotificationSettings 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 3d901c4617..c6d34c6969 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt @@ -25,6 +25,7 @@ import androidx.compose.material.icons.outlined.Help import androidx.compose.material.icons.outlined.InsertChart import androidx.compose.material.icons.outlined.Notifications import androidx.compose.material.icons.outlined.OpenInNew +import androidx.compose.material.icons.outlined.Settings import androidx.compose.material.icons.outlined.VerifiedUser import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -58,6 +59,7 @@ fun PreferencesRootView( onOpenRageShake: () -> Unit, onOpenAbout: () -> Unit, onOpenDeveloperSettings: () -> Unit, + onOpenAdvancedSettings: () -> Unit, onSuccessLogout: (logoutUrlResult: String?) -> Unit, onOpenNotificationSettings: () -> Unit, modifier: Modifier = Modifier, @@ -125,6 +127,13 @@ fun PreferencesRootView( DeveloperPreferencesView(onOpenDeveloperSettings) HorizontalDivider() } + HorizontalDivider() + PreferenceText( + title = stringResource(id = CommonStrings.common_advanced_settings), + icon = Icons.Outlined.Settings, + onClick = onOpenAdvancedSettings, + ) + HorizontalDivider() LogoutPreferenceView( state = state.logoutState, onSuccessLogout = onSuccessLogout, @@ -168,6 +177,7 @@ private fun ContentToPreview(matrixUser: MatrixUser) { onOpenAnalytics = {}, onOpenRageShake = {}, onOpenDeveloperSettings = {}, + onOpenAdvancedSettings = {}, onOpenAbout = {}, onVerifyClicked = {}, onSuccessLogout = {}, diff --git a/libraries/preferences/api/build.gradle.kts b/libraries/preferences/api/build.gradle.kts new file mode 100644 index 0000000000..f782dd328b --- /dev/null +++ b/libraries/preferences/api/build.gradle.kts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + id("io.element.android-library") +} + +android { + namespace = "io.element.android.libraries.preferences.api" +} + +dependencies { + implementation(libs.coroutines.core) +} diff --git a/libraries/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/store/PreferencesStore.kt b/libraries/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/store/PreferencesStore.kt new file mode 100644 index 0000000000..57ad7859c1 --- /dev/null +++ b/libraries/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/store/PreferencesStore.kt @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.api.store + +import kotlinx.coroutines.flow.Flow + +interface PreferencesStore { + suspend fun setRichTextEditorEnabled(enabled: Boolean) + fun isRichTextEditorEnabledFlow(): Flow + + suspend fun setDevelopModeEnabled(enabled: Boolean) + fun isDevelopModeEnabledFlow(): Flow + + suspend fun reset() +} diff --git a/libraries/preferences/impl/build.gradle.kts b/libraries/preferences/impl/build.gradle.kts new file mode 100644 index 0000000000..9c31d83481 --- /dev/null +++ b/libraries/preferences/impl/build.gradle.kts @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + id("io.element.android-library") + alias(libs.plugins.anvil) +} + +android { + namespace = "io.element.android.libraries.preferences.impl" +} + +anvil { + generateDaggerFactories.set(true) +} + +dependencies { + api(projects.libraries.preferences.api) + implementation(libs.dagger) + implementation(libs.androidx.datastore.preferences) + implementation(projects.libraries.di) + implementation(projects.libraries.core) +} diff --git a/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultPreferencesStore.kt b/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultPreferencesStore.kt new file mode 100644 index 0000000000..5b0cbfb9ee --- /dev/null +++ b/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultPreferencesStore.kt @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.preferences.impl.store + +import android.content.Context +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.core.booleanPreferencesKey +import androidx.datastore.preferences.core.edit +import androidx.datastore.preferences.preferencesDataStore +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.features.preferences.api.store.PreferencesStore +import io.element.android.libraries.core.bool.orFalse +import io.element.android.libraries.core.bool.orTrue +import io.element.android.libraries.di.AppScope +import io.element.android.libraries.di.ApplicationContext +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +import javax.inject.Inject + +private val Context.dataStore: DataStore by preferencesDataStore(name = "elementx_preferences") + +private val richTextEditorKey = booleanPreferencesKey("richTextEditor") +private val developerModeKey = booleanPreferencesKey("developerMode") + +@ContributesBinding(AppScope::class) +class DefaultPreferencesStore @Inject constructor( + @ApplicationContext context: Context +) : PreferencesStore { + private val store = context.dataStore + + override suspend fun setRichTextEditorEnabled(enabled: Boolean) { + store.edit { prefs -> + prefs[richTextEditorKey] = enabled + } + } + + override fun isRichTextEditorEnabledFlow(): Flow { + return store.data.map { prefs -> + // enabled by default + prefs[richTextEditorKey].orTrue() + } + } + + override suspend fun setDevelopModeEnabled(enabled: Boolean) { + store.edit { prefs -> + prefs[developerModeKey] = enabled + } + } + + override fun isDevelopModeEnabledFlow(): Flow { + return store.data.map { prefs -> + // disabled by default + prefs[developerModeKey].orFalse() + } + } + + override suspend fun reset() { + store.edit { it.clear() } + } +} diff --git a/libraries/preferences/test/build.gradle.kts b/libraries/preferences/test/build.gradle.kts new file mode 100644 index 0000000000..86b891b21e --- /dev/null +++ b/libraries/preferences/test/build.gradle.kts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + id("io.element.android-library") +} + +android { + namespace = "io.element.android.libraries.preferences.test" + + dependencies { + api(projects.libraries.preferences.api) + implementation(libs.coroutines.core) + } +} diff --git a/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/featureflag/test/InMemoryPreferencesStore.kt b/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/featureflag/test/InMemoryPreferencesStore.kt new file mode 100644 index 0000000000..550713747e --- /dev/null +++ b/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/featureflag/test/InMemoryPreferencesStore.kt @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.featureflag.test + +import io.element.android.features.preferences.api.store.PreferencesStore +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow + +class InMemoryPreferencesStore( + isRichTextEditorEnabled: Boolean = false, + isDeveloperModeEnabled: Boolean = false, +) : PreferencesStore { + private var _isRichTextEditorEnabled = MutableStateFlow(isRichTextEditorEnabled) + private var _isDeveloperModeEnabled = MutableStateFlow(isDeveloperModeEnabled) + + override suspend fun setRichTextEditorEnabled(enabled: Boolean) { + _isRichTextEditorEnabled.value = enabled + } + + override fun isRichTextEditorEnabledFlow(): Flow { + return _isRichTextEditorEnabled + } + + override suspend fun setDevelopModeEnabled(enabled: Boolean) { + _isDeveloperModeEnabled.value = enabled + } + + override fun isDevelopModeEnabledFlow(): Flow { + return _isDeveloperModeEnabled + } + + override suspend fun reset() { + // No op + } +} diff --git a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt index 592cf3c52a..1029100823 100644 --- a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt +++ b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt @@ -92,6 +92,7 @@ fun DependencyHandlerScope.allLibrariesImpl() { implementation(project(":libraries:pushproviders:unifiedpush")) implementation(project(":libraries:featureflag:impl")) implementation(project(":libraries:pushstore:impl")) + implementation(project(":libraries:preferences:impl")) implementation(project(":libraries:architecture")) implementation(project(":libraries:dateformatter:impl")) implementation(project(":libraries:di")) From 657ac05e01d6f817c2afb636e1801acb7e956020 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 14 Sep 2023 11:26:02 +0200 Subject: [PATCH 166/234] Remove feature flag RichTextEditor, it's replaced by an advanced settings. --- features/messages/impl/build.gradle.kts | 2 ++ .../messages/impl/MessagesPresenter.kt | 28 +++++++++++-------- .../messages/MessagesPresenterTest.kt | 7 +++-- .../libraries/featureflag/api/FeatureFlags.kt | 5 ---- .../impl/StaticFeatureFlagProvider.kt | 1 - 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/features/messages/impl/build.gradle.kts b/features/messages/impl/build.gradle.kts index 00d65eba6a..cd0b6dda2d 100644 --- a/features/messages/impl/build.gradle.kts +++ b/features/messages/impl/build.gradle.kts @@ -48,6 +48,7 @@ dependencies { implementation(projects.libraries.mediapickers.api) implementation(projects.libraries.featureflag.api) implementation(projects.libraries.mediaupload.api) + implementation(projects.libraries.preferences.api) implementation(projects.features.networkmonitor.api) implementation(projects.services.analytics.api) implementation(libs.coil.compose) @@ -76,6 +77,7 @@ dependencies { testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.mediaupload.test) testImplementation(projects.libraries.mediapickers.test) + testImplementation(projects.libraries.preferences.test) testImplementation(projects.libraries.textcomposer.test) testImplementation(libs.test.mockk) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index 8c985d45d9..1636687d74 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -57,6 +57,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.utils.messagesummary.MessageSummaryFormatter import io.element.android.features.networkmonitor.api.NetworkMonitor import io.element.android.features.networkmonitor.api.NetworkStatus +import io.element.android.features.preferences.api.store.PreferencesStore import io.element.android.libraries.androidutils.clipboard.ClipboardHelper import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Presenter @@ -66,8 +67,6 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.utils.SnackbarDispatcher import io.element.android.libraries.designsystem.utils.SnackbarMessage import io.element.android.libraries.designsystem.utils.collectSnackbarMessageAsState -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState @@ -97,7 +96,7 @@ class MessagesPresenter @AssistedInject constructor( private val dispatchers: CoroutineDispatchers, private val clipboardHelper: ClipboardHelper, private val analyticsService: AnalyticsService, - private val featureFlagService: FeatureFlagService, + private val preferencesStore: PreferencesStore, @Assisted private val navigator: MessagesNavigator, ) : Presenter { @@ -146,15 +145,17 @@ class MessagesPresenter @AssistedInject constructor( timelineState.eventSink(TimelineEvents.SetHighlightedEvent(composerState.mode.relatedEventId)) } - var enableTextFormatting by remember { mutableStateOf(true) } - LaunchedEffect(Unit) { - enableTextFormatting = featureFlagService.isFeatureEnabled(FeatureFlags.RichTextEditor) - } + val enableTextFormatting by preferencesStore.isRichTextEditorEnabledFlow().collectAsState(initial = true) fun handleEvents(event: MessagesEvents) { when (event) { is MessagesEvents.HandleAction -> { - localCoroutineScope.handleTimelineAction(event.action, event.event, composerState) + localCoroutineScope.handleTimelineAction( + action = event.action, + targetEvent = event.event, + composerState = composerState, + enableTextFormatting = enableTextFormatting, + ) } is MessagesEvents.ToggleReaction -> { localCoroutineScope.toggleReaction(event.emoji, event.eventId) @@ -204,11 +205,12 @@ class MessagesPresenter @AssistedInject constructor( action: TimelineItemAction, targetEvent: TimelineItem.Event, composerState: MessageComposerState, + enableTextFormatting: Boolean, ) = launch { when (action) { TimelineItemAction.Copy -> handleCopyContents(targetEvent) TimelineItemAction.Redact -> handleActionRedact(targetEvent) - TimelineItemAction.Edit -> handleActionEdit(targetEvent, composerState) + TimelineItemAction.Edit -> handleActionEdit(targetEvent, composerState, enableTextFormatting) TimelineItemAction.Reply, TimelineItemAction.ReplyInThread -> handleActionReply(targetEvent, composerState) TimelineItemAction.Developer -> handleShowDebugInfoAction(targetEvent) @@ -260,11 +262,15 @@ class MessagesPresenter @AssistedInject constructor( } } - private suspend fun handleActionEdit(targetEvent: TimelineItem.Event, composerState: MessageComposerState) { + private suspend fun handleActionEdit( + targetEvent: TimelineItem.Event, + composerState: MessageComposerState, + enableTextFormatting: Boolean, + ) { val composerMode = MessageComposerMode.Edit( targetEvent.eventId, (targetEvent.content as? TimelineItemTextBasedContent)?.let { - if (featureFlagService.isFeatureEnabled(FeatureFlags.RichTextEditor)) { + if (enableTextFormatting) { it.htmlBody ?: it.body } else { it.body diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt index c9ef88f18c..cb455425a0 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt @@ -54,6 +54,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.utils.SnackbarDispatcher import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.test.FakeFeatureFlagService +import io.element.android.libraries.featureflag.test.InMemoryPreferencesStore import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState @@ -614,7 +615,7 @@ class MessagesPresenterTest { messageComposerContext = MessageComposerContextImpl(), richTextEditorStateFactory = TestRichTextEditorStateFactory(), - ) + ) val timelinePresenter = TimelinePresenter( timelineItemsFactory = aTimelineItemsFactory(), room = matrixRoom, @@ -627,7 +628,7 @@ class MessagesPresenterTest { val customReactionPresenter = CustomReactionPresenter(emojibaseProvider = FakeEmojibaseProvider()) val reactionSummaryPresenter = ReactionSummaryPresenter(room = matrixRoom) val retrySendMenuPresenter = RetrySendMenuPresenter(room = matrixRoom) - val featureFlagsService = FakeFeatureFlagService(mapOf(FeatureFlags.RichTextEditor.key to true)) + val preferencesStore = InMemoryPreferencesStore(isRichTextEditorEnabled = true) return MessagesPresenter( room = matrixRoom, composerPresenter = messageComposerPresenter, @@ -642,7 +643,7 @@ class MessagesPresenterTest { navigator = navigator, clipboardHelper = clipboardHelper, analyticsService = analyticsService, - featureFlagService = featureFlagsService, + preferencesStore = preferencesStore, dispatchers = coroutineDispatchers, ) } diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt index ca68b0cbd1..990aee3a93 100644 --- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt +++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt @@ -43,9 +43,4 @@ enum class FeatureFlags( title = "Show notification settings", defaultValue = true, ), - RichTextEditor( - key = "feature.richtexteditor", - title = "Enable rich text editor", - defaultValue = true, - ), } diff --git a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/StaticFeatureFlagProvider.kt b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/StaticFeatureFlagProvider.kt index d7759ac474..82184d510c 100644 --- a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/StaticFeatureFlagProvider.kt +++ b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/StaticFeatureFlagProvider.kt @@ -35,7 +35,6 @@ class StaticFeatureFlagProvider @Inject constructor() : FeatureFlags.LocationSharing -> true FeatureFlags.Polls -> true FeatureFlags.NotificationSettings -> true - FeatureFlags.RichTextEditor -> true } } else { false From 0424192834d726f512aada9a7be5721b0a34a9d6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 14 Sep 2023 11:35:58 +0200 Subject: [PATCH 167/234] Rename Developer -> ViewSource --- .../features/messages/impl/MessagesPresenter.kt | 2 +- .../impl/actionlist/ActionListPresenter.kt | 8 ++++---- .../impl/actionlist/ActionListStateProvider.kt | 4 ++-- .../impl/actionlist/model/TimelineItemAction.kt | 2 +- .../features/messages/MessagesPresenterTest.kt | 2 +- .../actionlist/ActionListPresenterTest.kt | 16 ++++++++-------- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index 1636687d74..1dc46aa2bd 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -213,7 +213,7 @@ class MessagesPresenter @AssistedInject constructor( TimelineItemAction.Edit -> handleActionEdit(targetEvent, composerState, enableTextFormatting) TimelineItemAction.Reply, TimelineItemAction.ReplyInThread -> handleActionReply(targetEvent, composerState) - TimelineItemAction.Developer -> handleShowDebugInfoAction(targetEvent) + TimelineItemAction.ViewSource -> handleShowDebugInfoAction(targetEvent) TimelineItemAction.Forward -> handleForwardAction(targetEvent) TimelineItemAction.ReportContent -> handleReportAction(targetEvent) TimelineItemAction.EndPoll -> handleEndPollAction(targetEvent) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt index e87523d702..2ba0230f85 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt @@ -86,7 +86,7 @@ class ActionListPresenter @Inject constructor( when (timelineItem.content) { is TimelineItemRedactedContent -> { if (buildMeta.isDebuggable) { - listOf(TimelineItemAction.Developer) + listOf(TimelineItemAction.ViewSource) } else { emptyList() } @@ -95,7 +95,7 @@ class ActionListPresenter @Inject constructor( buildList { add(TimelineItemAction.Copy) if (buildMeta.isDebuggable) { - add(TimelineItemAction.Developer) + add(TimelineItemAction.ViewSource) } } } @@ -116,7 +116,7 @@ class ActionListPresenter @Inject constructor( add(TimelineItemAction.Copy) } if (buildMeta.isDebuggable) { - add(TimelineItemAction.Developer) + add(TimelineItemAction.ViewSource) } if (!timelineItem.isMine) { add(TimelineItemAction.ReportContent) @@ -145,7 +145,7 @@ class ActionListPresenter @Inject constructor( add(TimelineItemAction.Copy) } if (buildMeta.isDebuggable) { - add(TimelineItemAction.Developer) + add(TimelineItemAction.ViewSource) } if (!timelineItem.isMine) { add(TimelineItemAction.ReportContent) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt index bb9c851288..44736bc076 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt @@ -111,7 +111,7 @@ fun aTimelineItemActionList(): ImmutableList { TimelineItemAction.Edit, TimelineItemAction.Redact, TimelineItemAction.ReportContent, - TimelineItemAction.Developer, + TimelineItemAction.ViewSource, ) } fun aTimelineItemPollActionList(): ImmutableList { @@ -119,7 +119,7 @@ fun aTimelineItemPollActionList(): ImmutableList { TimelineItemAction.EndPoll, TimelineItemAction.Reply, TimelineItemAction.Copy, - TimelineItemAction.Developer, + TimelineItemAction.ViewSource, TimelineItemAction.ReportContent, TimelineItemAction.Redact, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt index 331edfa1a5..948c0b0cb1 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/model/TimelineItemAction.kt @@ -34,7 +34,7 @@ sealed class TimelineItemAction( data object Reply : TimelineItemAction(CommonStrings.action_reply, VectorIcons.Reply) data object ReplyInThread : TimelineItemAction(CommonStrings.action_reply_in_thread, VectorIcons.Reply) data object Edit : TimelineItemAction(CommonStrings.action_edit, VectorIcons.Edit) - data object Developer : TimelineItemAction(CommonStrings.action_view_source, VectorIcons.DeveloperMode) + data object ViewSource : TimelineItemAction(CommonStrings.action_view_source, VectorIcons.DeveloperMode) data object ReportContent : TimelineItemAction(CommonStrings.action_report_content, VectorIcons.ReportContent, destructive = true) data object EndPoll : TimelineItemAction(CommonStrings.action_end_poll, VectorIcons.PollEnd) } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt index cb455425a0..9d37f39e85 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt @@ -365,7 +365,7 @@ class MessagesPresenterTest { presenter.present() }.test { val initialState = awaitItem() - initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Developer, aMessageEvent())) + initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.ViewSource, aMessageEvent())) assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None) assertThat(navigator.onShowEventDebugInfoClickedCount).isEqualTo(1) } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt index 2682a71207..f07fbd0091 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt @@ -71,7 +71,7 @@ class ActionListPresenterTest { ActionListState.Target.Success( messageEvent, persistentListOf( - TimelineItemAction.Developer, + TimelineItemAction.ViewSource, ) ) ) @@ -96,7 +96,7 @@ class ActionListPresenterTest { ActionListState.Target.Success( messageEvent, persistentListOf( - TimelineItemAction.Developer, + TimelineItemAction.ViewSource, ) ) ) @@ -127,7 +127,7 @@ class ActionListPresenterTest { TimelineItemAction.Reply, TimelineItemAction.Forward, TimelineItemAction.Copy, - TimelineItemAction.Developer, + TimelineItemAction.ViewSource, TimelineItemAction.ReportContent, ) ) @@ -158,7 +158,7 @@ class ActionListPresenterTest { persistentListOf( TimelineItemAction.Forward, TimelineItemAction.Copy, - TimelineItemAction.Developer, + TimelineItemAction.ViewSource, TimelineItemAction.ReportContent, ) ) @@ -188,7 +188,7 @@ class ActionListPresenterTest { TimelineItemAction.Reply, TimelineItemAction.Forward, TimelineItemAction.Copy, - TimelineItemAction.Developer, + TimelineItemAction.ViewSource, TimelineItemAction.ReportContent, TimelineItemAction.Redact, ) @@ -222,7 +222,7 @@ class ActionListPresenterTest { TimelineItemAction.Forward, TimelineItemAction.Edit, TimelineItemAction.Copy, - TimelineItemAction.Developer, + TimelineItemAction.ViewSource, TimelineItemAction.Redact, ) ) @@ -253,7 +253,7 @@ class ActionListPresenterTest { persistentListOf( TimelineItemAction.Reply, TimelineItemAction.Forward, - TimelineItemAction.Developer, + TimelineItemAction.ViewSource, TimelineItemAction.Redact, ) ) @@ -283,7 +283,7 @@ class ActionListPresenterTest { stateEvent, persistentListOf( TimelineItemAction.Copy, - TimelineItemAction.Developer, + TimelineItemAction.ViewSource, ) ) ) From 7d9b865575482b334ce8041cca3422df42ed7e5c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 14 Sep 2023 14:11:53 +0200 Subject: [PATCH 168/234] Show "View Event" if the developer mode is enabled. --- .../impl/actionlist/ActionListPresenter.kt | 17 ++++++--- .../messages/MessagesPresenterTest.kt | 6 +-- .../actionlist/ActionListPresenterTest.kt | 37 ++++++++++--------- 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt index 2ba0230f85..4bcccd3d25 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt @@ -18,6 +18,7 @@ package io.element.android.features.messages.impl.actionlist import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -30,15 +31,15 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent import io.element.android.features.messages.impl.timeline.model.event.canBeCopied import io.element.android.features.messages.impl.timeline.model.event.canReact +import io.element.android.features.preferences.api.store.PreferencesStore import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.core.meta.BuildMeta import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import javax.inject.Inject class ActionListPresenter @Inject constructor( - private val buildMeta: BuildMeta, + private val preferencesStore: PreferencesStore, ) : Presenter { @Composable @@ -49,6 +50,8 @@ class ActionListPresenter @Inject constructor( mutableStateOf(ActionListState.Target.None) } + val isDeveloperModeEnabled by preferencesStore.isDevelopModeEnabledFlow().collectAsState(initial = false) + val displayEmojiReactions by remember { derivedStateOf { val event = (target.value as? ActionListState.Target.Success)?.event @@ -63,6 +66,7 @@ class ActionListPresenter @Inject constructor( timelineItem = event.event, userCanRedact = event.canRedact, userCanSendMessage = event.canSendMessage, + isDeveloperModeEnabled = isDeveloperModeEnabled, target = target, ) } @@ -79,13 +83,14 @@ class ActionListPresenter @Inject constructor( timelineItem: TimelineItem.Event, userCanRedact: Boolean, userCanSendMessage: Boolean, + isDeveloperModeEnabled: Boolean, target: MutableState ) = launch { target.value = ActionListState.Target.Loading(timelineItem) val actions = when (timelineItem.content) { is TimelineItemRedactedContent -> { - if (buildMeta.isDebuggable) { + if (isDeveloperModeEnabled) { listOf(TimelineItemAction.ViewSource) } else { emptyList() @@ -94,7 +99,7 @@ class ActionListPresenter @Inject constructor( is TimelineItemStateContent -> { buildList { add(TimelineItemAction.Copy) - if (buildMeta.isDebuggable) { + if (isDeveloperModeEnabled) { add(TimelineItemAction.ViewSource) } } @@ -115,7 +120,7 @@ class ActionListPresenter @Inject constructor( if (timelineItem.content.canBeCopied()) { add(TimelineItemAction.Copy) } - if (buildMeta.isDebuggable) { + if (isDeveloperModeEnabled) { add(TimelineItemAction.ViewSource) } if (!timelineItem.isMine) { @@ -144,7 +149,7 @@ class ActionListPresenter @Inject constructor( if (timelineItem.content.canBeCopied()) { add(TimelineItemAction.Copy) } - if (buildMeta.isDebuggable) { + if (isDeveloperModeEnabled) { add(TimelineItemAction.ViewSource) } if (!timelineItem.isMine) { diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt index 9d37f39e85..db2abcc1dd 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt @@ -65,7 +65,6 @@ import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_ROOM_ID 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.core.aBuildMeta import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.libraries.matrix.test.room.aRoomMember import io.element.android.libraries.mediapickers.test.FakePickerProvider @@ -623,12 +622,11 @@ class MessagesPresenterTest { appScope = this, analyticsService = analyticsService, ) - val buildMeta = aBuildMeta() - val actionListPresenter = ActionListPresenter(buildMeta = buildMeta) + val preferencesStore = InMemoryPreferencesStore(isRichTextEditorEnabled = true) + val actionListPresenter = ActionListPresenter(preferencesStore = preferencesStore) val customReactionPresenter = CustomReactionPresenter(emojibaseProvider = FakeEmojibaseProvider()) val reactionSummaryPresenter = ReactionSummaryPresenter(room = matrixRoom) val retrySendMenuPresenter = RetrySendMenuPresenter(room = matrixRoom) - val preferencesStore = InMemoryPreferencesStore(isRichTextEditorEnabled = true) return MessagesPresenter( room = matrixRoom, composerPresenter = messageComposerPresenter, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt index f07fbd0091..316e39317e 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt @@ -31,8 +31,8 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemPollContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemStateEventContent +import io.element.android.libraries.featureflag.test.InMemoryPreferencesStore import io.element.android.libraries.matrix.test.A_MESSAGE -import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.tests.testutils.WarmUpRule import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.test.runTest @@ -46,7 +46,7 @@ class ActionListPresenterTest { @Test fun `present - initial state`() = runTest { - val presenter = anActionListPresenter(isBuildDebuggable = true) + val presenter = anActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -57,7 +57,7 @@ class ActionListPresenterTest { @Test fun `present - compute for message from me redacted`() = runTest { - val presenter = anActionListPresenter(isBuildDebuggable = true) + val presenter = anActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -82,7 +82,7 @@ class ActionListPresenterTest { @Test fun `present - compute for message from others redacted`() = runTest { - val presenter = anActionListPresenter(isBuildDebuggable = true) + val presenter = anActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -107,7 +107,7 @@ class ActionListPresenterTest { @Test fun `present - compute for others message`() = runTest { - val presenter = anActionListPresenter(isBuildDebuggable = true) + val presenter = anActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -139,7 +139,7 @@ class ActionListPresenterTest { @Test fun `present - compute for others message cannot sent message`() = runTest { - val presenter = anActionListPresenter(isBuildDebuggable = true) + val presenter = anActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -170,7 +170,7 @@ class ActionListPresenterTest { @Test fun `present - compute for others message and can redact`() = runTest { - val presenter = anActionListPresenter(isBuildDebuggable = true) + val presenter = anActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -201,7 +201,7 @@ class ActionListPresenterTest { @Test fun `present - compute for my message`() = runTest { - val presenter = anActionListPresenter(isBuildDebuggable = true) + val presenter = anActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -234,7 +234,7 @@ class ActionListPresenterTest { @Test fun `present - compute for a media item`() = runTest { - val presenter = anActionListPresenter(isBuildDebuggable = true) + val presenter = anActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -265,7 +265,7 @@ class ActionListPresenterTest { @Test fun `present - compute for a state item in debug build`() = runTest { - val presenter = anActionListPresenter(isBuildDebuggable = true) + val presenter = anActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -294,7 +294,7 @@ class ActionListPresenterTest { @Test fun `present - compute for a state item in non-debuggable build`() = runTest { - val presenter = anActionListPresenter(isBuildDebuggable = false) + val presenter = anActionListPresenter(isDeveloperModeEnabled = false) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -322,7 +322,7 @@ class ActionListPresenterTest { @Test fun `present - compute message in non-debuggable build`() = runTest { - val presenter = anActionListPresenter(isBuildDebuggable = false) + val presenter = anActionListPresenter(isDeveloperModeEnabled = false) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -354,7 +354,7 @@ class ActionListPresenterTest { @Test fun `present - compute message with no actions`() = runTest { - val presenter = anActionListPresenter(isBuildDebuggable = false) + val presenter = anActionListPresenter(isDeveloperModeEnabled = false) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -381,7 +381,7 @@ class ActionListPresenterTest { @Test fun `present - compute not sent message`() = runTest { - val presenter = anActionListPresenter(isBuildDebuggable = false) + val presenter = anActionListPresenter(isDeveloperModeEnabled = false) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -410,7 +410,7 @@ class ActionListPresenterTest { @Test fun `present - compute for poll message`() = runTest { - val presenter = anActionListPresenter(isBuildDebuggable = false) + val presenter = anActionListPresenter(isDeveloperModeEnabled = false) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -436,7 +436,7 @@ class ActionListPresenterTest { @Test fun `present - compute for ended poll message`() = runTest { - val presenter = anActionListPresenter(isBuildDebuggable = false) + val presenter = anActionListPresenter(isDeveloperModeEnabled = false) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -460,5 +460,8 @@ class ActionListPresenterTest { } } -private fun anActionListPresenter(isBuildDebuggable: Boolean) = ActionListPresenter(buildMeta = aBuildMeta(isDebuggable = isBuildDebuggable)) +private fun anActionListPresenter(isDeveloperModeEnabled: Boolean): ActionListPresenter { + val preferencesStore = InMemoryPreferencesStore(isDeveloperModeEnabled = isDeveloperModeEnabled) + return ActionListPresenter(preferencesStore = preferencesStore) +} From 4fe2f7a64bd0181e4cd82b5880f786b6276e391a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 14 Sep 2023 14:17:30 +0200 Subject: [PATCH 169/234] Developer mode on for debug build. --- .../preferences/impl/store/DefaultPreferencesStore.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultPreferencesStore.kt b/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultPreferencesStore.kt index 5b0cbfb9ee..4d2465a1a0 100644 --- a/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultPreferencesStore.kt +++ b/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultPreferencesStore.kt @@ -24,8 +24,9 @@ import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.preferencesDataStore import com.squareup.anvil.annotations.ContributesBinding import io.element.android.features.preferences.api.store.PreferencesStore -import io.element.android.libraries.core.bool.orFalse import io.element.android.libraries.core.bool.orTrue +import io.element.android.libraries.core.meta.BuildMeta +import io.element.android.libraries.core.meta.BuildType import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.ApplicationContext import kotlinx.coroutines.flow.Flow @@ -39,7 +40,8 @@ private val developerModeKey = booleanPreferencesKey("developerMode") @ContributesBinding(AppScope::class) class DefaultPreferencesStore @Inject constructor( - @ApplicationContext context: Context + @ApplicationContext context: Context, + private val buildMeta: BuildMeta, ) : PreferencesStore { private val store = context.dataStore @@ -64,8 +66,8 @@ class DefaultPreferencesStore @Inject constructor( override fun isDevelopModeEnabledFlow(): Flow { return store.data.map { prefs -> - // disabled by default - prefs[developerModeKey].orFalse() + // disabled by default on release and nightly, enabled by default on debug + prefs[developerModeKey] ?: (buildMeta.buildType == BuildType.DEBUG) } } From 32f41414803ae35a3f6a066ea8180c64fb00885c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 14 Sep 2023 14:18:28 +0200 Subject: [PATCH 170/234] Fix typo in fun names. --- .../features/messages/impl/actionlist/ActionListPresenter.kt | 2 +- .../preferences/impl/advanced/AdvancedSettingsPresenter.kt | 4 ++-- .../features/preferences/api/store/PreferencesStore.kt | 4 ++-- .../preferences/impl/store/DefaultPreferencesStore.kt | 4 ++-- .../libraries/featureflag/test/InMemoryPreferencesStore.kt | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt index 4bcccd3d25..588adb1020 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt @@ -50,7 +50,7 @@ class ActionListPresenter @Inject constructor( mutableStateOf(ActionListState.Target.None) } - val isDeveloperModeEnabled by preferencesStore.isDevelopModeEnabledFlow().collectAsState(initial = false) + val isDeveloperModeEnabled by preferencesStore.isDeveloperModeEnabledFlow().collectAsState(initial = false) val displayEmojiReactions by remember { derivedStateOf { diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenter.kt index b30ca63dc8..5738fe43c8 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenter.kt @@ -36,7 +36,7 @@ class AdvancedSettingsPresenter @Inject constructor( .isRichTextEditorEnabledFlow() .collectAsState(initial = false) val isDeveloperModeEnabled by preferencesStore - .isDevelopModeEnabledFlow() + .isDeveloperModeEnabledFlow() .collectAsState(initial = false) fun handleEvents(event: AdvancedSettingsEvents) { @@ -45,7 +45,7 @@ class AdvancedSettingsPresenter @Inject constructor( preferencesStore.setRichTextEditorEnabled(event.enabled) } is AdvancedSettingsEvents.SetDeveloperModeEnabled -> localCoroutineScope.launch { - preferencesStore.setDevelopModeEnabled(event.enabled) + preferencesStore.setDeveloperModeEnabled(event.enabled) } } } diff --git a/libraries/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/store/PreferencesStore.kt b/libraries/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/store/PreferencesStore.kt index 57ad7859c1..8ad2c098f6 100644 --- a/libraries/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/store/PreferencesStore.kt +++ b/libraries/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/store/PreferencesStore.kt @@ -22,8 +22,8 @@ interface PreferencesStore { suspend fun setRichTextEditorEnabled(enabled: Boolean) fun isRichTextEditorEnabledFlow(): Flow - suspend fun setDevelopModeEnabled(enabled: Boolean) - fun isDevelopModeEnabledFlow(): Flow + suspend fun setDeveloperModeEnabled(enabled: Boolean) + fun isDeveloperModeEnabledFlow(): Flow suspend fun reset() } diff --git a/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultPreferencesStore.kt b/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultPreferencesStore.kt index 4d2465a1a0..337301f23e 100644 --- a/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultPreferencesStore.kt +++ b/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultPreferencesStore.kt @@ -58,13 +58,13 @@ class DefaultPreferencesStore @Inject constructor( } } - override suspend fun setDevelopModeEnabled(enabled: Boolean) { + override suspend fun setDeveloperModeEnabled(enabled: Boolean) { store.edit { prefs -> prefs[developerModeKey] = enabled } } - override fun isDevelopModeEnabledFlow(): Flow { + override fun isDeveloperModeEnabledFlow(): Flow { return store.data.map { prefs -> // disabled by default on release and nightly, enabled by default on debug prefs[developerModeKey] ?: (buildMeta.buildType == BuildType.DEBUG) diff --git a/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/featureflag/test/InMemoryPreferencesStore.kt b/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/featureflag/test/InMemoryPreferencesStore.kt index 550713747e..a2a9fdaa3f 100644 --- a/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/featureflag/test/InMemoryPreferencesStore.kt +++ b/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/featureflag/test/InMemoryPreferencesStore.kt @@ -35,11 +35,11 @@ class InMemoryPreferencesStore( return _isRichTextEditorEnabled } - override suspend fun setDevelopModeEnabled(enabled: Boolean) { + override suspend fun setDeveloperModeEnabled(enabled: Boolean) { _isDeveloperModeEnabled.value = enabled } - override fun isDevelopModeEnabledFlow(): Flow { + override fun isDeveloperModeEnabledFlow(): Flow { return _isDeveloperModeEnabled } From 93da8d419e876b6d3973d919f2830af32034136a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 14 Sep 2023 14:37:45 +0200 Subject: [PATCH 171/234] Add test on AdvancedSettingsPresenterTest --- features/preferences/impl/build.gradle.kts | 1 + .../advanced/AdvancedSettingsPresenterTest.kt | 78 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenterTest.kt diff --git a/features/preferences/impl/build.gradle.kts b/features/preferences/impl/build.gradle.kts index 447adb5fa3..f523a2c6f4 100644 --- a/features/preferences/impl/build.gradle.kts +++ b/features/preferences/impl/build.gradle.kts @@ -67,6 +67,7 @@ dependencies { testImplementation(libs.test.turbine) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.featureflag.test) + testImplementation(projects.libraries.preferences.test) testImplementation(projects.features.rageshake.test) testImplementation(projects.features.rageshake.impl) testImplementation(projects.features.logout.impl) diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenterTest.kt new file mode 100644 index 0000000000..76808ee5f9 --- /dev/null +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenterTest.kt @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.advanced + +import app.cash.molecule.RecompositionMode +import app.cash.molecule.moleculeFlow +import app.cash.turbine.test +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.featureflag.test.InMemoryPreferencesStore +import io.element.android.tests.testutils.WarmUpRule +import kotlinx.coroutines.test.runTest +import org.junit.Rule +import org.junit.Test + +class AdvancedSettingsPresenterTest { + + @get:Rule + val warmUpRule = WarmUpRule() + + @Test + fun `present - initial state`() = runTest { + val store = InMemoryPreferencesStore() + val presenter = AdvancedSettingsPresenter(store) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + assertThat(initialState.isDeveloperModeEnabled).isFalse() + assertThat(initialState.isRichTextEditorEnabled).isFalse() + } + } + + @Test + fun `present - developer mode on off`() = runTest { + val store = InMemoryPreferencesStore() + val presenter = AdvancedSettingsPresenter(store) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + assertThat(initialState.isDeveloperModeEnabled).isFalse() + initialState.eventSink.invoke(AdvancedSettingsEvents.SetDeveloperModeEnabled(true)) + assertThat(awaitItem().isDeveloperModeEnabled).isTrue() + initialState.eventSink.invoke(AdvancedSettingsEvents.SetDeveloperModeEnabled(false)) + assertThat(awaitItem().isDeveloperModeEnabled).isFalse() + } + } + + @Test + fun `present - rich text editor on off`() = runTest { + val store = InMemoryPreferencesStore() + val presenter = AdvancedSettingsPresenter(store) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + assertThat(initialState.isRichTextEditorEnabled).isFalse() + initialState.eventSink.invoke(AdvancedSettingsEvents.SetRichTextEditorEnabled(true)) + assertThat(awaitItem().isRichTextEditorEnabled).isTrue() + initialState.eventSink.invoke(AdvancedSettingsEvents.SetRichTextEditorEnabled(false)) + assertThat(awaitItem().isRichTextEditorEnabled).isFalse() + } + } +} From c01cc4aeb4a4e440b9013f49584ef6969fdebb6f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 14 Sep 2023 18:31:51 +0200 Subject: [PATCH 172/234] Move developer settings and remove extra dividers. --- .../features/preferences/impl/root/PreferencesRootView.kt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) 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 c6d34c6969..16c7df6b51 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 @@ -123,16 +123,14 @@ fun PreferencesRootView( ) HorizontalDivider() } - if (state.showDeveloperSettings) { - DeveloperPreferencesView(onOpenDeveloperSettings) - HorizontalDivider() - } - HorizontalDivider() PreferenceText( title = stringResource(id = CommonStrings.common_advanced_settings), icon = Icons.Outlined.Settings, onClick = onOpenAdvancedSettings, ) + if (state.showDeveloperSettings) { + DeveloperPreferencesView(onOpenDeveloperSettings) + } HorizontalDivider() LogoutPreferenceView( state = state.logoutState, From 429b6fef924b0eb084d045b1644d43cadb0c4db3 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 14 Sep 2023 16:48:54 +0000 Subject: [PATCH 173/234] Update screenshots --- ...null_AdvancedSettingsView-D-0_1_null_0,NEXUS_5,1.0,en].png | 3 +++ ...null_AdvancedSettingsView-D-0_1_null_1,NEXUS_5,1.0,en].png | 3 +++ ...null_AdvancedSettingsView-D-0_1_null_2,NEXUS_5,1.0,en].png | 3 +++ ...null_AdvancedSettingsView-N-0_2_null_0,NEXUS_5,1.0,en].png | 3 +++ ...null_AdvancedSettingsView-N-0_2_null_1,NEXUS_5,1.0,en].png | 3 +++ ...null_AdvancedSettingsView-N-0_2_null_2,NEXUS_5,1.0,en].png | 3 +++ ...ull_ConfigureTracingView-D-1_2_null_0,NEXUS_5,1.0,en].png} | 0 ...ull_ConfigureTracingView-N-1_3_null_0,NEXUS_5,1.0,en].png} | 0 ...tNotificationSettingOption-D-2_3_null,NEXUS_5,1.0,en].png} | 0 ...tNotificationSettingOption-N-2_4_null,NEXUS_5,1.0,en].png} | 0 ...ll_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ll_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...l_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...l_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- 14 files changed, 26 insertions(+), 8 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-D-0_1_null_0,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-D-0_1_null_1,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-D-0_1_null_2,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-N-0_2_null_0,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-N-0_2_null_1,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-N-0_2_null_2,NEXUS_5,1.0,en].png rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.preferences.impl.developer.tracing_null_ConfigureTracingView-D-0_1_null_0,NEXUS_5,1.0,en].png => ui_S_t[f.preferences.impl.developer.tracing_null_ConfigureTracingView-D-1_2_null_0,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.preferences.impl.developer.tracing_null_ConfigureTracingView-N-0_2_null_0,NEXUS_5,1.0,en].png => ui_S_t[f.preferences.impl.developer.tracing_null_ConfigureTracingView-N-1_3_null_0,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOption-D-1_2_null,NEXUS_5,1.0,en].png => ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOption-D-2_3_null,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOption-N-1_3_null,NEXUS_5,1.0,en].png => ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOption-N-2_4_null,NEXUS_5,1.0,en].png} (100%) diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-D-0_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-D-0_1_null_0,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..aa5e7b202a --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-D-0_1_null_0,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a11d23d53b983a6cb5448f6083e448902b50889d6393f48454ef1b19c0ad0f07 +size 38028 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-D-0_1_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-D-0_1_null_1,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..99efbef109 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-D-0_1_null_1,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:18063647932eef08f66236825751456801e2a172a72ff09691a1d4b93897466d +size 37617 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-D-0_1_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-D-0_1_null_2,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..9cfecc1b15 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-D-0_1_null_2,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:333e3cb2b49f6d2794e732b7b9fc4204a7fc8564d0518b8cf60a9e7f14ea9a39 +size 37688 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-N-0_2_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-N-0_2_null_0,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..ca2c271e89 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-N-0_2_null_0,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:47332a39d0c1a95a8396548b45bc3822b734111b268c06d917fa2ffb2d277cc1 +size 35649 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-N-0_2_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-N-0_2_null_1,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..e31840c360 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-N-0_2_null_1,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9deacb3ff9bdd2dbee7dd97686941cee9b1f19855f6b87c7e6860e9d47c671e4 +size 35278 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-N-0_2_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-N-0_2_null_2,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..44081fe3ab --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.advanced_null_AdvancedSettingsView-N-0_2_null_2,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16b226707d1e862aa004c426221b89dbc9c7b2cedee19b11ff8843fa524a76ad +size 35378 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.developer.tracing_null_ConfigureTracingView-D-0_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.developer.tracing_null_ConfigureTracingView-D-1_2_null_0,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.developer.tracing_null_ConfigureTracingView-D-0_1_null_0,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.developer.tracing_null_ConfigureTracingView-D-1_2_null_0,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.developer.tracing_null_ConfigureTracingView-N-0_2_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.developer.tracing_null_ConfigureTracingView-N-1_3_null_0,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.developer.tracing_null_ConfigureTracingView-N-0_2_null_0,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.developer.tracing_null_ConfigureTracingView-N-1_3_null_0,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOption-D-1_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOption-D-2_3_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOption-D-1_2_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOption-D-2_3_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOption-N-1_3_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOption-N-2_4_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOption-N-1_3_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications.edit_null_DefaultNotificationSettingOption-N-2_4_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png index 05ac81ce49..72fbec227e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aed6ab34c685d32aa77e926c416621716acedd586eea2e76e51f1c51867be6cf -size 43419 +oid sha256:56f2a7a7aca8336fb669030a98af4fd851ab1bf52c68d33be36fe8df922c01ee +size 46097 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png index 66bf07e1ce..a2d529d3a0 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewDark--1_1_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d4dce8dec2408bcf8e1e8a547689cdac25145d2fef603b21ff20ba2a40e181b1 -size 42741 +oid sha256:6936337fd9365fc5d38d5570798ceaa409099240593e32a468e7688398926e4d +size 45415 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png index 793b31326f..29b2a82cea 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b01d7dcb16041285c2915b7572c16e39d199ac930ed0f6a69b1219bdf5d0ccd5 -size 46362 +oid sha256:c9bc0aa48e94e2a4fb61ebc52b5d62d3fd960a3a3c52300906c76ad52f92b662 +size 49333 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png index 399417d8ac..97fc36e283 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.root_null_PreferencesRootViewLight--0_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a9667115ed339726a09e7917737a6aa5698f4f03249f2704f162461775ddc20b -size 46229 +oid sha256:bc40ec0fb6fa758768fc697496f54b9381a0fd0a67cce1ee36b6dd703e11ea18 +size 49229 From 7a7cc2692e7a322f8f7161d93c439bfa43c7e2c6 Mon Sep 17 00:00:00 2001 From: David Langley Date: Thu, 14 Sep 2023 19:28:56 +0100 Subject: [PATCH 174/234] Fix test compilation --- .../android/features/roomlist/impl/RoomListPresenterTests.kt | 4 +++- .../libraries/matrix/test/roomlist/FakeRoomListService.kt | 4 ++++ .../io/element/android/samples/minimal/RoomListScreen.kt | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt index b7bfd3ecb4..8acaa69830 100644 --- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt @@ -325,7 +325,9 @@ class RoomListPresenterTests { client.roomListService, lastMessageTimestampFormatter, roomLastMessageFormatter, - coroutineDispatchers = testCoroutineDispatchers() + coroutineDispatchers = testCoroutineDispatchers(), + notificationSettingsService = client.notificationSettingsService(), + appScope = this ) ) } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/FakeRoomListService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/FakeRoomListService.kt index 7e0f3e8891..75a91508d0 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/FakeRoomListService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/FakeRoomListService.kt @@ -58,6 +58,10 @@ class FakeRoomListService : RoomListService { latestSlidingSyncRange = range } + override fun rebuildRoomSummaries() { + + } + override fun allRooms(): RoomList { return SimpleRoomList( summaries = allRoomSummariesFlow, diff --git a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt index faaccc9b8e..425888f003 100644 --- a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt +++ b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt @@ -78,6 +78,8 @@ class RoomListScreen( stateContentFormatter = StateContentFormatter(stringProvider), ), coroutineDispatchers = coroutineDispatchers, + notificationSettingsService = matrixClient.notificationSettingsService(), + appScope = Singleton.appScope ) ) From 57aeac9a444fa155b47c049e0179bd6f5b3fbd6b Mon Sep 17 00:00:00 2001 From: David Langley Date: Thu, 14 Sep 2023 20:31:34 +0100 Subject: [PATCH 175/234] Update RoomListDataSource.kt --- .../impl/datasource/RoomListDataSource.kt | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt index 2cf28a6913..ac0b3ca568 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt @@ -35,6 +35,7 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine @@ -52,17 +53,13 @@ class RoomListDataSource @Inject constructor( private val lastMessageTimestampFormatter: LastMessageTimestampFormatter, private val roomLastMessageFormatter: RoomLastMessageFormatter, private val coroutineDispatchers: CoroutineDispatchers, - notificationSettingsService: NotificationSettingsService, - appScope: CoroutineScope, + private val notificationSettingsService: NotificationSettingsService, + private val appScope: CoroutineScope, ) { init { - notificationSettingsService.notificationSettingsChangeFlow - .debounce(0.5.seconds) - .onEach { - roomListService.rebuildRoomSummaries() - } - .launchIn(appScope) + observerNotificationSettings() } + private val _filter = MutableStateFlow("") private val _allRooms = MutableStateFlow>(persistentListOf()) private val _filteredRooms = MutableStateFlow>(persistentListOf()) @@ -105,6 +102,16 @@ class RoomListDataSource @Inject constructor( val allRooms: StateFlow> = _allRooms val filteredRooms: StateFlow> = _filteredRooms + @OptIn(FlowPreview::class) + private fun observerNotificationSettings() { + notificationSettingsService.notificationSettingsChangeFlow + .debounce(0.5.seconds) + .onEach { + roomListService.rebuildRoomSummaries() + } + .launchIn(appScope) + } + private suspend fun replaceWith(roomSummaries: List) = withContext(coroutineDispatchers.computation) { lock.withLock { diffCacheUpdater.updateWith(roomSummaries) From ef6c1827e70b6cb319cdec331a091aa4bec9a54c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 14 Sep 2023 20:30:44 +0000 Subject: [PATCH 176/234] Update dependency app.cash.molecule:molecule-runtime to v1.2.1 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cdc80fbd1b..42e4c3659d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,7 @@ android_gradle_plugin = "8.1.1" kotlin = "1.9.10" ksp = "1.9.10-1.0.13" -molecule = "1.2.0" +molecule = "1.2.1" # AndroidX material = "1.9.0" From 912244f37e321d0d843d27f9af17dce577ad6340 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 14 Sep 2023 20:30:50 +0000 Subject: [PATCH 177/234] Update dependency com.google.firebase:firebase-bom to v32.3.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cdc80fbd1b..e8a90f9857 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -66,7 +66,7 @@ android_gradle_plugin = { module = "com.android.tools.build:gradle", version.ref android_desugar = "com.android.tools:desugar_jdk_libs:2.0.3" kotlin_gradle_plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } # https://firebase.google.com/docs/android/setup#available-libraries -google_firebase_bom = "com.google.firebase:firebase-bom:32.2.3" +google_firebase_bom = "com.google.firebase:firebase-bom:32.3.0" # AndroidX androidx_material = { module = "com.google.android.material:material", version.ref = "material" } From 9190880643ae6b140ba512e97c8bba5cc8ace5d7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 14 Sep 2023 22:25:11 +0000 Subject: [PATCH 178/234] Update dependency com.google.gms:google-services to v4.4.0 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 5c958fc397..7e7c1c1c9e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,7 @@ import org.jetbrains.kotlin.cli.common.toBooleanLenient buildscript { dependencies { classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.10") - classpath("com.google.gms:google-services:4.3.15") + classpath("com.google.gms:google-services:4.4.0") } } From 5c4da4b26e7278e20c806a7218de064efe1a9611 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 15 Sep 2023 09:19:30 +0200 Subject: [PATCH 179/234] Revert "Update codecov/codecov-action action to v4" --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2fdaa2195e..f662e5352d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -81,6 +81,6 @@ jobs: # https://github.com/codecov/codecov-action - name: ☂️ Upload coverage reports to codecov if: always() - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v3 # with: # files: build/reports/kover/merged/xml/report.xml From aa29efcd763a65a1aaadd326955afd55549b7400 Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Fri, 15 Sep 2023 09:20:29 +0200 Subject: [PATCH 180/234] Remove suppressUnsupportedCompileSdk We're now an AGP 8.1.0 so should be safe to remove as per the comment. --- gradle.properties | 3 --- 1 file changed, 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 6f311e45ef..9847be0949 100644 --- a/gradle.properties +++ b/gradle.properties @@ -56,6 +56,3 @@ android.experimental.enableTestFixtures=true # Create BuildConfig files as bytecode to avoid Java compilation phase android.enableBuildConfigAsBytecode=true - -# This should be removed after upgrading to AGP 8.1.0 -android.suppressUnsupportedCompileSdk=34 From 2bd442b3a436bd7bc14a415c9c3c627dcb4c80d9 Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Fri, 15 Sep 2023 09:24:55 +0200 Subject: [PATCH 181/234] Add preview for progressIndicatorTrackColor Forgot to add it in https://github.com/vector-im/element-x-android/pull/1295 --- .../element/android/libraries/designsystem/theme/ColorAliases.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ColorAliases.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ColorAliases.kt index 52e0a69430..77ca4bd010 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ColorAliases.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ColorAliases.kt @@ -100,6 +100,7 @@ private fun ContentToPreview() { "placeholderBackground" to ElementTheme.colors.placeholderBackground, "messageFromMeBackground" to ElementTheme.colors.messageFromMeBackground, "messageFromOtherBackground" to ElementTheme.colors.messageFromOtherBackground, + "progressIndicatorTrackColor" to ElementTheme.colors.progressIndicatorTrackColor, "temporaryColorBgSpecial" to ElementTheme.colors.temporaryColorBgSpecial, ) ) From c0f6e55b78fbb895a263d30d045723fef957709d Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 15 Sep 2023 07:44:17 +0000 Subject: [PATCH 182/234] Update screenshots --- ...tem.theme_null_ColorAliasesDark_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...em.theme_null_ColorAliasesLight_0_null,NEXUS_5,1.0,en].png | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme_null_ColorAliasesDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme_null_ColorAliasesDark_0_null,NEXUS_5,1.0,en].png index 5c56f5f39b..b1c6c996d8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme_null_ColorAliasesDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme_null_ColorAliasesDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:38642daa43d72b6b8e0626ed5fcd034df1e79bb844af8ade06112225dfc0f5b7 -size 40707 +oid sha256:d57924194a017902912825d4f43fcd290db11430d4d64abd89abe39b9e2ffc27 +size 48726 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme_null_ColorAliasesLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme_null_ColorAliasesLight_0_null,NEXUS_5,1.0,en].png index 0b39e21087..eaf130c209 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme_null_ColorAliasesLight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme_null_ColorAliasesLight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4aa0a56393799bcc582f8c384b4bf782fff63bc8402bbef5733c938ce564a75f -size 40000 +oid sha256:0eaa20c7c00c18cf08135aca70407d55ea9fc33a7f262aee3fa6ced272f7ab16 +size 48465 From 50c7892eab19dc5c96be0db0bfe8689a3a4fa7c8 Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Thu, 14 Sep 2023 13:45:01 +0200 Subject: [PATCH 183/234] Make PollContentView a11y friendly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Improves a bit how screen readers read polls in the timeline. - Adds a few `contentDescription` so that talkback reads “poll” or “ended poll” before the poll question. - Changes the compose structure of the answers so that they are properly scanned by the screen reader. This meant getting rid of the `IconToggleButton` which was made redundant by the use of the `selectable`. --- .../features/poll/api/PollAnswerView.kt | 94 ++++++++----------- .../features/poll/api/PollContentView.kt | 55 ++++++----- .../src/main/res/values/localazy.xml | 2 + 3 files changed, 74 insertions(+), 77 deletions(-) diff --git a/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollAnswerView.kt b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollAnswerView.kt index 4e7a23094b..0e4b168866 100644 --- a/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollAnswerView.kt +++ b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollAnswerView.kt @@ -21,24 +21,21 @@ 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.selection.selectable import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.CheckCircle import androidx.compose.material.icons.filled.RadioButtonUnchecked -import androidx.compose.material3.IconButtonDefaults import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.StrokeCap import androidx.compose.ui.res.pluralStringResource -import androidx.compose.ui.semantics.Role -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import io.element.android.libraries.designsystem.preview.ElementThemedPreview +import io.element.android.libraries.designsystem.preview.DayNightPreviews +import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.theme.components.Icon -import io.element.android.libraries.designsystem.theme.components.IconToggleButton import io.element.android.libraries.designsystem.theme.components.LinearProgressIndicator import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.progressIndicatorTrackColor @@ -47,41 +44,33 @@ import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.ui.strings.CommonPlurals @Composable -fun PollAnswerView( +internal fun PollAnswerView( answerItem: PollAnswerItem, - onClick: () -> Unit, modifier: Modifier = Modifier, ) { Row( - modifier - .fillMaxWidth() - .selectable( - selected = answerItem.isSelected, - enabled = answerItem.isEnabled, - onClick = onClick, - role = Role.RadioButton, - ) + modifier = modifier.fillMaxWidth(), ) { - IconToggleButton( - modifier = Modifier.size(22.dp), - checked = answerItem.isSelected, - enabled = answerItem.isEnabled, - colors = IconButtonDefaults.iconToggleButtonColors( - contentColor = ElementTheme.colors.iconSecondary, - checkedContentColor = ElementTheme.colors.iconPrimary, - disabledContentColor = ElementTheme.colors.iconDisabled, - ), - onCheckedChange = { onClick() }, - ) { - Icon( - imageVector = if (answerItem.isSelected) { - Icons.Default.CheckCircle + Icon( + imageVector = if (answerItem.isSelected) { + Icons.Default.CheckCircle + } else { + Icons.Default.RadioButtonUnchecked + }, + contentDescription = null, + modifier = Modifier + .padding(0.5.dp) + .size(22.dp), + tint = if (answerItem.isEnabled) { + if (answerItem.isSelected) { + ElementTheme.colors.iconPrimary } else { - Icons.Default.RadioButtonUnchecked - }, - contentDescription = null, - ) - } + ElementTheme.colors.iconSecondary + } + } else { + ElementTheme.colors.iconDisabled + }, + ) Spacer(modifier = Modifier.width(12.dp)) Column { Row { @@ -119,65 +108,58 @@ fun PollAnswerView( } } -@Preview +@DayNightPreviews @Composable -internal fun PollAnswerDisclosedNotSelectedPreview() = ElementThemedPreview { +internal fun PollAnswerDisclosedNotSelectedPreview() = ElementPreview { PollAnswerView( answerItem = aPollAnswerItem(isDisclosed = true, isSelected = false), - onClick = { }, ) } -@Preview +@DayNightPreviews @Composable -internal fun PollAnswerDisclosedSelectedPreview() = ElementThemedPreview { +internal fun PollAnswerDisclosedSelectedPreview() = ElementPreview { PollAnswerView( answerItem = aPollAnswerItem(isDisclosed = true, isSelected = true), - onClick = { } ) } -@Preview +@DayNightPreviews @Composable -internal fun PollAnswerUndisclosedNotSelectedPreview() = ElementThemedPreview { +internal fun PollAnswerUndisclosedNotSelectedPreview() = ElementPreview { PollAnswerView( answerItem = aPollAnswerItem(isDisclosed = false, isSelected = false), - onClick = { }, ) } -@Preview +@DayNightPreviews @Composable -internal fun PollAnswerUndisclosedSelectedPreview() = ElementThemedPreview { +internal fun PollAnswerUndisclosedSelectedPreview() = ElementPreview { PollAnswerView( answerItem = aPollAnswerItem(isDisclosed = false, isSelected = true), - onClick = { } ) } -@Preview +@DayNightPreviews @Composable -internal fun PollAnswerEndedWinnerNotSelectedPreview() = ElementThemedPreview { +internal fun PollAnswerEndedWinnerNotSelectedPreview() = ElementPreview { PollAnswerView( answerItem = aPollAnswerItem(isDisclosed = true, isSelected = false, isEnabled = false, isWinner = true), - onClick = { } ) } -@Preview +@DayNightPreviews @Composable -internal fun PollAnswerEndedWinnerSelectedPreview() = ElementThemedPreview { +internal fun PollAnswerEndedWinnerSelectedPreview() = ElementPreview { PollAnswerView( answerItem = aPollAnswerItem(isDisclosed = true, isSelected = true, isEnabled = false, isWinner = true), - onClick = { } ) } -@Preview +@DayNightPreviews @Composable -internal fun PollAnswerEndedSelectedPreview() = ElementThemedPreview { +internal fun PollAnswerEndedSelectedPreview() = ElementPreview { PollAnswerView( answerItem = aPollAnswerItem(isDisclosed = true, isSelected = true, isEnabled = false, isWinner = false), - onClick = { } ) } diff --git a/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollContentView.kt b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollContentView.kt index 7e03d7a46e..a47d69c780 100644 --- a/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollContentView.kt +++ b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/PollContentView.kt @@ -23,11 +23,14 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.selection.selectable import androidx.compose.foundation.selection.selectableGroup import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.Role import androidx.compose.ui.unit.dp import io.element.android.libraries.designsystem.VectorIcons import io.element.android.libraries.designsystem.preview.DayNightPreviews @@ -56,24 +59,24 @@ fun PollContentView( } Column( - modifier = modifier - .selectableGroup() - .fillMaxWidth(), + modifier = modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(16.dp), ) { PollTitle(title = question, isPollEnded = isPollEnded) PollAnswers(answerItems = answerItems, onAnswerSelected = ::onAnswerSelected) - when { - isPollEnded || pollKind == PollKind.Disclosed -> DisclosedPollBottomNotice(answerItems) - pollKind == PollKind.Undisclosed -> UndisclosedPollBottomNotice() + if (isPollEnded || pollKind == PollKind.Disclosed) { + val votesCount = remember(answerItems) { answerItems.sumOf { it.votesCount } } + DisclosedPollBottomNotice(votesCount = votesCount) + } else { + UndisclosedPollBottomNotice() } } } @Composable -internal fun PollTitle( +private fun PollTitle( title: String, isPollEnded: Boolean, modifier: Modifier = Modifier @@ -85,13 +88,13 @@ internal fun PollTitle( if (isPollEnded) { Icon( resourceId = VectorIcons.PollEnd, - contentDescription = null, + contentDescription = stringResource(id = CommonStrings.a11y_poll_end), modifier = Modifier.size(22.dp) ) } else { Icon( resourceId = VectorIcons.Poll, - contentDescription = null, + contentDescription = stringResource(id = CommonStrings.a11y_poll), modifier = Modifier.size(22.dp) ) } @@ -103,27 +106,35 @@ internal fun PollTitle( } @Composable -internal fun PollAnswers( +private fun PollAnswers( answerItems: ImmutableList, onAnswerSelected: (PollAnswer) -> Unit, modifier: Modifier = Modifier, ) { - - answerItems.forEach { answerItem -> - PollAnswerView( - modifier = modifier, - answerItem = answerItem, - onClick = { onAnswerSelected(answerItem.answer) } - ) + Column( + modifier = modifier.selectableGroup(), + verticalArrangement = Arrangement.spacedBy(16.dp), + ) { + answerItems.forEach { + PollAnswerView( + answerItem = it, + modifier = Modifier + .selectable( + selected = it.isSelected, + enabled = it.isEnabled, + onClick = { onAnswerSelected(it.answer) }, + role = Role.RadioButton, + ), + ) + } } } @Composable -internal fun ColumnScope.DisclosedPollBottomNotice( - answerItems: ImmutableList, +private fun ColumnScope.DisclosedPollBottomNotice( + votesCount: Int, modifier: Modifier = Modifier ) { - val votesCount = answerItems.sumOf { it.votesCount } Text( modifier = modifier.align(Alignment.End), style = ElementTheme.typography.fontBodyXsRegular, @@ -133,7 +144,9 @@ internal fun ColumnScope.DisclosedPollBottomNotice( } @Composable -fun ColumnScope.UndisclosedPollBottomNotice(modifier: Modifier = Modifier) { +private fun ColumnScope.UndisclosedPollBottomNotice( + modifier: Modifier = Modifier +) { Text( modifier = modifier .align(Alignment.Start) diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 2355e4b603..dfb095d05a 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -3,6 +3,8 @@ "Hide password" "Mentions only" "Muted" + "Poll" + "Ended poll" "Send files" "Show password" "User menu" From 626ee7fefc85b6d47a677435303af300df6d69e9 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 15 Sep 2023 08:09:51 +0000 Subject: [PATCH 184/234] Update screenshots --- ...ll_TimelineItemPollView-D-13_14_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ll_TimelineItemPollView-D-13_14_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...ll_TimelineItemPollView-N-13_15_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...ll_TimelineItemPollView-N-13_15_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...TimelineItemEventTimestampBelow_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...lAnswerDisclosedNotSelected-D-0_0_null,NEXUS_5,1.0,en].png | 3 +++ ...lAnswerDisclosedNotSelected-N-0_1_null,NEXUS_5,1.0,en].png | 3 +++ ..._PollAnswerDisclosedNotSelected_0_null,NEXUS_5,1.0,en].png | 3 --- ...PollAnswerDisclosedSelected-D-1_1_null,NEXUS_5,1.0,en].png | 3 +++ ...PollAnswerDisclosedSelected-N-1_2_null,NEXUS_5,1.0,en].png | 3 +++ ...ull_PollAnswerDisclosedSelected_0_null,NEXUS_5,1.0,en].png | 3 --- ...ull_PollAnswerEndedSelected-D-6_6_null,NEXUS_5,1.0,en].png | 3 +++ ...ull_PollAnswerEndedSelected-N-6_7_null,NEXUS_5,1.0,en].png | 3 +++ ...pi_null_PollAnswerEndedSelected_0_null,NEXUS_5,1.0,en].png | 3 --- ...nswerEndedWinnerNotSelected-D-4_4_null,NEXUS_5,1.0,en].png | 3 +++ ...nswerEndedWinnerNotSelected-N-4_5_null,NEXUS_5,1.0,en].png | 3 +++ ...ollAnswerEndedWinnerNotSelected_0_null,NEXUS_5,1.0,en].png | 3 --- ...llAnswerEndedWinnerSelected-D-5_5_null,NEXUS_5,1.0,en].png | 3 +++ ...llAnswerEndedWinnerSelected-N-5_6_null,NEXUS_5,1.0,en].png | 3 +++ ...l_PollAnswerEndedWinnerSelected_0_null,NEXUS_5,1.0,en].png | 3 --- ...nswerUndisclosedNotSelected-D-2_2_null,NEXUS_5,1.0,en].png | 3 +++ ...nswerUndisclosedNotSelected-N-2_3_null,NEXUS_5,1.0,en].png | 3 +++ ...ollAnswerUndisclosedNotSelected_0_null,NEXUS_5,1.0,en].png | 3 --- ...llAnswerUndisclosedSelected-D-3_3_null,NEXUS_5,1.0,en].png | 3 +++ ...llAnswerUndisclosedSelected-N-3_4_null,NEXUS_5,1.0,en].png | 3 +++ ...l_PollAnswerUndisclosedSelected_0_null,NEXUS_5,1.0,en].png | 3 --- ...i_null_PollContentDisclosed-D-1_1_null,NEXUS_5,1.0,en].png | 3 --- ...i_null_PollContentDisclosed-D-8_8_null,NEXUS_5,1.0,en].png | 3 +++ ...i_null_PollContentDisclosed-N-1_2_null,NEXUS_5,1.0,en].png | 3 --- ...i_null_PollContentDisclosed-N-8_9_null,NEXUS_5,1.0,en].png | 3 +++ ...l.api_null_PollContentEnded-D-2_2_null,NEXUS_5,1.0,en].png | 3 --- ...l.api_null_PollContentEnded-D-9_9_null,NEXUS_5,1.0,en].png | 3 +++ ...l.api_null_PollContentEnded-N-2_3_null,NEXUS_5,1.0,en].png | 3 --- ....api_null_PollContentEnded-N-9_10_null,NEXUS_5,1.0,en].png | 3 +++ ...null_PollContentUndisclosed-D-0_0_null,NEXUS_5,1.0,en].png | 3 --- ...null_PollContentUndisclosed-D-7_7_null,NEXUS_5,1.0,en].png | 3 +++ ...null_PollContentUndisclosed-N-0_1_null,NEXUS_5,1.0,en].png | 3 --- ...null_PollContentUndisclosed-N-7_8_null,NEXUS_5,1.0,en].png | 3 +++ 38 files changed, 70 insertions(+), 49 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedNotSelected-D-0_0_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedNotSelected-N-0_1_null,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedNotSelected_0_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedSelected-D-1_1_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedSelected-N-1_2_null,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedSelected_0_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedSelected-D-6_6_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedSelected-N-6_7_null,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedSelected_0_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerNotSelected-D-4_4_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerNotSelected-N-4_5_null,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerNotSelected_0_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerSelected-D-5_5_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerSelected-N-5_6_null,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerSelected_0_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedNotSelected-D-2_2_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedNotSelected-N-2_3_null,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedNotSelected_0_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedSelected-D-3_3_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedSelected-N-3_4_null,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedSelected_0_null,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-D-1_1_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-D-8_8_null,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-N-1_2_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-N-8_9_null,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-D-2_2_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-D-9_9_null,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-N-2_3_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-N-9_10_null,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-D-0_0_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-D-7_7_null,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-N-0_1_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-N-7_8_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_0,NEXUS_5,1.0,en].png index 8ba3fa59a7..18764bef11 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:801f832469346524fdce0b5ad8654c3405daf0f21ae0601c62dc7f148b576ce8 -size 49074 +oid sha256:188c362ebd8bc32a47b66a080331db7643cd97714f2d4e952d7bec8c11520dcd +size 49026 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_1,NEXUS_5,1.0,en].png index 2af13b5df7..1117d239f3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-D-13_14_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:944eb2ef8abf2e8f1715d063020767940c80b40690aae1129f69d02ddafac9d0 -size 51029 +oid sha256:9de6ab591cb02f6545218a2606d031f4f93c82e71e99523eacaf77ffa78fadb1 +size 50940 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_0,NEXUS_5,1.0,en].png index 0e2fb91a11..8bae8c65fa 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:adf6f3f79b9d8f62172171dd8a172bff1958bc4698df4586bf83c73fe4c6c6f3 -size 46198 +oid sha256:b4b00894025844927932e790a1738c85cfbb61e61a81dfbbbd7e342f38f40b99 +size 46061 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_1,NEXUS_5,1.0,en].png index c06bfdad7b..5f8c7437c9 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components.event_null_TimelineItemPollView-N-13_15_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:38183d1d69e36c2570259c987be079d09ecfc0a0cba7508fc43d33e95c574121 -size 48368 +oid sha256:bd88ed3aeb9a20f148e914c4a5d4554220a1fecd8e8a8fe87400de78ff4bf248 +size 48237 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventTimestampBelow_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventTimestampBelow_0_null,NEXUS_5,1.0,en].png index ea0825524c..0b071c5d9d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventTimestampBelow_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.timeline.components_null_TimelineItemEventTimestampBelow_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:54a4fe8e7f968bf487168a517baa0d9c9f6fc5b2354f4eff45f56de77b043f8f -size 56535 +oid sha256:5490f2501c6ef257f926fc2f4bd9d94ef4e6e3017d4da290e2199eaeaa2ac5b5 +size 56571 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedNotSelected-D-0_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedNotSelected-D-0_0_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..b40e0b863b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedNotSelected-D-0_0_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:045a09f485856b01e1084a91fefca0ccd7f9e7ef7470a22a4db0a60e95fb8667 +size 23119 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedNotSelected-N-0_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedNotSelected-N-0_1_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..320f918fd3 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedNotSelected-N-0_1_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:31a8f8e06cc101bcdccb973f3a003238cc093342f04613975cb9512072b051c2 +size 21619 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedNotSelected_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedNotSelected_0_null,NEXUS_5,1.0,en].png deleted file mode 100644 index 7a81cb7428..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedNotSelected_0_null,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9f97a2f591619aa2dd914f79a2bdfabea3e4e8239e6d80f29400e2c02c6ae21d -size 39250 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedSelected-D-1_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedSelected-D-1_1_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..b74ef6f2e3 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedSelected-D-1_1_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1abb2b1c635b5a6666ce7de0ffbe10c753d32c6f0f2e95e8cf17d481bfa5228b +size 23024 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedSelected-N-1_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedSelected-N-1_2_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..e8e5307f60 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedSelected-N-1_2_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:609279d1f2e25b86b8ae5a598bb6602a43a6714fa8e98a4625c349470d9d7e85 +size 21345 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedSelected_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedSelected_0_null,NEXUS_5,1.0,en].png deleted file mode 100644 index 5e990f7141..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerDisclosedSelected_0_null,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:03b4bfab1cbbbedd9219423834f3bdf47f40e20c0da791be2c892cb2af86cf7d -size 38694 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedSelected-D-6_6_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedSelected-D-6_6_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..ed8c54d817 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedSelected-D-6_6_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:08550f84b603d0c0424d63e7aef09856a048b7a862288ac43911673019ae7a5d +size 23075 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedSelected-N-6_7_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedSelected-N-6_7_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..e63b4b34ba --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedSelected-N-6_7_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7e6000321200788598744d82d8b11c9f2d6eb509bf8c9c0bf362c10d1b27b9ae +size 21474 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedSelected_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedSelected_0_null,NEXUS_5,1.0,en].png deleted file mode 100644 index 7ebe08ccd8..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedSelected_0_null,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1672ff3a807b387b1f780920111c19484261b36884f1f68d72e108c90a4104d2 -size 38948 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerNotSelected-D-4_4_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerNotSelected-D-4_4_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..1ae62e8a37 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerNotSelected-D-4_4_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:013bfb3d3bd78d8db9f0ac51b11a41c2b82daaa28f87cdfd866260d3fb40bf0d +size 23125 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerNotSelected-N-4_5_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerNotSelected-N-4_5_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..243da80797 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerNotSelected-N-4_5_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7c039ab6649ff160b540256dacba1037b15c5907d9994a041cbab3be0ee5cacd +size 21283 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerNotSelected_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerNotSelected_0_null,NEXUS_5,1.0,en].png deleted file mode 100644 index 96596d6000..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerNotSelected_0_null,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:43da602c904210df0112a1af831cd2a2f7a7c5109d26605efad464a3c5b58995 -size 38864 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerSelected-D-5_5_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerSelected-D-5_5_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..e9142acb1d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerSelected-D-5_5_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a99ff857afe6478e579c96b984e1abdbf981638e6964a7d2c94b53153aff078d +size 23135 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerSelected-N-5_6_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerSelected-N-5_6_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..f0115f6311 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerSelected-N-5_6_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d97ba3288f5fcdaaed917a994df9273d3e82d5a6e0c7978044dbaf03152e3269 +size 21270 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerSelected_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerSelected_0_null,NEXUS_5,1.0,en].png deleted file mode 100644 index 5396c8592b..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerEndedWinnerSelected_0_null,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bf806b2490fc8a1df278bde94535cb1b5d38f66531df85d6fd1251e6671d9f56 -size 38756 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedNotSelected-D-2_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedNotSelected-D-2_2_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..6875a6a28b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedNotSelected-D-2_2_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:05af414578ab61e5b24b6e0a4895e0b52c3566625fd47f00b32f38b416dbe7fa +size 21498 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedNotSelected-N-2_3_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedNotSelected-N-2_3_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..99fde7c140 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedNotSelected-N-2_3_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9ccde06f5825c37c1c58ef0d9aee44f7b65425988386a97ba744360d8c22e470 +size 19563 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedNotSelected_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedNotSelected_0_null,NEXUS_5,1.0,en].png deleted file mode 100644 index a9c192a685..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedNotSelected_0_null,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:eeaa924482fa2fc29079f7f0d4bddacb96567a2133808bed8b49be2ad7afe80f -size 36481 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedSelected-D-3_3_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedSelected-D-3_3_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..ae98097be2 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedSelected-D-3_3_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ab9d7637c2c64d39beaa96244e348f39fc9b42fcebf54016fd27b4fd8e0a8c69 +size 21352 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedSelected-N-3_4_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedSelected-N-3_4_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..aee5375e86 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedSelected-N-3_4_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16ea9da926c330f56bde968e90f8df1bc015bf8d55853edc21edfaf3f793adfe +size 19266 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedSelected_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedSelected_0_null,NEXUS_5,1.0,en].png deleted file mode 100644 index b16b55dc1c..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollAnswerUndisclosedSelected_0_null,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:de340de9f0f07a44c9d2c1af196abc059d32f62fc857214cdf2c1d1e1951d267 -size 35915 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-D-1_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-D-1_1_null,NEXUS_5,1.0,en].png deleted file mode 100644 index 8ba3fa59a7..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-D-1_1_null,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:801f832469346524fdce0b5ad8654c3405daf0f21ae0601c62dc7f148b576ce8 -size 49074 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-D-8_8_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-D-8_8_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..18764bef11 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-D-8_8_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:188c362ebd8bc32a47b66a080331db7643cd97714f2d4e952d7bec8c11520dcd +size 49026 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-N-1_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-N-1_2_null,NEXUS_5,1.0,en].png deleted file mode 100644 index 0e2fb91a11..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-N-1_2_null,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:adf6f3f79b9d8f62172171dd8a172bff1958bc4698df4586bf83c73fe4c6c6f3 -size 46198 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-N-8_9_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-N-8_9_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..8bae8c65fa --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentDisclosed-N-8_9_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b4b00894025844927932e790a1738c85cfbb61e61a81dfbbbd7e342f38f40b99 +size 46061 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-D-2_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-D-2_2_null,NEXUS_5,1.0,en].png deleted file mode 100644 index e54dcafe51..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-D-2_2_null,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7d0674f2bac8e4912bb1faec069be0e86e3b796f61e6217494cfe42cce89dca2 -size 49143 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-D-9_9_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-D-9_9_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..c8e001c9af --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-D-9_9_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88230f28f7761d8f76bc5a50dbc4ba08a694eaf0d64207257f5196c741fb7b52 +size 49078 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-N-2_3_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-N-2_3_null,NEXUS_5,1.0,en].png deleted file mode 100644 index 2a9c20d9c2..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-N-2_3_null,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f54d112dc90c4e2402eeab5fe8e649ffc397e208c395a19f37889038206c8179 -size 45927 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-N-9_10_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-N-9_10_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..495cb4c484 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentEnded-N-9_10_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a6e31f773b884608499081ab3c7a27297edfbf8af76f502d9076b4753956e2db +size 45929 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-D-0_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-D-0_0_null,NEXUS_5,1.0,en].png deleted file mode 100644 index 05fb3ba861..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-D-0_0_null,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4fe5ffa68f8ea13ae4343a4fd915c58c1ff9157433248ac93ffa8ab6d8ecbbdf -size 47223 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-D-7_7_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-D-7_7_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..b813fd723d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-D-7_7_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc814fc52a37c0724ac5a45a0337af25a2371ed8c4a0d4ce4f899bfb0a6c2ef5 +size 47138 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-N-0_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-N-0_1_null,NEXUS_5,1.0,en].png deleted file mode 100644 index 59cc1e7ce4..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-N-0_1_null,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:137bce4fc589d2275239c84ebea5a3fc07f90a31a8dbb0a5efb830a9433aa437 -size 43650 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-N-7_8_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-N-7_8_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..eecf7113c0 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.poll.api_null_PollContentUndisclosed-N-7_8_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f5f8f51b498725d57c6086741ff07123c504c81c8c2bfafd483130afc2559b35 +size 43471 From 7914ec0a28b3541a0d582d83f08bb8d7f0cc1022 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 15 Sep 2023 10:27:57 +0200 Subject: [PATCH 185/234] Update rust sdk to 0.1.53 --- gradle/libs.versions.toml | 2 +- .../matrix/impl/auth/RustMatrixAuthenticationService.kt | 2 ++ .../matrix/impl/roomlist/RoomSummaryListProcessor.kt | 8 ++++---- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e8a90f9857..ec3d760a27 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -149,7 +149,7 @@ jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" } appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = { module = "app.cash.molecule:molecule-runtime", version.ref = "molecule" } timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.52" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.53" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "com.squareup.sqldelight:android-driver", version.ref = "sqldelight" } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt index 6014644733..f2acb0b1be 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt @@ -57,6 +57,8 @@ class RustMatrixAuthenticationService @Inject constructor( userAgent = userAgentProvider.provide(), oidcConfiguration = oidcConfiguration, customSlidingSyncProxy = null, + sessionDelegate = null, + crossProcessRefreshLockId = null, ) private var currentHomeserver = MutableStateFlow(null) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt index 03b58ed2ce..4bade9cc81 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt @@ -59,7 +59,7 @@ class RoomSummaryListProcessor( } } - private suspend fun MutableList.applyUpdate(update: RoomListEntriesUpdate) { + private fun MutableList.applyUpdate(update: RoomListEntriesUpdate) { when (update) { is RoomListEntriesUpdate.Append -> { val roomSummaries = update.values.map { @@ -102,7 +102,7 @@ class RoomSummaryListProcessor( } } - private suspend fun buildSummaryForRoomListEntry(entry: RoomListEntry): RoomSummary { + private fun buildSummaryForRoomListEntry(entry: RoomListEntry): RoomSummary { return when (entry) { RoomListEntry.Empty -> buildEmptyRoomSummary() is RoomListEntry.Filled -> buildAndCacheRoomSummaryForIdentifier(entry.roomId) @@ -116,9 +116,9 @@ class RoomSummaryListProcessor( return RoomSummary.Empty(UUID.randomUUID().toString()) } - private suspend fun buildAndCacheRoomSummaryForIdentifier(identifier: String): RoomSummary { + private fun buildAndCacheRoomSummaryForIdentifier(identifier: String): RoomSummary { val builtRoomSummary = roomListService.roomOrNull(identifier)?.use { roomListItem -> - roomListItem.roomInfo().use { roomInfo -> + roomListItem.roomInfoBlocking().use { roomInfo -> RoomSummary.Filled( details = roomSummaryDetailsFactory.create(roomInfo) ) From 0cdc5f514921c633dfc9df23bb043ce8eb565400 Mon Sep 17 00:00:00 2001 From: David Langley Date: Fri, 15 Sep 2023 10:25:10 +0100 Subject: [PATCH 186/234] Cancel scope in tests. --- .../roomlist/impl/RoomListPresenterTests.kt | 52 ++++++++++++++----- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt index 8acaa69830..a9327f64df 100644 --- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt @@ -53,6 +53,9 @@ import io.element.android.libraries.matrix.test.verification.FakeSessionVerifica import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.consumeItemsUntilPredicate import io.element.android.tests.testutils.testCoroutineDispatchers +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.cancel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest @@ -66,7 +69,8 @@ class RoomListPresenterTests { @Test fun `present - should start with no user and then load user with success`() = runTest { - val presenter = createRoomListPresenter() + val scope = CoroutineScope(coroutineContext + SupervisorJob()) + val presenter = createRoomListPresenter(coroutineScope = scope) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -77,6 +81,7 @@ class RoomListPresenterTests { Truth.assertThat(withUserState.matrixUser!!.userId).isEqualTo(A_USER_ID) Truth.assertThat(withUserState.matrixUser!!.displayName).isEqualTo(A_USER_NAME) Truth.assertThat(withUserState.matrixUser!!.avatarUrl).isEqualTo(AN_AVATAR_URL) + scope.cancel() } } @@ -86,7 +91,8 @@ class RoomListPresenterTests { userDisplayName = Result.failure(AN_EXCEPTION), userAvatarURLString = Result.failure(AN_EXCEPTION), ) - val presenter = createRoomListPresenter(matrixClient) + val scope = CoroutineScope(coroutineContext + SupervisorJob()) + val presenter = createRoomListPresenter(client = matrixClient, coroutineScope = scope) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -94,12 +100,14 @@ class RoomListPresenterTests { Truth.assertThat(initialState.matrixUser).isNull() val withUserState = awaitItem() Truth.assertThat(withUserState.matrixUser).isNotNull() + scope.cancel() } } @Test fun `present - should filter room with success`() = runTest { - val presenter = createRoomListPresenter() + val scope = CoroutineScope(coroutineContext + SupervisorJob()) + val presenter = createRoomListPresenter(coroutineScope = scope) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -109,8 +117,8 @@ class RoomListPresenterTests { withUserState.eventSink.invoke(RoomListEvents.UpdateFilter("t")) val withFilterState = awaitItem() Truth.assertThat(withFilterState.filter).isEqualTo("t") - cancelAndIgnoreRemainingEvents() + scope.cancel() } } @@ -120,7 +128,8 @@ class RoomListPresenterTests { val matrixClient = FakeMatrixClient( roomListService = roomListService ) - val presenter = createRoomListPresenter(matrixClient) + val scope = CoroutineScope(coroutineContext + SupervisorJob()) + val presenter = createRoomListPresenter(client = matrixClient, coroutineScope = scope) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -133,6 +142,7 @@ class RoomListPresenterTests { Truth.assertThat(withRoomState.roomList.size).isEqualTo(1) Truth.assertThat(withRoomState.roomList.first()) .isEqualTo(aRoomListRoomSummary) + scope.cancel() } } @@ -142,7 +152,8 @@ class RoomListPresenterTests { val matrixClient = FakeMatrixClient( roomListService = roomListService ) - val presenter = createRoomListPresenter(matrixClient) + val scope = CoroutineScope(coroutineContext + SupervisorJob()) + val presenter = createRoomListPresenter(matrixClient, coroutineScope = scope) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -160,6 +171,7 @@ class RoomListPresenterTests { val withNotFilteredRoomState = consumeItemsUntilPredicate { state -> state.filteredRoomList.size == 0 }.last() Truth.assertThat(withNotFilteredRoomState.filter).isEqualTo("tada") Truth.assertThat(withNotFilteredRoomState.filteredRoomList).isEmpty() + scope.cancel() } } @@ -169,7 +181,8 @@ class RoomListPresenterTests { val matrixClient = FakeMatrixClient( roomListService = roomListService ) - val presenter = createRoomListPresenter(matrixClient) + val scope = CoroutineScope(coroutineContext + SupervisorJob()) + val presenter = createRoomListPresenter(client = matrixClient, coroutineScope = scope) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -200,6 +213,7 @@ class RoomListPresenterTests { Truth.assertThat(roomListService.latestSlidingSyncRange) .isEqualTo(IntRange(129, 279)) cancelAndIgnoreRemainingEvents() + scope.cancel() } } @@ -209,12 +223,14 @@ class RoomListPresenterTests { val matrixClient = FakeMatrixClient( roomListService = roomListService, ) + val scope = CoroutineScope(context = coroutineContext + SupervisorJob()) val presenter = createRoomListPresenter( client = matrixClient, sessionVerificationService = FakeSessionVerificationService().apply { givenIsReady(true) givenVerifiedStatus(SessionVerifiedStatus.NotVerified) }, + coroutineScope = scope, ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -224,6 +240,7 @@ class RoomListPresenterTests { eventSink(RoomListEvents.DismissRequestVerificationPrompt) Truth.assertThat(awaitItem().displayVerificationPrompt).isFalse() + scope.cancel() } } @@ -231,7 +248,8 @@ class RoomListPresenterTests { fun `present - sets invite state`() = runTest { val inviteStateFlow = MutableStateFlow(InvitesState.NoInvites) val inviteStateDataSource = FakeInviteDataSource(inviteStateFlow) - val presenter = createRoomListPresenter(inviteStateDataSource = inviteStateDataSource) + val scope = CoroutineScope(coroutineContext + SupervisorJob()) + val presenter = createRoomListPresenter(inviteStateDataSource = inviteStateDataSource, coroutineScope = scope) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -246,12 +264,14 @@ class RoomListPresenterTests { inviteStateFlow.value = InvitesState.NoInvites Truth.assertThat(awaitItem().invitesState).isEqualTo(InvitesState.NoInvites) + scope.cancel() } } @Test fun `present - show context menu`() = runTest { - val presenter = createRoomListPresenter() + val scope = CoroutineScope(coroutineContext + SupervisorJob()) + val presenter = createRoomListPresenter(coroutineScope = scope) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -264,12 +284,14 @@ class RoomListPresenterTests { val shownState = awaitItem() Truth.assertThat(shownState.contextMenu) .isEqualTo(RoomListState.ContextMenu.Shown(summary.roomId, summary.name)) + scope.cancel() } } @Test fun `present - hide context menu`() = runTest { - val presenter = createRoomListPresenter() + val scope = CoroutineScope(coroutineContext + SupervisorJob()) + val presenter = createRoomListPresenter(coroutineScope = scope) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -286,13 +308,15 @@ class RoomListPresenterTests { val hiddenState = awaitItem() Truth.assertThat(hiddenState.contextMenu).isEqualTo(RoomListState.ContextMenu.Hidden) + scope.cancel() } } @Test fun `present - leave room calls into leave room presenter`() = runTest { val leaveRoomPresenter = LeaveRoomPresenterFake() - val presenter = createRoomListPresenter(leaveRoomPresenter = leaveRoomPresenter) + val scope = CoroutineScope(coroutineContext + SupervisorJob()) + val presenter = createRoomListPresenter(leaveRoomPresenter = leaveRoomPresenter, coroutineScope = scope) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -300,6 +324,7 @@ class RoomListPresenterTests { initialState.eventSink(RoomListEvents.LeaveRoom(A_ROOM_ID)) Truth.assertThat(leaveRoomPresenter.events).containsExactly(LeaveRoomEvent.ShowConfirmation(A_ROOM_ID)) cancelAndIgnoreRemainingEvents() + scope.cancel() } } @@ -313,7 +338,8 @@ class RoomListPresenterTests { lastMessageTimestampFormatter: LastMessageTimestampFormatter = FakeLastMessageTimestampFormatter().apply { givenFormat(A_FORMATTED_DATE) }, - roomLastMessageFormatter: RoomLastMessageFormatter = FakeRoomLastMessageFormatter() + roomLastMessageFormatter: RoomLastMessageFormatter = FakeRoomLastMessageFormatter(), + coroutineScope: CoroutineScope = this ) = RoomListPresenter( client = client, sessionVerificationService = sessionVerificationService, @@ -327,7 +353,7 @@ class RoomListPresenterTests { roomLastMessageFormatter, coroutineDispatchers = testCoroutineDispatchers(), notificationSettingsService = client.notificationSettingsService(), - appScope = this + appScope = coroutineScope ) ) } From 4a3ffd37fb0b28b535d821911cef242e57fee598 Mon Sep 17 00:00:00 2001 From: David Langley Date: Fri, 15 Sep 2023 10:42:54 +0100 Subject: [PATCH 187/234] Use userDefinedNotificationMode. --- .../libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt index f9f63ab271..a9d46296db 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt @@ -40,7 +40,7 @@ class RoomSummaryDetailsFactory(private val roomMessageFactory: RoomMessageFacto lastMessage = latestRoomMessage, lastMessageTimestamp = latestRoomMessage?.originServerTs, inviter = roomInfo.inviter?.let(RoomMemberMapper::map), - notificationMode = roomInfo.notificationMode?.let(RoomNotificationSettingsMapper::mapMode), + notificationMode = roomInfo.userDefinedNotificationMode?.let(RoomNotificationSettingsMapper::mapMode), ) } } From db02b0cd67d4915efcb1c98a25bcec0e9fee61d0 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 15 Sep 2023 10:01:18 +0000 Subject: [PATCH 188/234] Update screenshots --- ...nents_null_RoomSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...nents_null_RoomSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...nents_null_RoomSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...nents_null_RoomSummaryRowDark_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...nents_null_RoomSummaryRowDark_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...nents_null_RoomSummaryRowDark_0_null_7,NEXUS_5,1.0,en].png | 3 +++ ...ents_null_RoomSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...ents_null_RoomSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...ents_null_RoomSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...ents_null_RoomSummaryRowLight_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...ents_null_RoomSummaryRowLight_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...ents_null_RoomSummaryRowLight_0_null_7,NEXUS_5,1.0,en].png | 3 +++ 12 files changed, 26 insertions(+), 20 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_7,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_7,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png index 5d673a1cff..e35b511282 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e710857b4a1c3da12ceb51e7400229d0fd7f42d6d6158a07e2c2814c728abfdc -size 12229 +oid sha256:1dd44adb59ebe1ac95bc9483c61d09cc2b59307b0e2f86883f1639ae35819b0f +size 12544 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png index d0ec7b4cb1..7d20bddd45 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:db014e76a88015053b1be458ac758dde99f8cf01a7a78850c0bf6ff4db27dcbc -size 13173 +oid sha256:6ca678d3cb26b3224c1fe44169eebd0a96ddcc344e2d9d45ff84c41116c03a0e +size 13829 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png index 606a183dce..b27b7924e2 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4d062feda6fc808aa87df5a5f4b3229153f7e50925e3c55a8c8a99a583212857 -size 13458 +oid sha256:8618c1af337c98cbd812632fc6dbb468b64a3b53e2141a7073a5ea52656ddaa7 +size 13611 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_5,NEXUS_5,1.0,en].png index 805e00c2b7..606a183dce 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7cd7f6969aa48fdde75e1ad046d595882ebdadfc310cd6b6753f43895aec7b99 -size 6281 +oid sha256:4d062feda6fc808aa87df5a5f4b3229153f7e50925e3c55a8c8a99a583212857 +size 13458 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_6,NEXUS_5,1.0,en].png index 7078257343..805e00c2b7 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:79b24ca5c6426aa966024d79bdbbc4a612169037cf6bda7496299ea298fa7517 -size 21951 +oid sha256:7cd7f6969aa48fdde75e1ad046d595882ebdadfc310cd6b6753f43895aec7b99 +size 6281 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_7,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..7078257343 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_7,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:79b24ca5c6426aa966024d79bdbbc4a612169037cf6bda7496299ea298fa7517 +size 21951 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png index e471eae254..ec64e498e6 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9c9b33e480bfad9c55d55e25cef2a0ab1f25235382e1b53c93107a75e95fa90e -size 11840 +oid sha256:f3d6f98e42089d2b8b1992a3aeb8c1c91847c3975d3759c00dc75bc85fb0ba5d +size 12195 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png index 582d30fdfc..d08e94a349 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:824e708f277ea66a161f17cb07a3070e03ddcfc326b9dd73d0ad6b7e62da32c1 -size 12807 +oid sha256:6f6bfe205fe096afe6d976ed242d823d02d06a01b8f81e5feca7b9a71d7b5767 +size 13543 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png index 0de6b64bec..4a51acc8ba 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:39b7b8354b98bca791698ad65f4e21619136f446b2fd050c302bdd27ce138a4a -size 13263 +oid sha256:8337468ce85f5f1aa9fec867d9037b71c7460fa823c7f6fdcbf0efe48ad97d40 +size 13293 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_5,NEXUS_5,1.0,en].png index 6bfb7eeabe..0de6b64bec 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c978bc799ab79290f89568de692d3ace219a4192ec9706fef63fe977a853f74d -size 6046 +oid sha256:39b7b8354b98bca791698ad65f4e21619136f446b2fd050c302bdd27ce138a4a +size 13263 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_6,NEXUS_5,1.0,en].png index fcf8b20fdc..6bfb7eeabe 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:64e7ca21b0213413ed45d0640295ceb2764b01b2bce20a01518e55e620925086 -size 22193 +oid sha256:c978bc799ab79290f89568de692d3ace219a4192ec9706fef63fe977a853f74d +size 6046 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_7,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..fcf8b20fdc --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_7,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:64e7ca21b0213413ed45d0640295ceb2764b01b2bce20a01518e55e620925086 +size 22193 From c64b38cf0495de77455a16c8c0a664f7c739f560 Mon Sep 17 00:00:00 2001 From: jonnyandrew Date: Fri, 15 Sep 2023 11:11:43 +0100 Subject: [PATCH 189/234] Fix placeholder spilling onto multiple lines --- .../io/element/android/libraries/textcomposer/TextComposer.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt index b7c2b8ea40..8ac4ddf48f 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt @@ -274,6 +274,8 @@ private fun TextInput( style = defaultTypography.copy( color = ElementTheme.colors.textDisabled, ), + maxLines = 1, + overflow = TextOverflow.Ellipsis, ) } From 9583171aa26f8556ba824dd7cdd58098e7434af7 Mon Sep 17 00:00:00 2001 From: jonnyandrew Date: Fri, 15 Sep 2023 11:14:30 +0100 Subject: [PATCH 190/234] Add changelog --- changelog.d/1347.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/1347.bugfix diff --git a/changelog.d/1347.bugfix b/changelog.d/1347.bugfix new file mode 100644 index 0000000000..277efb1c95 --- /dev/null +++ b/changelog.d/1347.bugfix @@ -0,0 +1 @@ +[Rich text editor] Fix placeholder spilling onto multiple lines \ No newline at end of file From 6563dca4f2c271441010b7e09682b93d2a6253c3 Mon Sep 17 00:00:00 2001 From: jonnyandrew Date: Fri, 15 Sep 2023 11:16:30 +0100 Subject: [PATCH 191/234] [Rich text editor] Update design (#1332) * Fix composer height and padding * Update plus and cancel icons with design system icons * Update border so that it is always visible * Update placeholder color * Update send and tick icons * Update design of formatting buttons * Update RTE icons * Reduce bottom padding --------- Co-authored-by: ElementBot --- changelog.d/1332.feature | 1 + .../libraries/designsystem/VectorIcons.kt | 2 + .../designsystem/theme/ColorAliases.kt | 11 +++ .../src/main/res/drawable/ic_bold.xml | 10 +-- .../src/main/res/drawable/ic_bullet_list.xml | 10 +-- .../src/main/res/drawable/ic_cancel.xml | 26 +++++++ .../src/main/res/drawable/ic_code_block.xml | 10 +-- .../main/res/drawable/ic_indent_decrease.xml | 10 +-- .../main/res/drawable/ic_indent_increase.xml | 10 +-- .../src/main/res/drawable/ic_inline_code.xml | 14 ++-- .../src/main/res/drawable/ic_italic.xml | 10 +-- .../src/main/res/drawable/ic_link.xml | 10 +-- .../main/res/drawable/ic_numbered_list.xml | 10 +-- .../src/main/res/drawable/ic_plus.xml | 29 ++++++++ .../src/main/res/drawable/ic_quote.xml | 16 ++--- .../main/res/drawable/ic_strikethrough.xml | 10 +-- .../src/main/res/drawable/ic_underline.xml | 10 +-- .../libraries/textcomposer/TextComposer.kt | 29 ++++---- .../components/FormattingOption.kt | 69 ++++++++++++++++--- .../impl/src/main/res/drawable/ic_cancel.xml | 9 --- .../impl/src/main/res/drawable/ic_plus.xml | 9 --- .../impl/src/main/res/drawable/ic_send.xml | 28 ++++++-- .../impl/src/main/res/drawable/ic_tick.xml | 10 +-- ...poserViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...oserViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...sagesViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...sagesViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 +- ...sagesViewDark_0_null_2,NEXUS_5,1.0,en].png | 4 +- ...sagesViewDark_0_null_4,NEXUS_5,1.0,en].png | 4 +- ...sagesViewDark_0_null_5,NEXUS_5,1.0,en].png | 4 +- ...agesViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 +- ...agesViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 +- ...agesViewLight_0_null_2,NEXUS_5,1.0,en].png | 4 +- ...agesViewLight_0_null_4,NEXUS_5,1.0,en].png | 4 +- ...agesViewLight_0_null_5,NEXUS_5,1.0,en].png | 4 +- ...olorAliasesDark_0_null,NEXUS_5,1.0,en].png | 4 +- ...lorAliasesLight_0_null,NEXUS_5,1.0,en].png | 4 +- ...ttingButton-D-4_5_null,NEXUS_5,1.0,en].png | 3 + ...ttingButton-N-4_6_null,NEXUS_5,1.0,en].png | 3 + ...omposerEdit-D-2_3_null,NEXUS_5,1.0,en].png | 4 +- ...omposerEdit-N-2_4_null,NEXUS_5,1.0,en].png | 4 +- ...rFormatting-D-1_2_null,NEXUS_5,1.0,en].png | 4 +- ...rFormatting-N-1_3_null,NEXUS_5,1.0,en].png | 4 +- ...mposerReply-D-3_4_null,NEXUS_5,1.0,en].png | 4 +- ...mposerReply-N-3_5_null,NEXUS_5,1.0,en].png | 4 +- ...poserSimple-D-0_1_null,NEXUS_5,1.0,en].png | 4 +- ...poserSimple-N-0_2_null,NEXUS_5,1.0,en].png | 4 +- 47 files changed, 282 insertions(+), 165 deletions(-) create mode 100644 changelog.d/1332.feature create mode 100644 libraries/designsystem/src/main/res/drawable/ic_cancel.xml create mode 100644 libraries/designsystem/src/main/res/drawable/ic_plus.xml delete mode 100644 libraries/textcomposer/impl/src/main/res/drawable/ic_cancel.xml delete mode 100644 libraries/textcomposer/impl/src/main/res/drawable/ic_plus.xml create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer.components_null_FormattingButton-D-4_5_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer.components_null_FormattingButton-N-4_6_null,NEXUS_5,1.0,en].png diff --git a/changelog.d/1332.feature b/changelog.d/1332.feature new file mode 100644 index 0000000000..2a08ae9d25 --- /dev/null +++ b/changelog.d/1332.feature @@ -0,0 +1 @@ +[Rich text editor] Update design \ No newline at end of file diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt index 0194e86518..5f9764d8f9 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/VectorIcons.kt @@ -42,4 +42,6 @@ object VectorIcons { val Strikethrough = R.drawable.ic_strikethrough val Underline = R.drawable.ic_underline val ThreadDecoration = R.drawable.ic_thread_decoration + val Plus = R.drawable.ic_plus + val Cancel = R.drawable.ic_cancel } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ColorAliases.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ColorAliases.kt index 77ca4bd010..e7878f9bed 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ColorAliases.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ColorAliases.kt @@ -75,6 +75,16 @@ val SemanticColors.progressIndicatorTrackColor Color(0x25F4F7FA) } +// This color is not present in Semantic color, so put hard-coded value for now +val SemanticColors.iconSuccessPrimaryBackground + get() = if (isLight) { + // We want LightDesignTokens.colorGreen300 + Color(0xffe3f7ed) + } else { + // We want DarkDesignTokens.colorGreen300 + Color(0xff002513) + } + // Temporary color, which is not in the token right now val SemanticColors.temporaryColorBgSpecial get() = if (isLight) Color(0xFFE4E8F0) else Color(0xFF3A4048) @@ -102,6 +112,7 @@ private fun ContentToPreview() { "messageFromOtherBackground" to ElementTheme.colors.messageFromOtherBackground, "progressIndicatorTrackColor" to ElementTheme.colors.progressIndicatorTrackColor, "temporaryColorBgSpecial" to ElementTheme.colors.temporaryColorBgSpecial, + "iconSuccessPrimaryBackground" to ElementTheme.colors.iconSuccessPrimaryBackground, ) ) } diff --git a/libraries/designsystem/src/main/res/drawable/ic_bold.xml b/libraries/designsystem/src/main/res/drawable/ic_bold.xml index c361f85d3d..5a08fee2f3 100644 --- a/libraries/designsystem/src/main/res/drawable/ic_bold.xml +++ b/libraries/designsystem/src/main/res/drawable/ic_bold.xml @@ -1,9 +1,9 @@ + android:width="20dp" + android:height="20dp" + android:viewportWidth="20" + android:viewportHeight="20"> diff --git a/libraries/designsystem/src/main/res/drawable/ic_bullet_list.xml b/libraries/designsystem/src/main/res/drawable/ic_bullet_list.xml index 72d8324622..103d0b380d 100644 --- a/libraries/designsystem/src/main/res/drawable/ic_bullet_list.xml +++ b/libraries/designsystem/src/main/res/drawable/ic_bullet_list.xml @@ -1,9 +1,9 @@ + android:width="20dp" + android:height="20dp" + android:viewportWidth="20" + android:viewportHeight="20"> diff --git a/libraries/designsystem/src/main/res/drawable/ic_cancel.xml b/libraries/designsystem/src/main/res/drawable/ic_cancel.xml new file mode 100644 index 0000000000..3e4ee21aee --- /dev/null +++ b/libraries/designsystem/src/main/res/drawable/ic_cancel.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/libraries/designsystem/src/main/res/drawable/ic_code_block.xml b/libraries/designsystem/src/main/res/drawable/ic_code_block.xml index 6e622f5b27..18279bd8b5 100644 --- a/libraries/designsystem/src/main/res/drawable/ic_code_block.xml +++ b/libraries/designsystem/src/main/res/drawable/ic_code_block.xml @@ -1,9 +1,9 @@ + android:width="20dp" + android:height="20dp" + android:viewportWidth="20" + android:viewportHeight="20"> diff --git a/libraries/designsystem/src/main/res/drawable/ic_indent_decrease.xml b/libraries/designsystem/src/main/res/drawable/ic_indent_decrease.xml index 5a0b284223..181f94c012 100644 --- a/libraries/designsystem/src/main/res/drawable/ic_indent_decrease.xml +++ b/libraries/designsystem/src/main/res/drawable/ic_indent_decrease.xml @@ -1,9 +1,9 @@ + android:width="20dp" + android:height="20dp" + android:viewportWidth="20" + android:viewportHeight="20"> diff --git a/libraries/designsystem/src/main/res/drawable/ic_indent_increase.xml b/libraries/designsystem/src/main/res/drawable/ic_indent_increase.xml index 367686ceac..06a9ede8d5 100644 --- a/libraries/designsystem/src/main/res/drawable/ic_indent_increase.xml +++ b/libraries/designsystem/src/main/res/drawable/ic_indent_increase.xml @@ -1,9 +1,9 @@ + android:width="20dp" + android:height="20dp" + android:viewportWidth="20" + android:viewportHeight="20"> diff --git a/libraries/designsystem/src/main/res/drawable/ic_inline_code.xml b/libraries/designsystem/src/main/res/drawable/ic_inline_code.xml index c0dc504ed9..c15248f8ea 100644 --- a/libraries/designsystem/src/main/res/drawable/ic_inline_code.xml +++ b/libraries/designsystem/src/main/res/drawable/ic_inline_code.xml @@ -1,15 +1,15 @@ + android:width="20dp" + android:height="20dp" + android:viewportWidth="20" + android:viewportHeight="20"> diff --git a/libraries/designsystem/src/main/res/drawable/ic_italic.xml b/libraries/designsystem/src/main/res/drawable/ic_italic.xml index f640c109f4..0a389dbf15 100644 --- a/libraries/designsystem/src/main/res/drawable/ic_italic.xml +++ b/libraries/designsystem/src/main/res/drawable/ic_italic.xml @@ -1,9 +1,9 @@ + android:width="20dp" + android:height="20dp" + android:viewportWidth="20" + android:viewportHeight="20"> diff --git a/libraries/designsystem/src/main/res/drawable/ic_link.xml b/libraries/designsystem/src/main/res/drawable/ic_link.xml index fd69ec4703..c8a37cdda2 100644 --- a/libraries/designsystem/src/main/res/drawable/ic_link.xml +++ b/libraries/designsystem/src/main/res/drawable/ic_link.xml @@ -1,9 +1,9 @@ + android:width="20dp" + android:height="20dp" + android:viewportWidth="20" + android:viewportHeight="20"> diff --git a/libraries/designsystem/src/main/res/drawable/ic_numbered_list.xml b/libraries/designsystem/src/main/res/drawable/ic_numbered_list.xml index f4f5862656..63e7269508 100644 --- a/libraries/designsystem/src/main/res/drawable/ic_numbered_list.xml +++ b/libraries/designsystem/src/main/res/drawable/ic_numbered_list.xml @@ -1,9 +1,9 @@ + android:width="20dp" + android:height="20dp" + android:viewportWidth="20" + android:viewportHeight="20"> diff --git a/libraries/designsystem/src/main/res/drawable/ic_plus.xml b/libraries/designsystem/src/main/res/drawable/ic_plus.xml new file mode 100644 index 0000000000..159ed32e1a --- /dev/null +++ b/libraries/designsystem/src/main/res/drawable/ic_plus.xml @@ -0,0 +1,29 @@ + + + + + + diff --git a/libraries/designsystem/src/main/res/drawable/ic_quote.xml b/libraries/designsystem/src/main/res/drawable/ic_quote.xml index e17565a6cc..8f4768f818 100644 --- a/libraries/designsystem/src/main/res/drawable/ic_quote.xml +++ b/libraries/designsystem/src/main/res/drawable/ic_quote.xml @@ -1,18 +1,18 @@ + android:width="20dp" + android:height="20dp" + android:viewportWidth="20" + android:viewportHeight="20"> diff --git a/libraries/designsystem/src/main/res/drawable/ic_strikethrough.xml b/libraries/designsystem/src/main/res/drawable/ic_strikethrough.xml index d1994f8045..4469c5572d 100644 --- a/libraries/designsystem/src/main/res/drawable/ic_strikethrough.xml +++ b/libraries/designsystem/src/main/res/drawable/ic_strikethrough.xml @@ -1,9 +1,9 @@ + android:width="20dp" + android:height="20dp" + android:viewportWidth="20" + android:viewportHeight="20"> diff --git a/libraries/designsystem/src/main/res/drawable/ic_underline.xml b/libraries/designsystem/src/main/res/drawable/ic_underline.xml index 09f92f2104..9da2f2e0b4 100644 --- a/libraries/designsystem/src/main/res/drawable/ic_underline.xml +++ b/libraries/designsystem/src/main/res/drawable/ic_underline.xml @@ -1,9 +1,9 @@ + android:width="20dp" + android:height="20dp" + android:viewportWidth="20" + android:viewportHeight="20"> diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt index b7c2b8ea40..d8906a49b0 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt @@ -114,7 +114,7 @@ fun TextComposer( start = 3.dp, end = 6.dp, top = 8.dp, - bottom = 5.dp, + bottom = 4.dp, ) .fillMaxWidth(), ) { @@ -137,7 +137,7 @@ fun TextComposer( ) { Icon( modifier = Modifier.size(30.dp.applyScaleUp()), - resourceId = R.drawable.ic_plus, // TODO Replace with design system icon when available + resourceId = VectorIcons.Plus, contentDescription = stringResource(R.string.rich_text_editor_a11y_add_attachment), tint = ElementTheme.colors.iconPrimary, ) @@ -146,7 +146,7 @@ fun TextComposer( val roundCornerLarge = 28.dp.applyScaleUp() val roundedCornerSize = remember(state.lineCount, composerMode) { - if (state.lineCount > 1 || composerMode is MessageComposerMode.Special) { + if (composerMode is MessageComposerMode.Special) { roundCornerSmall } else { roundCornerLarge @@ -156,17 +156,13 @@ fun TextComposer( targetValue = roundedCornerSize, animationSpec = tween( durationMillis = 100, - ) + ), + label = "roundedCornerSizeAnimation" ) val roundedCorners = RoundedCornerShape(roundedCornerSizeState.value) val colors = ElementTheme.colors val bgColor = colors.bgSubtleSecondary - - val borderColor by remember(state.hasFocus, colors) { - derivedStateOf { - if (state.hasFocus) colors.borderDisabled else bgColor - } - } + val borderColor = colors.borderDisabled Column( modifier = Modifier @@ -180,7 +176,7 @@ fun TextComposer( .fillMaxWidth() .clip(roundedCorners) .background(color = bgColor) - .border(1.dp, borderColor, roundedCorners) + .border(0.5.dp, borderColor, roundedCorners) ) { if (composerMode is MessageComposerMode.Special) { ComposerModeView(composerMode = composerMode, onResetComposerMode = onResetComposerMode) @@ -272,7 +268,7 @@ private fun TextInput( Text( placeholder, style = defaultTypography.copy( - color = ElementTheme.colors.textDisabled, + color = ElementTheme.colors.textSecondary, ), ) } @@ -280,6 +276,7 @@ private fun TextInput( RichTextEditor( state = state, modifier = Modifier + .padding(top = 6.dp, bottom = 6.dp) .fillMaxWidth(), style = RichTextEditorDefaults.style( text = RichTextEditorDefaults.textStyle( @@ -323,7 +320,7 @@ private fun TextFormatting( ) { Icon( modifier = Modifier.size(30.dp.applyScaleUp()), - resourceId = R.drawable.ic_cancel, // TODO Replace with design system icon when available + resourceId = VectorIcons.Cancel, contentDescription = stringResource(CommonStrings.action_close), tint = ElementTheme.colors.iconPrimary, ) @@ -335,8 +332,8 @@ private fun TextFormatting( .constrainAs(formatting) { top.linkTo(parent.top) bottom.linkTo(parent.bottom) - start.linkTo(close.end, margin = 3.dp) - end.linkTo(send.start, margin = 20.dp) + start.linkTo(close.end, margin = 1.dp) + end.linkTo(send.start, margin = 14.dp) width = fillToConstraints } .horizontalScroll(scrollState), @@ -589,7 +586,7 @@ private fun SendButton( ) { Icon( modifier = Modifier - .height(18.dp.applyScaleUp()) + .height(24.dp.applyScaleUp()) .align(Alignment.Center), resourceId = iconId, contentDescription = contentDescription, diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/FormattingOption.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/FormattingOption.kt index 7eb1d08293..a3635b28c3 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/FormattingOption.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/FormattingOption.kt @@ -18,17 +18,26 @@ package io.element.android.libraries.textcomposer.components import androidx.compose.foundation.background import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.ripple.rememberRipple import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.vectorResource import androidx.compose.ui.unit.dp +import io.element.android.libraries.designsystem.VectorIcons +import io.element.android.libraries.designsystem.preview.DayNightPreviews +import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.text.applyScaleUp import io.element.android.libraries.designsystem.theme.components.Icon +import io.element.android.libraries.designsystem.theme.iconSuccessPrimaryBackground import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.compound.generated.SemanticColors @@ -42,27 +51,65 @@ internal fun FormattingOption( colors: SemanticColors = ElementTheme.colors, ) { val backgroundColor = when (state) { - FormattingOptionState.Selected -> colors.bgActionPrimaryRest + FormattingOptionState.Selected -> colors.iconSuccessPrimaryBackground FormattingOptionState.Default, FormattingOptionState.Disabled -> Color.Transparent } val foregroundColor = when (state) { - FormattingOptionState.Selected -> colors.iconOnSolidPrimary - FormattingOptionState.Default -> colors.iconPrimary + FormattingOptionState.Selected -> colors.iconSuccessPrimary + FormattingOptionState.Default -> colors.iconSecondary FormattingOptionState.Disabled -> colors.iconDisabled } Box( modifier = modifier - .clickable { onClick() } - .size(44.dp.applyScaleUp()) - .background(backgroundColor, shape = RoundedCornerShape(4.dp.applyScaleUp())) + .clickable( + onClick = onClick, + interactionSource = remember { MutableInteractionSource() }, + indication = rememberRipple( + bounded = false, + radius = 20.dp, + ), + ) + .size(48.dp.applyScaleUp()) ) { - Icon( - modifier = Modifier.align(Alignment.Center), - imageVector = imageVector, - contentDescription = contentDescription, - tint = foregroundColor, + Box( + modifier = Modifier + .size(36.dp.applyScaleUp()) + .align(Alignment.Center) + .background(backgroundColor, shape = RoundedCornerShape(8.dp.applyScaleUp())) + ) { + Icon( + modifier = Modifier.align(Alignment.Center), + imageVector = imageVector, + contentDescription = contentDescription, + tint = foregroundColor, + ) + } + } +} + +@DayNightPreviews +@Composable +internal fun FormattingButtonPreview() = ElementPreview { + Row { + FormattingOption( + state = FormattingOptionState.Default, + onClick = { }, + imageVector = ImageVector.vectorResource(VectorIcons.Bold), + contentDescription = "", + ) + FormattingOption( + state = FormattingOptionState.Selected, + onClick = { }, + imageVector = ImageVector.vectorResource(VectorIcons.Italic), + contentDescription = "", + ) + FormattingOption( + state = FormattingOptionState.Disabled, + onClick = { }, + imageVector = ImageVector.vectorResource(VectorIcons.Underline), + contentDescription = "", ) } } diff --git a/libraries/textcomposer/impl/src/main/res/drawable/ic_cancel.xml b/libraries/textcomposer/impl/src/main/res/drawable/ic_cancel.xml deleted file mode 100644 index 5c27ba82d9..0000000000 --- a/libraries/textcomposer/impl/src/main/res/drawable/ic_cancel.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/libraries/textcomposer/impl/src/main/res/drawable/ic_plus.xml b/libraries/textcomposer/impl/src/main/res/drawable/ic_plus.xml deleted file mode 100644 index ead38721dc..0000000000 --- a/libraries/textcomposer/impl/src/main/res/drawable/ic_plus.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/libraries/textcomposer/impl/src/main/res/drawable/ic_send.xml b/libraries/textcomposer/impl/src/main/res/drawable/ic_send.xml index bf346b3a01..2ed6e6e53e 100644 --- a/libraries/textcomposer/impl/src/main/res/drawable/ic_send.xml +++ b/libraries/textcomposer/impl/src/main/res/drawable/ic_send.xml @@ -1,9 +1,25 @@ + + + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + android:pathData="M21.829,13.085 L6.259,20.867c-1.049,0.525 -2.141,-0.601 -1.628,-1.627 0,0 1.93,-3.897 2.461,-4.918 0.531,-1.021 1.138,-1.197 6.781,-1.927 0.209,-0.027 0.38,-0.185 0.38,-0.395 0,-0.21 -0.171,-0.368 -0.38,-0.395C8.23,10.876 7.622,10.699 7.091,9.678c-0.531,-1.02 -2.461,-4.918 -2.461,-4.918 -0.513,-1.026 0.579,-2.152 1.628,-1.627L21.829,10.915c0.894,0.446 0.894,1.723 0,2.17z" + android:fillColor="#ffffff"/> diff --git a/libraries/textcomposer/impl/src/main/res/drawable/ic_tick.xml b/libraries/textcomposer/impl/src/main/res/drawable/ic_tick.xml index cf1d71a56f..dd7863bab8 100644 --- a/libraries/textcomposer/impl/src/main/res/drawable/ic_tick.xml +++ b/libraries/textcomposer/impl/src/main/res/drawable/ic_tick.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewDark_0_null_0,NEXUS_5,1.0,en].png index 67b7525ddc..c5fc8a7df4 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6bf428927e9a3493284d9fa7ba307b51315ed52b317a60ac345e87ba70849d0f -size 10523 +oid sha256:b237f45b9db8f1a7ac6dde6a2f513d28d697f6251e4a384a4b343daa417d3f15 +size 10441 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewLight_0_null_0,NEXUS_5,1.0,en].png index 8007500f81..f88e231886 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl.messagecomposer_null_MessageComposerViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6eced1d7173c2d0100351f5bb9cd14c649a826b2e355e426b9c6d4add90015d9 -size 10833 +oid sha256:933d3530f5267dd015c1a80536c92428b4b5018a76952f5911782acc2d82b53a +size 10813 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_0,NEXUS_5,1.0,en].png index a80b2ce36d..e01bc2261a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b55dbcb731dfc40a1e100e8caf26802f759b4bcd186dbbc4432644db08f8316 -size 52141 +oid sha256:ed4ba249dab6dc1e906bfb70886b531c4bf76e3acae8b8162496afe3b5a0f572 +size 52085 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_1,NEXUS_5,1.0,en].png index 03f50fe82f..bf8898fadc 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d5953ae4bb021c39157b4118ea628ca9bb2277f9672749cc6313f0b378d31cb8 -size 53312 +oid sha256:9cfd42ac1e4931d4fb01ac8cecffa635adc92d67f1107a4c4051d66eeaab954a +size 53336 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png index 8d7e2dcf95..78bffbdb73 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c329165fa341a2130b43a448b8bba465f1e5f458136efa6da80f2cdeee9d6caa -size 52369 +oid sha256:7eac088a0d14a2b1b85f541d0df5a1d38bdca3f7612560770bbfcffe0c1b2389 +size 52442 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_4,NEXUS_5,1.0,en].png index 35d5965ff3..7a830c8020 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dc662d180d1766706f249f1585fb100f5933206b65d4644fae65abc6a121a633 -size 51331 +oid sha256:9c65887eeeff0a815136ddfe9dbfae86d60e6abf4f409192d7950aad01c0bb0c +size 51098 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_5,NEXUS_5,1.0,en].png index b2e621fc71..04a7cbfe71 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewDark_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:db0107e648e2acfc253d83f5e3b2f3e41de1abc9bdc4922dfd923ad4e50b8f5f -size 49700 +oid sha256:eddb7e59898d7aaf644f958ae0b05578b7e1ef3802e352d7fb78651c2de97cf6 +size 49638 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_0,NEXUS_5,1.0,en].png index 65cdf717bb..a960aed41d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3eb1479510a8cd04d133265e33ea15115158ac55c93387d1dafa93a3a3a858f0 -size 53620 +oid sha256:53bafb3688148dbeb3859aef1b8a9bf086340fc799f3d825ed246eba0cdda0f6 +size 53463 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_1,NEXUS_5,1.0,en].png index a5959f6d60..87c5b51154 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c0d5272b14b347f18b2d67d5fae6eaf507b8d6f7c9d361317bb6b8a062e63ceb -size 54899 +oid sha256:22854689cac05b6ff1ec58a2b086c751516938161b844694b9300641de5e6ca9 +size 54871 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png index ec09599aca..6d8c175733 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b4e5e9d920ea2a7733453e030bb365c9e2af7263de8fe216ab56088e0861fa5 -size 53997 +oid sha256:ea6bebc608259c37a2b88c14e6b247696a2f9967152bcf2eb0c2a5d70f540ee4 +size 53944 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_4,NEXUS_5,1.0,en].png index 8212494315..7071e778c7 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dff46ed537c81602be0dea8782e37bb78669ee798ec4d422c23ff29cbbdebc17 -size 55927 +oid sha256:885000bd08b05ca49eddbae17aa672fbf10a3acdcaf64d71fef77888229ae5c5 +size 55813 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_5,NEXUS_5,1.0,en].png index cbdda6b794..1bac3210f9 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.messages.impl_null_MessagesViewLight_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e162503c27609f01e05bb2c634c2d3123abf6e786ecfe763c902d400ead050f -size 51283 +oid sha256:f1fd5d62a43ccfca8e157371068dcf125a72cd22920df447689b50464d8d42e6 +size 51137 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme_null_ColorAliasesDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme_null_ColorAliasesDark_0_null,NEXUS_5,1.0,en].png index b1c6c996d8..014374fdb1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme_null_ColorAliasesDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme_null_ColorAliasesDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d57924194a017902912825d4f43fcd290db11430d4d64abd89abe39b9e2ffc27 -size 48726 +oid sha256:e6625c102a88cc1096fea5425d044a96ef6e403317fa944cef8ec1ce5cd63a23 +size 52632 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme_null_ColorAliasesLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme_null_ColorAliasesLight_0_null,NEXUS_5,1.0,en].png index eaf130c209..c23cc8a0e2 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme_null_ColorAliasesLight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme_null_ColorAliasesLight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0eaa20c7c00c18cf08135aca70407d55ea9fc33a7f262aee3fa6ced272f7ab16 -size 48465 +oid sha256:dc7900cfc6a214acef16f642a2273088abef88f99cbf68b1aa99e43daab837ca +size 52528 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer.components_null_FormattingButton-D-4_5_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer.components_null_FormattingButton-D-4_5_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..3c7c46d2da --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer.components_null_FormattingButton-D-4_5_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d4a44b93e0791e4fdf7d9bd11e0d9a0fff44a271530d01ff0e6aa1e8789742ef +size 6297 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer.components_null_FormattingButton-N-4_6_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer.components_null_FormattingButton-N-4_6_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..36ec55a50b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer.components_null_FormattingButton-N-4_6_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2236ffed5666f85ce3b1093437dc8c0d72ec630f6c707394d99ff4b19d7c3f47 +size 6158 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-D-2_3_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-D-2_3_null,NEXUS_5,1.0,en].png index 9d906ebe35..3fa65b5075 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-D-2_3_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-D-2_3_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:46683edccf9c7686a07d7098c4387f296556ad2678381aad35efe2787cf6ad0a -size 14173 +oid sha256:192e86517a6add5eb3d58d9a3d4633afc455666fff4472f112c605dc441f24d1 +size 13843 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-N-2_4_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-N-2_4_null,NEXUS_5,1.0,en].png index 4b9d77d2b1..c11445bc3f 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-N-2_4_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerEdit-N-2_4_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6485de8235af05a9815a558b1af03b51e8c4b30ad0372aea0aa9fb2303525c9b -size 13286 +oid sha256:ea17e3d7f26d1b3f233ee9db5875dcb363b22de12ed07d32693a2c0aa727fbb6 +size 13001 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-D-1_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-D-1_2_null,NEXUS_5,1.0,en].png index f9dc3f8b9a..4569825f69 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-D-1_2_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-D-1_2_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1f065f63fb37fa9a5441cfaeca04e867e4e8f6f744dd02a83c459fc128ee353d -size 38384 +oid sha256:31013d59ca9755e316bfcb0f5bccf5206446223b1e4f5ce79060a442bb256292 +size 40936 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-N-1_3_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-N-1_3_null,NEXUS_5,1.0,en].png index ca3a85e52c..cc6aa467f3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-N-1_3_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerFormatting-N-1_3_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a5ded1cbc536c544b0cb188ba0a333a541157eaf1772cd0e06c7338307549adc -size 36483 +oid sha256:569a5c4b667e259ca895b41a1248234c339d16d7776a827ded5e151472fe2c5d +size 38601 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png index 0d9c311dcc..c244d01fb3 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-D-3_4_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:69e98a3521ae6545700e395bff211b06bb02095b01d9c254b3e0d2d0b8b88d26 -size 80484 +oid sha256:1b8da842d61ebcdede9a5337890279d740288c1a07b1b42505457ab65408cc76 +size 84240 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png index ef035d6cd5..a50bba4ac8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerReply-N-3_5_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:27dee9eaae6736a128107c9fd93048a677287a40d24c334223243b3c55f1cf69 -size 77686 +oid sha256:feae2409d9887cd752d2cff4be059a566c071094955b824faa72555e69269d91 +size 80648 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-D-0_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-D-0_1_null,NEXUS_5,1.0,en].png index 06fbfc6c7f..de4ca7c908 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-D-0_1_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-D-0_1_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:267f482ceddeadea4c3b580d6783fed1048015fa05a11e385dd547e60f72e1e8 -size 44206 +oid sha256:ed1aa73f94dac6839f91729bcea59b4b3b14b885fa32a90335faf483e9f886f8 +size 45176 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-N-0_2_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-N-0_2_null,NEXUS_5,1.0,en].png index a237bcce80..f5a53317ca 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-N-0_2_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.textcomposer_null_TextComposerSimple-N-0_2_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9f5e7ab52469b406509964d71f12475df546973f1382944ce7f2e1a437e4f880 -size 41536 +oid sha256:76f54b7c7ab5c54b53a0fa9e410db942a2bce35fc0552569707ba2f3928ebd3b +size 42306 From 149677a2e6848e1603a1977e2a3c88a93672a569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 13 Sep 2023 15:59:05 +0200 Subject: [PATCH 192/234] Add preference screen for user profile --- features/preferences/impl/build.gradle.kts | 4 +- .../preferences/impl/PreferencesFlowNode.kt | 11 + .../impl/root/PreferencesRootNode.kt | 8 +- .../impl/root/PreferencesRootView.kt | 10 +- .../impl/user/screen/UserPreferencesEvents.kt | 26 ++ .../impl/user/screen/UserPreferencesNode.kt | 46 +++ .../user/screen/UserPreferencesPresenter.kt | 146 ++++++++++ .../impl/user/screen/UserPreferencesState.kt | 33 +++ .../screen/UserPreferencesStateProvider.kt | 40 +++ .../impl/user/screen/UserPreferencesView.kt | 271 ++++++++++++++++++ .../libraries/matrix/api/MatrixClient.kt | 3 + libraries/matrix/impl/build.gradle.kts | 4 +- .../libraries/matrix/impl/RustMatrixClient.kt | 17 ++ 13 files changed, 614 insertions(+), 5 deletions(-) create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesEvents.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesNode.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesPresenter.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesState.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesStateProvider.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesView.kt diff --git a/features/preferences/impl/build.gradle.kts b/features/preferences/impl/build.gradle.kts index 34a33ff80b..4d0403809d 100644 --- a/features/preferences/impl/build.gradle.kts +++ b/features/preferences/impl/build.gradle.kts @@ -44,10 +44,12 @@ dependencies { implementation(projects.libraries.preferences.api) implementation(projects.libraries.testtags) implementation(projects.libraries.uiStrings) + implementation(projects.libraries.matrixui) + implementation(projects.libraries.mediapickers.api) + implementation(projects.libraries.mediaupload.api) implementation(projects.features.rageshake.api) implementation(projects.features.analytics.api) implementation(projects.features.ftue.api) - implementation(projects.libraries.matrixui) implementation(projects.features.logout.api) implementation(projects.services.analytics.api) implementation(projects.services.toolbox.api) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt index 238b4006e7..0ee29dd1f9 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt @@ -38,6 +38,7 @@ import io.element.android.features.preferences.impl.developer.tracing.ConfigureT import io.element.android.features.preferences.impl.notifications.NotificationSettingsNode import io.element.android.features.preferences.impl.notifications.edit.EditDefaultNotificationSettingNode import io.element.android.features.preferences.impl.root.PreferencesRootNode +import io.element.android.features.preferences.impl.user.screen.UserPreferencesNode import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.createNode @@ -81,6 +82,9 @@ class PreferencesFlowNode @AssistedInject constructor( @Parcelize data class EditDefaultNotificationSetting(val isOneToOne: Boolean) : NavTarget + + @Parcelize + data object UserProfile : NavTarget } override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { @@ -114,6 +118,10 @@ class PreferencesFlowNode @AssistedInject constructor( override fun onOpenAdvancedSettings() { backstack.push(NavTarget.AdvancedSettings) } + + override fun onOpenUserProfile() { + backstack.push(NavTarget.UserProfile) + } } createNode(buildContext, plugins = listOf(callback)) } @@ -149,6 +157,9 @@ class PreferencesFlowNode @AssistedInject constructor( NavTarget.AdvancedSettings -> { createNode(buildContext) } + NavTarget.UserProfile -> { + createNode(buildContext) + } } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt index b4495d8899..3a12ba4478 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt @@ -47,6 +47,7 @@ class PreferencesRootNode @AssistedInject constructor( fun onOpenDeveloperSettings() fun onOpenNotificationSettings() fun onOpenAdvancedSettings() + fun onOpenUserProfile() } private fun onOpenBugReport() { @@ -91,6 +92,10 @@ class PreferencesRootNode @AssistedInject constructor( plugins().forEach { it.onOpenNotificationSettings() } } + private fun onOpenUserProfile() { + plugins().forEach { it.onOpenUserProfile() } + } + @Composable override fun View(modifier: Modifier) { val state = presenter.present() @@ -108,7 +113,8 @@ class PreferencesRootNode @AssistedInject constructor( onOpenAdvancedSettings = this::onOpenAdvancedSettings, onSuccessLogout = { onSuccessLogout(activity, it) }, onManageAccountClicked = { onManageAccountClicked(activity, it, isDark) }, - onOpenNotificationSettings = this::onOpenNotificationSettings + onOpenNotificationSettings = this::onOpenNotificationSettings, + onOpenUserProfile = this::onOpenUserProfile, ) } 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 16c7df6b51..d8a05b0db8 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 @@ -16,6 +16,7 @@ package io.element.android.features.preferences.impl.root +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons @@ -62,6 +63,7 @@ fun PreferencesRootView( onOpenAdvancedSettings: () -> Unit, onSuccessLogout: (logoutUrlResult: String?) -> Unit, onOpenNotificationSettings: () -> Unit, + onOpenUserProfile: () -> Unit, modifier: Modifier = Modifier, ) { val snackbarHostState = rememberSnackbarHostState(snackbarMessage = state.snackbarMessage) @@ -73,7 +75,12 @@ fun PreferencesRootView( title = stringResource(id = CommonStrings.common_settings), snackbarHost = { SnackbarHost(snackbarHostState) } ) { - UserPreferences(state.myUser) + UserPreferences( + modifier = Modifier.clickable { + onOpenUserProfile() + }, + user = state.myUser, + ) if (state.showCompleteVerification) { PreferenceText( title = stringResource(id = CommonStrings.action_complete_verification), @@ -181,5 +188,6 @@ private fun ContentToPreview(matrixUser: MatrixUser) { onSuccessLogout = {}, onManageAccountClicked = {}, onOpenNotificationSettings = {}, + onOpenUserProfile = {}, ) } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesEvents.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesEvents.kt new file mode 100644 index 0000000000..c54ea98afc --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesEvents.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.user.screen + +import io.element.android.libraries.matrix.ui.media.AvatarAction + +sealed interface UserPreferencesEvents { + data class HandleAvatarAction(val action: AvatarAction) : UserPreferencesEvents + data class UpdateDisplayName(val name: String) : UserPreferencesEvents + data object Save : UserPreferencesEvents + data object CancelSaveChanges : UserPreferencesEvents +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesNode.kt new file mode 100644 index 0000000000..eaccb6fbbd --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesNode.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.user.screen + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode +import io.element.android.libraries.di.SessionScope + +@ContributesNode(SessionScope::class) +class UserPreferencesNode @AssistedInject constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + private val presenter: UserPreferencesPresenter, +) : Node(buildContext, plugins = plugins) { + + @Composable + override fun View(modifier: Modifier) { + val state = presenter.present() + UserPreferencesView( + state = state, + onBackPressed = ::navigateUp, + onProfileEdited = ::navigateUp, // TODO: check if something else is needed + modifier = modifier + ) + } +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesPresenter.kt new file mode 100644 index 0000000000..49e28144bb --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesPresenter.kt @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.user.screen + +import android.net.Uri +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import io.element.android.libraries.architecture.Async +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.architecture.runCatchingUpdatingState +import io.element.android.libraries.core.mimetype.MimeTypes +import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.api.user.getCurrentUser +import io.element.android.libraries.matrix.ui.media.AvatarAction +import io.element.android.libraries.mediapickers.api.PickerProvider +import io.element.android.libraries.mediaupload.api.MediaPreProcessor +import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +import timber.log.Timber +import javax.inject.Inject + +class UserPreferencesPresenter @Inject constructor( + private val matrixClient: MatrixClient, + private val mediaPickerProvider: PickerProvider, + private val mediaPreProcessor: MediaPreProcessor, +) : Presenter { + + @Composable + override fun present(): UserPreferencesState { + var currentUser by remember { mutableStateOf(null) } + var userAvatarUri by rememberSaveable(currentUser) { mutableStateOf(currentUser?.avatarUrl?.let { Uri.parse(it) }) } + var userDisplayName by rememberSaveable(currentUser) { mutableStateOf(currentUser?.displayName) } + val cameraPhotoPicker = mediaPickerProvider.registerCameraPhotoPicker( + onResult = { uri -> if (uri != null) userAvatarUri = uri } + ) + val galleryImagePicker = mediaPickerProvider.registerGalleryImagePicker( + onResult = { uri -> if (uri != null) userAvatarUri = uri } + ) + + LaunchedEffect(Unit) { + currentUser = matrixClient.getCurrentUser() + } + + val avatarActions by remember(userAvatarUri) { + derivedStateOf { + listOfNotNull( + AvatarAction.TakePhoto, + AvatarAction.ChoosePhoto, + AvatarAction.Remove.takeIf { userAvatarUri != null }, + ).toImmutableList() + } + } + + val saveAction: MutableState> = remember { mutableStateOf(Async.Uninitialized) } + val localCoroutineScope = rememberCoroutineScope() + fun handleEvents(event: UserPreferencesEvents) { + when (event) { + is UserPreferencesEvents.Save -> currentUser?.let { + localCoroutineScope.saveChanges(userDisplayName, userAvatarUri, it, saveAction) + } + is UserPreferencesEvents.HandleAvatarAction -> { + when (event.action) { + AvatarAction.ChoosePhoto -> galleryImagePicker.launch() + AvatarAction.TakePhoto -> cameraPhotoPicker.launch() + AvatarAction.Remove -> userAvatarUri = null + } + } + + is UserPreferencesEvents.UpdateDisplayName -> userDisplayName = event.name + UserPreferencesEvents.CancelSaveChanges -> saveAction.value = Async.Uninitialized + } + } + + val canSave = remember(userDisplayName, userAvatarUri, currentUser) { + val hasProfileChanged = hasDisplayNameChanged(userDisplayName, currentUser) + || hasAvatarUrlChanged(userAvatarUri, currentUser) + !userDisplayName.isNullOrBlank() && hasProfileChanged + } + + return UserPreferencesState( + userId = currentUser?.userId, + displayName = userDisplayName.orEmpty(), + userAvatarUrl = userAvatarUri, + avatarActions = avatarActions, + saveButtonEnabled = canSave && saveAction.value !is Async.Loading, + saveAction = saveAction.value, + eventSink = ::handleEvents + ) + } + + private fun hasDisplayNameChanged(name: String?, currentUser: MatrixUser?) = name?.trim() != currentUser?.displayName?.trim() + private fun hasAvatarUrlChanged(avatarUri: Uri?, currentUser: MatrixUser?) = avatarUri?.toString()?.trim() != currentUser?.avatarUrl?.trim() + + private fun CoroutineScope.saveChanges(name: String?, avatarUri: Uri?, currentUser: MatrixUser, action: MutableState>) = launch { + matrixClient.getCurrentUser() + val results = mutableListOf>() + suspend { + if (!name.isNullOrEmpty() && name.trim() != currentUser.displayName.orEmpty().trim()) { + results.add(matrixClient.setDisplayName(name).onFailure { + Timber.e(it, "Failed to set user's display name") + }) + } + if (avatarUri?.toString()?.trim() != currentUser.avatarUrl?.trim()) { + results.add(updateAvatar(avatarUri).onFailure { + Timber.e(it, "Failed to update user's avatar") + }) + } + if (results.all { it.isSuccess }) Unit else results.first { it.isFailure }.getOrThrow() + }.runCatchingUpdatingState(action) + } + + private suspend fun updateAvatar(avatarUri: Uri?): Result { + return runCatching { + if (avatarUri != null) { + val preprocessed = mediaPreProcessor.process(avatarUri, MimeTypes.Jpeg, compressIfPossible = false).getOrThrow() + matrixClient.uploadAvatar(MimeTypes.Jpeg, preprocessed.file.readBytes()).getOrThrow() + } else { + matrixClient.removeAvatar().getOrThrow() + } + } + } +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesState.kt new file mode 100644 index 0000000000..ee70194638 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesState.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.user.screen + +import android.net.Uri +import io.element.android.libraries.architecture.Async +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.ui.media.AvatarAction +import kotlinx.collections.immutable.ImmutableList + +data class UserPreferencesState( + val userId: UserId?, + val displayName: String, + val userAvatarUrl: Uri?, + val avatarActions: ImmutableList, + val saveButtonEnabled: Boolean, + val saveAction: Async, + val eventSink: (UserPreferencesEvents) -> Unit +) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesStateProvider.kt new file mode 100644 index 0000000000..2c87c591c6 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesStateProvider.kt @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.user.screen + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.architecture.Async +import io.element.android.libraries.matrix.api.core.UserId +import kotlinx.collections.immutable.persistentListOf + +open class UserPreferencesStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + aUserPreferencesState(), + // Add other states here + ) +} + +fun aUserPreferencesState() = UserPreferencesState( + userId = UserId("@john.doe:matrix.org"), + displayName = "John Doe", + userAvatarUrl = null, + avatarActions = persistentListOf(), + saveAction = Async.Uninitialized, + saveButtonEnabled = true, + eventSink = {} +) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesView.kt new file mode 100644 index 0000000000..aba122cef4 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesView.kt @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.user.screen + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.gestures.detectTapGestures +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.imePadding +import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.ModalBottomSheetValue +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.AddAPhoto +import androidx.compose.material.rememberModalBottomSheetState +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.focus.FocusManager +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.dp +import io.element.android.libraries.architecture.Async +import io.element.android.libraries.designsystem.components.LabelledTextField +import io.element.android.libraries.designsystem.components.ProgressDialog +import io.element.android.libraries.designsystem.components.avatar.Avatar +import io.element.android.libraries.designsystem.components.avatar.AvatarData +import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.components.button.BackButton +import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog +import io.element.android.libraries.designsystem.preview.ElementPreviewDark +import io.element.android.libraries.designsystem.preview.ElementPreviewLight +import io.element.android.libraries.designsystem.theme.aliasScreenTitle +import io.element.android.libraries.designsystem.theme.components.Icon +import io.element.android.libraries.designsystem.theme.components.Scaffold +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.components.TextButton +import io.element.android.libraries.designsystem.theme.components.TopAppBar +import io.element.android.libraries.matrix.ui.components.AvatarActionBottomSheet +import io.element.android.libraries.matrix.ui.components.UnsavedAvatar +import io.element.android.libraries.theme.ElementTheme +import io.element.android.libraries.ui.strings.CommonStrings +import kotlinx.coroutines.launch + +@OptIn(ExperimentalMaterialApi::class, ExperimentalMaterial3Api::class) +@Composable +fun UserPreferencesView( + state: UserPreferencesState, + onBackPressed: () -> Unit, + onProfileEdited: () -> Unit, + modifier: Modifier = Modifier, +) { + val coroutineScope = rememberCoroutineScope() + val focusManager = LocalFocusManager.current + val itemActionsBottomSheetState = rememberModalBottomSheetState( + initialValue = ModalBottomSheetValue.Hidden, + ) + + fun onAvatarClicked() { + focusManager.clearFocus() + coroutineScope.launch { + itemActionsBottomSheetState.show() + } + } + + Scaffold( + modifier = modifier.clearFocusOnTap(focusManager), + topBar = { + TopAppBar( + title = { + Text( + text = "Edit profile", + style = ElementTheme.typography.aliasScreenTitle, + ) + }, + navigationIcon = { BackButton(onClick = onBackPressed) }, + actions = { + TextButton( + text = stringResource(CommonStrings.action_save), + enabled = state.saveButtonEnabled, + onClick = { + focusManager.clearFocus() + state.eventSink(UserPreferencesEvents.Save) + }, + ) + } + ) + }, + ) { padding -> + Column( + modifier = Modifier + .padding(padding) + .padding(horizontal = 16.dp) + .navigationBarsPadding() + .imePadding() + .verticalScroll(rememberScrollState()) + ) { + Spacer(modifier = Modifier.height(24.dp)) + EditableAvatarView(state, ::onAvatarClicked) + Spacer(modifier = Modifier.height(60.dp)) + + LabelledTextField( + label = "Display name", + value = state.displayName, + placeholder = stringResource(CommonStrings.common_room_name_placeholder), + singleLine = true, + onValueChange = { state.eventSink(UserPreferencesEvents.UpdateDisplayName(it)) }, + ) + } + + AvatarActionBottomSheet( + actions = state.avatarActions, + modalBottomSheetState = itemActionsBottomSheetState, + onActionSelected = { state.eventSink(UserPreferencesEvents.HandleAvatarAction(it)) } + ) + + when (state.saveAction) { + is Async.Loading -> { + ProgressDialog(text = "Updating profile...") + } + + is Async.Failure -> { + ErrorDialog( + content = "Error updating profile", + onDismiss = { state.eventSink(UserPreferencesEvents.CancelSaveChanges) }, + ) + } + + is Async.Success -> { + LaunchedEffect(state.saveAction) { + onProfileEdited() + } + } + + else -> Unit + } + } +} + +@Composable +private fun EditableAvatarView( + state: UserPreferencesState, + onAvatarClicked: () -> Unit, + modifier: Modifier = Modifier, +) { + Column(modifier = modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { + Box( + modifier = Modifier + .size(70.dp) + .clickable(onClick = onAvatarClicked) + ) { + // TODO this might be able to be simplified into a single component once send/receive media is done + when (state.userAvatarUrl?.scheme) { + null, "mxc" -> { + Avatar( + avatarData = AvatarData(state.userId.toString(), state.displayName, state.userAvatarUrl?.toString(), size = AvatarSize.RoomHeader), + modifier = Modifier.fillMaxSize(), + ) + } + + else -> { + UnsavedAvatar( + avatarUri = state.userAvatarUrl, + modifier = Modifier.fillMaxSize(), + ) + } + } + + Box( + modifier = Modifier + .align(Alignment.BottomEnd) + .clip(CircleShape) + .background(MaterialTheme.colorScheme.primary) + .size(24.dp), + contentAlignment = Alignment.Center, + ) { + Icon( + modifier = Modifier.size(16.dp), + imageVector = Icons.Outlined.AddAPhoto, + contentDescription = "", + tint = MaterialTheme.colorScheme.onPrimary, + ) + } + } + } +} + +@Composable +private fun LabelledReadOnlyField( + title: String, + value: String, + modifier: Modifier = Modifier +) { + Column( + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(8.dp), + ) { + Text( + modifier = Modifier.padding(horizontal = 16.dp), + style = ElementTheme.typography.fontBodyMdRegular, + color = MaterialTheme.colorScheme.primary, + text = title, + ) + + Text( + modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 12.dp), + style = MaterialTheme.typography.bodyLarge, + color = MaterialTheme.colorScheme.primary, + text = value, + ) + } +} + +private fun Modifier.clearFocusOnTap(focusManager: FocusManager): Modifier = + pointerInput(Unit) { + detectTapGestures(onTap = { + focusManager.clearFocus() + }) + } + +@Preview +@Composable +fun UserPreferencesViewLightPreview(@PreviewParameter(UserPreferencesStateProvider::class) state: UserPreferencesState) = + ElementPreviewLight { ContentToPreview(state) } + +@Preview +@Composable +fun UserPreferencesViewDarkPreview(@PreviewParameter(UserPreferencesStateProvider::class) state: UserPreferencesState) = + ElementPreviewDark { ContentToPreview(state) } + +@Composable +private fun ContentToPreview(state: UserPreferencesState) { + UserPreferencesView( + onBackPressed = {}, + onProfileEdited = {}, + state = state, + ) +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt index 611cb4303c..fc215e4780 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt @@ -47,6 +47,9 @@ interface MatrixClient : Closeable { suspend fun createDM(userId: UserId): Result suspend fun getProfile(userId: UserId): Result suspend fun searchUsers(searchTerm: String, limit: Long): Result + suspend fun setDisplayName(displayName: String): Result + suspend fun uploadAvatar(mimeType: String, data: ByteArray): Result + suspend fun removeAvatar(): Result fun syncService(): SyncService fun sessionVerificationService(): SessionVerificationService fun pushersService(): PushersService diff --git a/libraries/matrix/impl/build.gradle.kts b/libraries/matrix/impl/build.gradle.kts index a2b616f989..97eb7b6864 100644 --- a/libraries/matrix/impl/build.gradle.kts +++ b/libraries/matrix/impl/build.gradle.kts @@ -29,8 +29,8 @@ anvil { } dependencies { - // implementation(projects.libraries.rustsdk) - implementation(libs.matrix.sdk) + implementation(projects.libraries.rustsdk) +// implementation(libs.matrix.sdk) implementation(projects.libraries.di) implementation(projects.libraries.androidutils) implementation(projects.libraries.network) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index c4a3ab3ef2..d99c60b286 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -276,6 +276,23 @@ class RustMatrixClient constructor( } } + override suspend fun setDisplayName(displayName: String): Result = + withContext(sessionDispatcher) { + runCatching { client.setDisplayName(displayName) } + } + + @OptIn(ExperimentalUnsignedTypes::class) + override suspend fun uploadAvatar(mimeType: String, data: ByteArray): Result = + withContext(sessionDispatcher) { + runCatching { client.uploadAvatar(mimeType, data.toUByteArray().toList()) } + } + + override suspend fun removeAvatar(): Result = + withContext(sessionDispatcher) { + runCatching { client.removeAvatar() } + } + + override fun syncService(): SyncService = rustSyncService override fun sessionVerificationService(): SessionVerificationService = verificationService From 2ccafec5645684ec663b194fe7f70b2971d93067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Fri, 15 Sep 2023 14:04:21 +0200 Subject: [PATCH 193/234] Changes: - Improve UI to match designs. - Extract `EditableAvatarView` component. - Create `LabelledOutlinedTextField`. - Get strings from Localazy. --- .../preferences/impl/PreferencesFlowNode.kt | 14 +- .../impl/root/PreferencesRootNode.kt | 7 +- .../impl/root/PreferencesRootView.kt | 4 +- .../EditUserProfileEvents.kt} | 12 +- .../EditUserProfileNode.kt} | 20 ++- .../EditUserProfilePresenter.kt} | 53 +++---- .../EditUserProfileState.kt} | 6 +- .../EditUserProfileStateProvider.kt} | 10 +- .../EditUserProfileView.kt} | 149 +++++------------- .../impl/src/main/res/values/localazy.xml | 9 ++ .../impl/edit/RoomDetailsEditView.kt | 76 ++------- .../components/LabelledOutlinedTextField.kt | 91 +++++++++++ .../components/avatar/AvatarSize.kt | 2 + libraries/matrix/impl/build.gradle.kts | 4 +- .../ui/components/EditableAvatarView.kt | 97 ++++++++++++ tools/localazy/config.json | 6 + 16 files changed, 325 insertions(+), 235 deletions(-) rename features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/{screen/UserPreferencesEvents.kt => editprofile/EditUserProfileEvents.kt} (64%) rename features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/{screen/UserPreferencesNode.kt => editprofile/EditUserProfileNode.kt} (69%) rename features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/{screen/UserPreferencesPresenter.kt => editprofile/EditUserProfilePresenter.kt} (77%) rename features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/{screen/UserPreferencesState.kt => editprofile/EditUserProfileState.kt} (87%) rename features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/{screen/UserPreferencesStateProvider.kt => editprofile/EditUserProfileStateProvider.kt} (78%) rename features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/{screen/UserPreferencesView.kt => editprofile/EditUserProfileView.kt} (57%) create mode 100644 features/preferences/impl/src/main/res/values/localazy.xml create mode 100644 libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LabelledOutlinedTextField.kt create mode 100644 libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/EditableAvatarView.kt diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt index 0ee29dd1f9..6cf0390db2 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt @@ -38,11 +38,12 @@ import io.element.android.features.preferences.impl.developer.tracing.ConfigureT import io.element.android.features.preferences.impl.notifications.NotificationSettingsNode import io.element.android.features.preferences.impl.notifications.edit.EditDefaultNotificationSettingNode import io.element.android.features.preferences.impl.root.PreferencesRootNode -import io.element.android.features.preferences.impl.user.screen.UserPreferencesNode +import io.element.android.features.preferences.impl.user.editprofile.EditUserProfileNode import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.createNode import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.user.MatrixUser import kotlinx.parcelize.Parcelize @ContributesNode(SessionScope::class) @@ -84,7 +85,7 @@ class PreferencesFlowNode @AssistedInject constructor( data class EditDefaultNotificationSetting(val isOneToOne: Boolean) : NavTarget @Parcelize - data object UserProfile : NavTarget + data class UserProfile(val matrixUser: MatrixUser) : NavTarget } override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { @@ -119,8 +120,8 @@ class PreferencesFlowNode @AssistedInject constructor( backstack.push(NavTarget.AdvancedSettings) } - override fun onOpenUserProfile() { - backstack.push(NavTarget.UserProfile) + override fun onOpenUserProfile(matrixUser: MatrixUser) { + backstack.push(NavTarget.UserProfile(matrixUser)) } } createNode(buildContext, plugins = listOf(callback)) @@ -157,8 +158,9 @@ class PreferencesFlowNode @AssistedInject constructor( NavTarget.AdvancedSettings -> { createNode(buildContext) } - NavTarget.UserProfile -> { - createNode(buildContext) + is NavTarget.UserProfile -> { + val inputs = EditUserProfileNode.Inputs(navTarget.matrixUser) + createNode(buildContext, listOf(inputs)) } } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt index 3a12ba4478..407832627b 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt @@ -29,6 +29,7 @@ import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode import io.element.android.libraries.androidutils.browser.openUrlInChromeCustomTab import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.theme.ElementTheme import timber.log.Timber @@ -47,7 +48,7 @@ class PreferencesRootNode @AssistedInject constructor( fun onOpenDeveloperSettings() fun onOpenNotificationSettings() fun onOpenAdvancedSettings() - fun onOpenUserProfile() + fun onOpenUserProfile(matrixUser: MatrixUser) } private fun onOpenBugReport() { @@ -92,8 +93,8 @@ class PreferencesRootNode @AssistedInject constructor( plugins().forEach { it.onOpenNotificationSettings() } } - private fun onOpenUserProfile() { - plugins().forEach { it.onOpenUserProfile() } + private fun onOpenUserProfile(matrixUser: MatrixUser) { + plugins().forEach { it.onOpenUserProfile(matrixUser) } } @Composable 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 d8a05b0db8..933f22bc13 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 @@ -63,7 +63,7 @@ fun PreferencesRootView( onOpenAdvancedSettings: () -> Unit, onSuccessLogout: (logoutUrlResult: String?) -> Unit, onOpenNotificationSettings: () -> Unit, - onOpenUserProfile: () -> Unit, + onOpenUserProfile: (MatrixUser) -> Unit, modifier: Modifier = Modifier, ) { val snackbarHostState = rememberSnackbarHostState(snackbarMessage = state.snackbarMessage) @@ -77,7 +77,7 @@ fun PreferencesRootView( ) { UserPreferences( modifier = Modifier.clickable { - onOpenUserProfile() + state.myUser?.let(onOpenUserProfile) }, user = state.myUser, ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesEvents.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileEvents.kt similarity index 64% rename from features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesEvents.kt rename to features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileEvents.kt index c54ea98afc..5c53ec23c4 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesEvents.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileEvents.kt @@ -14,13 +14,13 @@ * limitations under the License. */ -package io.element.android.features.preferences.impl.user.screen +package io.element.android.features.preferences.impl.user.editprofile import io.element.android.libraries.matrix.ui.media.AvatarAction -sealed interface UserPreferencesEvents { - data class HandleAvatarAction(val action: AvatarAction) : UserPreferencesEvents - data class UpdateDisplayName(val name: String) : UserPreferencesEvents - data object Save : UserPreferencesEvents - data object CancelSaveChanges : UserPreferencesEvents +sealed interface EditUserProfileEvents { + data class HandleAvatarAction(val action: AvatarAction) : EditUserProfileEvents + data class UpdateDisplayName(val name: String) : EditUserProfileEvents + data object Save : EditUserProfileEvents + data object CancelSaveChanges : EditUserProfileEvents } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileNode.kt similarity index 69% rename from features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesNode.kt rename to features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileNode.kt index eaccb6fbbd..738ae4ec6d 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileNode.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.preferences.impl.user.screen +package io.element.android.features.preferences.impl.user.editprofile import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -24,22 +24,32 @@ import com.bumble.appyx.core.plugin.Plugin import dagger.assisted.Assisted import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode +import io.element.android.libraries.architecture.NodeInputs +import io.element.android.libraries.architecture.inputs import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.user.MatrixUser @ContributesNode(SessionScope::class) -class UserPreferencesNode @AssistedInject constructor( +class EditUserProfileNode @AssistedInject constructor( @Assisted buildContext: BuildContext, @Assisted plugins: List, - private val presenter: UserPreferencesPresenter, + presenterFactory: EditUserProfilePresenter.Factory, ) : Node(buildContext, plugins = plugins) { + data class Inputs( + val matrixUser: MatrixUser + ) : NodeInputs + + val matrixUser = inputs().matrixUser + val presenter = presenterFactory.create(matrixUser) + @Composable override fun View(modifier: Modifier) { val state = presenter.present() - UserPreferencesView( + EditUserProfileView( state = state, onBackPressed = ::navigateUp, - onProfileEdited = ::navigateUp, // TODO: check if something else is needed + onProfileEdited = ::navigateUp, modifier = modifier ) } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt similarity index 77% rename from features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesPresenter.kt rename to features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt index 49e28144bb..6557079de3 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt @@ -14,19 +14,19 @@ * limitations under the License. */ -package io.element.android.features.preferences.impl.user.screen +package io.element.android.features.preferences.impl.user.editprofile import android.net.Uri import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.runCatchingUpdatingState @@ -41,19 +41,23 @@ import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import timber.log.Timber -import javax.inject.Inject -class UserPreferencesPresenter @Inject constructor( +class EditUserProfilePresenter @AssistedInject constructor( + @Assisted private val matrixUser: MatrixUser, private val matrixClient: MatrixClient, private val mediaPickerProvider: PickerProvider, private val mediaPreProcessor: MediaPreProcessor, -) : Presenter { +) : Presenter { + + @AssistedFactory + interface Factory { + fun create(matrixUser: MatrixUser): EditUserProfilePresenter + } @Composable - override fun present(): UserPreferencesState { - var currentUser by remember { mutableStateOf(null) } - var userAvatarUri by rememberSaveable(currentUser) { mutableStateOf(currentUser?.avatarUrl?.let { Uri.parse(it) }) } - var userDisplayName by rememberSaveable(currentUser) { mutableStateOf(currentUser?.displayName) } + override fun present(): EditUserProfileState { + var userAvatarUri = remember { matrixUser.avatarUrl?.let { Uri.parse(it) } } + var userDisplayName = remember { matrixUser.displayName } val cameraPhotoPicker = mediaPickerProvider.registerCameraPhotoPicker( onResult = { uri -> if (uri != null) userAvatarUri = uri } ) @@ -61,10 +65,6 @@ class UserPreferencesPresenter @Inject constructor( onResult = { uri -> if (uri != null) userAvatarUri = uri } ) - LaunchedEffect(Unit) { - currentUser = matrixClient.getCurrentUser() - } - val avatarActions by remember(userAvatarUri) { derivedStateOf { listOfNotNull( @@ -77,12 +77,10 @@ class UserPreferencesPresenter @Inject constructor( val saveAction: MutableState> = remember { mutableStateOf(Async.Uninitialized) } val localCoroutineScope = rememberCoroutineScope() - fun handleEvents(event: UserPreferencesEvents) { + fun handleEvents(event: EditUserProfileEvents) { when (event) { - is UserPreferencesEvents.Save -> currentUser?.let { - localCoroutineScope.saveChanges(userDisplayName, userAvatarUri, it, saveAction) - } - is UserPreferencesEvents.HandleAvatarAction -> { + is EditUserProfileEvents.Save -> localCoroutineScope.saveChanges(userDisplayName, userAvatarUri, matrixUser, saveAction) + is EditUserProfileEvents.HandleAvatarAction -> { when (event.action) { AvatarAction.ChoosePhoto -> galleryImagePicker.launch() AvatarAction.TakePhoto -> cameraPhotoPicker.launch() @@ -90,19 +88,19 @@ class UserPreferencesPresenter @Inject constructor( } } - is UserPreferencesEvents.UpdateDisplayName -> userDisplayName = event.name - UserPreferencesEvents.CancelSaveChanges -> saveAction.value = Async.Uninitialized + is EditUserProfileEvents.UpdateDisplayName -> userDisplayName = event.name + EditUserProfileEvents.CancelSaveChanges -> saveAction.value = Async.Uninitialized } } - val canSave = remember(userDisplayName, userAvatarUri, currentUser) { - val hasProfileChanged = hasDisplayNameChanged(userDisplayName, currentUser) - || hasAvatarUrlChanged(userAvatarUri, currentUser) + val canSave = remember(userDisplayName, userAvatarUri) { + val hasProfileChanged = hasDisplayNameChanged(userDisplayName, matrixUser) + || hasAvatarUrlChanged(userAvatarUri, matrixUser) !userDisplayName.isNullOrBlank() && hasProfileChanged } - return UserPreferencesState( - userId = currentUser?.userId, + return EditUserProfileState( + userId = matrixUser.userId, displayName = userDisplayName.orEmpty(), userAvatarUrl = userAvatarUri, avatarActions = avatarActions, @@ -116,7 +114,6 @@ class UserPreferencesPresenter @Inject constructor( private fun hasAvatarUrlChanged(avatarUri: Uri?, currentUser: MatrixUser?) = avatarUri?.toString()?.trim() != currentUser?.avatarUrl?.trim() private fun CoroutineScope.saveChanges(name: String?, avatarUri: Uri?, currentUser: MatrixUser, action: MutableState>) = launch { - matrixClient.getCurrentUser() val results = mutableListOf>() suspend { if (!name.isNullOrEmpty() && name.trim() != currentUser.displayName.orEmpty().trim()) { diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileState.kt similarity index 87% rename from features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesState.kt rename to features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileState.kt index ee70194638..87668e6f45 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileState.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.preferences.impl.user.screen +package io.element.android.features.preferences.impl.user.editprofile import android.net.Uri import io.element.android.libraries.architecture.Async @@ -22,12 +22,12 @@ import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.ui.media.AvatarAction import kotlinx.collections.immutable.ImmutableList -data class UserPreferencesState( +data class EditUserProfileState( val userId: UserId?, val displayName: String, val userAvatarUrl: Uri?, val avatarActions: ImmutableList, val saveButtonEnabled: Boolean, val saveAction: Async, - val eventSink: (UserPreferencesEvents) -> Unit + val eventSink: (EditUserProfileEvents) -> Unit ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileStateProvider.kt similarity index 78% rename from features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesStateProvider.kt rename to features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileStateProvider.kt index 2c87c591c6..5e4ccb95cb 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesStateProvider.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileStateProvider.kt @@ -14,22 +14,22 @@ * limitations under the License. */ -package io.element.android.features.preferences.impl.user.screen +package io.element.android.features.preferences.impl.user.editprofile import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.architecture.Async import io.element.android.libraries.matrix.api.core.UserId import kotlinx.collections.immutable.persistentListOf -open class UserPreferencesStateProvider : PreviewParameterProvider { - override val values: Sequence +open class EditUserProfileStateProvider : PreviewParameterProvider { + override val values: Sequence get() = sequenceOf( - aUserPreferencesState(), + aEditUserProfileState(), // Add other states here ) } -fun aUserPreferencesState() = UserPreferencesState( +fun aEditUserProfileState() = EditUserProfileState( userId = UserId("@john.doe:matrix.org"), displayName = "John Doe", userAvatarUrl = null, diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileView.kt similarity index 57% rename from features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesView.kt rename to features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileView.kt index aba122cef4..02423470a9 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/screen/UserPreferencesView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileView.kt @@ -14,71 +14,59 @@ * limitations under the License. */ -package io.element.android.features.preferences.impl.user.screen +package io.element.android.features.preferences.impl.user.editprofile -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.gestures.detectTapGestures -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.verticalScroll import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ModalBottomSheetValue -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.AddAPhoto import androidx.compose.material.rememberModalBottomSheetState import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.focus.FocusManager import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp +import io.element.android.features.preferences.impl.R import io.element.android.libraries.architecture.Async -import io.element.android.libraries.designsystem.components.LabelledTextField +import io.element.android.libraries.designsystem.components.LabelledOutlinedTextField import io.element.android.libraries.designsystem.components.ProgressDialog -import io.element.android.libraries.designsystem.components.avatar.Avatar -import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.theme.aliasScreenTitle -import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.matrix.ui.components.AvatarActionBottomSheet -import io.element.android.libraries.matrix.ui.components.UnsavedAvatar +import io.element.android.libraries.matrix.ui.components.EditableAvatarView import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.coroutines.launch @OptIn(ExperimentalMaterialApi::class, ExperimentalMaterial3Api::class) @Composable -fun UserPreferencesView( - state: UserPreferencesState, +fun EditUserProfileView( + state: EditUserProfileState, onBackPressed: () -> Unit, onProfileEdited: () -> Unit, modifier: Modifier = Modifier, @@ -102,7 +90,7 @@ fun UserPreferencesView( TopAppBar( title = { Text( - text = "Edit profile", + text = stringResource(R.string.screen_edit_profile_title), style = ElementTheme.typography.aliasScreenTitle, ) }, @@ -113,7 +101,7 @@ fun UserPreferencesView( enabled = state.saveButtonEnabled, onClick = { focusManager.clearFocus() - state.eventSink(UserPreferencesEvents.Save) + state.eventSink(EditUserProfileEvents.Save) }, ) } @@ -129,33 +117,50 @@ fun UserPreferencesView( .verticalScroll(rememberScrollState()) ) { Spacer(modifier = Modifier.height(24.dp)) - EditableAvatarView(state, ::onAvatarClicked) - Spacer(modifier = Modifier.height(60.dp)) + EditableAvatarView( + userId = state.userId?.value, + displayName = state.displayName, + avatarUrl = state.userAvatarUrl, + avatarSize = AvatarSize.RoomHeader, + onAvatarClicked = { onAvatarClicked() }, + modifier = Modifier.align(Alignment.CenterHorizontally), + ) + Spacer(modifier = Modifier.height(16.dp)) + state.userId?.let { + Text( + modifier = Modifier.fillMaxWidth(), + text = it.value, + style = ElementTheme.typography.fontBodyLgRegular, + textAlign = TextAlign.Center, + ) + } + Spacer(modifier = Modifier.height(40.dp)) - LabelledTextField( - label = "Display name", + LabelledOutlinedTextField( + label = stringResource(R.string.screen_edit_profile_display_name), value = state.displayName, placeholder = stringResource(CommonStrings.common_room_name_placeholder), singleLine = true, - onValueChange = { state.eventSink(UserPreferencesEvents.UpdateDisplayName(it)) }, + onValueChange = { state.eventSink(EditUserProfileEvents.UpdateDisplayName(it)) }, ) } AvatarActionBottomSheet( actions = state.avatarActions, modalBottomSheetState = itemActionsBottomSheetState, - onActionSelected = { state.eventSink(UserPreferencesEvents.HandleAvatarAction(it)) } + onActionSelected = { state.eventSink(EditUserProfileEvents.HandleAvatarAction(it)) } ) when (state.saveAction) { is Async.Loading -> { - ProgressDialog(text = "Updating profile...") + ProgressDialog(text = stringResource(R.string.screen_edit_profile_updating_details)) } is Async.Failure -> { ErrorDialog( - content = "Error updating profile", - onDismiss = { state.eventSink(UserPreferencesEvents.CancelSaveChanges) }, + title = stringResource(R.string.screen_edit_profile_error_title), + content = stringResource(R.string.screen_edit_profile_error), + onDismiss = { state.eventSink(EditUserProfileEvents.CancelSaveChanges) }, ) } @@ -170,82 +175,8 @@ fun UserPreferencesView( } } -@Composable -private fun EditableAvatarView( - state: UserPreferencesState, - onAvatarClicked: () -> Unit, - modifier: Modifier = Modifier, -) { - Column(modifier = modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { - Box( - modifier = Modifier - .size(70.dp) - .clickable(onClick = onAvatarClicked) - ) { - // TODO this might be able to be simplified into a single component once send/receive media is done - when (state.userAvatarUrl?.scheme) { - null, "mxc" -> { - Avatar( - avatarData = AvatarData(state.userId.toString(), state.displayName, state.userAvatarUrl?.toString(), size = AvatarSize.RoomHeader), - modifier = Modifier.fillMaxSize(), - ) - } - - else -> { - UnsavedAvatar( - avatarUri = state.userAvatarUrl, - modifier = Modifier.fillMaxSize(), - ) - } - } - - Box( - modifier = Modifier - .align(Alignment.BottomEnd) - .clip(CircleShape) - .background(MaterialTheme.colorScheme.primary) - .size(24.dp), - contentAlignment = Alignment.Center, - ) { - Icon( - modifier = Modifier.size(16.dp), - imageVector = Icons.Outlined.AddAPhoto, - contentDescription = "", - tint = MaterialTheme.colorScheme.onPrimary, - ) - } - } - } -} - -@Composable -private fun LabelledReadOnlyField( - title: String, - value: String, - modifier: Modifier = Modifier -) { - Column( - modifier = modifier, - verticalArrangement = Arrangement.spacedBy(8.dp), - ) { - Text( - modifier = Modifier.padding(horizontal = 16.dp), - style = ElementTheme.typography.fontBodyMdRegular, - color = MaterialTheme.colorScheme.primary, - text = title, - ) - - Text( - modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 12.dp), - style = MaterialTheme.typography.bodyLarge, - color = MaterialTheme.colorScheme.primary, - text = value, - ) - } -} - private fun Modifier.clearFocusOnTap(focusManager: FocusManager): Modifier = - pointerInput(Unit) { + this.pointerInput(Unit) { detectTapGestures(onTap = { focusManager.clearFocus() }) @@ -253,17 +184,17 @@ private fun Modifier.clearFocusOnTap(focusManager: FocusManager): Modifier = @Preview @Composable -fun UserPreferencesViewLightPreview(@PreviewParameter(UserPreferencesStateProvider::class) state: UserPreferencesState) = +fun EditUserProfileViewLightPreview(@PreviewParameter(EditUserProfileStateProvider::class) state: EditUserProfileState) = ElementPreviewLight { ContentToPreview(state) } @Preview @Composable -fun UserPreferencesViewDarkPreview(@PreviewParameter(UserPreferencesStateProvider::class) state: UserPreferencesState) = +fun EditUserProfileViewDarkPreview(@PreviewParameter(EditUserProfileStateProvider::class) state: EditUserProfileState) = ElementPreviewDark { ContentToPreview(state) } @Composable -private fun ContentToPreview(state: UserPreferencesState) { - UserPreferencesView( +private fun ContentToPreview(state: EditUserProfileState) { + EditUserProfileView( onBackPressed = {}, onProfileEdited = {}, state = state, diff --git a/features/preferences/impl/src/main/res/values/localazy.xml b/features/preferences/impl/src/main/res/values/localazy.xml new file mode 100644 index 0000000000..f01ae2b5e1 --- /dev/null +++ b/features/preferences/impl/src/main/res/values/localazy.xml @@ -0,0 +1,9 @@ + + + "Display name" + "Your display name" + "An unknown error was encountered and the information couldn\'t be changed." + "Unable to update profile" + "Edit profile" + "Updating profile…" + diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/edit/RoomDetailsEditView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/edit/RoomDetailsEditView.kt index cd0cbf878e..4553161d73 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/edit/RoomDetailsEditView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/edit/RoomDetailsEditView.kt @@ -18,37 +18,27 @@ package io.element.android.features.roomdetails.impl.edit -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.verticalScroll import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ModalBottomSheetValue -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.AddAPhoto import androidx.compose.material.rememberModalBottomSheetState import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.focus.FocusManager import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.platform.LocalFocusManager @@ -61,21 +51,18 @@ import io.element.android.features.roomdetails.impl.R import io.element.android.libraries.architecture.Async import io.element.android.libraries.designsystem.components.LabelledTextField import io.element.android.libraries.designsystem.components.ProgressDialog -import io.element.android.libraries.designsystem.components.avatar.Avatar -import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.theme.aliasScreenTitle -import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.matrix.ui.components.AvatarActionBottomSheet -import io.element.android.libraries.matrix.ui.components.UnsavedAvatar +import io.element.android.libraries.matrix.ui.components.EditableAvatarView import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.coroutines.launch @@ -134,7 +121,14 @@ fun RoomDetailsEditView( .verticalScroll(rememberScrollState()) ) { Spacer(modifier = Modifier.height(24.dp)) - EditableAvatarView(state, ::onAvatarClicked) + EditableAvatarView( + userId = state.roomId, + displayName = state.roomName, + avatarUrl = state.roomAvatarUrl, + avatarSize = AvatarSize.EditRoomDetails, + onAvatarClicked = ::onAvatarClicked, + modifier = Modifier.fillMaxWidth(), + ) Spacer(modifier = Modifier.height(60.dp)) if (state.canChangeName) { @@ -202,56 +196,6 @@ fun RoomDetailsEditView( } } -@Composable -private fun EditableAvatarView( - state: RoomDetailsEditState, - onAvatarClicked: () -> Unit, - modifier: Modifier = Modifier, -) { - Column(modifier = modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { - Box( - modifier = Modifier - .size(70.dp) - .clickable(onClick = onAvatarClicked, enabled = state.canChangeAvatar) - ) { - // TODO this might be able to be simplified into a single component once send/receive media is done - when (state.roomAvatarUrl?.scheme) { - null, "mxc" -> { - Avatar( - avatarData = AvatarData(state.roomId, state.roomName, state.roomAvatarUrl?.toString(), size = AvatarSize.RoomHeader), - modifier = Modifier.fillMaxSize(), - ) - } - - else -> { - UnsavedAvatar( - avatarUri = state.roomAvatarUrl, - modifier = Modifier.fillMaxSize(), - ) - } - } - - if (state.canChangeAvatar) { - Box( - modifier = Modifier - .align(Alignment.BottomEnd) - .clip(CircleShape) - .background(MaterialTheme.colorScheme.primary) - .size(24.dp), - contentAlignment = Alignment.Center, - ) { - Icon( - modifier = Modifier.size(16.dp), - imageVector = Icons.Outlined.AddAPhoto, - contentDescription = "", - tint = MaterialTheme.colorScheme.onPrimary, - ) - } - } - } - } -} - @Composable private fun LabelledReadOnlyField( title: String, @@ -279,7 +223,7 @@ private fun LabelledReadOnlyField( } private fun Modifier.clearFocusOnTap(focusManager: FocusManager): Modifier = - pointerInput(Unit) { + this.pointerInput(Unit) { detectTapGestures(onTap = { focusManager.clearFocus() }) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LabelledOutlinedTextField.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LabelledOutlinedTextField.kt new file mode 100644 index 0000000000..a273acf25c --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LabelledOutlinedTextField.kt @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.designsystem.components + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import io.element.android.libraries.designsystem.preview.ElementPreviewDark +import io.element.android.libraries.designsystem.preview.ElementPreviewLight +import io.element.android.libraries.designsystem.theme.components.OutlinedTextField +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.theme.ElementTheme + +@Composable +fun LabelledOutlinedTextField( + label: String, + value: String, + modifier: Modifier = Modifier, + placeholder: String? = null, + singleLine: Boolean = false, + maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE, + keyboardOptions: KeyboardOptions = KeyboardOptions.Default, + onValueChange: (String) -> Unit = {}, +) { + Column( + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(8.dp), + ) { + Text( + modifier = Modifier.padding(horizontal = 16.dp), + style = ElementTheme.typography.fontBodyMdRegular, + color = MaterialTheme.colorScheme.primary, + text = label + ) + + OutlinedTextField( + modifier = Modifier.fillMaxWidth(), + value = value, + placeholder = placeholder?.let { { Text(placeholder) } }, + onValueChange = onValueChange, + singleLine = singleLine, + maxLines = maxLines, + keyboardOptions = keyboardOptions, + ) + } +} + +@Preview +@Composable +internal fun LabelledOutlinedTextFieldLightPreview() = ElementPreviewLight { ContentToPreview() } + +@Preview +@Composable +internal fun LabelledOutlinedTextFieldDarkPreview() = ElementPreviewDark { ContentToPreview() } + +@Composable +private fun ContentToPreview() { + Column { + LabelledOutlinedTextField( + label = "Room name", + value = "", + placeholder = "e.g. Product Sprint", + ) + LabelledOutlinedTextField( + label = "Room name", + value = "a room name", + placeholder = "e.g. Product Sprint", + ) + } +} 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 38b1df6dce..45d7780393 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 @@ -43,5 +43,7 @@ enum class AvatarSize(val dp: Dp) { RoomInviteItem(52.dp), InviteSender(16.dp), + EditRoomDetails(70.dp), + NotificationsOptIn(32.dp), } diff --git a/libraries/matrix/impl/build.gradle.kts b/libraries/matrix/impl/build.gradle.kts index 97eb7b6864..88cc929e79 100644 --- a/libraries/matrix/impl/build.gradle.kts +++ b/libraries/matrix/impl/build.gradle.kts @@ -29,8 +29,8 @@ anvil { } dependencies { - implementation(projects.libraries.rustsdk) -// implementation(libs.matrix.sdk) +// implementation(projects.libraries.rustsdk) + implementation(libs.matrix.sdk) implementation(projects.libraries.di) implementation(projects.libraries.androidutils) implementation(projects.libraries.network) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/EditableAvatarView.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/EditableAvatarView.kt new file mode 100644 index 0000000000..f97227be7e --- /dev/null +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/EditableAvatarView.kt @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.ui.components + +import android.net.Uri +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.AddAPhoto +import androidx.compose.material.ripple.rememberRipple +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.unit.dp +import io.element.android.libraries.designsystem.components.avatar.Avatar +import io.element.android.libraries.designsystem.components.avatar.AvatarData +import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.theme.components.Icon + +@Composable +fun EditableAvatarView( + userId: String?, + displayName: String?, + avatarUrl: Uri?, + avatarSize: AvatarSize, + onAvatarClicked: () -> Unit, + modifier: Modifier = Modifier, +) { + Column(modifier = modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { + Box( + modifier = Modifier + .size(avatarSize.dp) + .clickable( + interactionSource = remember { MutableInteractionSource() }, + onClick = onAvatarClicked, + indication = rememberRipple(bounded = false), + ) + ) { + when (avatarUrl?.scheme) { + null, "mxc" -> { + userId?.let { + Avatar( + avatarData = AvatarData(it, displayName, avatarUrl?.toString(), size = avatarSize), + modifier = Modifier.fillMaxSize(), + ) + } + } + else -> { + UnsavedAvatar( + avatarUri = avatarUrl, + modifier = Modifier.fillMaxSize(), + ) + } + } + + Box( + modifier = Modifier + .align(Alignment.BottomEnd) + .clip(CircleShape) + .background(MaterialTheme.colorScheme.primary) + .size(24.dp), + contentAlignment = Alignment.Center, + ) { + Icon( + modifier = Modifier.size(16.dp), + imageVector = Icons.Outlined.AddAPhoto, + contentDescription = "", + tint = MaterialTheme.colorScheme.onPrimary, + ) + } + } + } +} diff --git a/tools/localazy/config.json b/tools/localazy/config.json index b92e02f670..a69b7d2273 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -128,6 +128,12 @@ "includeRegex": [ "screen_create_poll_.*" ] + }, + { + "name": ":features:preferences:impl", + "includeRegex": [ + "screen_edit_profile_.*" + ] } ] } From 60104822cd15a72fe20f5b89fa3f4feadc1c9dbb Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 15 Sep 2023 14:45:46 +0200 Subject: [PATCH 194/234] Notification: log roomId and eventId --- .../push/impl/notifications/NotificationBroadcastReceiver.kt | 3 ++- .../android/libraries/push/impl/push/DefaultPushHandler.kt | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiver.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiver.kt index 59a763bd55..b2ccebbb05 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiver.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiver.kt @@ -41,10 +41,11 @@ class NotificationBroadcastReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { if (intent == null || context == null) return context.bindings().inject(this) - Timber.tag(loggerTag.value).v("NotificationBroadcastReceiver received : $intent") + Timber.tag(loggerTag.value).d("received: ${intent.action} ${intent.data}") val sessionId = intent.extras?.getString(KEY_SESSION_ID)?.let(::SessionId) ?: return val roomId = intent.getStringExtra(KEY_ROOM_ID)?.let(::RoomId) val eventId = intent.getStringExtra(KEY_EVENT_ID)?.let(::EventId) + Timber.tag(loggerTag.value).d("received for: ${roomId?.value}/${eventId?.value}") when (intent.action) { actionIds.smartReply -> handleSmartReply(intent, context) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt index 7c5d24c31a..b9ca4a5cca 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt @@ -67,7 +67,7 @@ class DefaultPushHandler @Inject constructor( * @param pushData the data received in the push. */ override suspend fun handle(pushData: PushData) { - Timber.tag(loggerTag.value).d("## handling pushData") + Timber.tag(loggerTag.value).d("## handling pushData: ${pushData.roomId}/${pushData.eventId}") if (buildMeta.lowPrivacyLoggingEnabled) { Timber.tag(loggerTag.value).d("## pushData: $pushData") From 1c56d95eab1b0dcc1cb9144953ec49b559a268e5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 15 Sep 2023 15:42:01 +0200 Subject: [PATCH 195/234] Do not render notification if the user has dismiss the notification. It should not change anything, just avoid doing useless notification rendering. --- .../invitelist/impl/InviteListPresenter.kt | 4 +- .../NotificationDrawerManager.kt | 2 +- .../DefaultNotificationDrawerManager.kt | 53 ++++++++++++------- .../NotificationBroadcastReceiver.kt | 14 ++--- .../FakeNotificationDrawerManager.kt | 2 +- 5 files changed, 44 insertions(+), 31 deletions(-) diff --git a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListPresenter.kt b/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListPresenter.kt index 8c43b815ae..648eb5094f 100644 --- a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListPresenter.kt +++ b/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListPresenter.kt @@ -141,7 +141,7 @@ class InviteListPresenter @Inject constructor( suspend { client.getRoom(roomId)?.use { it.join().getOrThrow() - notificationDrawerManager.clearMembershipNotificationForRoom(client.sessionId, roomId) + notificationDrawerManager.clearMembershipNotificationForRoom(client.sessionId, roomId, doRender = true) analyticsService.capture(it.toAnalyticsJoinedRoom(JoinedRoom.Trigger.Invite)) } roomId @@ -152,7 +152,7 @@ class InviteListPresenter @Inject constructor( suspend { client.getRoom(roomId)?.use { it.leave().getOrThrow() - notificationDrawerManager.clearMembershipNotificationForRoom(client.sessionId, roomId) + notificationDrawerManager.clearMembershipNotificationForRoom(client.sessionId, roomId, doRender = true) }.let { } }.runCatchingUpdatingState(declinedAction) } diff --git a/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/NotificationDrawerManager.kt b/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/NotificationDrawerManager.kt index 9a778195fa..ecdf32f906 100644 --- a/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/NotificationDrawerManager.kt +++ b/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/NotificationDrawerManager.kt @@ -21,5 +21,5 @@ import io.element.android.libraries.matrix.api.core.SessionId interface NotificationDrawerManager { fun clearMembershipNotificationForSession(sessionId: SessionId) - fun clearMembershipNotificationForRoom(sessionId: SessionId, roomId: RoomId) + fun clearMembershipNotificationForRoom(sessionId: SessionId, roomId: RoomId, doRender: Boolean) } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt index 91b3987251..db198bd138 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt @@ -89,7 +89,11 @@ class DefaultNotificationDrawerManager @Inject constructor( is NavigationState.Space -> {} is NavigationState.Room -> { // Cleanup notification for current room - clearMessagesForRoom(navigationState.parentSpace.parentSession.sessionId, navigationState.roomId) + clearMessagesForRoom( + sessionId = navigationState.parentSpace.parentSession.sessionId, + roomId = navigationState.roomId, + doRender = true, + ) } is NavigationState.Thread -> { onEnteringThread( @@ -132,7 +136,7 @@ class DefaultNotificationDrawerManager @Inject constructor( * Events might be grouped and there might not be one notification per event! */ fun onNotifiableEventReceived(notifiableEvent: NotifiableEvent) { - updateEvents { + updateEvents(doRender = true) { it.onNotifiableEventReceived(notifiableEvent) } } @@ -140,8 +144,8 @@ class DefaultNotificationDrawerManager @Inject constructor( /** * Clear all known events and refresh the notification drawer. */ - fun clearAllMessagesEvents(sessionId: SessionId) { - updateEvents { + fun clearAllMessagesEvents(sessionId: SessionId, doRender: Boolean) { + updateEvents(doRender = doRender) { it.clearMessagesForSession(sessionId) } } @@ -150,7 +154,7 @@ class DefaultNotificationDrawerManager @Inject constructor( * Clear all notifications related to the session and refresh the notification drawer. */ fun clearAllEvents(sessionId: SessionId) { - updateEvents { + updateEvents(doRender = true) { it.clearAllForSession(sessionId) } } @@ -160,14 +164,14 @@ class DefaultNotificationDrawerManager @Inject constructor( * Used to ignore events related to that room (no need to display notification) and clean any existing notification on this room. * Can also be called when a notification for this room is dismissed by the user. */ - fun clearMessagesForRoom(sessionId: SessionId, roomId: RoomId) { - updateEvents { + fun clearMessagesForRoom(sessionId: SessionId, roomId: RoomId, doRender: Boolean) { + updateEvents(doRender = doRender) { it.clearMessagesForRoom(sessionId, roomId) } } override fun clearMembershipNotificationForSession(sessionId: SessionId) { - updateEvents { + updateEvents(doRender = true) { it.clearMembershipNotificationForSession(sessionId) } } @@ -175,8 +179,12 @@ class DefaultNotificationDrawerManager @Inject constructor( /** * Clear invitation notification for the provided room. */ - override fun clearMembershipNotificationForRoom(sessionId: SessionId, roomId: RoomId) { - updateEvents { + override fun clearMembershipNotificationForRoom( + sessionId: SessionId, + roomId: RoomId, + doRender: Boolean, + ) { + updateEvents(doRender = doRender) { it.clearMembershipNotificationForRoom(sessionId, roomId) } } @@ -184,8 +192,8 @@ class DefaultNotificationDrawerManager @Inject constructor( /** * Clear the notifications for a single event. */ - fun clearEvent(eventId: EventId) { - updateEvents { + fun clearEvent(eventId: EventId, doRender: Boolean) { + updateEvents(doRender = doRender) { it.clearEvent(eventId) } } @@ -195,14 +203,14 @@ class DefaultNotificationDrawerManager @Inject constructor( * Used to ignore events related to that thread (no need to display notification) and clean any existing notification on this room. */ private fun onEnteringThread(sessionId: SessionId, roomId: RoomId, threadId: ThreadId) { - updateEvents { + updateEvents(doRender = true) { it.clearMessagesForThread(sessionId, roomId, threadId) } } // TODO EAx Must be per account fun notificationStyleChanged() { - updateEvents { + updateEvents(doRender = true) { val newSettings = true // pushDataStore.useCompleteNotificationFormat() if (newSettings != useCompleteNotificationFormat) { // Settings has changed, remove all current notifications @@ -212,21 +220,24 @@ class DefaultNotificationDrawerManager @Inject constructor( } } - private fun updateEvents(action: DefaultNotificationDrawerManager.(NotificationEventQueue) -> Unit) { + private fun updateEvents( + doRender: Boolean, + action: DefaultNotificationDrawerManager.(NotificationEventQueue) -> Unit, + ) { notificationState.updateQueuedEvents(this) { queuedEvents, _ -> action(queuedEvents) } - coroutineScope.refreshNotificationDrawer() + coroutineScope.refreshNotificationDrawer(doRender) } - private fun CoroutineScope.refreshNotificationDrawer() = launch { + private fun CoroutineScope.refreshNotificationDrawer(doRender: Boolean) = launch { // Implement last throttler val canHandle = firstThrottler.canHandle() Timber.v("refreshNotificationDrawer(), delay: ${canHandle.waitMillis()} ms") withContext(dispatchers.io) { delay(canHandle.waitMillis()) try { - refreshNotificationDrawerBg() + refreshNotificationDrawerBg(doRender) } catch (throwable: Throwable) { // It can happen if for instance session has been destroyed. It's a bit ugly to try catch like this, but it's safer Timber.w(throwable, "refreshNotificationDrawerBg failure") @@ -234,7 +245,7 @@ class DefaultNotificationDrawerManager @Inject constructor( } } - private suspend fun refreshNotificationDrawerBg() { + private suspend fun refreshNotificationDrawerBg(doRender: Boolean) { Timber.v("refreshNotificationDrawerBg()") val eventsToRender = notificationState.updateQueuedEvents(this) { queuedEvents, renderedEvents -> notifiableEventProcessor.process(queuedEvents.rawEvents(), renderedEvents).also { @@ -246,7 +257,9 @@ class DefaultNotificationDrawerManager @Inject constructor( Timber.d("Skipping notification update due to event list not changing") } else { notificationState.clearAndAddRenderedEvents(eventsToRender) - renderEvents(eventsToRender) + if (doRender) { + renderEvents(eventsToRender) + } persistEvents() } } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiver.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiver.kt index b2ccebbb05..2709f3840c 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiver.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiver.kt @@ -50,26 +50,26 @@ class NotificationBroadcastReceiver : BroadcastReceiver() { actionIds.smartReply -> handleSmartReply(intent, context) actionIds.dismissRoom -> if (roomId != null) { - defaultNotificationDrawerManager.clearMessagesForRoom(sessionId, roomId) + defaultNotificationDrawerManager.clearMessagesForRoom(sessionId, roomId, doRender = false) } actionIds.dismissSummary -> - defaultNotificationDrawerManager.clearAllMessagesEvents(sessionId) + defaultNotificationDrawerManager.clearAllMessagesEvents(sessionId, doRender = false) actionIds.dismissInvite -> if (roomId != null) { - defaultNotificationDrawerManager.clearMembershipNotificationForRoom(sessionId, roomId) + defaultNotificationDrawerManager.clearMembershipNotificationForRoom(sessionId, roomId, doRender = false) } actionIds.dismissEvent -> if (eventId != null) { - defaultNotificationDrawerManager.clearEvent(eventId) + defaultNotificationDrawerManager.clearEvent(eventId, doRender = false) } actionIds.markRoomRead -> if (roomId != null) { - defaultNotificationDrawerManager.clearMessagesForRoom(sessionId, roomId) + defaultNotificationDrawerManager.clearMessagesForRoom(sessionId, roomId, doRender = true) handleMarkAsRead(sessionId, roomId) } actionIds.join -> if (roomId != null) { - defaultNotificationDrawerManager.clearMembershipNotificationForRoom(sessionId, roomId) + defaultNotificationDrawerManager.clearMembershipNotificationForRoom(sessionId, roomId, doRender = true) handleJoinRoom(sessionId, roomId) } actionIds.reject -> if (roomId != null) { - defaultNotificationDrawerManager.clearMembershipNotificationForRoom(sessionId, roomId) + defaultNotificationDrawerManager.clearMembershipNotificationForRoom(sessionId, roomId, doRender = true) handleRejectRoom(sessionId, roomId) } } diff --git a/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/notifications/FakeNotificationDrawerManager.kt b/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/notifications/FakeNotificationDrawerManager.kt index 1531d2df48..702e46c3ae 100644 --- a/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/notifications/FakeNotificationDrawerManager.kt +++ b/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/notifications/FakeNotificationDrawerManager.kt @@ -28,7 +28,7 @@ class FakeNotificationDrawerManager : NotificationDrawerManager { clearMemberShipNotificationForSessionCallsCount.merge(sessionId.value, 1) { oldValue, value -> oldValue + value } } - override fun clearMembershipNotificationForRoom(sessionId: SessionId, roomId: RoomId) { + override fun clearMembershipNotificationForRoom(sessionId: SessionId, roomId: RoomId, doRender: Boolean) { val key = getMembershipNotificationKey(sessionId, roomId) clearMemberShipNotificationForRoomCallsCount.merge(key, 1) { oldValue, value -> oldValue + value } } From 9a461f4b74cb86523f99e36547978193ac5610f8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 15 Sep 2023 15:11:22 +0200 Subject: [PATCH 196/234] No need to force `DefaultNotificationDrawerManager` receiver for this private fun. --- .../push/impl/notifications/DefaultNotificationDrawerManager.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt index db198bd138..0fbd28aa3b 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt @@ -222,7 +222,7 @@ class DefaultNotificationDrawerManager @Inject constructor( private fun updateEvents( doRender: Boolean, - action: DefaultNotificationDrawerManager.(NotificationEventQueue) -> Unit, + action: (NotificationEventQueue) -> Unit, ) { notificationState.updateQueuedEvents(this) { queuedEvents, _ -> action(queuedEvents) From 020839f17e8c01362f544a5f9a5968adedf36294 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 15 Sep 2023 15:22:25 +0200 Subject: [PATCH 197/234] Simplify again the code. --- .../impl/notifications/DefaultNotificationDrawerManager.kt | 4 ++-- .../libraries/push/impl/notifications/NotificationState.kt | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt index 0fbd28aa3b..211d8d935a 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt @@ -224,7 +224,7 @@ class DefaultNotificationDrawerManager @Inject constructor( doRender: Boolean, action: (NotificationEventQueue) -> Unit, ) { - notificationState.updateQueuedEvents(this) { queuedEvents, _ -> + notificationState.updateQueuedEvents { queuedEvents, _ -> action(queuedEvents) } coroutineScope.refreshNotificationDrawer(doRender) @@ -247,7 +247,7 @@ class DefaultNotificationDrawerManager @Inject constructor( private suspend fun refreshNotificationDrawerBg(doRender: Boolean) { Timber.v("refreshNotificationDrawerBg()") - val eventsToRender = notificationState.updateQueuedEvents(this) { queuedEvents, renderedEvents -> + val eventsToRender = notificationState.updateQueuedEvents { queuedEvents, renderedEvents -> notifiableEventProcessor.process(queuedEvents.rawEvents(), renderedEvents).also { queuedEvents.clearAndAdd(it.onlyKeptEvents()) } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationState.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationState.kt index 4737e891aa..0d8731548d 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationState.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationState.kt @@ -39,11 +39,10 @@ class NotificationState( ) { fun updateQueuedEvents( - drawerManager: DefaultNotificationDrawerManager, - action: DefaultNotificationDrawerManager.(NotificationEventQueue, List>) -> T + action: (NotificationEventQueue, List>) -> T ): T { return synchronized(queuedEvents) { - action(drawerManager, queuedEvents, renderedEvents) + action(queuedEvents, renderedEvents) } } From 7d080ea3373f18f9b99f4375e19c7d4232da88e5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 15 Sep 2023 15:57:39 +0200 Subject: [PATCH 198/234] Add Timber tags. --- .../notifications/NotifiableEventProcessor.kt | 10 +++++--- .../notifications/NotifiableEventResolver.kt | 4 ++-- .../notifications/NotificationRenderer.kt | 24 +++++++++++-------- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventProcessor.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventProcessor.kt index 50f1b88783..709dfd14e8 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventProcessor.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventProcessor.kt @@ -16,7 +16,9 @@ package io.element.android.libraries.push.impl.notifications +import io.element.android.libraries.core.log.logger.LoggerTag import io.element.android.libraries.matrix.api.timeline.item.event.EventType +import io.element.android.libraries.push.impl.log.notificationLoggerTag import io.element.android.libraries.push.impl.notifications.model.FallbackNotifiableEvent import io.element.android.libraries.push.impl.notifications.model.InviteNotifiableEvent import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent @@ -29,6 +31,8 @@ import javax.inject.Inject private typealias ProcessedEvents = List> +private val loggerTag = LoggerTag("NotifiableEventProcessor", notificationLoggerTag) + class NotifiableEventProcessor @Inject constructor( private val outdatedDetector: OutdatedEventDetector, private val appNavigationStateService: AppNavigationStateService, @@ -45,10 +49,10 @@ class NotifiableEventProcessor @Inject constructor( is NotifiableMessageEvent -> when { it.shouldIgnoreEventInRoom(appState) -> { ProcessedEvent.Type.REMOVE - .also { Timber.d("notification message removed due to currently viewing the same room or thread") } + .also { Timber.tag(loggerTag.value).d("notification message removed due to currently viewing the same room or thread") } } outdatedDetector.isMessageOutdated(it) -> ProcessedEvent.Type.REMOVE - .also { Timber.d("notification message removed due to being read") } + .also { Timber.tag(loggerTag.value).d("notification message removed due to being read") } else -> ProcessedEvent.Type.KEEP } is SimpleNotifiableEvent -> when (it.type) { @@ -58,7 +62,7 @@ class NotifiableEventProcessor @Inject constructor( is FallbackNotifiableEvent -> when { it.shouldIgnoreEventInRoom(appState) -> { ProcessedEvent.Type.REMOVE - .also { Timber.d("notification fallback removed due to currently viewing the same room or thread") } + .also { Timber.tag(loggerTag.value).d("notification fallback removed due to currently viewing the same room or thread") } } else -> ProcessedEvent.Type.KEEP } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventResolver.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventResolver.kt index e5af7785db..66ca7a0abd 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventResolver.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventResolver.kt @@ -36,7 +36,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageTy import io.element.android.libraries.matrix.api.timeline.item.event.UnknownMessageType import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageType import io.element.android.libraries.push.impl.R -import io.element.android.libraries.push.impl.log.pushLoggerTag +import io.element.android.libraries.push.impl.log.notificationLoggerTag import io.element.android.libraries.push.impl.notifications.model.FallbackNotifiableEvent import io.element.android.libraries.push.impl.notifications.model.InviteNotifiableEvent import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent @@ -47,7 +47,7 @@ import io.element.android.services.toolbox.api.systemclock.SystemClock import timber.log.Timber import javax.inject.Inject -private val loggerTag = LoggerTag("NotifiableEventResolver", pushLoggerTag) +private val loggerTag = LoggerTag("NotifiableEventResolver", notificationLoggerTag) /** * The notifiable event resolver is able to create a NotifiableEvent (view model for notifications) from an sdk Event. diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationRenderer.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationRenderer.kt index a6179b3ec8..69292e5c6b 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationRenderer.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationRenderer.kt @@ -16,8 +16,10 @@ package io.element.android.libraries.push.impl.notifications +import io.element.android.libraries.core.log.logger.LoggerTag import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.push.impl.log.notificationLoggerTag import io.element.android.libraries.push.impl.notifications.model.FallbackNotifiableEvent import io.element.android.libraries.push.impl.notifications.model.InviteNotifiableEvent import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent @@ -26,6 +28,8 @@ import io.element.android.libraries.push.impl.notifications.model.SimpleNotifiab import timber.log.Timber import javax.inject.Inject +private val loggerTag = LoggerTag("NotificationRenderer", notificationLoggerTag) + class NotificationRenderer @Inject constructor( private val notificationIdProvider: NotificationIdProvider, private val notificationDisplayer: NotificationDisplayer, @@ -54,7 +58,7 @@ class NotificationRenderer @Inject constructor( // Remove summary first to avoid briefly displaying it after dismissing the last notification if (summaryNotification == SummaryNotification.Removed) { - Timber.d("Removing summary notification") + Timber.tag(loggerTag.value).d("Removing summary notification") notificationDisplayer.cancelNotificationMessage( tag = null, id = notificationIdProvider.getSummaryNotificationId(currentUser.userId) @@ -64,14 +68,14 @@ class NotificationRenderer @Inject constructor( roomNotifications.forEach { wrapper -> when (wrapper) { is RoomNotification.Removed -> { - Timber.d("Removing room messages notification ${wrapper.roomId}") + Timber.tag(loggerTag.value).d("Removing room messages notification ${wrapper.roomId}") notificationDisplayer.cancelNotificationMessage( tag = wrapper.roomId.value, id = notificationIdProvider.getRoomMessagesNotificationId(currentUser.userId) ) } is RoomNotification.Message -> if (useCompleteNotificationFormat) { - Timber.d("Updating room messages notification ${wrapper.meta.roomId}") + Timber.tag(loggerTag.value).d("Updating room messages notification ${wrapper.meta.roomId}") notificationDisplayer.showNotificationMessage( tag = wrapper.meta.roomId.value, id = notificationIdProvider.getRoomMessagesNotificationId(currentUser.userId), @@ -84,14 +88,14 @@ class NotificationRenderer @Inject constructor( invitationNotifications.forEach { wrapper -> when (wrapper) { is OneShotNotification.Removed -> { - Timber.d("Removing invitation notification ${wrapper.key}") + Timber.tag(loggerTag.value).d("Removing invitation notification ${wrapper.key}") notificationDisplayer.cancelNotificationMessage( tag = wrapper.key, id = notificationIdProvider.getRoomInvitationNotificationId(currentUser.userId) ) } is OneShotNotification.Append -> if (useCompleteNotificationFormat) { - Timber.d("Updating invitation notification ${wrapper.meta.key}") + Timber.tag(loggerTag.value).d("Updating invitation notification ${wrapper.meta.key}") notificationDisplayer.showNotificationMessage( tag = wrapper.meta.key, id = notificationIdProvider.getRoomInvitationNotificationId(currentUser.userId), @@ -104,14 +108,14 @@ class NotificationRenderer @Inject constructor( simpleNotifications.forEach { wrapper -> when (wrapper) { is OneShotNotification.Removed -> { - Timber.d("Removing simple notification ${wrapper.key}") + Timber.tag(loggerTag.value).d("Removing simple notification ${wrapper.key}") notificationDisplayer.cancelNotificationMessage( tag = wrapper.key, id = notificationIdProvider.getRoomEventNotificationId(currentUser.userId) ) } is OneShotNotification.Append -> if (useCompleteNotificationFormat) { - Timber.d("Updating simple notification ${wrapper.meta.key}") + Timber.tag(loggerTag.value).d("Updating simple notification ${wrapper.meta.key}") notificationDisplayer.showNotificationMessage( tag = wrapper.meta.key, id = notificationIdProvider.getRoomEventNotificationId(currentUser.userId), @@ -124,14 +128,14 @@ class NotificationRenderer @Inject constructor( fallbackNotifications.forEach { wrapper -> when (wrapper) { is OneShotNotification.Removed -> { - Timber.d("Removing fallback notification ${wrapper.key}") + Timber.tag(loggerTag.value).d("Removing fallback notification ${wrapper.key}") notificationDisplayer.cancelNotificationMessage( tag = wrapper.key, id = notificationIdProvider.getFallbackNotificationId(currentUser.userId) ) } is OneShotNotification.Append -> if (useCompleteNotificationFormat) { - Timber.d("Updating fallback notification ${wrapper.meta.key}") + Timber.tag(loggerTag.value).d("Updating fallback notification ${wrapper.meta.key}") notificationDisplayer.showNotificationMessage( tag = wrapper.meta.key, id = notificationIdProvider.getFallbackNotificationId(currentUser.userId), @@ -143,7 +147,7 @@ class NotificationRenderer @Inject constructor( // Update summary last to avoid briefly displaying it before other notifications if (summaryNotification is SummaryNotification.Update) { - Timber.d("Updating summary notification") + Timber.tag(loggerTag.value).d("Updating summary notification") notificationDisplayer.showNotificationMessage( tag = null, id = notificationIdProvider.getSummaryNotificationId(currentUser.userId), From f88507117b63538b18877f7c13862a7716a1ac2e Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Fri, 15 Sep 2023 16:39:44 +0200 Subject: [PATCH 199/234] Element Call SPA integration (#1283) * Integrate Element Call into EX, being able to open its URLs and handle the call in-app. * Add custom scheme support with format `element:call?url=...`. * Update androix.webkit * Silence the foreground service notification. - Allow foreground service tap action to re-open the ongoing call. - Unify notification small icons in different modules using a vector one. --------- Co-authored-by: ElementBot --- app/build.gradle.kts | 1 + changelog.d/1300.feature | 1 + features/call/build.gradle.kts | 37 ++++ features/call/src/main/AndroidManifest.xml | 61 +++++ .../features/call/CallForegroundService.kt | 89 ++++++++ .../features/call/CallIntentDataParser.kt | 45 ++++ .../android/features/call/CallScreenView.kt | 152 +++++++++++++ .../features/call/ElementCallActivity.kt | 208 ++++++++++++++++++ .../android/features/call/di/CallBindings.kt | 26 +++ .../src/main/res/values-fr/translations.xml | 6 + .../src/main/res/values/do_not_translate.xml | 20 ++ .../call/src/main/res/values/localazy.xml | 6 + .../call/CallIntentDataParserTests.kt | 105 +++++++++ .../features/call/MapWebkitPermissionsTest.kt | 44 ++++ gradle/libs.versions.toml | 1 + .../designsystem/utils/CommonResources.kt | 21 ++ .../res/drawable/ic_notification_small.xml | 7 + libraries/push/impl/build.gradle.kts | 1 + .../factories/NotificationFactory.kt | 13 +- .../res/drawable-xxhdpi/ic_notification.png | Bin 1269 -> 0 bytes .../src/main/res/values-cs/translations.xml | 4 +- .../src/main/res/values-fr/translations.xml | 3 - .../src/main/res/values-ru/translations.xml | 4 +- .../src/main/res/values/localazy.xml | 8 +- tests/uitests/build.gradle.kts | 1 + ...lScreenView-D-0_0_null,NEXUS_5,1.0,en].png | 3 + ...lScreenView-N-0_1_null,NEXUS_5,1.0,en].png | 3 + tools/lint/lint.xml | 2 + tools/localazy/config.json | 6 + 29 files changed, 862 insertions(+), 16 deletions(-) create mode 100644 changelog.d/1300.feature create mode 100644 features/call/build.gradle.kts create mode 100644 features/call/src/main/AndroidManifest.xml create mode 100644 features/call/src/main/kotlin/io/element/android/features/call/CallForegroundService.kt create mode 100644 features/call/src/main/kotlin/io/element/android/features/call/CallIntentDataParser.kt create mode 100644 features/call/src/main/kotlin/io/element/android/features/call/CallScreenView.kt create mode 100644 features/call/src/main/kotlin/io/element/android/features/call/ElementCallActivity.kt create mode 100644 features/call/src/main/kotlin/io/element/android/features/call/di/CallBindings.kt create mode 100644 features/call/src/main/res/values-fr/translations.xml create mode 100644 features/call/src/main/res/values/do_not_translate.xml create mode 100644 features/call/src/main/res/values/localazy.xml create mode 100644 features/call/src/test/kotlin/io/element/android/features/call/CallIntentDataParserTests.kt create mode 100644 features/call/src/test/kotlin/io/element/android/features/call/MapWebkitPermissionsTest.kt create mode 100644 libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/CommonResources.kt create mode 100644 libraries/designsystem/src/main/res/drawable/ic_notification_small.xml delete mode 100644 libraries/push/impl/src/main/res/drawable-xxhdpi/ic_notification.png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.call_null_CallScreenView-D-0_0_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.call_null_CallScreenView-N-0_1_null,NEXUS_5,1.0,en].png diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 2821fcbd04..839a5095dd 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -198,6 +198,7 @@ dependencies { allLibrariesImpl() allServicesImpl() allFeaturesImpl(rootDir, logger) + implementation(projects.features.call) implementation(projects.anvilannotations) implementation(projects.appnav) anvil(projects.anvilcodegen) diff --git a/changelog.d/1300.feature b/changelog.d/1300.feature new file mode 100644 index 0000000000..bfa40bfc3b --- /dev/null +++ b/changelog.d/1300.feature @@ -0,0 +1 @@ +Integrate Element Call into EX by embedding a call in a WebView. diff --git a/features/call/build.gradle.kts b/features/call/build.gradle.kts new file mode 100644 index 0000000000..69046e33b4 --- /dev/null +++ b/features/call/build.gradle.kts @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +plugins { + id("io.element.android-compose-library") + alias(libs.plugins.anvil) + alias(libs.plugins.ksp) +} + +android { + namespace = "io.element.android.features.call" +} + +dependencies { + implementation(projects.libraries.architecture) + implementation(projects.libraries.designsystem) + implementation(projects.libraries.network) + implementation(libs.androidx.webkit) + ksp(libs.showkase.processor) + + testImplementation(libs.test.junit) + testImplementation(libs.test.truth) + testImplementation(libs.test.robolectric) +} diff --git a/features/call/src/main/AndroidManifest.xml b/features/call/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..1aed77cd95 --- /dev/null +++ b/features/call/src/main/AndroidManifest.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/features/call/src/main/kotlin/io/element/android/features/call/CallForegroundService.kt b/features/call/src/main/kotlin/io/element/android/features/call/CallForegroundService.kt new file mode 100644 index 0000000000..12355290e3 --- /dev/null +++ b/features/call/src/main/kotlin/io/element/android/features/call/CallForegroundService.kt @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.call + +import android.app.Service +import android.content.Context +import android.content.Intent +import android.os.Build +import android.os.IBinder +import androidx.core.app.NotificationChannelCompat +import androidx.core.app.NotificationCompat +import androidx.core.app.NotificationManagerCompat +import androidx.core.app.PendingIntentCompat +import androidx.core.graphics.drawable.IconCompat +import io.element.android.libraries.designsystem.utils.CommonDrawables + +class CallForegroundService : Service() { + + companion object { + fun start(context: Context) { + val intent = Intent(context, CallForegroundService::class.java) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + context.startForegroundService(intent) + } else { + context.startService(intent) + } + } + + fun stop(context: Context) { + val intent = Intent(context, CallForegroundService::class.java) + context.stopService(intent) + } + } + + private lateinit var notificationManagerCompat: NotificationManagerCompat + + override fun onCreate() { + super.onCreate() + + notificationManagerCompat = NotificationManagerCompat.from(this) + + val foregroundServiceChannel = NotificationChannelCompat.Builder( + "call_foreground_service_channel", + NotificationManagerCompat.IMPORTANCE_LOW, + ).setName( + getString(R.string.call_foreground_service_channel_title_android).ifEmpty { "Ongoing call" } + ).build() + notificationManagerCompat.createNotificationChannel(foregroundServiceChannel) + + val callActivityIntent = Intent(this, ElementCallActivity::class.java) + val pendingIntent = PendingIntentCompat.getActivity(this, 0, callActivityIntent, 0, false) + val notification = NotificationCompat.Builder(this, foregroundServiceChannel.id) + .setSmallIcon(IconCompat.createWithResource(this, CommonDrawables.ic_notification_small)) + .setContentTitle(getString(R.string.call_foreground_service_title_android)) + .setContentText(getString(R.string.call_foreground_service_message_android)) + .setContentIntent(pendingIntent) + .build() + startForeground(1, notification) + } + + @Suppress("DEPRECATION") + override fun onDestroy() { + super.onDestroy() + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + stopForeground(STOP_FOREGROUND_REMOVE) + } else { + stopForeground(true) + } + } + + override fun onBind(intent: Intent?): IBinder? { + return null + } +} diff --git a/features/call/src/main/kotlin/io/element/android/features/call/CallIntentDataParser.kt b/features/call/src/main/kotlin/io/element/android/features/call/CallIntentDataParser.kt new file mode 100644 index 0000000000..a664e562f3 --- /dev/null +++ b/features/call/src/main/kotlin/io/element/android/features/call/CallIntentDataParser.kt @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.call + +import android.net.Uri +import java.net.URLDecoder + +object CallIntentDataParser { + + private val validHttpSchemes = sequenceOf("http", "https") + + fun parse(data: String?): String? { + val parsedUrl = data?.let { Uri.parse(data) } ?: return null + val scheme = parsedUrl.scheme + return when { + scheme in validHttpSchemes && parsedUrl.host == "call.element.io" -> data + scheme == "element" && parsedUrl.host == "call" -> { + // We use this custom scheme to load arbitrary URLs for other instances of Element Call, + // so we can only verify it's an HTTP/HTTPs URL with a non-empty host + parsedUrl.getQueryParameter("url") + ?.let { URLDecoder.decode(it, "utf-8") } + ?.takeIf { + val internalUri = Uri.parse(it) + internalUri.scheme in validHttpSchemes && !internalUri.host.isNullOrBlank() + } + } + // This should never be possible, but we still need to take into account the possibility + else -> null + } + } +} diff --git a/features/call/src/main/kotlin/io/element/android/features/call/CallScreenView.kt b/features/call/src/main/kotlin/io/element/android/features/call/CallScreenView.kt new file mode 100644 index 0000000000..08ad687f91 --- /dev/null +++ b/features/call/src/main/kotlin/io/element/android/features/call/CallScreenView.kt @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.call + +import android.annotation.SuppressLint +import android.view.ViewGroup +import android.webkit.PermissionRequest +import android.webkit.WebChromeClient +import android.webkit.WebView +import androidx.compose.foundation.layout.consumeWindowInsets +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Close +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalInspectionMode +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.viewinterop.AndroidView +import io.element.android.libraries.designsystem.components.button.BackButton +import io.element.android.libraries.designsystem.preview.DayNightPreviews +import io.element.android.libraries.designsystem.theme.components.Scaffold +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.components.TopAppBar +import io.element.android.libraries.theme.ElementTheme + +typealias RequestPermissionCallback = (Array) -> Unit + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +internal fun CallScreenView( + url: String?, + userAgent: String, + requestPermissions: (Array, RequestPermissionCallback) -> Unit, + onClose: () -> Unit, + modifier: Modifier = Modifier, +) { + ElementTheme { + Scaffold( + modifier = modifier, + topBar = { + TopAppBar( + title = { Text(stringResource(R.string.element_call)) }, + navigationIcon = { + BackButton( + imageVector = Icons.Default.Close, + onClick = onClose + ) + } + ) + } + ) { padding -> + CallWebView( + modifier = Modifier + .padding(padding) + .consumeWindowInsets(padding) + .fillMaxSize(), + url = url, + userAgent = userAgent, + onPermissionsRequested = { request -> + val androidPermissions = mapWebkitPermissions(request.resources) + val callback: RequestPermissionCallback = { request.grant(it) } + requestPermissions(androidPermissions.toTypedArray(), callback) + } + ) + } + } +} + +@Composable +private fun CallWebView( + url: String?, + userAgent: String, + onPermissionsRequested: (PermissionRequest) -> Unit, + modifier: Modifier = Modifier, +) { + val isInpectionMode = LocalInspectionMode.current + AndroidView( + modifier = modifier, + factory = { context -> + WebView(context).apply { + if (!isInpectionMode) { + setup(userAgent, onPermissionsRequested) + if (url != null) { + loadUrl(url) + } + } + } + }, + update = { webView -> + if (!isInpectionMode && url != null) { + webView.loadUrl(url) + } + }, + onRelease = { webView -> + webView.destroy() + } + ) +} + +@SuppressLint("SetJavaScriptEnabled") +private fun WebView.setup(userAgent: String, onPermissionsRequested: (PermissionRequest) -> Unit) { + layoutParams = ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + + with(settings) { + javaScriptEnabled = true + allowContentAccess = true + allowFileAccess = true + domStorageEnabled = true + mediaPlaybackRequiresUserGesture = false + databaseEnabled = true + loadsImagesAutomatically = true + userAgentString = userAgent + } + + webChromeClient = object : WebChromeClient() { + override fun onPermissionRequest(request: PermissionRequest) { + onPermissionsRequested(request) + } + } +} + +@DayNightPreviews +@Composable +internal fun CallScreenViewPreview() { + ElementTheme { + CallScreenView( + url = "https://call.element.io/some-actual-call?with=parameters", + userAgent = "", + requestPermissions = { _, _ -> }, + onClose = { }, + ) + } +} diff --git a/features/call/src/main/kotlin/io/element/android/features/call/ElementCallActivity.kt b/features/call/src/main/kotlin/io/element/android/features/call/ElementCallActivity.kt new file mode 100644 index 0000000000..69ef3963cb --- /dev/null +++ b/features/call/src/main/kotlin/io/element/android/features/call/ElementCallActivity.kt @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.call + +import android.Manifest +import android.content.Intent +import android.content.res.Configuration +import android.media.AudioAttributes +import android.media.AudioFocusRequest +import android.media.AudioManager +import android.os.Build +import android.os.Bundle +import android.view.WindowManager +import android.webkit.PermissionRequest +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.contract.ActivityResultContracts +import androidx.compose.runtime.mutableStateOf +import io.element.android.features.call.di.CallBindings +import io.element.android.libraries.architecture.bindings +import io.element.android.libraries.network.useragent.UserAgentProvider +import javax.inject.Inject + +class ElementCallActivity : ComponentActivity() { + + @Inject lateinit var userAgentProvider: UserAgentProvider + + private lateinit var audioManager: AudioManager + + private var requestPermissionCallback: RequestPermissionCallback? = null + + private var audiofocusRequest: AudioFocusRequest? = null + private var audioFocusChangeListener: AudioManager.OnAudioFocusChangeListener? = null + + private val requestPermissionsLauncher = registerPermissionResultLauncher() + + private var isDarkMode = false + private val urlState = mutableStateOf(null) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + applicationContext.bindings().inject(this) + + window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + + urlState.value = intent?.dataString?.let(::parseUrl) ?: run { + finish() + return + } + + if (savedInstanceState == null) { + updateUiMode(resources.configuration) + } + + audioManager = getSystemService(AUDIO_SERVICE) as AudioManager + requestAudioFocus() + + val userAgent = userAgentProvider.provide() + + setContent { + CallScreenView( + url = urlState.value, + userAgent = userAgent, + onClose = this::finish, + requestPermissions = { permissions, callback -> + requestPermissionCallback = callback + requestPermissionsLauncher.launch(permissions) + } + ) + } + } + + override fun onConfigurationChanged(newConfig: Configuration) { + super.onConfigurationChanged(newConfig) + + updateUiMode(newConfig) + } + + override fun onNewIntent(intent: Intent?) { + super.onNewIntent(intent) + + val intentUrl = intent?.dataString?.let(::parseUrl) + when { + // New URL, update it and reload the webview + intentUrl != null -> urlState.value = intentUrl + // Re-opened the activity but we have no url to load or a cached one, finish the activity + intent?.dataString == null && urlState.value == null -> finish() + // Coming back from notification, do nothing + else -> return + } + } + + override fun onStart() { + super.onStart() + CallForegroundService.stop(this) + } + + override fun onStop() { + super.onStop() + if (!isFinishing && !isChangingConfigurations) { + CallForegroundService.start(this) + } + } + + override fun onDestroy() { + super.onDestroy() + releaseAudioFocus() + CallForegroundService.stop(this) + } + + override fun finish() { + // Also remove the task from recents + finishAndRemoveTask() + } + + private fun parseUrl(url: String?): String? = CallIntentDataParser.parse(url) + + private fun registerPermissionResultLauncher(): ActivityResultLauncher> { + return registerForActivityResult( + ActivityResultContracts.RequestMultiplePermissions() + ) { permissions -> + val callback = requestPermissionCallback ?: return@registerForActivityResult + val permissionsToGrant = mutableListOf() + permissions.forEach { (permission, granted) -> + if (granted) { + val webKitPermission = when (permission) { + Manifest.permission.CAMERA -> PermissionRequest.RESOURCE_VIDEO_CAPTURE + Manifest.permission.RECORD_AUDIO -> PermissionRequest.RESOURCE_AUDIO_CAPTURE + else -> return@forEach + } + permissionsToGrant.add(webKitPermission) + } + } + callback(permissionsToGrant.toTypedArray()) + } + } + + @Suppress("DEPRECATION") + private fun requestAudioFocus() { + val audioAttributes = AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION) + .build() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val request = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN) + .setAudioAttributes(audioAttributes) + .build() + audioManager.requestAudioFocus(request) + audiofocusRequest = request + } else { + val listener = AudioManager.OnAudioFocusChangeListener { } + audioManager.requestAudioFocus( + listener, + AudioManager.STREAM_VOICE_CALL, + AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE, + ) + + audioFocusChangeListener = listener + } + } + + @Suppress("DEPRECATION") + private fun releaseAudioFocus() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + audiofocusRequest?.let { audioManager.abandonAudioFocusRequest(it) } + } else { + audioFocusChangeListener?.let { audioManager.abandonAudioFocus(it) } + } + } + + private fun updateUiMode(configuration: Configuration) { + val prevDarkMode = isDarkMode + val currentNightMode = configuration.uiMode and Configuration.UI_MODE_NIGHT_YES + isDarkMode = currentNightMode != 0 + if (prevDarkMode != isDarkMode) { + if (isDarkMode) { + window.setBackgroundDrawableResource(android.R.drawable.screen_background_dark) + } else { + window.setBackgroundDrawableResource(android.R.drawable.screen_background_light) + } + } + } +} + +internal fun mapWebkitPermissions(permissions: Array): List { + return permissions.mapNotNull { permission -> + when (permission) { + PermissionRequest.RESOURCE_AUDIO_CAPTURE -> Manifest.permission.RECORD_AUDIO + PermissionRequest.RESOURCE_VIDEO_CAPTURE -> Manifest.permission.CAMERA + else -> null + } + } +} diff --git a/features/call/src/main/kotlin/io/element/android/features/call/di/CallBindings.kt b/features/call/src/main/kotlin/io/element/android/features/call/di/CallBindings.kt new file mode 100644 index 0000000000..1e261cc225 --- /dev/null +++ b/features/call/src/main/kotlin/io/element/android/features/call/di/CallBindings.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.call.di + +import com.squareup.anvil.annotations.ContributesTo +import io.element.android.features.call.ElementCallActivity +import io.element.android.libraries.di.AppScope + +@ContributesTo(AppScope::class) +interface CallBindings { + fun inject(callActivity: ElementCallActivity) +} diff --git a/features/call/src/main/res/values-fr/translations.xml b/features/call/src/main/res/values-fr/translations.xml new file mode 100644 index 0000000000..e35473b31b --- /dev/null +++ b/features/call/src/main/res/values-fr/translations.xml @@ -0,0 +1,6 @@ + + + "Appel en cours" + "Appuyez pour retourner à l\'appel." + "☎️ Appel en cours" + diff --git a/features/call/src/main/res/values/do_not_translate.xml b/features/call/src/main/res/values/do_not_translate.xml new file mode 100644 index 0000000000..c1fe10cdfb --- /dev/null +++ b/features/call/src/main/res/values/do_not_translate.xml @@ -0,0 +1,20 @@ + + + + + Element Call + diff --git a/features/call/src/main/res/values/localazy.xml b/features/call/src/main/res/values/localazy.xml new file mode 100644 index 0000000000..cfe40526f4 --- /dev/null +++ b/features/call/src/main/res/values/localazy.xml @@ -0,0 +1,6 @@ + + + "Ongoing call" + "Tap to return to the call" + "☎️ Call in progress" + diff --git a/features/call/src/test/kotlin/io/element/android/features/call/CallIntentDataParserTests.kt b/features/call/src/test/kotlin/io/element/android/features/call/CallIntentDataParserTests.kt new file mode 100644 index 0000000000..da41692b40 --- /dev/null +++ b/features/call/src/test/kotlin/io/element/android/features/call/CallIntentDataParserTests.kt @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.call + +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import java.net.URLEncoder + +@RunWith(RobolectricTestRunner::class) +class CallIntentDataParserTests { + + @Test + fun `a null data returns null`() { + val url: String? = null + assertThat(CallIntentDataParser.parse(url)).isNull() + } + + @Test + fun `empty data returns null`() { + val url = "" + assertThat(CallIntentDataParser.parse(url)).isNull() + } + + @Test + fun `invalid data returns null`() { + val url = "!" + assertThat(CallIntentDataParser.parse(url)).isNull() + } + + @Test + fun `data with no scheme returns null`() { + val url = "test" + assertThat(CallIntentDataParser.parse(url)).isNull() + } + + @Test + fun `Element Call urls will be returned as is`() { + val httpBaseUrl = "http://call.element.io" + val httpCallUrl = "http://call.element.io/some-actual-call?with=parameters" + val httpsBaseUrl = "https://call.element.io" + val httpsCallUrl = "https://call.element.io/some-actual-call?with=parameters" + assertThat(CallIntentDataParser.parse(httpBaseUrl)).isEqualTo(httpBaseUrl) + assertThat(CallIntentDataParser.parse(httpCallUrl)).isEqualTo(httpCallUrl) + assertThat(CallIntentDataParser.parse(httpsBaseUrl)).isEqualTo(httpsBaseUrl) + assertThat(CallIntentDataParser.parse(httpsCallUrl)).isEqualTo(httpsCallUrl) + } + + @Test + fun `HTTP and HTTPS urls that don't come from EC return null`() { + val httpBaseUrl = "http://app.element.io" + val httpsBaseUrl = "https://app.element.io" + val httpInvalidUrl = "http://" + val httpsInvalidUrl = "http://" + assertThat(CallIntentDataParser.parse(httpBaseUrl)).isNull() + assertThat(CallIntentDataParser.parse(httpsBaseUrl)).isNull() + assertThat(CallIntentDataParser.parse(httpInvalidUrl)).isNull() + assertThat(CallIntentDataParser.parse(httpsInvalidUrl)).isNull() + } + + @Test + fun `element scheme with call host and url param gets url extracted`() { + val embeddedUrl = "http://call.element.io/some-actual-call?with=parameters" + val encodedUrl = URLEncoder.encode(embeddedUrl, "utf-8") + val url = "element://call?url=$encodedUrl" + assertThat(CallIntentDataParser.parse(url)).isEqualTo(embeddedUrl) + } + + @Test + fun `element scheme with call host and no url param returns null`() { + val embeddedUrl = "http://call.element.io/some-actual-call?with=parameters" + val encodedUrl = URLEncoder.encode(embeddedUrl, "utf-8") + val url = "element://call?no-url=$encodedUrl" + assertThat(CallIntentDataParser.parse(url)).isNull() + } + + @Test + fun `element scheme with no call host returns null`() { + val embeddedUrl = "http://call.element.io/some-actual-call?with=parameters" + val encodedUrl = URLEncoder.encode(embeddedUrl, "utf-8") + val url = "element://no-call?url=$encodedUrl" + assertThat(CallIntentDataParser.parse(url)).isNull() + } + + @Test + fun `element scheme with no data returns null`() { + val url = "element://call?url=" + assertThat(CallIntentDataParser.parse(url)).isNull() + } +} diff --git a/features/call/src/test/kotlin/io/element/android/features/call/MapWebkitPermissionsTest.kt b/features/call/src/test/kotlin/io/element/android/features/call/MapWebkitPermissionsTest.kt new file mode 100644 index 0000000000..f82e31c068 --- /dev/null +++ b/features/call/src/test/kotlin/io/element/android/features/call/MapWebkitPermissionsTest.kt @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.call + +import android.Manifest +import android.webkit.PermissionRequest +import com.google.common.truth.Truth.assertThat +import org.junit.Test + +class MapWebkitPermissionsTest { + + @Test + fun `given Webkit's RESOURCE_AUDIO_CAPTURE returns Android's RECORD_AUDIO permission`() { + val permission = mapWebkitPermissions(arrayOf(PermissionRequest.RESOURCE_AUDIO_CAPTURE)) + assertThat(permission).isEqualTo(listOf(Manifest.permission.RECORD_AUDIO)) + } + + @Test + fun `given Webkit's RESOURCE_VIDEO_CAPTURE returns Android's CAMERA permission`() { + val permission = mapWebkitPermissions(arrayOf(PermissionRequest.RESOURCE_VIDEO_CAPTURE)) + assertThat(permission).isEqualTo(listOf(Manifest.permission.CAMERA)) + } + + @Test + fun `given any other permission, it returns nothing`() { + val permission = mapWebkitPermissions(arrayOf(PermissionRequest.RESOURCE_PROTECTED_MEDIA_ID)) + assertThat(permission).isEqualTo(emptyList()) + } + +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ebd4f4c888..b164dfbb95 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -91,6 +91,7 @@ androidx_activity_activity = { module = "androidx.activity:activity", version.re androidx_activity_compose = { module = "androidx.activity:activity-compose", version.ref = "activity" } androidx_startup = { module = "androidx.startup:startup-runtime", version.ref = "startup" } androidx_preference = "androidx.preference:preference:1.2.1" +androidx_webkit = "androidx.webkit:webkit:1.8.0" androidx_compose_bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose_bom" } # Warning: issue on alpha07, make sure this is working when upgrading diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/CommonResources.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/CommonResources.kt new file mode 100644 index 0000000000..adcfd93af8 --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/CommonResources.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.designsystem.utils + +import io.element.android.libraries.designsystem.R + +typealias CommonDrawables = R.drawable diff --git a/libraries/designsystem/src/main/res/drawable/ic_notification_small.xml b/libraries/designsystem/src/main/res/drawable/ic_notification_small.xml new file mode 100644 index 0000000000..cf84d679cd --- /dev/null +++ b/libraries/designsystem/src/main/res/drawable/ic_notification_small.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/libraries/push/impl/build.gradle.kts b/libraries/push/impl/build.gradle.kts index b961146e78..c7e3251ffb 100644 --- a/libraries/push/impl/build.gradle.kts +++ b/libraries/push/impl/build.gradle.kts @@ -38,6 +38,7 @@ dependencies { implementation(projects.libraries.architecture) implementation(projects.libraries.core) + implementation(projects.libraries.designsystem) implementation(projects.libraries.di) implementation(projects.libraries.androidutils) implementation(projects.libraries.network) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationFactory.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationFactory.kt index b359f540f8..105b5789e4 100755 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationFactory.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationFactory.kt @@ -25,6 +25,7 @@ import androidx.core.app.NotificationCompat import androidx.core.content.ContextCompat import androidx.core.content.res.ResourcesCompat import io.element.android.libraries.core.meta.BuildMeta +import io.element.android.libraries.designsystem.utils.CommonDrawables import io.element.android.libraries.di.ApplicationContext import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.user.MatrixUser @@ -67,7 +68,7 @@ class NotificationFactory @Inject constructor( else -> pendingIntentFactory.createOpenRoomPendingIntent(roomInfo.sessionId, roomInfo.roomId) } - val smallIcon = R.drawable.ic_notification + val smallIcon = CommonDrawables.ic_notification_small val channelId = notificationChannels.getChannelIdForMessage(roomInfo.shouldBing) return NotificationCompat.Builder(context, channelId) @@ -141,7 +142,7 @@ class NotificationFactory @Inject constructor( inviteNotifiableEvent: InviteNotifiableEvent ): Notification { val accentColor = ContextCompat.getColor(context, R.color.notification_accent_color) - val smallIcon = R.drawable.ic_notification + val smallIcon = CommonDrawables.ic_notification_small val channelId = notificationChannels.getChannelIdForMessage(inviteNotifiableEvent.noisy) return NotificationCompat.Builder(context, channelId) .setOnlyAlertOnce(true) @@ -185,7 +186,7 @@ class NotificationFactory @Inject constructor( simpleNotifiableEvent: SimpleNotifiableEvent, ): Notification { val accentColor = ContextCompat.getColor(context, R.color.notification_accent_color) - val smallIcon = R.drawable.ic_notification + val smallIcon = CommonDrawables.ic_notification_small val channelId = notificationChannels.getChannelIdForMessage(simpleNotifiableEvent.noisy) return NotificationCompat.Builder(context, channelId) @@ -220,7 +221,7 @@ class NotificationFactory @Inject constructor( fallbackNotifiableEvent: FallbackNotifiableEvent, ): Notification { val accentColor = ContextCompat.getColor(context, R.color.notification_accent_color) - val smallIcon = R.drawable.ic_notification + val smallIcon = CommonDrawables.ic_notification_small val channelId = notificationChannels.getChannelIdForMessage(false) return NotificationCompat.Builder(context, channelId) @@ -261,7 +262,7 @@ class NotificationFactory @Inject constructor( lastMessageTimestamp: Long ): Notification { val accentColor = ContextCompat.getColor(context, R.color.notification_accent_color) - val smallIcon = R.drawable.ic_notification + val smallIcon = CommonDrawables.ic_notification_small val channelId = notificationChannels.getChannelIdForMessage(noisy) return NotificationCompat.Builder(context, channelId) .setOnlyAlertOnce(true) @@ -301,7 +302,7 @@ class NotificationFactory @Inject constructor( return NotificationCompat.Builder(context, notificationChannels.getChannelIdForTest()) .setContentTitle(buildMeta.applicationName) .setContentText(stringProvider.getString(R.string.notification_test_push_notification_content)) - .setSmallIcon(R.drawable.ic_notification) + .setSmallIcon(CommonDrawables.ic_notification_small) .setLargeIcon(getBitmap(R.drawable.element_logo_green)) .setColor(ContextCompat.getColor(context, R.color.notification_accent_color)) .setPriority(NotificationCompat.PRIORITY_MAX) diff --git a/libraries/push/impl/src/main/res/drawable-xxhdpi/ic_notification.png b/libraries/push/impl/src/main/res/drawable-xxhdpi/ic_notification.png deleted file mode 100644 index a86508b71b432a095780bc8fd6b8122816c10e47..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1269 zcmV1Jw|1DI%CxRJEgpPxkR`%a>$bk(*HW;Aqq7G$E4ZYbsNeFH$D1x3 z$C*1^e?oo3Hv!or`BIW2&`Xl@wSy60Vs>%X7Y<`jC?yd6(j|1!MnR51mbAvYrIR9v z)KmydMV>%h01XAj2BLstFsBYc_rm5B6Enay;;^EQKqp0O^2EAXh4>Sf)Qty{V0;sZ ze=_aPY%cGqBM=48%haam&x0odI!F#HPd3FgLxk!p4F^ z0kKvtu*A%$Cm^nejXMef-1Ao@G62sGb9EPGC5(?FeL3e2DFV-(KOR)46P& zEc4|Udghc7P`ubZzuRYssyCAa{r)B!$!YMJAlP;7!liSAx6>69C``S_Z??O6F-!K*pBnDXlxx8LWmcg@>B6qq(R9@8XS{daDS<>BtDXBUvB!MF zu5+uVqb5vxK}Q5+Rh(J+*y2g+QGJoEWxPkT(L1LBQA?F=Rs3WnJs~?`-1NNA)ER9~ zlpTjSK~qJawMvs?fOUe<#k0>?f(pyESpPg680hTSCJ+)EviU%p{{c4GcfsYJLD))^ zJN@`NM^QKcU9@7>bhdHVGQgpbNM0%5S3m-K8j9uzHkK`e*fxd}$`E+u(pU%C0@+V3 z-`Si-jfLogThdjseQW-~6ZFH<*~i46Qf5G^&onMg`6Anb!}?^gXE5hw*(Y#IK#bci zz>~DAS9qPy4-9Bq$JscRa7$g;Un~?p4FUwnV}rMDh>br8<{bK7{JTwe5R?+FQ^;w zs`H_XLUxW}Ly~wgh+CBpUA1W^Ylb*QTYr%v>4^lH5QH!HV^cn%R6yrvu<|U(5rjRZ z$Wrqisa+4~v#~z4(3+AK&BXjdpV0;Ay;WzWh;DV*{Z32++={K7B98DoYtP1`pqzkP zO_7r%;q6A6+13-sTOM{2*>TPObWa66>+IfgY;a_CjlBT3qe=}Gjx6ur3HTrVW{Fxt zHlGD$LX>0SkRt|NrGhuPoBESmuq;tmdoR9?LKavFGPw6=@&%O}X f5!@Uq=nBn0jKJO8Fdhew00000NkvXXu0mjfM&?#H diff --git a/libraries/ui-strings/src/main/res/values-cs/translations.xml b/libraries/ui-strings/src/main/res/values-cs/translations.xml index 0ff43bceb7..271b614dc4 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -195,9 +195,9 @@ "Další nastavení" "Halsové a video hovory" "Neshoda konfigurace" - "Zjednodušili jsme nastavení oznámení, abychom usnadnili hledání možností. + "Zjednodušili jsme nastavení oznámení, abychom usnadnili hledání možností. -Některá vlastní nastavení, která jste si vybrali v minulosti, se zde nezobrazují, ale jsou stále aktivní. +Některá vlastní nastavení, která jste si vybrali v minulosti, se zde nezobrazují, ale jsou stále aktivní. Pokud budete pokračovat, některá nastavení se mohou změnit." "Přímé zprávy" diff --git a/libraries/ui-strings/src/main/res/values-fr/translations.xml b/libraries/ui-strings/src/main/res/values-fr/translations.xml index 67b738cc21..4978cdb68c 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -67,9 +67,6 @@ "Prendre une photo" "Afficher la source" "Oui" - "Appel en cours" - "Appuyez pour retourner à l\'appel." - "☎️ Appel en cours" "À propos" "Politique d\'utilisation acceptable" "Paramètres avancés" diff --git a/libraries/ui-strings/src/main/res/values-ru/translations.xml b/libraries/ui-strings/src/main/res/values-ru/translations.xml index 798515fa6a..d37e28dc7a 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -194,9 +194,9 @@ "Дополнительные параметры" "Аудио и видео звонки" "Несоответствие конфигурации" - "Мы упростили настройки уведомлений, чтобы упростить поиск опций. + "Мы упростили настройки уведомлений, чтобы упростить поиск опций. -Некоторые пользовательские настройки, выбранные вами ранее, не отображаются в данном меню, но они все еще активны. +Некоторые пользовательские настройки, выбранные вами ранее, не отображаются в данном меню, но они все еще активны. Если вы продолжите, некоторые настройки могут быть изменены." "Прямые чаты" diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 2355e4b603..0cd0b7df0e 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -67,9 +67,6 @@ "Take photo" "View Source" "Yes" - "Ongoing call" - "Tap to return to the call" - "☎️ Call in progress" "About" "Acceptable use policy" "Advanced settings" @@ -207,6 +204,11 @@ "This is the beginning of this conversation." "New" "Share analytics data" + "Display name" + "Your display name" + "An unknown error was encountered and the information couldn\'t be changed." + "Unable to update profile" + "Updating profile…" "Failed selecting media, please try again." "Failed processing media to upload, please try again." "Failed uploading media, please try again." diff --git a/tests/uitests/build.gradle.kts b/tests/uitests/build.gradle.kts index ffa3e50aff..9556d653bf 100644 --- a/tests/uitests/build.gradle.kts +++ b/tests/uitests/build.gradle.kts @@ -52,6 +52,7 @@ dependencies { // `testOptions { unitTests.isIncludeAndroidResources = true }` in the app build.gradle.kts file // implementation(projects.app) implementation(projects.appnav) + implementation(projects.features.call) allLibrariesImpl() allServicesImpl() allFeaturesImpl(rootDir, logger) diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.call_null_CallScreenView-D-0_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.call_null_CallScreenView-D-0_0_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..9fdfd38cee --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.call_null_CallScreenView-D-0_0_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26df292602cdf27ddd42b3b4c1dcc3fc7ae41e207af48d76c7b65bd66babf649 +size 10561 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.call_null_CallScreenView-N-0_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.call_null_CallScreenView-N-0_1_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..e524d75c96 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.call_null_CallScreenView-N-0_1_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f28b5214727111f39cef9a1d625469f30481fe2cbbe02df0efc53807a968d210 +size 9787 diff --git a/tools/lint/lint.xml b/tools/lint/lint.xml index db1a20701c..ce49e50a7a 100644 --- a/tools/lint/lint.xml +++ b/tools/lint/lint.xml @@ -48,6 +48,8 @@ + + diff --git a/tools/localazy/config.json b/tools/localazy/config.json index b92e02f670..c2cb5cef3e 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -128,6 +128,12 @@ "includeRegex": [ "screen_create_poll_.*" ] + }, + { + "name": ":features:call", + "includeRegex": [ + "call_.*" + ] } ] } From e73f96eb6adb1f9922ac7f5568a744a804209965 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 6 Sep 2023 16:06:47 +0200 Subject: [PATCH 200/234] Avoid logging warning why attempting to delete unexisting file. --- .../io/element/android/libraries/androidutils/file/File.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/file/File.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/file/File.kt index ea214ff683..d7628202c0 100644 --- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/file/File.kt +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/file/File.kt @@ -25,6 +25,7 @@ import java.util.Locale import java.util.UUID fun File.safeDelete() { + if (exists().not()) return tryOrNull( onError = { Timber.e(it, "Error, unable to delete file $path") From d3231487aa554b2c1af205d416cc65f336c215bd Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 15 Sep 2023 16:42:04 +0200 Subject: [PATCH 201/234] Log param. --- .../impl/notifications/DefaultNotificationDrawerManager.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt index 211d8d935a..9621663e98 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt @@ -233,7 +233,7 @@ class DefaultNotificationDrawerManager @Inject constructor( private fun CoroutineScope.refreshNotificationDrawer(doRender: Boolean) = launch { // Implement last throttler val canHandle = firstThrottler.canHandle() - Timber.v("refreshNotificationDrawer(), delay: ${canHandle.waitMillis()} ms") + Timber.v("refreshNotificationDrawer($doRender), delay: ${canHandle.waitMillis()} ms") withContext(dispatchers.io) { delay(canHandle.waitMillis()) try { @@ -246,7 +246,7 @@ class DefaultNotificationDrawerManager @Inject constructor( } private suspend fun refreshNotificationDrawerBg(doRender: Boolean) { - Timber.v("refreshNotificationDrawerBg()") + Timber.v("refreshNotificationDrawerBg($doRender)") val eventsToRender = notificationState.updateQueuedEvents { queuedEvents, renderedEvents -> notifiableEventProcessor.process(queuedEvents.rawEvents(), renderedEvents).also { queuedEvents.clearAndAdd(it.onlyKeptEvents()) From b9317ee2aa313b3c4d62205cb5730f8dd49b1d50 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 15 Sep 2023 16:43:24 +0200 Subject: [PATCH 202/234] Add log tag --- .../DefaultNotificationDrawerManager.kt | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt index 9621663e98..09ed8f1194 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt @@ -20,6 +20,7 @@ import io.element.android.libraries.androidutils.throttler.FirstThrottler import io.element.android.libraries.core.cache.CircularCache import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.data.tryOrNull +import io.element.android.libraries.core.log.logger.LoggerTag import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.SingleIn @@ -30,6 +31,7 @@ import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.push.api.notifications.NotificationDrawerManager +import io.element.android.libraries.push.impl.log.notificationLoggerTag import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent import io.element.android.services.appnavstate.api.AppNavigationStateService import io.element.android.services.appnavstate.api.NavigationState @@ -41,6 +43,8 @@ import kotlinx.coroutines.withContext import timber.log.Timber import javax.inject.Inject +private val loggerTag = LoggerTag("DefaultNotificationDrawerManager", notificationLoggerTag) + /** * The NotificationDrawerManager receives notification events as they arrived (from event stream or fcm) and * organise them in order to display them in the notification drawer. @@ -116,13 +120,13 @@ class DefaultNotificationDrawerManager @Inject constructor( private fun NotificationEventQueue.onNotifiableEventReceived(notifiableEvent: NotifiableEvent) { if (buildMeta.lowPrivacyLoggingEnabled) { - Timber.d("onNotifiableEventReceived(): $notifiableEvent") + Timber.tag(loggerTag.value).d("onNotifiableEventReceived(): $notifiableEvent") } else { - Timber.d("onNotifiableEventReceived(): is push: ${notifiableEvent.canBeReplaced}") + Timber.tag(loggerTag.value).d("onNotifiableEventReceived(): is push: ${notifiableEvent.canBeReplaced}") } if (filteredEventDetector.shouldBeIgnored(notifiableEvent)) { - Timber.d("onNotifiableEventReceived(): ignore the event") + Timber.tag(loggerTag.value).d("onNotifiableEventReceived(): ignore the event") return } @@ -233,20 +237,20 @@ class DefaultNotificationDrawerManager @Inject constructor( private fun CoroutineScope.refreshNotificationDrawer(doRender: Boolean) = launch { // Implement last throttler val canHandle = firstThrottler.canHandle() - Timber.v("refreshNotificationDrawer($doRender), delay: ${canHandle.waitMillis()} ms") + Timber.tag(loggerTag.value).v("refreshNotificationDrawer($doRender), delay: ${canHandle.waitMillis()} ms") withContext(dispatchers.io) { delay(canHandle.waitMillis()) try { refreshNotificationDrawerBg(doRender) } catch (throwable: Throwable) { // It can happen if for instance session has been destroyed. It's a bit ugly to try catch like this, but it's safer - Timber.w(throwable, "refreshNotificationDrawerBg failure") + Timber.tag(loggerTag.value).w(throwable, "refreshNotificationDrawerBg failure") } } } private suspend fun refreshNotificationDrawerBg(doRender: Boolean) { - Timber.v("refreshNotificationDrawerBg($doRender)") + Timber.tag(loggerTag.value).v("refreshNotificationDrawerBg($doRender)") val eventsToRender = notificationState.updateQueuedEvents { queuedEvents, renderedEvents -> notifiableEventProcessor.process(queuedEvents.rawEvents(), renderedEvents).also { queuedEvents.clearAndAdd(it.onlyKeptEvents()) @@ -254,7 +258,7 @@ class DefaultNotificationDrawerManager @Inject constructor( } if (notificationState.hasAlreadyRendered(eventsToRender)) { - Timber.d("Skipping notification update due to event list not changing") + Timber.tag(loggerTag.value).d("Skipping notification update due to event list not changing") } else { notificationState.clearAndAddRenderedEvents(eventsToRender) if (doRender) { @@ -278,7 +282,7 @@ class DefaultNotificationDrawerManager @Inject constructor( eventsForSessions.forEach { (sessionId, notifiableEvents) -> val currentUser = tryOrNull( - onError = { Timber.e(it, "Unable to retrieve info for user ${sessionId.value}") }, + onError = { Timber.tag(loggerTag.value).e(it, "Unable to retrieve info for user ${sessionId.value}") }, operation = { val client = matrixClientProvider.getOrRestore(sessionId).getOrThrow() // myUserDisplayName cannot be empty else NotificationCompat.MessagingStyle() will crash From f287a651b5f49b1ceb4180f315ad18620a72945c Mon Sep 17 00:00:00 2001 From: David Langley Date: Fri, 15 Sep 2023 15:47:16 +0100 Subject: [PATCH 203/234] Reverting the change to only show the green dot for all messages. --- .../roomlist/impl/components/RoomSummaryRow.kt | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt index 33a8564efb..4cd546f6f4 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt @@ -152,7 +152,7 @@ private fun RowScope.NameAndTimestampRow(room: RoomListRoomSummary) { Text( text = room.timestamp ?: "", style = ElementTheme.typography.fontBodySmRegular, - color = if (room.shouldDisplayNotificationAlertDecoration) { + color = if (room.hasUnread) { ElementTheme.colors.unreadIndicator } else { MaterialTheme.roomListRoomMessageDate() @@ -182,7 +182,7 @@ private fun RowScope.LastMessageAndIndicatorRow(room: RoomListRoomSummary) { horizontalArrangement = Arrangement.spacedBy(8.dp) ) { NotificationIcon(room) - if (room.shouldDisplayNotificationAlertDecoration) { + if (room.hasUnread) { UnreadIndicatorAtom( modifier = Modifier.padding(top = 3.dp), ) @@ -190,28 +190,23 @@ private fun RowScope.LastMessageAndIndicatorRow(room: RoomListRoomSummary) { } } -// We should never show a green dot/icon for mute. Also mentions is not yet supported by the mobile app. -// In some cases a green @ was incorrectly shown when we switch from ALL_MESSAGES to MENTIONS_AND_KEYWORDS_ONLY -// and we don't know whether the room has mentions, just that it has unread. -private val RoomListRoomSummary.shouldDisplayNotificationAlertDecoration get() = hasUnread - && notificationMode != RoomNotificationMode.MUTE - && notificationMode != RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY @Composable private fun NotificationIcon(room: RoomListRoomSummary) { + val tint = if(room.hasUnread) ElementTheme.colors.unreadIndicator else ElementTheme.colors.iconQuaternary when(room.notificationMode) { null, RoomNotificationMode.ALL_MESSAGES -> return RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> Icon( contentDescription = stringResource(CommonStrings.screen_notification_settings_mode_mentions), imageVector = ImageVector.vectorResource(VectorIcons.Mention), - tint = ElementTheme.colors.iconQuaternary, + tint = tint, ) RoomNotificationMode.MUTE -> Icon( contentDescription = stringResource(CommonStrings.common_mute), imageVector = ImageVector.vectorResource(VectorIcons.Mute), - tint = ElementTheme.colors.iconQuaternary, + tint = tint, ) } } From 2e9cc25759d1111cf6698b0d545ac783572187ef Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 15 Sep 2023 16:52:46 +0200 Subject: [PATCH 204/234] Log the tag if present. --- .../android/libraries/matrix/impl/tracing/RustTracingTree.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/tracing/RustTracingTree.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/tracing/RustTracingTree.kt index 275994081d..f97b08a018 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/tracing/RustTracingTree.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/tracing/RustTracingTree.kt @@ -49,7 +49,7 @@ internal class RustTracingTree(private val retrieveFromStackTrace: Boolean) : Ti line = location.line, level = logLevel, target = Target.ELEMENT.filter, - message = message, + message = if (tag != null) "[$tag] $message" else message, ) } From 0d204f5e98d5e343e84dfcb62ddfffbf65782c05 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 15 Sep 2023 17:03:32 +0200 Subject: [PATCH 205/234] Share tag with other modules. --- .../libraries/core/log/logger/LoggerTag.kt | 6 ++--- .../libraries/push/impl/PushersManager.kt | 3 +-- .../libraries/push/impl/log/LoggerTag.kt | 22 ------------------- .../DefaultNotificationDrawerManager.kt | 3 +-- .../notifications/NotifiableEventProcessor.kt | 3 +-- .../notifications/NotifiableEventResolver.kt | 3 +-- .../NotificationBroadcastReceiver.kt | 6 ++--- .../NotificationEventPersistence.kt | 3 +-- .../notifications/NotificationRenderer.kt | 3 +-- .../push/impl/push/DefaultPushHandler.kt | 3 +-- .../firebase/FirebaseNewTokenHandler.kt | 2 +- .../firebase/FirebasePushProvider.kt | 2 +- .../VectorFirebaseMessagingService.kt | 2 +- .../UnifiedPushNewGatewayHandler.kt | 2 +- .../VectorUnifiedPushMessagingReceiver.kt | 2 +- 15 files changed, 16 insertions(+), 49 deletions(-) delete mode 100644 libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/log/LoggerTag.kt diff --git a/libraries/core/src/main/kotlin/io/element/android/libraries/core/log/logger/LoggerTag.kt b/libraries/core/src/main/kotlin/io/element/android/libraries/core/log/logger/LoggerTag.kt index 2c9add5e8d..1bec5524cd 100644 --- a/libraries/core/src/main/kotlin/io/element/android/libraries/core/log/logger/LoggerTag.kt +++ b/libraries/core/src/main/kotlin/io/element/android/libraries/core/log/logger/LoggerTag.kt @@ -24,10 +24,8 @@ package io.element.android.libraries.core.log.logger */ open class LoggerTag(name: String, parentTag: LoggerTag? = null) { - object SYNC : LoggerTag("SYNC") - object VOIP : LoggerTag("VOIP") - object CRYPTO : LoggerTag("CRYPTO") - object RENDEZVOUS : LoggerTag("RZ") + object PushLoggerTag : LoggerTag("Push") + object NotificationLoggerTag : LoggerTag("Notification", PushLoggerTag) val value: String = if (parentTag == null) { name diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/PushersManager.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/PushersManager.kt index f3afb940cd..39ff4323a5 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/PushersManager.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/PushersManager.kt @@ -24,7 +24,6 @@ import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.pusher.SetHttpPusherData import io.element.android.libraries.push.impl.config.PushConfig -import io.element.android.libraries.push.impl.log.pushLoggerTag import io.element.android.libraries.push.impl.pushgateway.PushGatewayNotifyRequest import io.element.android.libraries.pushproviders.api.PusherSubscriber import io.element.android.libraries.pushstore.api.UserPushStoreFactory @@ -35,7 +34,7 @@ import javax.inject.Inject internal const val DEFAULT_PUSHER_FILE_TAG = "mobile" -private val loggerTag = LoggerTag("PushersManager", pushLoggerTag) +private val loggerTag = LoggerTag("PushersManager", LoggerTag.PushLoggerTag) @ContributesBinding(AppScope::class) class PushersManager @Inject constructor( diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/log/LoggerTag.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/log/LoggerTag.kt deleted file mode 100644 index 3fa613d097..0000000000 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/log/LoggerTag.kt +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2023 New Vector Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.element.android.libraries.push.impl.log - -import io.element.android.libraries.core.log.logger.LoggerTag - -internal val pushLoggerTag = LoggerTag("Push") -internal val notificationLoggerTag = LoggerTag("Notification", pushLoggerTag) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt index 09ed8f1194..318b7cbd49 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationDrawerManager.kt @@ -31,7 +31,6 @@ import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.push.api.notifications.NotificationDrawerManager -import io.element.android.libraries.push.impl.log.notificationLoggerTag import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent import io.element.android.services.appnavstate.api.AppNavigationStateService import io.element.android.services.appnavstate.api.NavigationState @@ -43,7 +42,7 @@ import kotlinx.coroutines.withContext import timber.log.Timber import javax.inject.Inject -private val loggerTag = LoggerTag("DefaultNotificationDrawerManager", notificationLoggerTag) +private val loggerTag = LoggerTag("DefaultNotificationDrawerManager", LoggerTag.NotificationLoggerTag) /** * The NotificationDrawerManager receives notification events as they arrived (from event stream or fcm) and diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventProcessor.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventProcessor.kt index 709dfd14e8..7f4c04da7b 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventProcessor.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventProcessor.kt @@ -18,7 +18,6 @@ package io.element.android.libraries.push.impl.notifications import io.element.android.libraries.core.log.logger.LoggerTag import io.element.android.libraries.matrix.api.timeline.item.event.EventType -import io.element.android.libraries.push.impl.log.notificationLoggerTag import io.element.android.libraries.push.impl.notifications.model.FallbackNotifiableEvent import io.element.android.libraries.push.impl.notifications.model.InviteNotifiableEvent import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent @@ -31,7 +30,7 @@ import javax.inject.Inject private typealias ProcessedEvents = List> -private val loggerTag = LoggerTag("NotifiableEventProcessor", notificationLoggerTag) +private val loggerTag = LoggerTag("NotifiableEventProcessor", LoggerTag.NotificationLoggerTag) class NotifiableEventProcessor @Inject constructor( private val outdatedDetector: OutdatedEventDetector, diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventResolver.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventResolver.kt index 66ca7a0abd..c93d517e89 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventResolver.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventResolver.kt @@ -36,7 +36,6 @@ import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageTy import io.element.android.libraries.matrix.api.timeline.item.event.UnknownMessageType import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageType import io.element.android.libraries.push.impl.R -import io.element.android.libraries.push.impl.log.notificationLoggerTag import io.element.android.libraries.push.impl.notifications.model.FallbackNotifiableEvent import io.element.android.libraries.push.impl.notifications.model.InviteNotifiableEvent import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent @@ -47,7 +46,7 @@ import io.element.android.services.toolbox.api.systemclock.SystemClock import timber.log.Timber import javax.inject.Inject -private val loggerTag = LoggerTag("NotifiableEventResolver", notificationLoggerTag) +private val loggerTag = LoggerTag("NotifiableEventResolver", LoggerTag.NotificationLoggerTag) /** * The notifiable event resolver is able to create a NotifiableEvent (view model for notifications) from an sdk Event. diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiver.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiver.kt index 2709f3840c..8f27d8692c 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiver.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiver.kt @@ -24,11 +24,10 @@ import io.element.android.libraries.core.log.logger.LoggerTag import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SessionId -import io.element.android.libraries.push.impl.log.notificationLoggerTag import timber.log.Timber import javax.inject.Inject -private val loggerTag = LoggerTag("NotificationBroadcastReceiver", notificationLoggerTag) +private val loggerTag = LoggerTag("NotificationBroadcastReceiver", LoggerTag.NotificationLoggerTag) /** * Receives actions broadcast by notification (on click, on dismiss, inline replies, etc.). @@ -41,11 +40,10 @@ class NotificationBroadcastReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { if (intent == null || context == null) return context.bindings().inject(this) - Timber.tag(loggerTag.value).d("received: ${intent.action} ${intent.data}") val sessionId = intent.extras?.getString(KEY_SESSION_ID)?.let(::SessionId) ?: return val roomId = intent.getStringExtra(KEY_ROOM_ID)?.let(::RoomId) val eventId = intent.getStringExtra(KEY_EVENT_ID)?.let(::EventId) - Timber.tag(loggerTag.value).d("received for: ${roomId?.value}/${eventId?.value}") + Timber.tag(loggerTag.value).d("onReceive: ${intent.action} ${intent.data} for: ${roomId?.value}/${eventId?.value}") when (intent.action) { actionIds.smartReply -> handleSmartReply(intent, context) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationEventPersistence.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationEventPersistence.kt index 613a8d2bb7..d1aee8c0b2 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationEventPersistence.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationEventPersistence.kt @@ -22,7 +22,6 @@ import io.element.android.libraries.androidutils.file.safeDelete import io.element.android.libraries.core.data.tryOrNull import io.element.android.libraries.core.log.logger.LoggerTag import io.element.android.libraries.di.ApplicationContext -import io.element.android.libraries.push.impl.log.notificationLoggerTag import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent import timber.log.Timber import java.io.File @@ -33,7 +32,7 @@ import javax.inject.Inject private const val ROOMS_NOTIFICATIONS_FILE_NAME_LEGACY = "im.vector.notifications.cache" private const val FILE_NAME = "notifications.bin" -private val loggerTag = LoggerTag("NotificationEventPersistence", notificationLoggerTag) +private val loggerTag = LoggerTag("NotificationEventPersistence", LoggerTag.NotificationLoggerTag) class NotificationEventPersistence @Inject constructor( @ApplicationContext private val context: Context, diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationRenderer.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationRenderer.kt index 69292e5c6b..03241bbdb8 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationRenderer.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationRenderer.kt @@ -19,7 +19,6 @@ package io.element.android.libraries.push.impl.notifications import io.element.android.libraries.core.log.logger.LoggerTag import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.user.MatrixUser -import io.element.android.libraries.push.impl.log.notificationLoggerTag import io.element.android.libraries.push.impl.notifications.model.FallbackNotifiableEvent import io.element.android.libraries.push.impl.notifications.model.InviteNotifiableEvent import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent @@ -28,7 +27,7 @@ import io.element.android.libraries.push.impl.notifications.model.SimpleNotifiab import timber.log.Timber import javax.inject.Inject -private val loggerTag = LoggerTag("NotificationRenderer", notificationLoggerTag) +private val loggerTag = LoggerTag("NotificationRenderer", LoggerTag.NotificationLoggerTag) class NotificationRenderer @Inject constructor( private val notificationIdProvider: NotificationIdProvider, diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt index b9ca4a5cca..6c9138fb15 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt @@ -24,7 +24,6 @@ import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.di.AppScope import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.push.impl.PushersManager -import io.element.android.libraries.push.impl.log.pushLoggerTag import io.element.android.libraries.push.impl.notifications.DefaultNotificationDrawerManager import io.element.android.libraries.push.impl.notifications.NotifiableEventResolver import io.element.android.libraries.push.impl.store.DefaultPushDataStore @@ -40,7 +39,7 @@ import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject -private val loggerTag = LoggerTag("PushHandler", pushLoggerTag) +private val loggerTag = LoggerTag("PushHandler", LoggerTag.PushLoggerTag) @ContributesBinding(AppScope::class) class DefaultPushHandler @Inject constructor( diff --git a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/FirebaseNewTokenHandler.kt b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/FirebaseNewTokenHandler.kt index dc938bd141..3e077841a4 100644 --- a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/FirebaseNewTokenHandler.kt +++ b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/FirebaseNewTokenHandler.kt @@ -26,7 +26,7 @@ import io.element.android.libraries.sessionstorage.api.toUserList import timber.log.Timber import javax.inject.Inject -private val loggerTag = LoggerTag("FirebaseNewTokenHandler") +private val loggerTag = LoggerTag("FirebaseNewTokenHandler", LoggerTag.PushLoggerTag) /** * Handle new token receive from Firebase. Will update all the sessions which are using Firebase as a push provider. diff --git a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/FirebasePushProvider.kt b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/FirebasePushProvider.kt index 5d496b39ca..63611a0ed9 100644 --- a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/FirebasePushProvider.kt +++ b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/FirebasePushProvider.kt @@ -26,7 +26,7 @@ import io.element.android.libraries.pushproviders.api.PusherSubscriber import timber.log.Timber import javax.inject.Inject -private val loggerTag = LoggerTag("FirebasePushProvider") +private val loggerTag = LoggerTag("FirebasePushProvider", LoggerTag.PushLoggerTag) @ContributesMultibinding(AppScope::class) class FirebasePushProvider @Inject constructor( diff --git a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/VectorFirebaseMessagingService.kt b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/VectorFirebaseMessagingService.kt index 56ac65a338..3d251f6e64 100644 --- a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/VectorFirebaseMessagingService.kt +++ b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/VectorFirebaseMessagingService.kt @@ -27,7 +27,7 @@ import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject -private val loggerTag = LoggerTag("Firebase") +private val loggerTag = LoggerTag("VectorFirebaseMessagingService", LoggerTag.PushLoggerTag) class VectorFirebaseMessagingService : FirebaseMessagingService() { @Inject lateinit var firebaseNewTokenHandler: FirebaseNewTokenHandler diff --git a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnifiedPushNewGatewayHandler.kt b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnifiedPushNewGatewayHandler.kt index 1a6cdb90c0..c10bc814d7 100644 --- a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnifiedPushNewGatewayHandler.kt +++ b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnifiedPushNewGatewayHandler.kt @@ -24,7 +24,7 @@ import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret import timber.log.Timber import javax.inject.Inject -private val loggerTag = LoggerTag("UnifiedPushNewGatewayHandler") +private val loggerTag = LoggerTag("UnifiedPushNewGatewayHandler", LoggerTag.PushLoggerTag) /** * Handle new endpoint received from UnifiedPush. Will update all the sessions which are using UnifiedPush as a push provider. diff --git a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/VectorUnifiedPushMessagingReceiver.kt b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/VectorUnifiedPushMessagingReceiver.kt index e2006f61cc..05400e87f2 100644 --- a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/VectorUnifiedPushMessagingReceiver.kt +++ b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/VectorUnifiedPushMessagingReceiver.kt @@ -28,7 +28,7 @@ import org.unifiedpush.android.connector.MessagingReceiver import timber.log.Timber import javax.inject.Inject -private val loggerTag = LoggerTag("VectorUnifiedPushMessagingReceiver") +private val loggerTag = LoggerTag("VectorUnifiedPushMessagingReceiver", LoggerTag.PushLoggerTag) class VectorUnifiedPushMessagingReceiver : MessagingReceiver() { @Inject lateinit var pushParser: UnifiedPushParser From 98bb91cd2733e1d829b4778e96825511807ca3ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Fri, 15 Sep 2023 16:00:36 +0200 Subject: [PATCH 206/234] Create tests --- features/preferences/impl/build.gradle.kts | 3 + .../editprofile/EditUserProfilePresenter.kt | 11 +- .../EditUserProfilePresenterTest.kt | 494 ++++++++++++++++++ .../libraries/matrix/test/FakeMatrixClient.kt | 37 ++ .../ui/components/MatrixUserProvider.kt | 7 +- 5 files changed, 546 insertions(+), 6 deletions(-) create mode 100644 features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenterTest.kt diff --git a/features/preferences/impl/build.gradle.kts b/features/preferences/impl/build.gradle.kts index 4d0403809d..b28a068708 100644 --- a/features/preferences/impl/build.gradle.kts +++ b/features/preferences/impl/build.gradle.kts @@ -66,8 +66,11 @@ dependencies { testImplementation(libs.molecule.runtime) testImplementation(libs.test.truth) testImplementation(libs.test.turbine) + testImplementation(libs.test.mockk) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.featureflag.test) + testImplementation(projects.libraries.mediapickers.test) + testImplementation(projects.libraries.mediaupload.test) testImplementation(projects.libraries.preferences.test) testImplementation(projects.libraries.pushstore.test) testImplementation(projects.features.rageshake.test) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt index 6557079de3..edbb2467f2 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt @@ -24,6 +24,8 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject @@ -33,7 +35,6 @@ import io.element.android.libraries.architecture.runCatchingUpdatingState import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.user.MatrixUser -import io.element.android.libraries.matrix.api.user.getCurrentUser import io.element.android.libraries.matrix.ui.media.AvatarAction import io.element.android.libraries.mediapickers.api.PickerProvider import io.element.android.libraries.mediaupload.api.MediaPreProcessor @@ -56,8 +57,8 @@ class EditUserProfilePresenter @AssistedInject constructor( @Composable override fun present(): EditUserProfileState { - var userAvatarUri = remember { matrixUser.avatarUrl?.let { Uri.parse(it) } } - var userDisplayName = remember { matrixUser.displayName } + var userAvatarUri by rememberSaveable { mutableStateOf(matrixUser.avatarUrl?.let { Uri.parse(it) }) } + var userDisplayName by rememberSaveable { mutableStateOf(matrixUser.displayName) } val cameraPhotoPicker = mediaPickerProvider.registerCameraPhotoPicker( onResult = { uri -> if (uri != null) userAvatarUri = uri } ) @@ -106,7 +107,7 @@ class EditUserProfilePresenter @AssistedInject constructor( avatarActions = avatarActions, saveButtonEnabled = canSave && saveAction.value !is Async.Loading, saveAction = saveAction.value, - eventSink = ::handleEvents + eventSink = { handleEvents(it) }, ) } @@ -138,6 +139,6 @@ class EditUserProfilePresenter @AssistedInject constructor( } else { matrixClient.removeAvatar().getOrThrow() } - } + }.onFailure { it.printStackTrace() } } } diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenterTest.kt new file mode 100644 index 0000000000..c377265689 --- /dev/null +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenterTest.kt @@ -0,0 +1,494 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.preferences.impl.user.editprofile + +import android.net.Uri +import app.cash.molecule.RecompositionMode +import app.cash.molecule.moleculeFlow +import app.cash.turbine.test +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.architecture.Async +import io.element.android.libraries.matrix.api.MatrixClient +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_USER_ID +import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.libraries.matrix.ui.components.aMatrixUser +import io.element.android.libraries.matrix.ui.media.AvatarAction +import io.element.android.libraries.mediapickers.test.FakePickerProvider +import io.element.android.libraries.mediaupload.api.MediaUploadInfo +import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor +import io.element.android.tests.testutils.WarmUpRule +import io.mockk.every +import io.mockk.mockk +import io.mockk.mockkStatic +import io.mockk.unmockkAll +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import java.io.File + +@ExperimentalCoroutinesApi +class EditUserProfilePresenterTest { + + @get:Rule + val warmUpRule = WarmUpRule() + + private lateinit var fakePickerProvider: FakePickerProvider + private lateinit var fakeMediaPreProcessor: FakeMediaPreProcessor + + private val userAvatarUri: Uri = mockk() + private val anotherAvatarUri: Uri = mockk() + + private val fakeFileContents = ByteArray(2) + + @Before + fun setup() { + fakePickerProvider = FakePickerProvider() + fakeMediaPreProcessor = FakeMediaPreProcessor() + mockkStatic(Uri::class) + + every { Uri.parse(AN_AVATAR_URL) } returns userAvatarUri + every { Uri.parse(ANOTHER_AVATAR_URL) } returns anotherAvatarUri + } + + @After + fun tearDown() { + unmockkAll() + } + + private fun anEditUserProfilePresenter( + matrixClient: MatrixClient = FakeMatrixClient(), + matrixUser: MatrixUser = aMatrixUser(), + ): EditUserProfilePresenter { + return EditUserProfilePresenter( + matrixClient = matrixClient, + matrixUser = matrixUser, + mediaPickerProvider = fakePickerProvider, + mediaPreProcessor = fakeMediaPreProcessor, + ) + } + + @Test + fun `present - initial state is created from room info`() = runTest { + val user = aMatrixUser(avatarUrl = AN_AVATAR_URL) + val presenter = anEditUserProfilePresenter(matrixUser = user) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + assertThat(initialState.userId).isEqualTo(user.userId.value) + assertThat(initialState.displayName).isEqualTo(user.displayName) + assertThat(initialState.userAvatarUrl).isEqualTo(userAvatarUri) + assertThat(initialState.avatarActions).containsExactly( + AvatarAction.ChoosePhoto, + AvatarAction.TakePhoto, + AvatarAction.Remove + ) + assertThat(initialState.saveButtonEnabled).isEqualTo(false) + assertThat(initialState.saveAction).isInstanceOf(Async.Uninitialized::class.java) + } + } + + @Test + fun `present - updates state in response to changes`() = runTest { + val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) + val presenter = anEditUserProfilePresenter(matrixUser = user) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + assertThat(initialState.displayName).isEqualTo("Name") + assertThat(initialState.userAvatarUrl).isEqualTo(userAvatarUri) + + initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("Name II")) + awaitItem().apply { + assertThat(displayName).isEqualTo("Name II") + assertThat(userAvatarUrl).isEqualTo(userAvatarUri) + } + + initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("Name III")) + awaitItem().apply { + assertThat(displayName).isEqualTo("Name III") + assertThat(userAvatarUrl).isEqualTo(userAvatarUri) + } + + initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.Remove)) + awaitItem().apply { + assertThat(displayName).isEqualTo("Name III") + assertThat(userAvatarUrl).isNull() + } + } + } + + @Test + fun `present - obtains avatar uris from gallery`() = runTest { + val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) + + fakePickerProvider.givenResult(anotherAvatarUri) + + val presenter = anEditUserProfilePresenter(matrixUser = user) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + assertThat(initialState.userAvatarUrl).isEqualTo(userAvatarUri) + + initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.ChoosePhoto)) + awaitItem().apply { + assertThat(userAvatarUrl).isEqualTo(anotherAvatarUri) + } + } + } + + @Test + fun `present - obtains avatar uris from camera`() = runTest { + val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) + + fakePickerProvider.givenResult(anotherAvatarUri) + + val presenter = anEditUserProfilePresenter(matrixUser = user) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + assertThat(initialState.userAvatarUrl).isEqualTo(userAvatarUri) + + initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.TakePhoto)) + awaitItem().apply { + assertThat(userAvatarUrl).isEqualTo(anotherAvatarUri) + } + } + } + + @Test + fun `present - updates save button state`() = runTest { + val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) + + fakePickerProvider.givenResult(userAvatarUri) + + val presenter = anEditUserProfilePresenter(matrixUser = user) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + assertThat(initialState.saveButtonEnabled).isEqualTo(false) + + // Once a change is made, the save button is enabled + initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("Name II")) + awaitItem().apply { + assertThat(saveButtonEnabled).isEqualTo(true) + } + + // If it's reverted then the save disables again + initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("Name")) + awaitItem().apply { + assertThat(saveButtonEnabled).isEqualTo(false) + } + + // Make a change... + initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.Remove)) + awaitItem().apply { + assertThat(saveButtonEnabled).isEqualTo(true) + } + + // Revert it... + initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.ChoosePhoto)) + awaitItem().apply { + assertThat(saveButtonEnabled).isEqualTo(false) + } + } + } + + @Test + fun `present - updates save button state when initial values are null`() = runTest { + val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = null) + + fakePickerProvider.givenResult(userAvatarUri) + + val presenter = anEditUserProfilePresenter(matrixUser = user) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + assertThat(initialState.saveButtonEnabled).isEqualTo(false) + + // Once a change is made, the save button is enabled + initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("Name II")) + awaitItem().apply { + assertThat(saveButtonEnabled).isEqualTo(true) + } + + // If it's reverted then the save disables again + initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("fallback")) + awaitItem().apply { + assertThat(saveButtonEnabled).isEqualTo(false) + } + + // Make a change... + initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.ChoosePhoto)) + awaitItem().apply { + assertThat(saveButtonEnabled).isEqualTo(true) + } + + // Revert it... + initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.Remove)) + awaitItem().apply { + assertThat(saveButtonEnabled).isEqualTo(false) + } + } + } + + @Test + fun `present - save changes room details if different`() = runTest { + val matrixClient = FakeMatrixClient() + val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) + + val presenter = anEditUserProfilePresenter( + matrixClient = matrixClient, + matrixUser = user + ) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + + initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("New name")) + initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.Remove)) + initialState.eventSink(EditUserProfileEvents.Save) + skipItems(5) + + assertThat(matrixClient.setDisplayNameCalled).isTrue() + assertThat(matrixClient.removeAvatarCalled).isTrue() + assertThat(matrixClient.uploadAvatarCalled).isFalse() + + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - save doesn't change room details if they're the same trimmed`() = runTest { + val matrixClient = FakeMatrixClient() + val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) + + val presenter = anEditUserProfilePresenter( + matrixClient = matrixClient, + matrixUser = user + ) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + + initialState.eventSink(EditUserProfileEvents.UpdateDisplayName(" Name ")) + initialState.eventSink(EditUserProfileEvents.Save) + + assertThat(matrixClient.setDisplayNameCalled).isTrue() + assertThat(matrixClient.uploadAvatarCalled).isFalse() + assertThat(matrixClient.removeAvatarCalled).isFalse() + + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - save doesn't change name if it's now empty`() = runTest { + val matrixClient = FakeMatrixClient() + val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) + + val presenter = anEditUserProfilePresenter( + matrixClient = matrixClient, + matrixUser = user + ) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + + initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("")) + initialState.eventSink(EditUserProfileEvents.Save) + + assertThat(matrixClient.setDisplayNameCalled).isFalse() + assertThat(matrixClient.uploadAvatarCalled).isFalse() + assertThat(matrixClient.removeAvatarCalled).isFalse() + + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `present - save processes and sets avatar when processor returns successfully`() = runTest { + val matrixClient = FakeMatrixClient() + val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) + + givenPickerReturnsFile() + + val presenter = anEditUserProfilePresenter( + matrixClient = matrixClient, + matrixUser = user + ) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + + initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.ChoosePhoto)) + initialState.eventSink(EditUserProfileEvents.Save) + skipItems(2) + + assertThat(matrixClient.uploadAvatarCalled).isTrue() + } + } + + @Test + fun `present - save does not set avatar data if processor fails`() = runTest { + val matrixClient = FakeMatrixClient() + val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) + + val presenter = anEditUserProfilePresenter( + matrixClient = matrixClient, + matrixUser = user + ) + + fakePickerProvider.givenResult(anotherAvatarUri) + fakeMediaPreProcessor.givenResult(Result.failure(Throwable("Oh no"))) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + + initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.ChoosePhoto)) + initialState.eventSink(EditUserProfileEvents.Save) + skipItems(2) + + assertThat(matrixClient.uploadAvatarCalled).isFalse() + + assertThat(awaitItem().saveAction).isInstanceOf(Async.Failure::class.java) + } + } + + @Test + fun `present - sets save action to failure if name update fails`() = runTest { + val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) + val matrixClient = FakeMatrixClient().apply { + givenSetDisplayNameResult(Result.failure(Throwable("!"))) + } + + saveAndAssertFailure(user, matrixClient, EditUserProfileEvents.UpdateDisplayName("New name")) + } + + @Test + fun `present - sets save action to failure if removing avatar fails`() = runTest { + val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) + val matrixClient = FakeMatrixClient().apply { + givenRemoveAvatarResult(Result.failure(Throwable("!"))) + } + + saveAndAssertFailure(user, matrixClient, EditUserProfileEvents.HandleAvatarAction(AvatarAction.Remove)) + } + + @Test + fun `present - sets save action to failure if setting avatar fails`() = runTest { + givenPickerReturnsFile() + + val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) + val matrixClient = FakeMatrixClient().apply { + givenUploadAvatarResult(Result.failure(Throwable("!"))) + } + + saveAndAssertFailure(user, matrixClient, EditUserProfileEvents.HandleAvatarAction(AvatarAction.ChoosePhoto)) + } + + @Test + fun `present - CancelSaveChanges resets save action state`() = runTest { + givenPickerReturnsFile() + + val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) + val matrixClient = FakeMatrixClient().apply { + givenSetDisplayNameResult(Result.failure(Throwable("!"))) + } + + val presenter = anEditUserProfilePresenter(matrixUser = user) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + + initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("foo")) + initialState.eventSink(EditUserProfileEvents.Save) + skipItems(2) + + assertThat(awaitItem().saveAction).isInstanceOf(Async.Failure::class.java) + + initialState.eventSink(EditUserProfileEvents.CancelSaveChanges) + assertThat(awaitItem().saveAction).isInstanceOf(Async.Uninitialized::class.java) + } + } + + private suspend fun saveAndAssertFailure(matrixUser: MatrixUser, matrixClient: MatrixClient, event: EditUserProfileEvents) { + val presenter = anEditUserProfilePresenter(matrixUser = matrixUser, matrixClient = matrixClient) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + + initialState.eventSink(event) + initialState.eventSink(EditUserProfileEvents.Save) + skipItems(1) + + assertThat(awaitItem().saveAction).isInstanceOf(Async.Loading::class.java) + assertThat(awaitItem().saveAction).isInstanceOf(Async.Failure::class.java) + } + } + + private fun givenPickerReturnsFile() { + mockkStatic(File::readBytes) + val processedFile: File = mockk { + every { readBytes() } returns fakeFileContents + } + + fakePickerProvider.givenResult(anotherAvatarUri) + fakeMediaPreProcessor.givenResult( + Result.success( + MediaUploadInfo.AnyFile( + file = processedFile, + fileInfo = mockk(), + ) + ) + ) + } + + companion object { + private const val ANOTHER_AVATAR_URL = "example://camera/foo.jpg" + } +} diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt index 660c1e268a..ce518730c4 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt @@ -58,6 +58,13 @@ class FakeMatrixClient( private val accountManagementUrlString: Result = Result.success(null), ) : MatrixClient { + var setDisplayNameCalled: Boolean = false + private set + var uploadAvatarCalled: Boolean = false + private set + var removeAvatarCalled: Boolean = false + private set + private var ignoreUserResult: Result = Result.success(Unit) private var unignoreUserResult: Result = Result.success(Unit) private var createRoomResult: Result = Result.success(A_ROOM_ID) @@ -69,6 +76,9 @@ class FakeMatrixClient( private val searchUserResults = mutableMapOf>() private val getProfileResults = mutableMapOf>() private var uploadMediaResult: Result = Result.success(AN_AVATAR_URL) + private var setDisplayNameResult: Result = Result.success(Unit) + private var uploadAvatarResult: Result = Result.success(Unit) + private var removeAvatarResult: Result = Result.success(Unit) override suspend fun getRoom(roomId: RoomId): MatrixRoom? { return getRoomResults[roomId] @@ -141,6 +151,21 @@ class FakeMatrixClient( return uploadMediaResult } + override suspend fun setDisplayName(displayName: String): Result { + setDisplayNameCalled = true + return setDisplayNameResult + } + + override suspend fun uploadAvatar(mimeType: String, data: ByteArray): Result { + uploadAvatarCalled = true + return uploadAvatarResult + } + + override suspend fun removeAvatar(): Result { + removeAvatarCalled = true + return removeAvatarResult + } + override fun sessionVerificationService(): SessionVerificationService = sessionVerificationService override fun pushersService(): PushersService = pushersService @@ -197,4 +222,16 @@ class FakeMatrixClient( fun givenUploadMediaResult(result: Result) { uploadMediaResult = result } + + fun givenSetDisplayNameResult(result: Result) { + setDisplayNameResult = result + } + + fun givenUploadAvatarResult(result: Result) { + uploadAvatarResult = result + } + + fun givenRemoveAvatarResult(result: Result) { + removeAvatarResult = result + } } 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 923afd94ad..1240b4c1b5 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 @@ -28,9 +28,14 @@ open class MatrixUserProvider : PreviewParameterProvider { ) } -fun aMatrixUser(id: String = "@id_of_alice:server.org", displayName: String = "Alice") = MatrixUser( +fun aMatrixUser( + id: String = "@id_of_alice:server.org", + displayName: String = "Alice", + avatarUrl: String? = null, +) = MatrixUser( userId = UserId(id), displayName = displayName, + avatarUrl = avatarUrl, ) fun aMatrixUserList() = listOf( From 6d7e51c2e0de9a47ce277372238cbaf9cd5b0c8a Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 15 Sep 2023 15:48:51 +0000 Subject: [PATCH 207/234] Update screenshots --- ...nents_null_RoomSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...ents_null_RoomSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png index e35b511282..4ad70e1e7d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowDark_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1dd44adb59ebe1ac95bc9483c61d09cc2b59307b0e2f86883f1639ae35819b0f -size 12544 +oid sha256:a4451ed5c83109d1a36d262b9d6cca1df4f65998fa2933e77b30ffeec2a1688e +size 12980 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png index ec64e498e6..6b4a39b0f8 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_null_RoomSummaryRowLight_0_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f3d6f98e42089d2b8b1992a3aeb8c1c91847c3975d3759c00dc75bc85fb0ba5d -size 12195 +oid sha256:496059d16235c52562acf31c209d917b3eff6142324e07476e01a732d9aaf816 +size 12661 From f7f9a78101022468026a0c11a0e3361300e659e5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 15 Sep 2023 18:20:44 +0200 Subject: [PATCH 208/234] Cleanup and compact code. Also prefer usage of DayNightPreview. --- .../editprofile/EditUserProfilePresenter.kt | 6 +- .../user/editprofile/EditUserProfileView.kt | 36 +++---- .../EditUserProfilePresenterTest.kt | 95 +++---------------- .../impl/edit/RoomDetailsEditView.kt | 2 +- .../components/LabelledOutlinedTextField.kt | 17 +--- libraries/matrix/impl/build.gradle.kts | 2 +- 6 files changed, 36 insertions(+), 122 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt index edbb2467f2..5d3821931e 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt @@ -95,8 +95,8 @@ class EditUserProfilePresenter @AssistedInject constructor( } val canSave = remember(userDisplayName, userAvatarUri) { - val hasProfileChanged = hasDisplayNameChanged(userDisplayName, matrixUser) - || hasAvatarUrlChanged(userAvatarUri, matrixUser) + val hasProfileChanged = hasDisplayNameChanged(userDisplayName, matrixUser) || + hasAvatarUrlChanged(userAvatarUri, matrixUser) !userDisplayName.isNullOrBlank() && hasProfileChanged } @@ -139,6 +139,6 @@ class EditUserProfilePresenter @AssistedInject constructor( } else { matrixClient.removeAvatar().getOrThrow() } - }.onFailure { it.printStackTrace() } + }.onFailure { Timber.e(it, "Unable to update avatar") } } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileView.kt index 02423470a9..5b921c047c 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfileView.kt @@ -40,7 +40,6 @@ import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.features.preferences.impl.R @@ -50,8 +49,8 @@ import io.element.android.libraries.designsystem.components.ProgressDialog import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog -import io.element.android.libraries.designsystem.preview.ElementPreviewDark -import io.element.android.libraries.designsystem.preview.ElementPreviewLight +import io.element.android.libraries.designsystem.preview.DayNightPreviews +import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.theme.aliasScreenTitle import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Text @@ -135,7 +134,6 @@ fun EditUserProfileView( ) } Spacer(modifier = Modifier.height(40.dp)) - LabelledOutlinedTextField( label = stringResource(R.string.screen_edit_profile_display_name), value = state.displayName, @@ -155,7 +153,6 @@ fun EditUserProfileView( is Async.Loading -> { ProgressDialog(text = stringResource(R.string.screen_edit_profile_updating_details)) } - is Async.Failure -> { ErrorDialog( title = stringResource(R.string.screen_edit_profile_error_title), @@ -163,40 +160,31 @@ fun EditUserProfileView( onDismiss = { state.eventSink(EditUserProfileEvents.CancelSaveChanges) }, ) } - is Async.Success -> { LaunchedEffect(state.saveAction) { onProfileEdited() } } - else -> Unit } } } private fun Modifier.clearFocusOnTap(focusManager: FocusManager): Modifier = - this.pointerInput(Unit) { + pointerInput(Unit) { detectTapGestures(onTap = { focusManager.clearFocus() }) } -@Preview -@Composable -fun EditUserProfileViewLightPreview(@PreviewParameter(EditUserProfileStateProvider::class) state: EditUserProfileState) = - ElementPreviewLight { ContentToPreview(state) } - -@Preview +@DayNightPreviews @Composable -fun EditUserProfileViewDarkPreview(@PreviewParameter(EditUserProfileStateProvider::class) state: EditUserProfileState) = - ElementPreviewDark { ContentToPreview(state) } +internal fun EditUserProfileViewPreview(@PreviewParameter(EditUserProfileStateProvider::class) state: EditUserProfileState) = + ElementPreview { + EditUserProfileView( + onBackPressed = {}, + onProfileEdited = {}, + state = state, + ) + } -@Composable -private fun ContentToPreview(state: EditUserProfileState) { - EditUserProfileView( - onBackPressed = {}, - onProfileEdited = {}, - state = state, - ) -} diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenterTest.kt index c377265689..d3580a82b1 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenterTest.kt @@ -74,7 +74,7 @@ class EditUserProfilePresenterTest { unmockkAll() } - private fun anEditUserProfilePresenter( + private fun createEditUserProfilePresenter( matrixClient: MatrixClient = FakeMatrixClient(), matrixUser: MatrixUser = aMatrixUser(), ): EditUserProfilePresenter { @@ -89,8 +89,7 @@ class EditUserProfilePresenterTest { @Test fun `present - initial state is created from room info`() = runTest { val user = aMatrixUser(avatarUrl = AN_AVATAR_URL) - val presenter = anEditUserProfilePresenter(matrixUser = user) - + val presenter = createEditUserProfilePresenter(matrixUser = user) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -111,27 +110,23 @@ class EditUserProfilePresenterTest { @Test fun `present - updates state in response to changes`() = runTest { val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) - val presenter = anEditUserProfilePresenter(matrixUser = user) - + val presenter = createEditUserProfilePresenter(matrixUser = user) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitItem() assertThat(initialState.displayName).isEqualTo("Name") assertThat(initialState.userAvatarUrl).isEqualTo(userAvatarUri) - initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("Name II")) awaitItem().apply { assertThat(displayName).isEqualTo("Name II") assertThat(userAvatarUrl).isEqualTo(userAvatarUri) } - initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("Name III")) awaitItem().apply { assertThat(displayName).isEqualTo("Name III") assertThat(userAvatarUrl).isEqualTo(userAvatarUri) } - initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.Remove)) awaitItem().apply { assertThat(displayName).isEqualTo("Name III") @@ -143,17 +138,13 @@ class EditUserProfilePresenterTest { @Test fun `present - obtains avatar uris from gallery`() = runTest { val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) - fakePickerProvider.givenResult(anotherAvatarUri) - - val presenter = anEditUserProfilePresenter(matrixUser = user) - + val presenter = createEditUserProfilePresenter(matrixUser = user) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitItem() assertThat(initialState.userAvatarUrl).isEqualTo(userAvatarUri) - initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.ChoosePhoto)) awaitItem().apply { assertThat(userAvatarUrl).isEqualTo(anotherAvatarUri) @@ -164,17 +155,13 @@ class EditUserProfilePresenterTest { @Test fun `present - obtains avatar uris from camera`() = runTest { val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) - fakePickerProvider.givenResult(anotherAvatarUri) - - val presenter = anEditUserProfilePresenter(matrixUser = user) - + val presenter = createEditUserProfilePresenter(matrixUser = user) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitItem() assertThat(initialState.userAvatarUrl).isEqualTo(userAvatarUri) - initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.TakePhoto)) awaitItem().apply { assertThat(userAvatarUrl).isEqualTo(anotherAvatarUri) @@ -185,35 +172,28 @@ class EditUserProfilePresenterTest { @Test fun `present - updates save button state`() = runTest { val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) - fakePickerProvider.givenResult(userAvatarUri) - - val presenter = anEditUserProfilePresenter(matrixUser = user) - + val presenter = createEditUserProfilePresenter(matrixUser = user) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitItem() assertThat(initialState.saveButtonEnabled).isEqualTo(false) - // Once a change is made, the save button is enabled initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("Name II")) awaitItem().apply { assertThat(saveButtonEnabled).isEqualTo(true) } - // If it's reverted then the save disables again initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("Name")) awaitItem().apply { assertThat(saveButtonEnabled).isEqualTo(false) } - // Make a change... initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.Remove)) awaitItem().apply { assertThat(saveButtonEnabled).isEqualTo(true) } - // Revert it... initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.ChoosePhoto)) awaitItem().apply { @@ -225,35 +205,28 @@ class EditUserProfilePresenterTest { @Test fun `present - updates save button state when initial values are null`() = runTest { val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = null) - fakePickerProvider.givenResult(userAvatarUri) - - val presenter = anEditUserProfilePresenter(matrixUser = user) - + val presenter = createEditUserProfilePresenter(matrixUser = user) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitItem() assertThat(initialState.saveButtonEnabled).isEqualTo(false) - // Once a change is made, the save button is enabled initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("Name II")) awaitItem().apply { assertThat(saveButtonEnabled).isEqualTo(true) } - // If it's reverted then the save disables again initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("fallback")) awaitItem().apply { assertThat(saveButtonEnabled).isEqualTo(false) } - // Make a change... initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.ChoosePhoto)) awaitItem().apply { assertThat(saveButtonEnabled).isEqualTo(true) } - // Revert it... initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.Remove)) awaitItem().apply { @@ -266,26 +239,21 @@ class EditUserProfilePresenterTest { fun `present - save changes room details if different`() = runTest { val matrixClient = FakeMatrixClient() val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) - - val presenter = anEditUserProfilePresenter( + val presenter = createEditUserProfilePresenter( matrixClient = matrixClient, matrixUser = user ) - moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitItem() - initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("New name")) initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.Remove)) initialState.eventSink(EditUserProfileEvents.Save) skipItems(5) - assertThat(matrixClient.setDisplayNameCalled).isTrue() assertThat(matrixClient.removeAvatarCalled).isTrue() assertThat(matrixClient.uploadAvatarCalled).isFalse() - cancelAndIgnoreRemainingEvents() } } @@ -294,24 +262,19 @@ class EditUserProfilePresenterTest { fun `present - save doesn't change room details if they're the same trimmed`() = runTest { val matrixClient = FakeMatrixClient() val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) - - val presenter = anEditUserProfilePresenter( + val presenter = createEditUserProfilePresenter( matrixClient = matrixClient, matrixUser = user ) - moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitItem() - initialState.eventSink(EditUserProfileEvents.UpdateDisplayName(" Name ")) initialState.eventSink(EditUserProfileEvents.Save) - assertThat(matrixClient.setDisplayNameCalled).isTrue() assertThat(matrixClient.uploadAvatarCalled).isFalse() assertThat(matrixClient.removeAvatarCalled).isFalse() - cancelAndIgnoreRemainingEvents() } } @@ -320,24 +283,19 @@ class EditUserProfilePresenterTest { fun `present - save doesn't change name if it's now empty`() = runTest { val matrixClient = FakeMatrixClient() val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) - - val presenter = anEditUserProfilePresenter( + val presenter = createEditUserProfilePresenter( matrixClient = matrixClient, matrixUser = user ) - moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitItem() - initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("")) initialState.eventSink(EditUserProfileEvents.Save) - assertThat(matrixClient.setDisplayNameCalled).isFalse() assertThat(matrixClient.uploadAvatarCalled).isFalse() assertThat(matrixClient.removeAvatarCalled).isFalse() - cancelAndIgnoreRemainingEvents() } } @@ -346,23 +304,18 @@ class EditUserProfilePresenterTest { fun `present - save processes and sets avatar when processor returns successfully`() = runTest { val matrixClient = FakeMatrixClient() val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) - givenPickerReturnsFile() - - val presenter = anEditUserProfilePresenter( + val presenter = createEditUserProfilePresenter( matrixClient = matrixClient, matrixUser = user ) - moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitItem() - initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.ChoosePhoto)) initialState.eventSink(EditUserProfileEvents.Save) skipItems(2) - assertThat(matrixClient.uploadAvatarCalled).isTrue() } } @@ -371,26 +324,20 @@ class EditUserProfilePresenterTest { fun `present - save does not set avatar data if processor fails`() = runTest { val matrixClient = FakeMatrixClient() val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) - - val presenter = anEditUserProfilePresenter( + val presenter = createEditUserProfilePresenter( matrixClient = matrixClient, matrixUser = user ) - fakePickerProvider.givenResult(anotherAvatarUri) fakeMediaPreProcessor.givenResult(Result.failure(Throwable("Oh no"))) - moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitItem() - initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.ChoosePhoto)) initialState.eventSink(EditUserProfileEvents.Save) skipItems(2) - assertThat(matrixClient.uploadAvatarCalled).isFalse() - assertThat(awaitItem().saveAction).isInstanceOf(Async.Failure::class.java) } } @@ -401,7 +348,6 @@ class EditUserProfilePresenterTest { val matrixClient = FakeMatrixClient().apply { givenSetDisplayNameResult(Result.failure(Throwable("!"))) } - saveAndAssertFailure(user, matrixClient, EditUserProfileEvents.UpdateDisplayName("New name")) } @@ -411,61 +357,49 @@ class EditUserProfilePresenterTest { val matrixClient = FakeMatrixClient().apply { givenRemoveAvatarResult(Result.failure(Throwable("!"))) } - saveAndAssertFailure(user, matrixClient, EditUserProfileEvents.HandleAvatarAction(AvatarAction.Remove)) } @Test fun `present - sets save action to failure if setting avatar fails`() = runTest { givenPickerReturnsFile() - val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) val matrixClient = FakeMatrixClient().apply { givenUploadAvatarResult(Result.failure(Throwable("!"))) } - saveAndAssertFailure(user, matrixClient, EditUserProfileEvents.HandleAvatarAction(AvatarAction.ChoosePhoto)) } @Test fun `present - CancelSaveChanges resets save action state`() = runTest { givenPickerReturnsFile() - val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) val matrixClient = FakeMatrixClient().apply { givenSetDisplayNameResult(Result.failure(Throwable("!"))) } - - val presenter = anEditUserProfilePresenter(matrixUser = user) - + val presenter = createEditUserProfilePresenter(matrixUser = user) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitItem() - initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("foo")) initialState.eventSink(EditUserProfileEvents.Save) skipItems(2) - assertThat(awaitItem().saveAction).isInstanceOf(Async.Failure::class.java) - initialState.eventSink(EditUserProfileEvents.CancelSaveChanges) assertThat(awaitItem().saveAction).isInstanceOf(Async.Uninitialized::class.java) } } private suspend fun saveAndAssertFailure(matrixUser: MatrixUser, matrixClient: MatrixClient, event: EditUserProfileEvents) { - val presenter = anEditUserProfilePresenter(matrixUser = matrixUser, matrixClient = matrixClient) - + val presenter = createEditUserProfilePresenter(matrixUser = matrixUser, matrixClient = matrixClient) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitItem() - initialState.eventSink(event) initialState.eventSink(EditUserProfileEvents.Save) skipItems(1) - assertThat(awaitItem().saveAction).isInstanceOf(Async.Loading::class.java) assertThat(awaitItem().saveAction).isInstanceOf(Async.Failure::class.java) } @@ -476,7 +410,6 @@ class EditUserProfilePresenterTest { val processedFile: File = mockk { every { readBytes() } returns fakeFileContents } - fakePickerProvider.givenResult(anotherAvatarUri) fakeMediaPreProcessor.givenResult( Result.success( diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/edit/RoomDetailsEditView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/edit/RoomDetailsEditView.kt index 4553161d73..ac9853a387 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/edit/RoomDetailsEditView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/edit/RoomDetailsEditView.kt @@ -223,7 +223,7 @@ private fun LabelledReadOnlyField( } private fun Modifier.clearFocusOnTap(focusManager: FocusManager): Modifier = - this.pointerInput(Unit) { + pointerInput(Unit) { detectTapGestures(onTap = { focusManager.clearFocus() }) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LabelledOutlinedTextField.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LabelledOutlinedTextField.kt index a273acf25c..4939cac38d 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LabelledOutlinedTextField.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/LabelledOutlinedTextField.kt @@ -24,10 +24,9 @@ import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import io.element.android.libraries.designsystem.preview.ElementPreviewDark -import io.element.android.libraries.designsystem.preview.ElementPreviewLight +import io.element.android.libraries.designsystem.preview.DayNightPreviews +import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.theme.components.OutlinedTextField import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.theme.ElementTheme @@ -66,16 +65,9 @@ fun LabelledOutlinedTextField( } } -@Preview +@DayNightPreviews @Composable -internal fun LabelledOutlinedTextFieldLightPreview() = ElementPreviewLight { ContentToPreview() } - -@Preview -@Composable -internal fun LabelledOutlinedTextFieldDarkPreview() = ElementPreviewDark { ContentToPreview() } - -@Composable -private fun ContentToPreview() { +internal fun LabelledOutlinedTextFieldPreview() = ElementPreview { Column { LabelledOutlinedTextField( label = "Room name", @@ -89,3 +81,4 @@ private fun ContentToPreview() { ) } } + diff --git a/libraries/matrix/impl/build.gradle.kts b/libraries/matrix/impl/build.gradle.kts index 88cc929e79..a2b616f989 100644 --- a/libraries/matrix/impl/build.gradle.kts +++ b/libraries/matrix/impl/build.gradle.kts @@ -29,7 +29,7 @@ anvil { } dependencies { -// implementation(projects.libraries.rustsdk) + // implementation(projects.libraries.rustsdk) implementation(libs.matrix.sdk) implementation(projects.libraries.di) implementation(projects.libraries.androidutils) From 27e567e6f4b63d11ec659a9c1920343e4d60673e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 15 Sep 2023 19:24:43 +0200 Subject: [PATCH 209/234] Fix the test. --- .../editprofile/EditUserProfilePresenter.kt | 9 +++- .../EditUserProfilePresenterTest.kt | 42 ++++++++++--------- .../libraries/matrix/test/FakeMatrixClient.kt | 7 ++-- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt index 5d3821931e..793c4840d7 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenter.kt @@ -26,6 +26,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import androidx.core.net.toUri import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject @@ -111,8 +112,12 @@ class EditUserProfilePresenter @AssistedInject constructor( ) } - private fun hasDisplayNameChanged(name: String?, currentUser: MatrixUser?) = name?.trim() != currentUser?.displayName?.trim() - private fun hasAvatarUrlChanged(avatarUri: Uri?, currentUser: MatrixUser?) = avatarUri?.toString()?.trim() != currentUser?.avatarUrl?.trim() + private fun hasDisplayNameChanged(name: String?, currentUser: MatrixUser) = + name?.trim() != currentUser.displayName?.trim() + + private fun hasAvatarUrlChanged(avatarUri: Uri?, currentUser: MatrixUser) = + // Need to call `toUri()?.toString()` to make the test pass (we mockk Uri) + avatarUri?.toString()?.trim() != currentUser.avatarUrl?.toUri()?.toString()?.trim() private fun CoroutineScope.saveChanges(name: String?, avatarUri: Uri?, currentUser: MatrixUser, action: MutableState>) = launch { val results = mutableListOf>() diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenterTest.kt index d3580a82b1..beece60c9a 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/user/editprofile/EditUserProfilePresenterTest.kt @@ -33,6 +33,7 @@ import io.element.android.libraries.mediapickers.test.FakePickerProvider import io.element.android.libraries.mediaupload.api.MediaUploadInfo import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.consumeItemsUntilPredicate import io.mockk.every import io.mockk.mockk import io.mockk.mockkStatic @@ -87,14 +88,14 @@ class EditUserProfilePresenterTest { } @Test - fun `present - initial state is created from room info`() = runTest { + fun `present - initial state is created from user info`() = runTest { val user = aMatrixUser(avatarUrl = AN_AVATAR_URL) val presenter = createEditUserProfilePresenter(matrixUser = user) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { val initialState = awaitItem() - assertThat(initialState.userId).isEqualTo(user.userId.value) + assertThat(initialState.userId).isEqualTo(user.userId) assertThat(initialState.displayName).isEqualTo(user.displayName) assertThat(initialState.userAvatarUrl).isEqualTo(userAvatarUri) assertThat(initialState.avatarActions).containsExactly( @@ -102,7 +103,7 @@ class EditUserProfilePresenterTest { AvatarAction.TakePhoto, AvatarAction.Remove ) - assertThat(initialState.saveButtonEnabled).isEqualTo(false) + assertThat(initialState.saveButtonEnabled).isFalse() assertThat(initialState.saveAction).isInstanceOf(Async.Uninitialized::class.java) } } @@ -178,26 +179,26 @@ class EditUserProfilePresenterTest { presenter.present() }.test { val initialState = awaitItem() - assertThat(initialState.saveButtonEnabled).isEqualTo(false) + assertThat(initialState.saveButtonEnabled).isFalse() // Once a change is made, the save button is enabled initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("Name II")) awaitItem().apply { - assertThat(saveButtonEnabled).isEqualTo(true) + assertThat(saveButtonEnabled).isTrue() } // If it's reverted then the save disables again initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("Name")) awaitItem().apply { - assertThat(saveButtonEnabled).isEqualTo(false) + assertThat(saveButtonEnabled).isFalse() } // Make a change... initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.Remove)) awaitItem().apply { - assertThat(saveButtonEnabled).isEqualTo(true) + assertThat(saveButtonEnabled).isTrue() } // Revert it... initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.ChoosePhoto)) awaitItem().apply { - assertThat(saveButtonEnabled).isEqualTo(false) + assertThat(saveButtonEnabled).isFalse() } } } @@ -211,26 +212,26 @@ class EditUserProfilePresenterTest { presenter.present() }.test { val initialState = awaitItem() - assertThat(initialState.saveButtonEnabled).isEqualTo(false) + assertThat(initialState.saveButtonEnabled).isFalse() // Once a change is made, the save button is enabled initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("Name II")) awaitItem().apply { - assertThat(saveButtonEnabled).isEqualTo(true) + assertThat(saveButtonEnabled).isTrue() } // If it's reverted then the save disables again - initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("fallback")) + initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("Name")) awaitItem().apply { - assertThat(saveButtonEnabled).isEqualTo(false) + assertThat(saveButtonEnabled).isFalse() } // Make a change... initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.ChoosePhoto)) awaitItem().apply { - assertThat(saveButtonEnabled).isEqualTo(true) + assertThat(saveButtonEnabled).isTrue() } // Revert it... initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.Remove)) awaitItem().apply { - assertThat(saveButtonEnabled).isEqualTo(false) + assertThat(saveButtonEnabled).isFalse() } } } @@ -250,7 +251,7 @@ class EditUserProfilePresenterTest { initialState.eventSink(EditUserProfileEvents.UpdateDisplayName("New name")) initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.Remove)) initialState.eventSink(EditUserProfileEvents.Save) - skipItems(5) + consumeItemsUntilPredicate { matrixClient.setDisplayNameCalled && matrixClient.removeAvatarCalled && !matrixClient.uploadAvatarCalled } assertThat(matrixClient.setDisplayNameCalled).isTrue() assertThat(matrixClient.removeAvatarCalled).isTrue() assertThat(matrixClient.uploadAvatarCalled).isFalse() @@ -259,7 +260,7 @@ class EditUserProfilePresenterTest { } @Test - fun `present - save doesn't change room details if they're the same trimmed`() = runTest { + fun `present - save does not change room details if they're the same trimmed`() = runTest { val matrixClient = FakeMatrixClient() val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) val presenter = createEditUserProfilePresenter( @@ -272,7 +273,8 @@ class EditUserProfilePresenterTest { val initialState = awaitItem() initialState.eventSink(EditUserProfileEvents.UpdateDisplayName(" Name ")) initialState.eventSink(EditUserProfileEvents.Save) - assertThat(matrixClient.setDisplayNameCalled).isTrue() + consumeItemsUntilPredicate { matrixClient.setDisplayNameCalled && !matrixClient.removeAvatarCalled && !matrixClient.uploadAvatarCalled } + assertThat(matrixClient.setDisplayNameCalled).isFalse() assertThat(matrixClient.uploadAvatarCalled).isFalse() assertThat(matrixClient.removeAvatarCalled).isFalse() cancelAndIgnoreRemainingEvents() @@ -280,7 +282,7 @@ class EditUserProfilePresenterTest { } @Test - fun `present - save doesn't change name if it's now empty`() = runTest { + fun `present - save does not change name if it's now empty`() = runTest { val matrixClient = FakeMatrixClient() val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL) val presenter = createEditUserProfilePresenter( @@ -315,7 +317,7 @@ class EditUserProfilePresenterTest { val initialState = awaitItem() initialState.eventSink(EditUserProfileEvents.HandleAvatarAction(AvatarAction.ChoosePhoto)) initialState.eventSink(EditUserProfileEvents.Save) - skipItems(2) + consumeItemsUntilPredicate { matrixClient.uploadAvatarCalled } assertThat(matrixClient.uploadAvatarCalled).isTrue() } } @@ -377,7 +379,7 @@ class EditUserProfilePresenterTest { val matrixClient = FakeMatrixClient().apply { givenSetDisplayNameResult(Result.failure(Throwable("!"))) } - val presenter = createEditUserProfilePresenter(matrixUser = user) + val presenter = createEditUserProfilePresenter(matrixUser = user, matrixClient = matrixClient) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt index ce518730c4..67a36f0db7 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt @@ -143,6 +143,7 @@ class FakeMatrixClient( override suspend fun getAccountManagementUrl(action: AccountManagementAction?): Result { return accountManagementUrlString } + override suspend fun uploadMedia( mimeType: String, data: ByteArray, @@ -151,17 +152,17 @@ class FakeMatrixClient( return uploadMediaResult } - override suspend fun setDisplayName(displayName: String): Result { + override suspend fun setDisplayName(displayName: String): Result = simulateLongTask { setDisplayNameCalled = true return setDisplayNameResult } - override suspend fun uploadAvatar(mimeType: String, data: ByteArray): Result { + override suspend fun uploadAvatar(mimeType: String, data: ByteArray): Result = simulateLongTask { uploadAvatarCalled = true return uploadAvatarResult } - override suspend fun removeAvatar(): Result { + override suspend fun removeAvatar(): Result = simulateLongTask { removeAvatarCalled = true return removeAvatarResult } From 24fb8dac58ceafc3d1317b6b3a79a5cd54e4d846 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 15 Sep 2023 17:40:19 +0000 Subject: [PATCH 210/234] Update screenshots --- ..._null_EditUserProfileView-D-3_4_null_0,NEXUS_5,1.0,en].png | 3 +++ ..._null_EditUserProfileView-N-3_5_null_0,NEXUS_5,1.0,en].png | 3 +++ ..._null_RoomDetailsEditViewDark_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ..._null_RoomDetailsEditViewDark_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ..._null_RoomDetailsEditViewDark_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ..._null_RoomDetailsEditViewDark_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ..._null_RoomDetailsEditViewDark_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ..._null_RoomDetailsEditViewDark_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...null_RoomDetailsEditViewLight_0_null_0,NEXUS_5,1.0,en].png | 4 ++-- ...null_RoomDetailsEditViewLight_0_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...null_RoomDetailsEditViewLight_0_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...null_RoomDetailsEditViewLight_0_null_4,NEXUS_5,1.0,en].png | 4 ++-- ...null_RoomDetailsEditViewLight_0_null_5,NEXUS_5,1.0,en].png | 4 ++-- ...null_RoomDetailsEditViewLight_0_null_6,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_42,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_43,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_44,NEXUS_5,1.0,en].png | 4 ++-- ...s.avatar_null_Avatars_Avatar_0_null_45,NEXUS_5,1.0,en].png | 3 +++ ...s.avatar_null_Avatars_Avatar_0_null_46,NEXUS_5,1.0,en].png | 3 +++ ...s.avatar_null_Avatars_Avatar_0_null_47,NEXUS_5,1.0,en].png | 3 +++ ...ull_LabelledOutlinedTextField-D_0_null,NEXUS_5,1.0,en].png | 3 +++ ...ull_LabelledOutlinedTextField-N_1_null,NEXUS_5,1.0,en].png | 3 +++ 22 files changed, 51 insertions(+), 30 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user.editprofile_null_EditUserProfileView-D-3_4_null_0,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user.editprofile_null_EditUserProfileView-N-3_5_null_0,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_45,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_46,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_47,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_LabelledOutlinedTextField-D_0_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_LabelledOutlinedTextField-N_1_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user.editprofile_null_EditUserProfileView-D-3_4_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user.editprofile_null_EditUserProfileView-D-3_4_null_0,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..a030c7b043 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user.editprofile_null_EditUserProfileView-D-3_4_null_0,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:717f9e1f59a958df1a2fef727e33280805a9c50e55c4d78d6ba16b428594589b +size 22646 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user.editprofile_null_EditUserProfileView-N-3_5_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user.editprofile_null_EditUserProfileView-N-3_5_null_0,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..c547d18192 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.user.editprofile_null_EditUserProfileView-N-3_5_null_0,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:727a8edc3a35b431583c53f73049c7e6e4e0e8d4cf998fb134d74ac86e077856 +size 21119 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_0,NEXUS_5,1.0,en].png index e0211eacbe..e7b0671305 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:19ac99f81f3e72f0492d33278a9e549763493ea7ff111412821c62d934a6b9f6 -size 29522 +oid sha256:5b9122206068d76d4e169dbd364d75e28c2fb5102ff2749340f829d15b02b124 +size 29053 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_1,NEXUS_5,1.0,en].png index e548c3c81f..096101e331 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d15154d8ad933acf9a52a73fb650d28489d780cae71b44c7edf10b682cec1ff9 -size 23143 +oid sha256:821f02fa92efca6f5912bbc8675f113e45f78654a0ec78bc30abc0b44c2ab0ed +size 22724 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_3,NEXUS_5,1.0,en].png index 487800c8dd..26474b93d6 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0958e2a99818be0125b700df470a944a3202e0336d440b073cc73ccc6305173f -size 28482 +oid sha256:840b6dfc827adbf183e04c68c8c4978cb87cd356141127a7e548229234359a0e +size 27984 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_4,NEXUS_5,1.0,en].png index 241c7e1400..116c775557 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da07b8de2fd24e9e6bc7fea309e4d5fce68f2143316a5940a41f4270e9d48646 -size 28099 +oid sha256:7e27c699d975a911fbac4cd1456258ad1305d3bfbea7f059f4e736892d33d4c6 +size 28749 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_5,NEXUS_5,1.0,en].png index 1de6e8de96..3b3cb18ea2 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1a7e0644fff4f219712719b4837cf4e5db5c8cf4c9ec1e21fcd1362859a155f3 -size 28607 +oid sha256:2362fecce2c14174679dbda32e9f163ffb23498ef6b15e4846590460faab1011 +size 28142 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_6,NEXUS_5,1.0,en].png index c078ce120e..fb78e13908 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewDark_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8444587bfa6ac65c6464b102bbac0bf679fecc0b193cc664540f39518b30c25d -size 24785 +oid sha256:9ad8c77df2595c643f3a394a406592328268f81a5f6bd14ebd1687f95773f305 +size 24396 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_0,NEXUS_5,1.0,en].png index dc1ba40727..104d4e7042 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_0,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_0,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:22b0a03bec31400bd88a51c160bf63132f0c8f7e1cf02041a901778c3f1e27ef -size 30856 +oid sha256:a2fa1c83e3ecddef2b489a8ce48db4195953fccd42534d2641bef619d5eb8bd1 +size 30325 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_1,NEXUS_5,1.0,en].png index cc49e4274d..1a66b0af31 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8308dc746a7a51a7bffa49cbf1436097565a175298073afe3d94558d77307510 -size 24145 +oid sha256:5ea00ab4789b78416b938057b7cf5df117042000894b3000536384e61284ffd0 +size 23652 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_3,NEXUS_5,1.0,en].png index ce4af21fcf..dfa5a058c1 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:32f3030c3bfb1bc9ed4c4378698df073cb29285477538c81592c38668953ffc8 -size 30562 +oid sha256:a9018f1e5339d1ad9fa6deab845e1365215d727bc68f243cccc907ead233a6e1 +size 30041 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_4,NEXUS_5,1.0,en].png index 090bda7bbf..bd9e15f3a5 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_4,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_4,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0587640a3ffb707c94d25da38d9f327500c3d3a96d0b57ba92a3c4201014fc11 -size 29448 +oid sha256:4c4af6710212228b3597d2e6cfaed5f6577e6aea90fb27240a7687d87f6f7ad7 +size 30043 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_5,NEXUS_5,1.0,en].png index 03d72aa037..357b55f52d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_5,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_5,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1017fcd62a71f7a2a82dbee3ee2a5233747eb3c888c4b6302f65d9aa02c5492c -size 30673 +oid sha256:baee8e594977d8ae84c71b12e764005c7f04d34e57c80fce92dfa7431a8a6392 +size 30258 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_6,NEXUS_5,1.0,en].png index acd3d83443..abcd30f771 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_6,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomdetails.impl.edit_null_RoomDetailsEditViewLight_0_null_6,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4e01d7e598c771260bf4ef91d0ae99081e80f318c1e0300cda3dc1ce780c80ee -size 28078 +oid sha256:b5f05df46a49a9d1de0495655ca3828727c0c7d00afd11abbd643c8fc6712c03 +size 27667 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_42,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_42,NEXUS_5,1.0,en].png index d69da80047..cb0e6b6fc9 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_42,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_42,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:820b23e9b9175b48461a4e7e359c2440b8c45cb598f512ea360519b0815621fc -size 18259 +oid sha256:eac20dcc3e285cde5f3d2515d65416162362de196940b3c208886934592070e4 +size 21346 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_43,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_43,NEXUS_5,1.0,en].png index 4cf9f8f839..f939fb7b9e 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_43,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_43,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3ce4abbf622711cf6a106cb6c74ed729c6e609d329579b7b00ba8c1581b4b953 -size 17463 +oid sha256:96d3a1b71b8372ca80b667ae57bf9f87b5e8167684ea62c8f71d90994113929f +size 19530 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_44,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_44,NEXUS_5,1.0,en].png index a475b2e7d1..f64b9f6a2d 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_44,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_44,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f0cb196c59e3bbd845f0e110150ac358ca78c9c08c212e184423ead5d841f67c -size 20219 +oid sha256:1f3a728b5791495710209e5b308dda4b38defded1a44d00bbd69fb1c45877218 +size 25254 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_45,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_45,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..d69da80047 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_45,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:820b23e9b9175b48461a4e7e359c2440b8c45cb598f512ea360519b0815621fc +size 18259 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_46,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_46,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..4cf9f8f839 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_46,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ce4abbf622711cf6a106cb6c74ed729c6e609d329579b7b00ba8c1581b4b953 +size 17463 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_47,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_47,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..a475b2e7d1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components.avatar_null_Avatars_Avatar_0_null_47,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f0cb196c59e3bbd845f0e110150ac358ca78c9c08c212e184423ead5d841f67c +size 20219 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_LabelledOutlinedTextField-D_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_LabelledOutlinedTextField-D_0_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..94e3fe87de --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_LabelledOutlinedTextField-D_0_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2edcff9494f8dfe74edeb988be57c205d98954887fc885375b850f76271df147 +size 15636 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_LabelledOutlinedTextField-N_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_LabelledOutlinedTextField-N_1_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..f7a31d7941 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_null_LabelledOutlinedTextField-N_1_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0aaa6be5eed7879e03fc81d054f3caaf9cd5660f616be9bf47247e8d2503f473 +size 14725 From 25c1cfffcab5f7522c2415b72ccc91979846d813 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 15 Sep 2023 22:34:32 +0000 Subject: [PATCH 211/234] Update dependency com.google.firebase:firebase-bom to v32.3.1 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b164dfbb95..69d3988f06 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -66,7 +66,7 @@ android_gradle_plugin = { module = "com.android.tools.build:gradle", version.ref android_desugar = "com.android.tools:desugar_jdk_libs:2.0.3" kotlin_gradle_plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } # https://firebase.google.com/docs/android/setup#available-libraries -google_firebase_bom = "com.google.firebase:firebase-bom:32.3.0" +google_firebase_bom = "com.google.firebase:firebase-bom:32.3.1" # AndroidX androidx_material = { module = "com.google.android.material:material", version.ref = "material" } From 519464fe5de805e6064468e685e1bb777200bce4 Mon Sep 17 00:00:00 2001 From: jonnyandrew Date: Sat, 16 Sep 2023 08:40:56 +0100 Subject: [PATCH 212/234] [Rich text editor] Ensure keyboard opens for reply and text formatting modes (#1337) --- changelog.d/1337.bugfix | 1 + .../android/libraries/androidutils/ui/View.kt | 24 ++++++++ .../textcomposer/SoftKeyboardEffect.kt | 55 +++++++++++++++++++ .../libraries/textcomposer/TextComposer.kt | 17 ++---- 4 files changed, 84 insertions(+), 13 deletions(-) create mode 100644 changelog.d/1337.bugfix create mode 100644 libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/SoftKeyboardEffect.kt diff --git a/changelog.d/1337.bugfix b/changelog.d/1337.bugfix new file mode 100644 index 0000000000..b7d6c300dd --- /dev/null +++ b/changelog.d/1337.bugfix @@ -0,0 +1 @@ +[Rich text editor] Ensure keyboard opens for reply and text formatting modes \ No newline at end of file diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/View.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/View.kt index 0639f29d1f..8bbaf1e5c3 100644 --- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/View.kt +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/ui/View.kt @@ -17,8 +17,11 @@ package io.element.android.libraries.androidutils.ui import android.view.View +import android.view.ViewTreeObserver import android.view.inputmethod.InputMethodManager import androidx.core.content.getSystemService +import kotlinx.coroutines.suspendCancellableCoroutine +import kotlin.coroutines.resume fun View.hideKeyboard() { val imm = context?.getSystemService() @@ -41,3 +44,24 @@ fun View.setHorizontalPadding(padding: Int) { paddingBottom ) } + +suspend fun View.awaitWindowFocus() = suspendCancellableCoroutine { continuation -> + if (hasWindowFocus()) { + continuation.resume(Unit) + } else { + val listener = object : ViewTreeObserver.OnWindowFocusChangeListener { + override fun onWindowFocusChanged(hasFocus: Boolean) { + if (hasFocus) { + viewTreeObserver.removeOnWindowFocusChangeListener(this) + continuation.resume(Unit) + } + } + } + + viewTreeObserver.addOnWindowFocusChangeListener(listener) + + continuation.invokeOnCancellation { + viewTreeObserver.removeOnWindowFocusChangeListener(listener) + } + } +} diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/SoftKeyboardEffect.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/SoftKeyboardEffect.kt new file mode 100644 index 0000000000..96b48dca6e --- /dev/null +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/SoftKeyboardEffect.kt @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.textcomposer + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.ui.platform.LocalView +import androidx.compose.ui.viewinterop.AndroidView +import io.element.android.libraries.androidutils.ui.awaitWindowFocus +import io.element.android.libraries.androidutils.ui.showKeyboard + +/** + * Shows the soft keyboard when a given key changes to meet the required condition. + * + * Uses [showKeyboard] to show the keyboard for compatibility with [AndroidView]. + * + * @param T + * @param key The key to watch for changes. + * @param onRequestFocus A callback to request focus to the view that will receive the keyboard input. + * @param predicate The predicate that [key] must meet before showing the keyboard. + */ +@Composable +internal fun SoftKeyboardEffect( + key: T, + onRequestFocus: () -> Unit, + predicate: (T) -> Boolean, +) { + val view = LocalView.current + LaunchedEffect(key) { + if (predicate(key)) { + // Await window focus in case returning from a dialog + view.awaitWindowFocus() + + // Show the keyboard, temporarily using the root view for focus + view.showKeyboard(andRequestFocus = true) + + // Refocus to the correct view + onRequestFocus() + } + } +} diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt index df51d5d1ef..40bf27dd5f 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt @@ -43,7 +43,6 @@ import androidx.compose.material.icons.filled.Close import androidx.compose.material.ripple.rememberRipple import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.remember @@ -52,7 +51,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource import androidx.compose.ui.text.style.TextAlign @@ -84,7 +82,6 @@ import io.element.android.wysiwyg.compose.RichTextEditor import io.element.android.wysiwyg.compose.RichTextEditorDefaults import io.element.android.wysiwyg.compose.RichTextEditorState import io.element.android.wysiwyg.view.models.InlineFormat -import kotlinx.coroutines.android.awaitFrame import uniffi.wysiwyg_composer.ActionState import uniffi.wysiwyg_composer.ComposerAction @@ -223,17 +220,11 @@ fun TextComposer( } } - // Request focus when changing mode, and show keyboard. - val keyboard = LocalSoftwareKeyboardController.current - LaunchedEffect(composerMode) { - if (composerMode is MessageComposerMode.Special) { - onRequestFocus() - keyboard?.let { - awaitFrame() - it.show() - } - } + SoftKeyboardEffect(composerMode, onRequestFocus) { + it is MessageComposerMode.Special } + + SoftKeyboardEffect(showTextFormatting, onRequestFocus) { it } } @Composable From d2f9b02bbf0eaf21b2a9c5b4c534930be30f9587 Mon Sep 17 00:00:00 2001 From: bmarty Date: Mon, 18 Sep 2023 00:09:19 +0000 Subject: [PATCH 213/234] Sync Strings from Localazy --- .../src/main/res/values-de/translations.xml | 6 + .../src/main/res/values-de/translations.xml | 6 + .../src/main/res/values-sk/translations.xml | 6 + .../src/main/res/values-de/translations.xml | 11 + .../src/main/res/values-de/translations.xml | 10 +- .../src/main/res/values-de/translations.xml | 9 + .../src/main/res/values-de/translations.xml | 39 ++++ .../src/main/res/values-de/translations.xml | 8 + .../src/main/res/values-de/translations.xml | 37 ++++ .../src/main/res/values-de/translations.xml | 10 + .../src/main/res/values-de/translations.xml | 3 +- .../src/main/res/values-de/translations.xml | 5 + .../src/main/res/values-de/translations.xml | 15 ++ .../src/main/res/values-de/translations.xml | 46 +++- .../src/main/res/values-de/translations.xml | 9 + .../src/main/res/values-de/translations.xml | 15 ++ .../src/main/res/values-de/translations.xml | 4 + .../src/main/res/values-de/translations.xml | 54 ++++- .../src/main/res/values-de/translations.xml | 45 ++++ .../src/main/res/values-de/translations.xml | 4 + .../src/main/res/values-cs/translations.xml | 4 +- .../src/main/res/values-de/translations.xml | 206 +++++++++++++++++- .../src/main/res/values-fr/translations.xml | 8 + .../src/main/res/values-ru/translations.xml | 4 +- .../src/main/res/values-sk/translations.xml | 17 ++ .../src/main/res/values/localazy.xml | 1 + 26 files changed, 571 insertions(+), 11 deletions(-) create mode 100644 features/call/src/main/res/values-de/translations.xml create mode 100644 features/call/src/main/res/values-sk/translations.xml create mode 100644 features/invitelist/impl/src/main/res/values-de/translations.xml create mode 100644 features/logout/api/src/main/res/values-de/translations.xml create mode 100644 features/onboarding/impl/src/main/res/values-de/translations.xml create mode 100644 features/rageshake/api/src/main/res/values-de/translations.xml create mode 100644 features/rageshake/impl/src/main/res/values-de/translations.xml create mode 100644 features/roomlist/impl/src/main/res/values-de/translations.xml create mode 100644 libraries/androidutils/src/main/res/values-de/translations.xml create mode 100644 libraries/textcomposer/impl/src/main/res/values-de/translations.xml diff --git a/features/analytics/impl/src/main/res/values-de/translations.xml b/features/analytics/impl/src/main/res/values-de/translations.xml index 4282ead092..a9b4173395 100644 --- a/features/analytics/impl/src/main/res/values-de/translations.xml +++ b/features/analytics/impl/src/main/res/values-de/translations.xml @@ -1,4 +1,10 @@ + "Wir zeichnen keine persönlichen Daten auf und erstellen keine Profile." + "Teilen Sie anonyme Nutzungsdaten, um uns bei der Identifizierung von Problemen zu helfen." + "Sie können alle unsere Bedingungen lesen%1$s." "hier" + "Sie können diese Funktion jederzeit deaktivieren" + "Wir geben Ihre Daten nicht an Dritte weiter" + "Hilf uns %1$s zu verbessern" diff --git a/features/call/src/main/res/values-de/translations.xml b/features/call/src/main/res/values-de/translations.xml new file mode 100644 index 0000000000..d58a616780 --- /dev/null +++ b/features/call/src/main/res/values-de/translations.xml @@ -0,0 +1,6 @@ + + + "Laufender Anruf" + "Tippen, um zum Anruf zurückzukehren" + "☎️ Anruf läuft" + diff --git a/features/call/src/main/res/values-sk/translations.xml b/features/call/src/main/res/values-sk/translations.xml new file mode 100644 index 0000000000..ec7d693f1d --- /dev/null +++ b/features/call/src/main/res/values-sk/translations.xml @@ -0,0 +1,6 @@ + + + "Prebiehajúci hovor" + "Ťuknutím sa vrátite k hovoru" + "☎️ Prebieha hovor" + diff --git a/features/createroom/impl/src/main/res/values-de/translations.xml b/features/createroom/impl/src/main/res/values-de/translations.xml index f033df7792..1a027c9d2d 100644 --- a/features/createroom/impl/src/main/res/values-de/translations.xml +++ b/features/createroom/impl/src/main/res/values-de/translations.xml @@ -1,4 +1,15 @@ + "Neuer Raum" + "Freunde zu Element einladen" + "Personen einladen" + "Beim Erstellen des Raums ist ein Fehler aufgetreten" + "Die Nachrichten in diesem Raum sind verschlüsselt. Die Verschlüsselung kann nicht nachträglich deaktiviert werden." + "Privater Raum (nur auf Einladung)" + "Die Nachrichten sind nicht verschlüsselt und können von jedem gelesen werden. Die Verschlüsselung kann zu einem späteren Zeitpunkt aktiviert werden." + "Öffentlicher Raum (für alle)" + "Raumname" + "Thema (optional)" + "Beim Versuch, einen Chat zu starten, ist ein Fehler aufgetreten" "Raum erstellen" diff --git a/features/ftue/impl/src/main/res/values-de/translations.xml b/features/ftue/impl/src/main/res/values-de/translations.xml index 36fc85fba5..8df01adc45 100644 --- a/features/ftue/impl/src/main/res/values-de/translations.xml +++ b/features/ftue/impl/src/main/res/values-de/translations.xml @@ -1,5 +1,13 @@ - "Du kannst deine Einstellungen später ändern." + "Dies ist ein einmaliger Vorgang, danke fürs Warten." + "Richten Sie Ihr Konto ein." + "Sie können Ihre Einstellungen später ändern." "Erlaube Benachrichtigungen und verpasse keine Nachricht" + "Anrufe, Umfragen, Suchfunktionen und mehr werden im Laufe des Jahres hinzugefügt." + "Der Nachrichtenverlauf für verschlüsselte Räume wird in diesem Update nicht verfügbar sein." + "Wir würden uns freuen, von Ihnen zu hören. Teilen Sie uns Ihre Meinung über die Einstellungsseite mit." + "Los geht\'s!" + "Folgendes müssen Sie wissen:" + "Willkommen bei %1$s!" diff --git a/features/invitelist/impl/src/main/res/values-de/translations.xml b/features/invitelist/impl/src/main/res/values-de/translations.xml new file mode 100644 index 0000000000..245634a971 --- /dev/null +++ b/features/invitelist/impl/src/main/res/values-de/translations.xml @@ -0,0 +1,9 @@ + + + "Möchten Sie die Einladung zum Betreten von %1$s wirklich ablehnen?" + "Einladung ablehnen" + "Sind Sie sicher, dass Sie diesen privaten Chat mit %1$s ablehnen möchten?" + "Chat ablehnen" + "Keine Einladungen" + "%1$s (%2$s) hat dich eingeladen" + diff --git a/features/login/impl/src/main/res/values-de/translations.xml b/features/login/impl/src/main/res/values-de/translations.xml index 8a69936ff8..ba012e8082 100644 --- a/features/login/impl/src/main/res/values-de/translations.xml +++ b/features/login/impl/src/main/res/values-de/translations.xml @@ -1,8 +1,47 @@ + "Kontoanbieter ändern" + "Homeserver-Adresse" + "Geben Sie einen Suchbegriff oder eine Domainadresse ein." + "Suchen Sie nach einem Unternehmen, einer Community oder einem privaten Server." + "Kontoanbieter finden" + "Hier werden Ihre Gespräche gespeichert – genau so, wie Sie einen E-Mail-Anbieter nutzen würden, um Ihre E-Mails aufzubewahren." + "Sie sind dabei, sich bei %s anzumelden" + "Hier werden Ihre Gespräche gespeichert – genau so, wie Sie einen E-Mail-Anbieter nutzen würden, um Ihre E-Mails aufzubewahren." + "Sie sind dabei, ein Konto bei %s zu erstellen" + "Matrix.org ist ein großer, kostenloser Server im öffentlichen Matrix-Netzwerk für eine sichere, dezentralisierte Kommunikation, der von der Matrix.org Foundation betrieben wird." + "Sonstige" + "Verwenden Sie einen anderen Kontoanbieter, z. B. Ihren eigenen privaten Server oder ein Geschäftskonto." + "Kontoanbieter wechseln" + "Wir konnten diesen Homeserver nicht erreichen. Bitte überprüfen Sie, ob Sie die Homeserver-URL korrekt eingegeben haben. Wenn die URL korrekt ist, wenden Sie sich an Ihren Homeserver-Administrator, um weitere Hilfe zu erhalten." + "Dieser Server unterstützt derzeit kein Sliding Sync." + "Homeserver-URL" + "Sie können nur eine Verbindung zu einem vorhandenen Server herstellen, der Sliding Sync unterstützt. Ihr Homeserver-Administrator muss das konfigurieren. %1$s" + "Wie lautet die Adresse Ihres Servers?" + "Dieses Konto wurde deaktiviert." + "Falscher Benutzername und/oder Passwort" + "Dies ist keine gültige Benutzerkennung. Erwartetes Format: \'@user:homeserver.org\'" + "Der ausgewählte Homeserver unterstützt weder den Login per Passwort noch per OIDC. Bitte kontaktieren Sie Ihren Admin oder wählen Sie einen anderen Homeserver." + "Geben Sie Ihre Daten ein" + "Willkommen zurück!" + "Anmelden bei %1$s" + "Kontoanbieter wechseln" + "Ein privater Server für die Mitarbeiter von Element." + "Matrix ist ein offenes Netzwerk für eine sichere, dezentrale Kommunikation." + "Hier werden Ihre Gespräche gespeichert - so wie Sie Ihre E-Mails bei einem E-Mail-Anbieter aufbewahren würden." + "Sie sind dabei, sich bei %1$s anzumelden" + "Sie sind dabei, ein Konto auf %1$s zu erstellen" + "Derzeit besteht eine hohe Nachfrage nach %1$s auf %2$s. Kehren Sie in ein paar Tagen zur App zurück und versuchen Sie es erneut. + +Danke für Ihre Geduld!" + "Willkommen bei %1$s!" + "Sie sind fast am Ziel." + "Sie sind dabei." "Weiter" "Weiter" + "Wählen Sie Ihren Server aus" "Passwort" "Weiter" + "Matrix ist ein offenes Netzwerk für eine sichere, dezentrale Kommunikation." "Benutzername" diff --git a/features/logout/api/src/main/res/values-de/translations.xml b/features/logout/api/src/main/res/values-de/translations.xml new file mode 100644 index 0000000000..893cc983b0 --- /dev/null +++ b/features/logout/api/src/main/res/values-de/translations.xml @@ -0,0 +1,8 @@ + + + "Sind Sie sicher, dass Sie sich abmelden wollen?" + "Abmelden" + "Abmelden…" + "Abmelden" + "Abmelden" + diff --git a/features/messages/impl/src/main/res/values-de/translations.xml b/features/messages/impl/src/main/res/values-de/translations.xml index 5d43a8167f..8208418e34 100644 --- a/features/messages/impl/src/main/res/values-de/translations.xml +++ b/features/messages/impl/src/main/res/values-de/translations.xml @@ -1,5 +1,42 @@ + + "%1$d Raumänderung" + "%1$d Raumänderungen" + + "Kamera" + "Foto machen" + "Video aufnehmen" + "Anhang" + "Foto- und Videobibliothek" + "Standort" + "Umfrage" "Textformatierung" + "Der Nachrichtenverlauf ist derzeit in diesem Raum nicht verfügbar" + "Benutzerdetails konnten nicht abgerufen werden" + "Möchten Sie sie wieder einladen?" + "Sie sind allein in diesem Chat" + "Nachricht wurde kopiert" + "Sie sind nicht berechtigt, in diesem Raum zu posten" + "Benutzerdefinierte Einstellung zulassen" + "Wenn Sie diese Option aktivieren, wird Ihre Standardeinstellung außer Kraft gesetzt." + "Benachrichtigen Sie mich in diesem Chat bei" + "Sie können das in Ihrem %1$s ändern." + "Globale Einstellungen" + "Standardeinstellung" + "Benutzerdefinierte Einstellung entfernen" + "Beim Laden der Benachrichtigungseinstellungen ist ein Fehler aufgetreten." + "Fehler beim Wiederherstellen des Standardmodus. Bitte versuchen Sie es erneut." + "Fehler beim Einstellen des Modus. Bitte versuchen Sie es erneut." + "Alle Nachrichten" + "Nur Erwähnungen und Schlüsselwörter" + "Benachrichtigen Sie mich in diesem Raum bei" + "Weniger anzeigen" + "Mehr anzeigen" + "Erneut senden" + "Ihre Nachricht konnte nicht gesendet werden" + "Emoji hinzufügen" + "Weniger anzeigen" + "Fehler beim Verarbeiten des hochgeladenen Mediums. Bitte versuchen Sie es erneut." "Entfernen" diff --git a/features/onboarding/impl/src/main/res/values-de/translations.xml b/features/onboarding/impl/src/main/res/values-de/translations.xml new file mode 100644 index 0000000000..08bc2abeee --- /dev/null +++ b/features/onboarding/impl/src/main/res/values-de/translations.xml @@ -0,0 +1,10 @@ + + + "Manuell anmelden" + "Mit QR-Code anmelden" + "Konto erstellen" + "Sicher kommunizieren und zusammenarbeiten" + "Willkommen beim schnellsten Element aller Zeiten. Optimiert für Geschwindigkeit und Einfachheit." + "Willkommen zu %1$s. Aufgeladen, für Geschwindigkeit und Einfachheit." + "Seien Sie in Ihrem Element" + diff --git a/features/poll/impl/src/main/res/values-de/translations.xml b/features/poll/impl/src/main/res/values-de/translations.xml index 762afd5fd8..c2b07baf16 100644 --- a/features/poll/impl/src/main/res/values-de/translations.xml +++ b/features/poll/impl/src/main/res/values-de/translations.xml @@ -4,8 +4,9 @@ "Ergebnisse erst nach Ende der Umfrage anzeigen" "Anonyme Umfrage" "Option %1$d" - "Bist du sicher, dass du diese Umfrage verwerfen willst?" + "Sind Sie sicher, dass Sie diese Umfrage verwerfen wollen?" "Umfrage verwerfen" "Frage oder Thema" + "Worum geht es bei der Umfrage?" "Umfrage erstellen" diff --git a/features/rageshake/api/src/main/res/values-de/translations.xml b/features/rageshake/api/src/main/res/values-de/translations.xml new file mode 100644 index 0000000000..7c49bf6225 --- /dev/null +++ b/features/rageshake/api/src/main/res/values-de/translations.xml @@ -0,0 +1,5 @@ + + + "%1$s ist bei der letzten Nutzung abgestürzt. Möchten Sie einen Absturzbericht mit uns teilen?" + "Sie scheinen das Telefon aus Frustration zu schütteln. Möchten Sie den Bildschirm für den Fehlerbericht öffnen?" + diff --git a/features/rageshake/impl/src/main/res/values-de/translations.xml b/features/rageshake/impl/src/main/res/values-de/translations.xml new file mode 100644 index 0000000000..f1a25237bf --- /dev/null +++ b/features/rageshake/impl/src/main/res/values-de/translations.xml @@ -0,0 +1,15 @@ + + + "Bildschirmfoto anhängen" + "Sie können mich kontaktieren, wenn Sie weitere Fragen haben." + "Kontaktieren Sie mich" + "Bildschirmfoto bearbeiten" + "Bitte beschreiben Sie den Fehler. Was haben Sie getan? Was haben Sie erwartet, was passiert? Was ist tatsächlich passiert. Bitte gehen Sie so detailliert wie möglich vor." + "Beschreiben Sie den Fehler…" + "Wenn möglich, verfassen Sie die Beschreibung bitte auf Englisch." + "Absturzprotokolle senden" + "Protokolle zulassen" + "Bildschirmfoto senden" + "Die Protokolle werden Ihrer Nachricht beigefügt, um sicherzustellen, dass alles ordnungsgemäß funktioniert. Um Ihre Nachricht ohne Protokolle zu senden, deaktivieren Sie diese Einstellung." + "%1$s ist bei der letzten Nutzung abgestürzt. Möchten Sie einen Absturzbericht mit uns teilen?" + diff --git a/features/roomdetails/impl/src/main/res/values-de/translations.xml b/features/roomdetails/impl/src/main/res/values-de/translations.xml index 7e33583ffd..e4f43c1ffe 100644 --- a/features/roomdetails/impl/src/main/res/values-de/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-de/translations.xml @@ -1,6 +1,50 @@ + + "%1$d Person" + "%1$d Personen" + + "Thema hinzufügen" + "Bereits Mitglied" + "Bereits eingeladen" + "Raum bearbeiten" + "Es ist ein unbekannter Fehler aufgetreten und die Informationen konnten nicht geändert werden." + "Raum kann nicht aktualisiert werden" + "Nachrichten sind mit Schlössern gesichert. Nur Sie und die Empfänger haben die eindeutigen Schlüssel, um sie zu entsperren." + "Nachrichtenverschlüsselung aktiviert" + "Beim Laden der Benachrichtigungseinstellungen ist ein Fehler aufgetreten." + "Die Stummschaltung dieses Raums ist fehlgeschlagen, bitte versuchen Sie es erneut." + "Die Deaktivierung der Stummschaltung dieses Raums ist fehlgeschlagen, bitte versuchen Sie es erneut." + "Personen einladen" + "Benutzerdefiniert" + "Standard" + "Benachrichtigungen" + "Raumname" + "Raum teilen" + "Raum wird aktualisiert…" + "Ausstehend" + "Raummitglieder" + "Benutzerdefinierte Einstellung zulassen" + "Wenn Sie diese Option aktivieren, wird Ihre Standardeinstellung außer Kraft gesetzt." + "Benachrichtigen Sie mich in diesem Chat bei" + "Sie können das in Ihrem %1$s ändern." + "Globale Einstellungen" + "Standardeinstellung" + "Benutzerdefinierte Einstellung entfernen" + "Beim Laden der Benachrichtigungseinstellungen ist ein Fehler aufgetreten." + "Fehler beim Wiederherstellen des Standardmodus. Bitte versuchen Sie es erneut." + "Fehler beim Einstellen des Modus. Bitte versuchen Sie es erneut." + "Alle Nachrichten" + "Nur Erwähnungen und Schlüsselwörter" + "Benachrichtigen Sie mich in diesem Raum bei" + "Sperren" + "Gesperrte Benutzer können Ihnen keine Nachrichten senden und alle ihre Nachrichten werden ausgeblendet. Sie können sie jederzeit entsperren." + "Benutzer sperren" + "Entsperren" + "Sie können dann wieder alle Nachrichten von ihnen sehen." + "Benutzer entsperren" "Raum verlassen" - "Menschen" + "Personen" + "Sicherheit" "Thema" diff --git a/features/roomlist/impl/src/main/res/values-de/translations.xml b/features/roomlist/impl/src/main/res/values-de/translations.xml new file mode 100644 index 0000000000..8ce40240ae --- /dev/null +++ b/features/roomlist/impl/src/main/res/values-de/translations.xml @@ -0,0 +1,9 @@ + + + "Eine neue Unterhaltung oder einen neuen Raum erstellen" + "Beginnen Sie, indem Sie jemandem eine Nachricht senden." + "Noch keine Chats." + "Alle Chats" + "Es sieht aus, als würden Sie ein neues Gerät verwenden. Verifizieren Sie es mit einem anderen Gerät, damit Sie auf Ihre verschlüsselten Nachrichten zugreifen können." + "Bestätigen Sie Ihre Identität" + diff --git a/features/verifysession/impl/src/main/res/values-de/translations.xml b/features/verifysession/impl/src/main/res/values-de/translations.xml index 6699697e79..5b4850ae57 100644 --- a/features/verifysession/impl/src/main/res/values-de/translations.xml +++ b/features/verifysession/impl/src/main/res/values-de/translations.xml @@ -1,4 +1,19 @@ + "Etwas scheint nicht zu stimmen. Entweder ist das Zeitlimit für die Anfrage abgelaufen oder die Anfrage wurde abgelehnt." + "Vergewissern Sie sich, dass die folgenden Emojis mit denen in Ihrer anderen Session übereinstimmen." + "Emojis vergleichen" + "Ihre neue Session ist nun verifiziert. Sie hat Zugriff auf Ihre verschlüsselten Nachrichten und wird von anderen Benutzern als vertrauenswürdig eingestuft." + "Beweisen Sie Ihre Identität, um auf Ihren verschlüsselten Nachrichtenverlauf zuzugreifen." + "Öffnen Sie eine bestehende Sitzung" + "Verifizierung wiederholen" + "Ich bin bereit" + "Warten auf eine Übereinstimmung" + "Vergleichen Sie die einzelnen Emojis und stellen Sie sicher, dass sie in der gleichen Reihenfolge erscheinen." + "Sie stimmen nicht überein" + "Sie stimmen überein" + "Akzeptieren Sie die Anfrage, um den Verifizierungsprozess in Ihrer anderen Session zu starten, um fortzufahren." + "Warten auf die Annahme der Anfrage" + "Verifizierung abgebrochen" "Start" diff --git a/libraries/androidutils/src/main/res/values-de/translations.xml b/libraries/androidutils/src/main/res/values-de/translations.xml new file mode 100644 index 0000000000..99b7294eb5 --- /dev/null +++ b/libraries/androidutils/src/main/res/values-de/translations.xml @@ -0,0 +1,4 @@ + + + "Für diese Aktion wurde keine kompatible App gefunden." + diff --git a/libraries/eventformatter/impl/src/main/res/values-de/translations.xml b/libraries/eventformatter/impl/src/main/res/values-de/translations.xml index 48d41bed39..a7773e49c7 100644 --- a/libraries/eventformatter/impl/src/main/res/values-de/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-de/translations.xml @@ -1,5 +1,57 @@ + "(Avatar wurde auch geändert)" + "%1$s hat den Avatar geändert" + "Sie haben Ihren Avatar geändert" + "%1$s hat den Anzeigenamen von %2$s auf %3$s geändert" + "Sie haben Ihren Anzeigenamen von %1$s auf %2$s geändert" + "%1$s hat den Anzeigenamen entfernt (war %2$s)" + "Sie haben Ihren Anzeigenamen entfernt (war %1$s)" + "%1$s setzen ihren Anzeigenamen auf %2$s" + "Sie haben Ihren Anzeigenamen zu %1$s geändert" + "%1$s hat den Raum-Avatar geändert" + "Sie haben den Raum-Avatar geändert" + "%1$s hat den Raum-Avatar entfernt" + "Sie haben den Raum-Avatar entfernt" + "%1$s hat %2$s gesperrt" + "Sie haben %1$s gesperrt" "%1$s hat den Raum erstellt" - "Du hast den Raum erstellt" + "Sie haben den Raum erstellt" + "%1$s hat %2$s eingeladen" + "%1$s hat die Einladung angenommen" + "Sie haben die Einladung angenommen" + "Sie haben %1$s eingeladen" + "%1$s hat dich eingeladen" + "%1$s hat den Raum betreten" + "Sie haben den Raum betreten" + "%1$s hat angefragt beizutreten" + "%1$s hat %2$s den Beitritt erlaubt" + "%1$s hat Ihnen den Betritt erlaubt" + "Sie haben angefragt beizutreten" + "%1$s hat die Beitrittsanfrage von %2$s abgelehnt" + "Sie haben die Beitrittsanfrage von %1$s abgelehnt" + "%1$s hat Ihre Beitrittsanfrage abgelehnt" + "%1$s ist nicht mehr an einem Beitritt interessiert" + "Sie haben Ihre Beitrittsanfrage zurückgezogen" + "%1$s hat den Raum verlassen" + "Sie haben den Raum verlassen" + "%1$s hat den Raumnamen geändert in: %2$s" + "Sie haben den Raumnamen geändert in: %1$s" + "%1$s hat den Raumnamen entfernt" + "Sie haben den Raumnamen entfernt" + "%1$s hat die Einladung abgelehnt" + "Sie haben die Einladung abgelehnt" + "%1$s hat %2$s entfernt" + "Sie haben %1$s entfernt" + "%1$s hat eine Einladung an %2$s gesendet, dem Raum beizutreten" + "Sie haben eine Einladung an %1$s gesendet, dem Raum beizutreten" + "%1$s hat die Einladung an %2$s zum Betreten des Raums zurückgezogen" + "Sie haben die Einladung an %1$s zum Betreten des Raums zurückgezogen" + "%1$s hat das Thema geändert in: %2$s" + "Sie haben das Thema geändert in: %1$s" + "%1$s hat das Raumthema entfernt" + "Sie haben das Raumthema entfernt" + "%1$s hat die Sperre für %2$s aufgehoben" + "Sie haben die Sperre für %1$s aufgehoben" + "%1$s hat eine unbekannte Raumänderung vorgenommen" diff --git a/libraries/push/impl/src/main/res/values-de/translations.xml b/libraries/push/impl/src/main/res/values-de/translations.xml index 496071416d..48c14e8247 100644 --- a/libraries/push/impl/src/main/res/values-de/translations.xml +++ b/libraries/push/impl/src/main/res/values-de/translations.xml @@ -1,7 +1,52 @@ + "Anruf" + "Auf Ereignisse achten" + "Laute Benachrichtigungen" + "Stumme Benachrichtigungen" + "** Fehler beim Senden - bitte Raum öffnen" + "Beitreten" + "Ablehnen" + "Sie wurden zu einem Chat eingeladen" + "Neue Nachrichten" + "Reagiert mit %1$s" + "Als gelesen markieren" + "Sie wurden eingeladen, den Raum zu betreten" + "Ich" + "Sie sehen sich die Benachrichtigung an! Klicken Sie hier!" "%1$s: %2$s" "%1$s: %2$s %3$s" "%1$s und %2$s" + "%1$s in %2$s" + "%1$s in %2$s und %3$s" + + "%1$s: %2$d Nachricht" + "%1$s: %2$d Nachrichten" + + + "%d Mitteilung" + "%d Mitteilungen" + + + "%d Einladung" + "%d Einladungen" + + + "%d neue Nachricht" + "%d neue Nachrichten" + + + "%d ungelesene gemeldete Nachricht" + "%d ungelesene gemeldete Nachrichten" + + + "%d Raum" + "%d Räume" + + "Wählen Sie aus, wie Sie Benachrichtigungen erhalten möchten" + "Hintergrundsynchronisation" + "Google-Dienste" + "Keine gültigen Google Play-Dienste gefunden. Benachrichtigungen funktionieren möglicherweise nicht richtig." + "Benachrichtigung" "Schnelle Antwort" diff --git a/libraries/textcomposer/impl/src/main/res/values-de/translations.xml b/libraries/textcomposer/impl/src/main/res/values-de/translations.xml new file mode 100644 index 0000000000..6b75a1c9a7 --- /dev/null +++ b/libraries/textcomposer/impl/src/main/res/values-de/translations.xml @@ -0,0 +1,4 @@ + + + "Anhang hinzufügen" + diff --git a/libraries/ui-strings/src/main/res/values-cs/translations.xml b/libraries/ui-strings/src/main/res/values-cs/translations.xml index 271b614dc4..0ff43bceb7 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -195,9 +195,9 @@ "Další nastavení" "Halsové a video hovory" "Neshoda konfigurace" - "Zjednodušili jsme nastavení oznámení, abychom usnadnili hledání možností. + "Zjednodušili jsme nastavení oznámení, abychom usnadnili hledání možností. -Některá vlastní nastavení, která jste si vybrali v minulosti, se zde nezobrazují, ale jsou stále aktivní. +Některá vlastní nastavení, která jste si vybrali v minulosti, se zde nezobrazují, ale jsou stále aktivní. Pokud budete pokračovat, některá nastavení se mohou změnit." "Přímé zprávy" diff --git a/libraries/ui-strings/src/main/res/values-de/translations.xml b/libraries/ui-strings/src/main/res/values-de/translations.xml index 4028ece8ed..d1af3b9cd1 100644 --- a/libraries/ui-strings/src/main/res/values-de/translations.xml +++ b/libraries/ui-strings/src/main/res/values-de/translations.xml @@ -1,65 +1,265 @@ + "Passwort verbergen" "Nur Erwähnungen" "Stummgeschaltet" + "Umfrage" + "Umfrage beendet" + "Dateien senden" + "Passwort anzeigen" + "Benutzermenü" + "Akzeptieren" + "Zurück" "Abbrechen" + "Foto auswählen" + "Löschen" + "Schließen" + "Verifizierung abschließen" "Bestätigen" "Weiter" "Kopieren" + "Link kopieren" + "Link zur Nachricht kopieren" + "Erstellen" "Raum erstellen" + "Ablehnen" + "Deaktivieren" "Erledigt" "Bearbeiten" "Aktivieren" "Umfrage beenden" + "Passwort vergessen?" + "Weiter" "Einladen" + "Freunde einladen" + "Freunde einladen %1$s" + "Laden Sie Personen in %1$s ein" + "Einladungen" "Mehr erfahren" "Verlassen" "Raum verlassen" + "Konto verwalten" + "Geräte verwalten" "Weiter" + "Nein" "Nicht jetzt" "OK" + "Öffnen mit" "Schnelle Antwort" "Zitat" + "Reagieren" "Entfernen" - "Antwort" + "Antworten" + "Im Thread antworten" "Fehler melden" "Inhalt melden" "Erneut versuchen" "Entschlüsselung wiederholen" + "Speichern" + "Suchen" "Senden" + "Nachricht senden" + "Teilen" + "Link teilen" + "Überspringen" "Start" "Chat starten" - "Überprüfung starten" + "Verifizierung starten" + "Tippen Sie, um die Karte zu laden" + "Foto machen" "Quelle anzeigen" + "Ja" + "Über" + "Nutzungsrichtlinie" + "Erweiterte Einstellungen" + "Analysedaten" + "Audio" + "Blasen" + "Copyright" + "Raum wird erstellt…" + "Raum verlassen" "Dekodierungsfehler" + "Entwickleroptionen" "(bearbeitet)" "Bearbeitung" + "* %1$s %2$s" "Verschlüsselung aktiviert" "Fehler" "Datei" + "Datei wurde unter Downloads gespeichert" + "Nachricht weiterleiten" "GIF" "Bild" + "Als Antwort auf %1$s" + "Diese Matrix-ID kann nicht gefunden werden, daher wird die Einladung möglicherweise nicht empfangen." + "Raum verlassen" "Link in die Zwischenablage kopiert" "Laden…" "Nachricht" + "Nachrichtenlayout" "Nachricht entfernt" + "Modern" + "Stummschalten" + "Keine Ergebnisse" + "Offline" "Passwort" - "Menschen" + "Personen" "Permalink" + "Stimmen insgesamt: %1$s" + "Die Ergebnisse werden nach Ende der Umfrage angezeigt" + "Datenschutz­erklärung" + "Reaktion" "Reaktionen" + "Wird erneuert…" + "%1$s antworten" + "Einen Fehler melden" + "Bericht eingereicht" + "Rich-Text-Editor" + "Raumname" + "z.B. Ihr Projektname" + "Nach jemandem suchen" + "Suchergebnisse" + "Sicherheit" + "Wählen Sie Ihren Server aus" + "Wird gesendet…" + "Server wird nicht unterstützt" + "Server-URL" "Einstellungen" + "Geteilter Standort" + "Chat wird gestartet…" "Sticker" + "Erfolg" "Vorschläge" + "Synchronisieren" "Text" + "Hinweise von Drittanbietern" + "Thread" "Thema" + "Worum geht es in diesem Raum?" + "Entschlüsselung nicht möglich" + "Einladungen konnten nicht an einen oder mehrere Benutzer gesendet werden." + "Einladung(en) konnte(n) nicht gesendet werden" + "Stummschaltung aufheben" "Nicht unterstütztes Ereignis" "Benutzername" + "Verifizierung abgebrochen" + "Verifizierung abgeschlossen" "Video" "Warten…" + "Bestätigung" + "Warnung" + "Aktivitäten" + "Flaggen" + "Essen & Trinken" + "Tiere & Natur" + "Objekte" + "Smileys & Menschen" + "Reisen & Orte" + "Symbole" + "Fehler beim Erstellen des Permalinks" + "%1$s konnte die Karte nicht laden. Bitte versuchen Sie es später erneut." + "Fehler beim Laden der Nachrichten" + "%1$s konnte nicht auf Ihren Standort zugreifen. Bitte versuchen Sie es später erneut." + "%1$s hat keine Erlaubnis, auf Ihren Standort zuzugreifen. Sie können den Zugriff in den Einstellungen aktivieren." + "%1$s hat keine Erlaubnis, auf Ihren Standort zuzugreifen. Aktivieren Sie unten den Zugriff." + "Einige Nachrichten wurden nicht gesendet" + "Entschuldigung, es ist ein Fehler aufgetreten" + "🔐️ Begleite mich auf %1$s" + "Hey, sprechen Sie mit mir auf %1$s: %2$s" + "Sind Sie sicher, dass Sie diesen Raum verlassen möchten? Sie sind die einzige Person hier. Wenn Sie austreten, kann in Zukunft niemand mehr eintreten, auch Sie nicht." + "Sind Sie sicher, dass Sie diesen Raum verlassen möchten? Dieser Raum ist nicht öffentlich und Sie können ihm ohne Einladung nicht erneut beitreten." + "Sind Sie sicher, dass Sie den Raum verlassen wollen?" + "%1$s Android" + + "%1$d Mitglied" + "%1$d Mitglieder" + + + "%d Stimme" + "%d Stimmen" + + "Schütteln Sie heftig zum Melden von Fehlern" + "Sie scheinen das Telefon aus Frustration zu schütteln. Möchten Sie den Bildschirm für den Fehlerbericht öffnen?" + "Diese Meldung wird an den Administrator Ihres Homeservers weitergeleitet. Dieser kann keine verschlüsselten Nachrichten lesen." + "Grund für die Meldung dieses Inhalts" + "Aufzählungsliste umschalten" "Formatierungsoptionen schließen" + "Codeblock umschalten" + "Nachricht…" "Einen Link erstellen" "Link bearbeiten" + "Fettes Format anwenden" + "Kursives Format anwenden" + "Durchgestrichenes Format anwenden" + "Unterstreichungsformat anwenden" + "Vollbildmodus umschalten" + "Einrückung" + "Inline-Codeformat anwenden" + "Link setzen" + "Nummerierte Liste umschalten" + "Optionen zum Verfassen öffnen" + "Vorschlag umschalten" + "Link entfernen" + "Ohne Einrückung" "Link" + "Dies ist der Anfang von %1$s." + "Dies ist der Anfang dieses Gesprächs." + "Neu" + "Analysedaten teilen" + "Anzeigename" + "Ihr Anzeigename" + "Ein unbekannter Fehler ist aufgetreten und die Informationen konnten nicht geändert werden." + "Profil kann nicht aktualisiert werden" + "Profil bearbeiten" + "Profil wird aktualisiert…" + "Medienauswahl fehlgeschlagen, bitte versuchen Sie es erneut." + "Fehler beim Verarbeiten des hochgeladenen Mediums. Bitte versuchen Sie es erneut." + "Das Hochladen der Medien ist fehlgeschlagen. Bitte versuchen Sie es erneut." + "Zusätzliche Einstellungen" + "Audio- und Videoanrufe" + "Konfiguration stimmt nicht überein" + "Wir haben die Einstellungen für Benachrichtigungen vereinfacht, damit die Optionen leichter zu finden sind. + +Einige benutzerdefinierte Einstellungen, die Sie in der Vergangenheit gewählt haben, werden hier nicht angezeigt, sind aber immer noch aktiv. + +Wenn Sie fortfahren, können sich einige Ihrer Einstellungen ändern." + "Direkte Chats" + "Benutzerdefinierte Einstellung pro Chat" + "Beim Aktualisieren der Benachrichtigungseinstellungen ist ein Fehler aufgetreten." + "Alle Nachrichten" + "Nur Erwähnungen und Schlüsselwörter" + "Bei direkten Chats, benachrichtigen Sie mich bei" + "Bei Gruppenchats benachrichtigen Sie mich bei" + "Benachrichtigungen auf diesem Gerät aktivieren" + "Die Konfiguration wurde nicht korrigiert, bitte versuchen Sie es erneut." + "Gruppenchats" + "Erwähnungen" + "Alle" + "Erwähnungen" + "Benachrichtige mich bei" + "Benachrichtige mich bei @room" + "Um Benachrichtigungen zu erhalten, ändern Sie bitte Ihre %1$s." + "Systemeinstellungen" + "Systembenachrichtigungen deaktiviert" + "Benachrichtigungen" + "Prüfen Sie, ob Sie alle aktuellen und zukünftigen Nachrichten dieses Benutzers ausblenden möchten" + "Konto und Geräte" + "Standort teilen" + "Meinen Standort teilen" + "In Apple Maps öffnen" + "In Google Maps öffnen" + "In OpenStreetMap öffnen" + "Diesen Standort teilen" + "Standort" + "Rageshake" + "Erkennungsschwelle" + "Allgemein" + "Version: %1$s (%2$s)" + "en" "Fehler" + "Erfolg" + "Teilen Sie anonyme Nutzungsdaten, um uns bei der Identifizierung von Problemen zu helfen." + "Sie können alle unsere Bedingungen lesen%1$s." "hier" + "Benutzer sperren" diff --git a/libraries/ui-strings/src/main/res/values-fr/translations.xml b/libraries/ui-strings/src/main/res/values-fr/translations.xml index 4978cdb68c..f6dc4f5ac0 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -3,6 +3,8 @@ "Masquer le mot de passe" "Mentions uniquement" "En sourdine" + "Sondage" + "Sondage terminé" "Envoyer des fichiers" "Afficher le mot de passe" "Menu utilisateur" @@ -204,6 +206,12 @@ "Ceci est le début de cette conversation." "Nouveau" "Partagez des données de statistiques d\'utilisation" + "Nom d\'affichage" + "Votre nom d\'affichage" + "Une erreur inconnue s\'est produite et les informations n\'ont pas pu être modifiées." + "Impossible de mettre à jour le profil" + "Modifier le profil" + "Mise à jour du profil…" "Échec de la sélection du média, veuillez réessayer." "Échec du traitement des médias à télécharger, veuillez réessayer." "Échec du téléchargement du média, veuillez réessayer." diff --git a/libraries/ui-strings/src/main/res/values-ru/translations.xml b/libraries/ui-strings/src/main/res/values-ru/translations.xml index d37e28dc7a..798515fa6a 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -194,9 +194,9 @@ "Дополнительные параметры" "Аудио и видео звонки" "Несоответствие конфигурации" - "Мы упростили настройки уведомлений, чтобы упростить поиск опций. + "Мы упростили настройки уведомлений, чтобы упростить поиск опций. -Некоторые пользовательские настройки, выбранные вами ранее, не отображаются в данном меню, но они все еще активны. +Некоторые пользовательские настройки, выбранные вами ранее, не отображаются в данном меню, но они все еще активны. Если вы продолжите, некоторые настройки могут быть изменены." "Прямые чаты" diff --git a/libraries/ui-strings/src/main/res/values-sk/translations.xml b/libraries/ui-strings/src/main/res/values-sk/translations.xml index 162ca8f9d8..53fc0a1045 100644 --- a/libraries/ui-strings/src/main/res/values-sk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml @@ -3,6 +3,8 @@ "Skryť heslo" "Iba zmienky" "Stlmené" + "Anketa" + "Ukončená anketa" "Odoslať súbory" "Zobraziť heslo" "Používateľské menu" @@ -36,6 +38,8 @@ "Zistiť viac" "Opustiť" "Opustiť miestnosť" + "Spravovať účet" + "Spravovať zariadenia" "Ďalej" "Nie" "Teraz nie" @@ -46,6 +50,7 @@ "Reagovať" "Odstrániť" "Odpovedať" + "Odpovedať vo vlákne" "Nahlásiť chybu" "Nahlásiť obsah" "Skúsiť znova" @@ -66,6 +71,7 @@ "Áno" "O aplikácii" "Zásady prijateľného používania" + "Pokročilé nastavenia" "Analytika" "Zvuk" "Bubliny" @@ -84,6 +90,7 @@ "Preposlať správu" "GIF" "Obrázok" + "V odpovedi na %1$s" "Toto Matrix ID sa nedá nájsť, takže pozvánka nemusí byť prijatá." "Opustenie miestnosti" "Odkaz bol skopírovaný do schránky" @@ -101,11 +108,13 @@ "Celkový počet hlasov: %1$s" "Výsledky sa zobrazia po ukončení ankety" "Zásady ochrany osobných údajov" + "Reakcia" "Reakcie" "Obnovuje sa…" "Odpoveď na %1$s" "Nahlásiť chybu" "Nahlásenie bolo odoslané" + "Rozšírený textový editor" "Názov miestnosti" "napr. názov vášho projektu" "Vyhľadať niekoho" @@ -124,6 +133,7 @@ "Synchronizuje sa" "Text" "Oznámenia tretích strán" + "Vlákno" "Téma" "O čom je táto miestnosť?" "Nie je možné dešifrovať" @@ -191,12 +201,19 @@ "Prepnúť číslovaný zoznam" "Otvoriť možnosti písania" "Prepnúť citáciu" + "Odstrániť odkaz" "Zrušiť odsadenie" "Odkaz" "Toto je začiatok %1$s." "Toto je začiatok tejto konverzácie." "Nové" "Zdieľať analytické údaje" + "Zobrazované meno" + "Vaše zobrazované meno" + "Vyskytla sa neznáma chyba a informácie nebolo možné zmeniť." + "Nepodarilo sa aktualizovať profil" + "Upraviť profil" + "Aktualizácia profilu…" "Nepodarilo sa vybrať médium, skúste to prosím znova." "Nepodarilo sa spracovať médiá na odoslanie, skúste to prosím znova." "Nepodarilo sa nahrať médiá, skúste to prosím znova." diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 7c1df85553..6509f3787e 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -210,6 +210,7 @@ "Your display name" "An unknown error was encountered and the information couldn\'t be changed." "Unable to update profile" + "Edit profile" "Updating profile…" "Failed selecting media, please try again." "Failed processing media to upload, please try again." From bc68d47d1f3ccec82eec59ed43c692d92465dbae Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 18 Sep 2023 10:29:52 +0200 Subject: [PATCH 214/234] Update rust-sdk to 0.1.54 --- gradle/libs.versions.toml | 2 +- .../libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt | 3 +++ .../matrix/impl/timeline/MatrixTimelineDiffProcessor.kt | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b164dfbb95..98e08f79f4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -150,7 +150,7 @@ jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" } appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = { module = "app.cash.molecule:molecule-runtime", version.ref = "molecule" } timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.53" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.54" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "com.squareup.sqldelight:android-driver", version.ref = "sqldelight" } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt index 4bade9cc81..1ab5b93e69 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt @@ -99,6 +99,9 @@ class RoomSummaryListProcessor( RoomListEntriesUpdate.Clear -> { clear() } + is RoomListEntriesUpdate.Truncate -> { + subList(update.length.toInt(), size).clear() + } } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt index fd880e7fe3..38c4ef8fb6 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt @@ -98,6 +98,9 @@ internal class MatrixTimelineDiffProcessor( TimelineChange.CLEAR -> { clear() } + TimelineChange.TRUNCATE -> { + // Not supported + } } } From e73afad96cbc9416c30599896454e3185f0f6320 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 18 Sep 2023 10:56:29 +0200 Subject: [PATCH 215/234] RoomSummary: RoomListEntry.Invalidated should not build empty room summary --- .../libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt index 1ab5b93e69..321a17d809 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt @@ -110,7 +110,7 @@ class RoomSummaryListProcessor( RoomListEntry.Empty -> buildEmptyRoomSummary() is RoomListEntry.Filled -> buildAndCacheRoomSummaryForIdentifier(entry.roomId) is RoomListEntry.Invalidated -> { - roomSummariesByIdentifier[entry.roomId] ?: buildEmptyRoomSummary() + roomSummariesByIdentifier[entry.roomId] ?: buildAndCacheRoomSummaryForIdentifier(entry.roomId) } } } From 5d15b1ab9142885c383a233dda4b722e278ee4a9 Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Mon, 18 Sep 2023 12:07:26 +0200 Subject: [PATCH 216/234] Enable Android 13/14 predictive back gesture https://developer.android.com/guide/navigation/custom-back/predictive-back-gesture --- app/src/main/AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7d1c45b1b1..2b77c7076e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -24,6 +24,7 @@ android:name=".ElementXApplication" android:allowBackup="false" android:dataExtractionRules="@xml/data_extraction_rules" + android:enableOnBackInvokedCallback="true" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" From a719f1df303f241f1b6c9d3bc16ce776b56ad96c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 18 Sep 2023 11:44:55 +0200 Subject: [PATCH 217/234] New app icon (imported with 64% of scale) --- app/src/main/ic_launcher-playstore.png | Bin 48308 -> 265836 bytes .../io/element/android/x/icon/IconPreview.kt | 27 ++++++++++++++++++ .../res/mipmap-anydpi-v26/ic_launcher.xml | 18 +++++++++++- .../mipmap-anydpi-v26/ic_launcher_round.xml | 18 +++++++++++- app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 4299 -> 0 bytes app/src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 0 -> 3996 bytes .../mipmap-hdpi/ic_launcher_background.png | Bin 12107 -> 0 bytes .../mipmap-hdpi/ic_launcher_background.webp | Bin 0 -> 10400 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 3987 -> 0 bytes .../mipmap-hdpi/ic_launcher_foreground.webp | Bin 0 -> 8014 bytes .../mipmap-hdpi/ic_launcher_monochrome.webp | Bin 0 -> 1426 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 5832 -> 0 bytes .../res/mipmap-hdpi/ic_launcher_round.webp | Bin 0 -> 5628 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 2894 -> 0 bytes app/src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 0 -> 2624 bytes .../mipmap-mdpi/ic_launcher_background.png | Bin 7174 -> 0 bytes .../mipmap-mdpi/ic_launcher_background.webp | Bin 0 -> 4836 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 2560 -> 0 bytes .../mipmap-mdpi/ic_launcher_foreground.webp | Bin 0 -> 4724 bytes .../mipmap-mdpi/ic_launcher_monochrome.webp | Bin 0 -> 946 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 3553 -> 0 bytes .../res/mipmap-mdpi/ic_launcher_round.webp | Bin 0 -> 3316 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 5955 -> 0 bytes .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 0 -> 6112 bytes .../mipmap-xhdpi/ic_launcher_background.png | Bin 17519 -> 0 bytes .../mipmap-xhdpi/ic_launcher_background.webp | Bin 0 -> 19754 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 5517 -> 0 bytes .../mipmap-xhdpi/ic_launcher_foreground.webp | Bin 0 -> 12522 bytes .../mipmap-xhdpi/ic_launcher_monochrome.webp | Bin 0 -> 1950 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 8186 -> 0 bytes .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 0 -> 8248 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 9627 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 0 -> 10394 bytes .../mipmap-xxhdpi/ic_launcher_background.png | Bin 29068 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_background.webp | Bin 0 -> 46592 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 9097 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_foreground.webp | Bin 0 -> 25188 bytes .../mipmap-xxhdpi/ic_launcher_monochrome.webp | Bin 0 -> 3340 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 13269 -> 0 bytes .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 0 -> 14182 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 13691 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 0 -> 15880 bytes .../mipmap-xxxhdpi/ic_launcher_background.png | Bin 43272 -> 0 bytes .../ic_launcher_background.webp | Bin 0 -> 86550 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 13561 -> 0 bytes .../ic_launcher_foreground.webp | Bin 0 -> 44302 bytes .../ic_launcher_monochrome.webp | Bin 0 -> 4664 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 19207 -> 0 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 0 -> 22000 bytes 49 files changed, 61 insertions(+), 2 deletions(-) delete mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.webp delete mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_background.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_background.webp delete mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.webp delete mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.webp delete mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.webp delete mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_background.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_background.webp delete mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.webp delete mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.webp delete mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.webp delete mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_background.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_background.webp delete mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.webp delete mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp delete mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.webp delete mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_background.webp delete mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.webp delete mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp delete mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp delete mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.webp delete mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.webp delete mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png index a5bcf735dc7d1846e71f2270f5d826376270b077..e94a69a3650227f40ad1ad0e38dacbeb3940da66 100644 GIT binary patch literal 265836 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Ν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

uZ6EVr&gKPOZMj;>r_vz*g4 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 mBzhAGkeESISp33k7hTj{;I{ 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à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

`8EYFyd~mHT+}w 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�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 diff --git a/app/src/main/kotlin/io/element/android/x/icon/IconPreview.kt b/app/src/main/kotlin/io/element/android/x/icon/IconPreview.kt index 52e3af1aab..2effcd9f4c 100644 --- a/app/src/main/kotlin/io/element/android/x/icon/IconPreview.kt +++ b/app/src/main/kotlin/io/element/android/x/icon/IconPreview.kt @@ -17,13 +17,20 @@ package io.element.android.x.icon import androidx.compose.foundation.Image +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp import io.element.android.x.R @Preview @@ -47,3 +54,23 @@ internal fun RoundIconPreview( Image(painter = painterResource(id = R.mipmap.ic_launcher_foreground), contentDescription = null) } } + +@Preview +@Composable +internal fun MonochromeIconPreview( + modifier: Modifier = Modifier, +) { + Box( + modifier = modifier + .size(108.dp) + .background(Color(0xFF2F3133)) + .clip(shape = RoundedCornerShape(32.dp)), + contentAlignment = Alignment.Center + ) { + Image( + painter = painterResource(id = R.mipmap.ic_launcher_monochrome), + colorFilter = ColorFilter.tint(Color(0xFFC3E0F6)), + contentDescription = null + ) + } +} diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index 82724deb96..e468c16c63 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,6 +1,22 @@ + + - + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml index 82724deb96..e468c16c63 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -1,6 +1,22 @@ + + - + diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 4bbfe30ed254d22a7166949070c7c87c594dfff4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4299 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 diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..f08c6730559eefbd33436161376aaf6e549a9c2d GIT binary patch literal 3996 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 CU}lj3 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_background.png b/app/src/main/res/mipmap-hdpi/ic_launcher_background.png deleted file mode 100644 index 3510298288ed5f75820ad66a5891062bd3dddc90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12107 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 diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..fff7bbbfd7368fc1ed127b0ef14e1056f3f40f74 GIT binary patch literal 8014 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 QMQhA#nkpaF{~z8R0AM#|eE_5Yv02dsGF z>7iY_wmnV6tw8HTzqVmsF9Tf~p?Mpw>8*%hGE$9{tSXY!TL&GZ_2^+;^osgo-%Rw_ zoEcM_wZ=pr8dEdXWk0DwpH{!J71g$xp>Nr&wo1C$guV_xQqai~^m*}X{&>? z9h^TLS-|M9*;c_TM%FC_KvptL$DSx4vl_`Sxc~^R&7r~?OMX+4ev0h|;Bhe(u905M z@Bo)>d3O3rAO&12r!r%*n~7fMH2u2g1ZN6}@SEhWn4TeGkLleUU@IdsJIXDJ^rgcl zMgRL&fPDWJ2YU<=My00LQB_a776ksR!C~zk4q_%zeNbjeq-{LZ22xLOz{d9+OeMmk z%pxTD|7L*ODNZ1UMI@$IQPiFR*PlWu*jo;k5moE*y2c24wSdb{ZEuai)I&9H zI}u)!*9H{t`2d_VPOJ!*6=tK$oQK?9stxj*CuUv%M}1Efif`h&FX4&}p?T5@gv7Rj zFfOZv&`6DIUx&n{768}-Ft;;zKqMinr$R3Q0JI2_&-e=3PKK4AxL+bq zWwlMDvKx0bj}H4y9+r(b1o()^AzAGb83+6-^n4ws4HVg>h}~S9M$dAta_>z=91?lM zwJ^kfhhI-%bfY!y7>aI_)l-qH+$qE+3&5U9_Rj?X0Bw}eQ&}ZMI&nJ?_W}SsWJGK) z@bNsMgskEs54lZiHZ*gjn^@cHkHokK*${+8c<`&zC0f(t8{rmgs3co z%bK4e;U;VQ5+sd)#FIq0frCp8P8(8ve%c?2lQIj|6IHzDprz5Fu!zEwkoZ1#IMkff{5lpj1{REXsp zGF==eV<$m@b~7Df#grSL96l~2n`Ns2+BSKBh?T>qY}~T9FH(owf*NlYd*X5NBT(hZ zymZNb4eH#=(t{lYmF{Qh!1jY$59a$XZ!4(wb+O-yPl9?Mh5glZ6I9%G7V{5lZVPI* zPgeV-=7|l;&YWua!CYg3(ql7Cugq^TQ2v!@ofq}dj?gO9laVS$QXNSKq4lU=+b}O= gxG{Ro+i*>XR%gJ9C!TKGwd>H+MBEC%U;qF4JK9H~_y7O^ literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 9dd38fd07302c34ffd6c83323d76cadfaf4835f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5832 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 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..9965e382c1fe1980f0a9110db4bea8e4678fd43d GIT binary patch literal 2624 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_background.png b/app/src/main/res/mipmap-mdpi/ic_launcher_background.png deleted file mode 100644 index d3ce4fb2272e34fee0fd6440e4d8ed88b3288ed6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7174 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 IM6N<$f{}r!{r~^~ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_background.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_background.webp new file mode 100644 index 0000000000000000000000000000000000000000..27d9d1db19f2da70780ef99ddae8213ad6d34bd8 GIT binary patch literal 4836 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 KA#fWzH1Yw8p&!Tq literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png deleted file mode 100644 index 2d4bab337cec2e89d85409f9173f10da0b439364..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2560 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 N%#1CKstkXL`8&RL_s#$S diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..f248938976179929fa816dae36a44bb11c4ff95b GIT binary patch literal 4724 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 U?JVH?V(rH1&TBVn{rT_z05u`l{r~^~ literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 42a631def34eda3fca57942c854f358fdf04e7b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3553 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 0adb2f3b52db1ced12a1ae9a632e091e53bc0bba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5955 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Ƹ??Klk-5x-J{~`D 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 J-$krb!vRUVJc|GT literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png deleted file mode 100644 index 33fd9ab6812d2757f645facd77c2cb4b4dfc74ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5517 zcmdT|c{J4T+qM%UN`ykFu?&i#B1VKPW0b5TyT+bmCd)7-Th=KP*_Rkg_MNfs$uhRF zhLAOTG=<@f-}!yt_s{p7-#_nr&S&}KdG2%W`?{XzexB z_dj;>GBN!9hF+0er=sFC&{9(|@UmD>W_iX(^6Su@unY4ee^G?eis_1893e)hXmv4chhRn`SGU2x?_PYTClc&DPQ<;~jc- zE~c>pJC7;@B^zD4N@2vRXt|N&4ZqDPk6)X|*gp(dq$e4JZpctV_l=hcYcRdO@}E2g zpDz^DstJV$LQAQG>6(EiPoiUZ{OR*$y1qm-(HOc1CF5X+ zvav5jZab3c3u;P`bCQ%}h645dC6+C4f#d!X)+e?7rWjd6B(d)OhVfR=N%gtBesW<% zftT)zcQzQz#Wsd~OpT)p2rWtd3I%xa3zhAViHgNGaM#OL>D5?8-*XgZnxenhJvv9w zH!pwYVlFX{naq2@aaI!vafxMuk)AqrG!M96PO=y>CRt|us>hbKC~gh z_e&VUdBufq#JDmZUS+ZEL($wv5rt2{j{mp}YRhq%3)n`^S@10zi6nsxYg9d+XW+D_ zv1nzdS;bSj#OTChpVB}wTWe=ThAW+nCDtL&Ql|1sPFTZyJ7TW)R>)6=P)CI+JQ$F2 z^=(T(;%+(N7m(3#$aZ0y+O|kXYn1JMq_P(mTsJ-;1 zbNsn(z|)~P-E%tE8u5vb?)bj$(p@jyNFJo?4|GB1S&Je)?wU^*Q#$QL zI+p*ux#1#n#w0G+`B~ARwOJ-D5{nN;Nb@_`Tk73Su=v9Cnp*9Fk^^ckssHB%X`y5-ZP{K?ls}G#jN;3An))_* zbG4%;bgQnz0U^WoPIf-?yd_CRVUa^>;8m1&j6{N(4DQdHr1)k;`s13gygMIz+dn@k zWq&6F9!nP_KgQ>IAX}>&)0PIF3&nKVsCD!#ueAyc_&aW&d6!cRmyS>&X1A*Wad>uC z@L%SJRkRKQMGV@9v`~&O>Ik>Nu;V*q@-OlD(0(vt;Im!mm|MpWX((il`?8wGll|2M z)79R>n-zk;gnSSWJNh<$$%5Fnn(^_7kyzQb*9VTv)~cSeCZV`d}p6_Mx!>B!q@k z%CnlY?OdtFfmzP6in$6fK0NBv6%k^RQ7-KyiO+c{M+b?E-WW=Xo)o^pGP4Se4X;Na zJvy{%h)cm&A5Rf{f<1#i1%fFQadffyRNd+|=LGCNx~I4<*TD@4YJ!6U*mQU;!Sg>s zmIi+G2_g7rs+I%%Q`?pM8Nr<%zufNnZ6kNOcYVzQE8_F%K)v4vyeJ=DMC#pE9pwz? zeX&~$Rch}Mb*}Q+(~|czN}I7(Pk^9yZ7@uH8_dg$Q{`}Tizi$E8OtDh z988SMcQToo9KKKS)G3z1#n>eCd*x~)|)eP1T=qJW5Wecgs-d zN53Ay*IkDAY5Td8c9SSUVt$1$wTO-MCLg+-ioXE3CWh%7!x;pbTO_d9TQL3ki4S>& z)AQw!Kc(wxRRd@lxApS}7TVT^z`S;Ga0zsWpZB%sDoz(ia!yWk^xMIgpg#<#tawdO zjNxa4OT=*`8!V4ogY}L%FV!R7WUWtFDR2F$@*VZPsm0M@N`cs3wCx zhwDBP_K6;b*+mX)<&yfHyGn5B)hel*^03OYODS9-Dr;SKR3^4re>YUSwBohZ(lt7_ zug^GY_Y zdQ|TBi;mvhZ3$2Ye?G*G^wDqmtVn}lH`9DLRzNgQc`JsJSO?;p5+IoqqLUSd?%xvV zxRmT_5tKO@obla*OH$hEK9IJB8605#GhG?)ThTyst@8S#WFijW=6!%<2SGJ)p5x!VfaN?9@FDyt+5?M4%=m7E2vrFQXZe7>Ylyyd$=D7u6cJ zRA`I2%(_>*A{a83d(8BH&|ROU zeK7Q8`hqRhd_3U%JObGa%b@4WWFLv_BsfI*HT&_5Of=oy332+pHgfD@uF9sQMvRBJ zbx{*^HA`n9Jzl_owrZa2V4ae5TAH$H9cu7=Bc;!+o`)N$tipnAyfBCM-dKl}>^c^a ze}-II^46W^-MwAeza#zX1b~NNuj0Yn+4Ey$SGY-e6+2ii%hN?v0VJ$xj!#Ss+Gxd0 zS2~O>J$%>DINNJIkGc;d=aft)8knDbD zzke5_4fK_4?FJz-)Cl%kI@d=9_u8 z!j#YK+@mZz%n>r_3m0TGz&x@Vy~{LwIxN-jSkJvZyJ%Pj_ z*??9r$IV*#$++_grCv~aVzTwCKYx^ZSDj=op6k^*ga|YW_I5ep&8W&8<%1&rRWsr4 zOeX!~0%l6Z{n6XNuY;~or}DzP#(+Nd?MtKk5l0O{Dc25&z2ix)pN1d9VS=`&FheC4 z`p9D6!uC4DQ@4P#i?l!58OH_LgE3!sxGJRS2rG@1z%eKu1n|8i*VC zZSj&xhaPL6L6N2dKbKE1fa7g|MUid&8YDbhKtwAl|h>mNl!z%Y!=H4%8@w*B3~$eEW@ zub&hMBJ1@wy*^BEcQjUIc~s^ZiE{jtKY$SENNp^PG+m-i7Ffb?8A~>XTpwsZ{u8rU zyWLodh*cQ)aE#fhpXQkUZb>jFeW}Jd`~w*bxSf|oQ~2O_I96rU_Yh{8+ec9Z5*KSN z(WsZsqGhW;&*)KKKxcGEM6ov1N0G!+UI=9VvskPQP2o*3%=G~nAM{c%8Hsex@iW>w;2gz2n%D zz)VRr#*V26*%{&K69H$jwb}T!pl?u8K-WMmgSrxrivo<=jPK<@%%KYxGwhOEMH-*iNQrP_q zNc9$_GlW$lB<@X)O*(I##T&?=yIc3`*)AnUMG+(1*+9kpM}GOYYA3>sqz<=pwoRs` z-=F#SihY{Jb=|kR(mi^AgkU^;YqWl?zRCZHU-i1VV6oB^(82l&PqJj~o`Ao8+;~ZI z?ce}~E{C<;7ht7`Q?dC97*QvSEhprSEx2YlqNY4dR zsIR4F{Ex1PQLajJzTPt-I?Ne$QN^mpnP8sVa#S?TN%K=!dE)nb0%{MiH#GA87F}`C zl1U0R&C4zGqdLduebTRuB$5y9;Sh!!DP32jpCXDgGD5gsa3>J5;}PC(rjH;fbWnKs zoSzM7myX~Zux;s{^xr;P#d$u~5kxnlDN%LjaD%no z($Ii8CwiQA-Fs8eIW6*KbrYX@cPCW`nCGfdoV(0M8HC=#!x}%WlpQtb!sZ{(zYIv9 zT;ND}kC%E5XW9iG`7DWV%1ir1@H#O|Uc6`Wt}Cs$1*#bHJ6g{_VezHg%ci1|XdgC!PYs#K(pU=6|+(U}BAcz7R?XO)l?mWw)3LySTzh!!q0- z{~OctZ8u%WS$f|ebd9ho9enW@6*)~o(vhDAB*SyzMO-t;ZfFAxp%(}%hQbB=wfrw8 zTugi%ejt~h_fS0Ue8r+>2%!j-UUCrv5S2Ey5H!1#FU`?SNc8~h0Wo#%(YNL^*uBJB zi8r&urR1NHqC=f#(UZQ}F0*IsB%b1w#tJbd_+~S=j1JmPe2z#g?1)v8Ex-iVb)~oy zT6x4~S<)!@m=Ku_z>Z{Vp#DA&TIS?w@Y+fO=aZ_Zk|62KFfbGepPXWAbup4bngX)iM+9TS5!%npe!G^ zdH_w&{X^K#Jo(NWpP)O8yLD!-W8(8KfO@U^AB9+X!$eiNI>BIx5$iJ2CH+9& zr$Mr10&4WS9&Gk zaxQ$%YQ-s^4J-B_h%3Jtz%EgGkIYe8Y%?smdkBBC7caqh@K^JxNW>fl** zkJRg(@*kHZg--Qnetfew(75z5O1=8I|7XM?Rx^>OzTXUC^+E4*pYeL-+V-*b8zfNd z-7WCg_I8xsSReRWg78@S?EMoREYZ`(RsBJJ<@=AQ_J9Go3yQ=@6JuXN6T2M=-=3br zW2%&XlJ%Vh4%I@1+{D0RzI2uE`rmL}=X!dq#QSsJqsz`tYoy+IK9u#)E%HEBElW9u z_QZ?u;Oc3?W>1Omv80IP`NQt;c>!*uo0~KD;qI#h_FSGfEGnM@We+Eqch6meSE%_`c>ZJ%2E_()Nh(eCoE4+3~^dkCgkTsc@zb(;F|NFDb&5AB=xxh27S(fWCG*OXU^poe5%1WJ{l}=#KBV$m=1={)<9Y#A#dejh`_ zY`tQ%(@q2AXp4;Cw`V83fZlmH*b&DFQz)JTyZS}O&^Sq+Fju#B=6FQ8b+Zno#s%DH z$uljHEF0&lI4%AElY#cXbopRB(pH*ROVvMT{zq0Mlj@&CWwMlYNb1+hg}*i{m6ke8 Ktx(nK^?w1_)_y<$ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..b4090e12b5aa21bd7bbc6d546ac8186f274bed2e GIT binary patch literal 12522 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 05f718cf3b5c83ac47c45ac07b41bca2f4e577a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8186 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 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..0537ce0a8b301605f74541c18b52bdc3cab27926 GIT binary patch literal 8248 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 6dd6aa3ee6bcb1d515b9597797162727298447e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9627 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 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..60ada6a758257238540c44857c7a178493f54e6a GIT binary patch literal 10394 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 E1xd}whyVZp literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png deleted file mode 100644 index 1a6c540c520224f541ee5ca3b6964ac33537e511..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29068 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

GA2@yrOJA=j2|%La6;(4CV73<~(jO9kGCG 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 XtN3$912~w^`8-zOr#RFOHDt8_j*wy` literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png deleted file mode 100644 index 7c4cf9729ba78368b6dfd271edd78762f8120c3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9097 zcmeHt_dgrl+kdyB)ZU}^Dyn7?ZZp&<)uNQ%s8vz5g@o2#p>|8n*sYO@8KbrL9wA0W z%_P*`e8cB^Klk$oJkM`WUa$O;SFUrebFFh-@Aru?&<9eGv5;N4a)m-$Oa1AUD_7Mo zzPE1?e|fbAY`=1a$3Rf8 zu)CA-Z*UV;-g6Q!;U(yp1)(A>%rAFbx)z4O7T9AT(X8uk6RVHF z*pG$xKmp^_C5!iJ1)N<#z7Os6;_)=8x;C6Yy8`Ip}Va1f#?z11j_X}VW zWMGGXET!;mm8OZvLYwF6Uk+TNfBz!aPY3O_IeTSgT}01SgH&NP+~79wHs(fd-r59%PCbxTaF)F@Q@Y3GWR!;!%-o67l5Dt8ia&_!Y_(%Li} zKTFE&CqMNMTEeex=j0lwu-iaKtNbU#r4JUQau|%r0D+f()zQH7)Yp_Pr(0D5=XvTV zoV<9MIo~sigD+ETQKiTxU5_@A;@srp3d7F$sYZ9fC!0>vi-a4$j(pf+vFx|fCoyvt zaWm#)tbVsZ$%K-P>bKZW?jQfNe0T7c!^HxgLF2QUgah4JtU8_elDcq@I8Bp?)}{44xl*N?9OR5kfGXUPoRvGL;d9K8 z+ZQKZ%FDr;^1Seu-nb*t^q^+G-$W{Y^Xuv{O_S=o%Z$h|#eZ@bu1jW|wu|LfzacI& zvLB*9bXnK&(Sx5m zk`@`+{XYcShrYQ5b*WsBnSOWULWTCB`l>>k{!PJ$!EdZO?CZAaJ`iI&M9B)d^@0C5 zpPoT=ro0bfI)o*ILVL)(n~8;h)AbwIE#s^e1_IKEa$G5_zR{g(HdtaD)vABeJ^1&r zm{PN?KwdZ6(dfKOUpuLSHX#BTK-=sPAr~zQg7`&si~l znjLx2aL+N&^thP}*q+_b{`ieC!t;?|sXsL<(o6n$?0W>BRr=gIvyf%YE0r%M$%`EZ zkE?n^+jLAt>I_{LP9(*de3px1?71I%?J2(l-NAMqt!c}LhWo6?3R9EVWM@!oJ{Vt> zw^74hPB$%_Jz0YA%?`O2B2>-F% zL82}*KV47-2=QJ>@~%#D9yH_D5St#qKYvvS)olyt{$!0o)_rNjLEUG3!dT0&lF@1SM93dVvcZ_QQm}xPG*7I!>$jm$Y;`xCw^+av ze9zV!KMcp-I}2$A&o$){CG+`}Xt~W4H5qyV#ocs)Z0%20=5w-?>Bk}rk#3tkwj1B| z&(6tK?=>ZrzM1YUP1_e1(R;IPS0^gpRwtuw{kcSsW%ysOvtWTDMq(eU2m_KD@Q z9`?4w4@%3~(n&|r3<-A9l_Ut5gD~B0`jc!eQ(_%RF=iqo(QC{ohgPD!>F>Z8I-Jet z`)%n07;nO7-eCi%G2!{DhI5Cx&}RK__fb;B+N?;Xwt9e%wnyhEHaPa*n#p=HR~cae zI1WM1X*86NhrBjnBj6O~kWbL_aJ5RzaFlV;OC={dR#auOvy+o8Aw2||@1yRF)8Csp zEXzApiq!CHmC2;SM1~^EHXtMNR-x%~nX+fMVgm>HkN9ZuPVOD$X({z>{^kmwPX{7} z@Nso-WZXs|cCz1WIPor4q6Fu4XP3rr7!>AIcP+7P4w&umAU;T(3KMOIEZtBYl(iz3 z<`ZLZVfOrr0sjhkp=kgdH)C|HsMF|K%q7O$hu8` zsP{-+CIGA39B(9yGme4rPmF74Xf0q$5WDFq`OH6~M*hhEWW<_vI5>INLd%T5x4gs; zz@o&hHuyNvX}O_!e0_#*&-=yXoa;vmqiwe-&!mW4a1%OID%%#y81F?YiB}O=E&mY2 zBv82oN6I^!rtO6b>eHA^8@~k3qPw`nc*ym}O-a#ox-$ z0lnKl#6N7;)r?H%jpP-;G?S)8FmDFJz5LaZYy?#|%6?eDuc>)^pcx_L=7??bsz} zpk`3Rc0FcZHSjtJ97@qP&?h67p)?GY5e#~}y2_mIBYHE3Cmy*z3UYb?UBd`W@#06j z>|V9V%xyZXe7G~Ej|(I3Kun@=Gl!6nEyyVrIglKITQ;e2%B#=_=n^qcu61W`bGoSn z+SYpmw8lLBB(qCkbfz(WIH{N-yJq1CQ+)3_grvqx&pHmWHL9{&G(8|}+XlW3SgogL zM%`UE*@d~=I2NCp4+N}M9i?toF~8 zelBUv$}5-q7N^41XJcBc@*X&^VZ?oTzY#CD7KEj)%kPUh{Wsq3 zMRaGltUVr(cX_o}dK}MhF6r%JXKw=d>{XIQa&G<#4pV96&ld!&VSr}5_(4bCB~^qg z316X+Z_*t122M_JkM*V+33}wlIz+SxZl9rJRu#pWKz&+*?1}M7{{@6>k|xmFM>y*m znvGUxBDG9g5slrf+p|0E7AJBkvGMT~I6i^0onCyt?_N-d&4_9U;lE`Bwivbk9^AqgbKWUOpm7`{=hwTDP zB|=Vp57qbRm4xB+!iOx(9PB#}9W-$Ins?j2(C85wc+5Ao zWQu?ZJ&rosOV}dC$+~JK%3{YHVRhjuaBg3_Pq^<2s_d)dRmL*bBZ_+^sVUdp@2pTn z&35|kKHmN*^IX8OZ1}ZO&ekqLc9GUNH8LPZ_7{NzRwpuS=SR!%J7x+q z?6#2;;$DL>a=3j0L%?G6dU5&}FN&MiK<(i=U62#m)5gZrd`L5QQ7c9L)s1b3QH_W+ zhNiAPBq!Bz$hX0575V+(an9xMLP4A=)oVMT2j)oj&ps3qD=$PE%E6Jbp}+}o>j1OW znvQe^36f*(q5}$RbEA*{(M&TehV|+rt;qhzmckO!iw++0vzaD*Gune#&mg*;?{+&& zA=t9ap#x`;;Zj%Lm7!)>R6FVs?Xuk4>50}eL)jA3STcE@m_u(wiICRe(O%jVsm(W8 z@j(d=imCl9MoQ#cImWO1Qg!z1DF-L3F%I!F zX6BMf%%{C=Iw@tzw8i%xSH|fdy|o%|`4mDa0U6adz3+9$rA9%KrJ_uw+B3?$Dxz|_ z1gvN7gNW5fSq=tiR!rsquVM#`hb)-?)=`3ZreHw_|brGmv|v zVO?XC%4)F2(lNFrS!2aa)87+Vk)Z_?)l}Grlya#<*qH3C@Aen zS{yDs79cF2hKDiv5>W-sfH=2TCky8{Ir)jl2pr$0e5oM1uq{d50LiNL z!+JI|Ar*(rltp@aCA`Uz2~iIgLj$K${*@Fl4%6ZR6j(KwqL}+8Ee7;gv0$@LfgIBJ z-}L)GA3!OL(>cF}5#yFGXHsfkzngtLz%`mLmsDj)-!_^eieCAYHg^WY@k z8;-pUj=79;Va#k5@Pt+}CvLY=WA;kWf45^){WpiR!-&|h7q$D67UlT+W&cq zRX(Tk-F@KNk(z_wi66*1<*t~#v*%z$G~X#gMSJ)p?q6?2p(DzoU^Rm(Mt?c%CxM1! zOt8{|E1!lz$ZhK18Y95`(|TbQ5#yE459>04R5NuRs#BFGly6>Hrx`^L?^@h>EYPd< zf-&-91-SH7rnvcMdG*f#y7Pos{x)I(eQSA=KUz%pbgU-svVW{RiRpa3O@rtY(p)_f zyOl?)slc)wiV>6ft$GVa^{UIw1GruURVJ{|_3+Bb9&BPa9hJ*e2fwJv|E0swU@Ja8 z-2#Ub0TlIr(tr@mE^lO8fc{9%9$;=HG+r){3iLh=j6`M@m~y+mTy@r&(>^}T>Imp% z=h>B|sVmBllWd4%C^HF0e~^6M47`x{bV&xlThtP*qK7J@fB%b`pWJb+62~zx!3)(WCCZsn?ue zk8x53^7gtrYp^mSrG~l3&u{ zfXNTK8ZT1$i+nkClR;UfZ;Ti^bg>gg-P^tm;eil!oixcoNu$qj+K1T~+(h*_0~DNL zqR#$R_21?whltQ148Kx|JHHU#qh%gS!-&`~o>zUIT^k;~C%+uLWTIpy+s9rBD}B|< zPbhTvo{5`G3ZRSI3YcKU4C6sBuMt5BAec5MypJ|py(Rri5c&=f#aZoU)6ov02c481xd*a z*JTkqC-U=ZkJbX8^p}B}q2Bk?(1aL;LuA<8n~}3vDO>Fm=ruZNDB(jv$Uv!*BcY9N+cV!Hk`>gMy4Ppy>%-fAyaR9p_>6Mu7q7Waq}L zpYaVmJB2QsjtS-A>`h!Ht|C;*=37;0Z;yx!KFcp*gdfDtjMuX6-iqi>F#v`qPB@-m zAE-g#dDt%hzl}W3=(&I0d~0DAXw(w`90!YzsJ={HYKQ z%ZK_u;Au>nibGe?mA7ebTwfoRtlNn{ z5_M8OKV4C@WuY%dV!Wjs8y*w1KxSkk1&z?0C(RCU5=>o)ES?gPO#%>0dlWgQqdUwm zRg8bL9lnnJ@LXs!9-t{=?7%MTY+~FyvgH;XQWz@jh3(>$v{aa=7b!@kNGQu#YwIh>5+%5<5?N zoGvb0+K2VafJ0;>=Q$GXC6(h0WsGbjg&T68mo;VoQYY}JEEf*4{?71<3^s1=bu6|I zn&^8ME1uQI-a0`3!b6kI-J$FmUJkM9pgwmbMpZ(43A0(Har)2&J#?ky6dHaz`B3M$ zPIbg%<@I0k>@Hv&rHrFJJ8LDFE2=E5i#PyzE%Q^F%E>H%hgmd&tOWWQ|ABy%tU_%7 z?W_SPpo$H#TnT9S0{pOI_Z& zX1Zud_qgrm34`}ZRZ^p8WbodD-0i%!IgOw~g6t#LWVEqVE)=?KE=bc({>w{k(~$dS zgD3~ms}AMXDvo@iW-t)kFF~o!zWw%J;O$e~cl{Xj5^pTlK+Hj*ggAMvVjc{tpEyrW<>Yhj7Z1Yly^{a6kB!FoqCn~eZY;a$Ht_jUA#aMjQ zA2!I>tHs}FKgcE(n`8LM0qOI0ECIhqL??@2tfn?Gtm@&(NYI28&AvXzMASccYh&>9 zRwZlRzToVi=F7S&nD8OC=6O~pbT@$FTWv$1#oYa`MEKT^?Y$4QEvMxjHg>m|8C;L1 zQ@sb-ol(oyMP~zOOLBpm4vZdEUEWJg?Hp!+F$*FD(!}?*A2I*K(hE0C$^yD$#mDnJ z=qSqh9`7YYJQd77%dI=v$N4%)#w)KM76SkTOc~+pz-8Z2P6DW&-Ha)z*am|pG|XOB z+++WlVwrCZW!lfTF}loKR+tTDw@^c6iBk4m^MYI#Eucg_Hz_Kud`myAHm(R2QO?9IxLKzrXf zF1p)Cv&lpIg8tQ9m&^xy9`fNP*#EeG6pp6)aMwu)8i4g?al7PGezhioBVu}vJt&VF zxljCPn{@ty_NX?iNAJd<$J-(s(^!=yUPXW^9d$p!ROrE_=CHHCmp=lBfCASWU z7vu-VWxLowBFR%_FzeT5-4XtZ)PwXwjRXzU@7(VGDE>a7P|f9v8&Xq_$}O>v#wUFe zzR+H74h+i>X(!prnVC2249@_nwaRdk&OZ`748CA_cGWf75Rlx1^p=Dg3A5fO9yN!$ z{Efg4K)4Wz&?T3~!6qMn&yvBl7r=2drt_g-0CfjTprO_5C1H4|3U7Oc)zKV=#4_$* zMWCrIZm}QimimQ5YWnrW{zGIAOxs5pVXHTzX`o+LQ~ty>c5Gc3~8H?ek~%X*|E-xMLnAdb7aVvl;JL zhvg6n&LO7CJ}ap6c3Q(zL~KNW!oj6-{-@I6H1pQ_^s1qhv#_y zi!%LqL2Wh`9XQt8)XtVK@PJ7krJN5az?^e*^YcL#1yBEI`qX7Sd@>OSK+ui$^U z+(M$xM^o3Iz~pUBwqlm|)ZiTl)(eA}HRG11BE_9YqM^sNC)){2743A}dqnD#x`<_% zGfnIU%LNyfA0LSZ-cfK>+W1l$%irg>@`!yS>#63jnbU6<&pS;ql|saV8Y{o_j>8+6 z5aBYiZ0(G2yJTX=hHk^S=@nx5AEA0kidsCrWp4H3_cgmuBsUZ}waGht2MKu4w%t@# zb9qnGwEggpk(oSqU@2+wrAPkn`N99-+YHe)PeDiGE08AQE0F)q*Cw|!&Tj%o$z`+o SuSH+%qphK@UaIWwWQ1a{|9eVGp9L5 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.webp new file mode 100644 index 0000000000000000000000000000000000000000..4f5c924f1f54b8cdf2a29fcb24027aa332d5d72b GIT binary patch literal 3340 zcmV+n4fFC+Nk&El4FCXFMM6+kP&iEZ3;+NxL%~oGDy!1=zjEaG(iS=Q`JL95xRI~J z_pa8z&-tJ3{}I!#_5v0OJG&i`kfUm#;~;G_^VH}#=NyMRscKNOjm@0++`vHRICyH{ zLg9r|8&q=xDDh`@zXk@g^0lGGCU%)q*PVsSy(rn}LoS;oyKANs?;?)3~ZHc-z_Y-utK%c3`>$2mlBs zI@`8w+qP}vY}>YNTg$d>dl}31KLMEO|4jd9`ajeEnf}l8eEc=fkdOSMgT5N14tWkxaZ0{)0^6FgVL7^gzX zNC?^v256=i{39(IlAEj9hCP@;kO~eeDH||Jy9v-CQ7+E_IK=~5stK4PtycoIlYSxS zyz-G?j$9#_JSMK=W_X5_DjZ9YYcyk01yVulwVqi4h+HRlgJhq2QR%X{%nlqH^b1kgGPp zYO!9jM+-cXEBDCN(?zFvfsqoBAlIId8Q!)&m42>94%9HxRf-wsb=dheCCPWO{7Q?P% zLYkoHr7Yc0-$tB+W7~m=3ZCjjlcEJiqgtT0dc6?ehIp4!l?p-$#PH0|H8eom#C5_U zA?{{Hr5Baz>(M}HA$>68q8dQlXD5|Hlolr#<&R$5qX!DQiGKiGT{+Bx#DusrW=-mV z^Ok9VAn`%v&?hfL4{y{kSp4EK(xM;utAN3yx8RLp<-&K2sR=SAW8u%Amfv})?5ip_E(JD)GdJfvu3 z9Ls85T$TC+Ea2rLb_!VNbkeqHhl~d69#Rzmd<-pPxbg-B%r+{19)?K=4mw*hX*>WL zr1qnG7?Lrr5|adM5OFy52k2zMnKy_Mhh{$pgo)sa4ivEQ98B+LIUy}(Fc=~}r6#kS zIlV9_UeC_+{or1$YVopN;P>M|mf}O^oEzPjcpaL5OY=q4Td^kt4_E^ z-B7&^eu~U>Yek4#u#&|vaJqx>!_i^*rRw}9AY7eM)c^=8kIWszh~q698G3G*2E2D* zy7y^NCE6)mdy?v)CdssVA@STNz_9p$G_qb~ys|2^r*Q46TA!7Wwf!!{wWr=GND@o8 zI_D9tSyhu$n8T7=5#g)DpkITbILN|6uH|&K8Y=HE~&W8dhbn z29fp;K}IRM5p|ZGs4KuaG8Sy0z5K&jAgQFIc44U}?eFYk2u{`)ja#TAabtnlq~~w0 zifAJtM;aM_P^Hoqje=D>uPWv-EdO;>w#>sH`U5Ejv5*$#Drb@7VyHB4tza!$tV%>$ z%q(Edf%nWgh={`>eqH=UuZ4_BFiI+qsS&L32C5`FSUhR`eS_%GcVYgX@Ff=5d79Ol zTqjt;LRI{^40V)Nwjke8F9du**$rxw-KVz{J zEvs5Kigq_IDJO{oIbIC73ttgAAwFdNvZ30n!nLa^3Hui|!-E{Wokf<#mAO_OvKDPY zs-H)=_Eg1`tIZ%c+`)k?hw)^*KMz@RCK&4NDO{aVHE4ryI)}G9n80!)jv^IdWbSMx z)uWxl75I%RhLoy02aC&Q$>C_05A)M3vq1Kmxk>#SoQv5>ceVp!C08%g_S0xrof$Hy7Eh4<~p402J>7Rb#K3 z!eD)xgV28KEsD+#^b(JQ1Z+}*CjvSQ*vn9<;rvUjkqRB1e$jr!qkp7;1-x9X%u>{* zP-5!RrE`Psm4`t17exgZUYfY{1_aDk%2j0^gSD0-k-6l^Eqv4V;iz!W&4|xZpMYTn zS5@^4ctn)~<{~Ai;t#+&aaw^Q-p|hyy@@3`S^+TBjw()DmN@kvBV-+|T%A6T0l!w| zRN~pFeEFxUh}YKDg$!d{`5(k$9cDOl-#;i9h((CoYD>&|nLLrCAjyCwlb!L_Diw!% z-M+oyZ@kOjsJ-V&b{#J%WZYuIQ~fEclraoAG@Gf-PU)fcUOP zQGd3%>@^X#u$L=}`Iv&2>(4};(#{r4CnqZ)jrz7@ zBgB25c45N_e3`#y!kj(Zm}vcNZKJZ_f)c5R_mw49Z*X7IjH|1&ara znk<@6*oIx;ffVa#n*kqUv{BilKefwa{Il1F+|{{81akGOXCb8W?a6)P)O$_@e~q`&y1djr@fU zL46qCMgv66JJ^OdN0B%4w@q9pp#6ifO$$VxbtMXQ&Lwx|t}P4oqIIdLCWyMmNR53^ z*ojL;cni&9=>|+nDL1r1L}ikL_e1Sr7g{u(x=(cx=f(~`)R8s&X@-c5X#Uh;zv%wg zzm@?&lXxH7g1T~wM?+fnj6j_^bHWWJK7+b*SJUknPec8gyO!Z*%=hQ&5G=`dGo$lR zm)2g-t@Q3dom$l7Mw)t1w~lIZ8%^gx9oy5}O3B1Z5MdV zaD2~@>Q+BD{?=Hpl#K*4CauMfsVMdORZDnFEBbX{hNdrI8MVI8*nodv*ruFvB%iS5w<4@1zqaHr6g0 W4q~SNGyR|G|4jd9`ajeEnRf;F3~F%z literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 448fa261ccc2ada3c896841162c71d9d412d3db3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13269 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 Td)dwO00000NkvXXu0mjfb0;EZ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..dfae045e0c02a9847f03f6e2ab8184892b14369b GIT binary patch literal 14182 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index adb2a0c7947fe03052bbdbb7b8299b7405cadbab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13691 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

Daqp^7-1s?%sB{+Gs2(raSl}|EXEl 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⁣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 VBc|u2nsmU&=%$%|)ph5X{{sd__@e*- diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.webp new file mode 100644 index 0000000000000000000000000000000000000000..b5cb68c7bb2ef2bf09f089a48b915a151de2c9e4 GIT binary patch literal 86550 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 F`vFW&FYy2X literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png deleted file mode 100644 index 89f421aafcc70c18dfa89fcd5862c4742756aeaf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13561 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 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..4efec9cdb2b7f23c1f4a8e045856015487d282e4 GIT binary patch literal 44302 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 S{y+5pq5lv4f9U`3yb%D1zl&@D literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.webp new file mode 100644 index 0000000000000000000000000000000000000000..c3490dc0b4641993c273d665bca26e43a9158c91 GIT binary patch literal 4664 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 u$=WA+!Jqq<7ML+XM&! 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 iOVlFbaqWV)Q2Kwkr%aG4UhhW$0000bEJ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..ecf5481f9414a77823a0b82e8fc2d8613aed23c8 GIT binary patch literal 22000 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 TKmd{l-K0#a2`p3vYYX>WWd%or literal 0 HcmV?d00001 From 5974ca09750de51ee08e2b534d5e3be50f04d0d8 Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Mon, 18 Sep 2023 14:42:42 +0200 Subject: [PATCH 218/234] Remove dead code in room summary row Not sure why it's unused but it's almost 1 year old so probably safe to remove. --- .../impl/components/RoomSummaryRow.kt | 30 ------------------- 1 file changed, 30 deletions(-) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt index aab174c6a4..a6982f8201 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt @@ -33,17 +33,10 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.geometry.Rect -import androidx.compose.ui.geometry.Size -import androidx.compose.ui.graphics.Outline -import androidx.compose.ui.graphics.Path -import androidx.compose.ui.graphics.Shape import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter -import androidx.compose.ui.unit.Density -import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import io.element.android.features.roomlist.impl.model.RoomListRoomSummary import io.element.android.features.roomlist.impl.model.RoomListRoomSummaryProvider @@ -175,29 +168,6 @@ private fun RowScope.LastMessageAndIndicatorRow(room: RoomListRoomSummary) { ) } -val TextPlaceholderShape = PercentRectangleSizeShape(0.5f) - -class PercentRectangleSizeShape(private val percent: Float) : Shape { - override fun createOutline( - size: Size, - layoutDirection: LayoutDirection, - density: Density - ): Outline { - val halfPercent = percent / 2f - val path = Path().apply { - val rect = Rect( - left = 0f, - top = size.height * halfPercent, - right = size.width, - bottom = size.height * (1 - halfPercent) - ) - addRect(rect) - close() - } - return Outline.Generic(path) - } -} - @Preview @Composable internal fun RoomSummaryRowLightPreview(@PreviewParameter(RoomListRoomSummaryProvider::class) data: RoomListRoomSummary) = From ae9ecd9a550cae7d0dc912f9a7c555a347cc7208 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 18 Sep 2023 13:37:11 +0200 Subject: [PATCH 219/234] Set different app icon background for debug/release/nightly. (#1089) --- app/src/debug/res/drawable/ic_launcher_background.xml | 10 ++++++++++ app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml | 2 +- .../main/res/mipmap-anydpi-v26/ic_launcher_round.xml | 2 +- .../nightly/res/drawable/ic_launcher_background.xml | 10 ++++++++++ .../release/res/drawable/ic_launcher_background.xml | 2 ++ 5 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 app/src/debug/res/drawable/ic_launcher_background.xml create mode 100644 app/src/nightly/res/drawable/ic_launcher_background.xml create mode 100644 app/src/release/res/drawable/ic_launcher_background.xml diff --git a/app/src/debug/res/drawable/ic_launcher_background.xml b/app/src/debug/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000000..d41447906a --- /dev/null +++ b/app/src/debug/res/drawable/ic_launcher_background.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index e468c16c63..804149846b 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -16,7 +16,7 @@ --> - + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml index e468c16c63..804149846b 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -16,7 +16,7 @@ --> - + diff --git a/app/src/nightly/res/drawable/ic_launcher_background.xml b/app/src/nightly/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000000..dc27f37adf --- /dev/null +++ b/app/src/nightly/res/drawable/ic_launcher_background.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/release/res/drawable/ic_launcher_background.xml b/app/src/release/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000000..6ff3e59543 --- /dev/null +++ b/app/src/release/res/drawable/ic_launcher_background.xml @@ -0,0 +1,2 @@ + From e48a9ee08d49833f3cb8c2113e9539aaa8eecd90 Mon Sep 17 00:00:00 2001 From: David Langley Date: Mon, 18 Sep 2023 15:05:43 +0100 Subject: [PATCH 220/234] Fix typo, remove unnecessary filter of all rooms in the datasource. --- .../impl/datasource/RoomListDataSource.kt | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt index ac0b3ca568..6a9c152af6 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt @@ -28,7 +28,6 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService -import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.api.roomlist.RoomSummary import kotlinx.collections.immutable.ImmutableList @@ -57,7 +56,7 @@ class RoomListDataSource @Inject constructor( private val appScope: CoroutineScope, ) { init { - observerNotificationSettings() + observeNotificationSettings() } private val _filter = MutableStateFlow("") @@ -103,7 +102,7 @@ class RoomListDataSource @Inject constructor( val filteredRooms: StateFlow> = _filteredRooms @OptIn(FlowPreview::class) - private fun observerNotificationSettings() { + private fun observeNotificationSettings() { notificationSettingsService.notificationSettingsChangeFlow .debounce(0.5.seconds) .onEach { @@ -140,16 +139,10 @@ class RoomListDataSource @Inject constructor( } } - private fun buildAndCacheItem(roomSummaries: List, index: Int, ): RoomListRoomSummary? { + private fun buildAndCacheItem(roomSummaries: List, index: Int): RoomListRoomSummary? { val roomListRoomSummary = when (val roomSummary = roomSummaries.getOrNull(index)) { is RoomSummary.Empty -> RoomListRoomSummaryPlaceholders.create(roomSummary.identifier) is RoomSummary.Filled -> { - // Only show a decoration if the mode is not ALL_MESSAGES - val notificationMode = if (roomSummary.details.notificationMode == RoomNotificationMode.ALL_MESSAGES) { - null - } else { - roomSummary.details.notificationMode - } val avatarData = AvatarData( id = roomSummary.identifier(), name = roomSummary.details.name, @@ -167,7 +160,7 @@ class RoomListDataSource @Inject constructor( roomLastMessageFormatter.format(message.event, roomSummary.details.isDirect) }.orEmpty(), avatarData = avatarData, - notificationMode = notificationMode + notificationMode = roomSummary.details.notificationMode, ) } null -> null From f42455cbb58045153d0a81c7a644ca5a0c71e4d1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 18 Sep 2023 16:07:27 +0200 Subject: [PATCH 221/234] Ensure locale is taken into account by paparazzi. --- tests/uitests/src/test/kotlin/ui/S.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/uitests/src/test/kotlin/ui/S.kt b/tests/uitests/src/test/kotlin/ui/S.kt index 33c7260e7f..0aaf234a7f 100644 --- a/tests/uitests/src/test/kotlin/ui/S.kt +++ b/tests/uitests/src/test/kotlin/ui/S.kt @@ -96,6 +96,7 @@ class S { paparazzi.unsafeUpdateConfig( deviceConfig = baseDeviceConfig.deviceConfig.copy( softButtons = false, + locale = localeStr, nightMode = componentTestPreview.isNightMode().let { when (it) { true -> NightMode.NIGHT From 0453ea590435c88f76ac1b23868eca463844ae24 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 18 Sep 2023 15:41:22 +0200 Subject: [PATCH 222/234] Localazy sync --- .../src/main/res/values-de/translations.xml | 6 +- .../src/main/res/values-fr/translations.xml | 4 +- .../src/main/res/values-fr/translations.xml | 2 +- .../src/main/res/values-fr/translations.xml | 18 +-- .../src/main/res/values-de/translations.xml | 4 +- .../src/main/res/values-fr/translations.xml | 10 +- .../src/main/res/values-de/translations.xml | 4 +- .../src/main/res/values-fr/translations.xml | 8 +- .../src/main/res/values-de/translations.xml | 24 ++-- .../src/main/res/values-fr/translations.xml | 38 +++--- .../src/main/res/values-fr/translations.xml | 2 +- .../src/main/res/values-de/translations.xml | 20 +-- .../src/main/res/values-fr/translations.xml | 30 ++--- .../src/main/res/values-de/translations.xml | 2 +- .../src/main/res/values-fr/translations.xml | 8 +- .../src/main/res/values-de/translations.xml | 2 +- .../src/main/res/values-de/translations.xml | 9 ++ .../src/main/res/values-fr/translations.xml | 9 ++ .../src/main/res/values-sk/translations.xml | 9 ++ .../src/main/res/values-de/translations.xml | 4 +- .../src/main/res/values-fr/translations.xml | 4 +- .../src/main/res/values-de/translations.xml | 10 +- .../src/main/res/values-fr/translations.xml | 10 +- .../src/main/res/values-de/translations.xml | 22 ++-- .../src/main/res/values-fr/translations.xml | 42 +++---- .../src/main/res/values-de/translations.xml | 2 +- .../src/main/res/values-fr/translations.xml | 8 +- .../src/main/res/values-fr/translations.xml | 8 +- .../src/main/res/values-fr/translations.xml | 2 +- .../src/main/res/values-fr/translations.xml | 72 +++++------ .../src/main/res/values-de/translations.xml | 8 +- .../src/main/res/values-fr/translations.xml | 24 ++-- .../src/main/res/values-de/translations.xml | 58 ++++----- .../src/main/res/values-fr/translations.xml | 118 +++++++++--------- .../src/main/res/values-sk/translations.xml | 6 - .../src/main/res/values/localazy.xml | 10 +- 36 files changed, 307 insertions(+), 310 deletions(-) create mode 100644 features/preferences/impl/src/main/res/values-de/translations.xml create mode 100644 features/preferences/impl/src/main/res/values-fr/translations.xml create mode 100644 features/preferences/impl/src/main/res/values-sk/translations.xml diff --git a/features/analytics/impl/src/main/res/values-de/translations.xml b/features/analytics/impl/src/main/res/values-de/translations.xml index a9b4173395..ac9149a4b6 100644 --- a/features/analytics/impl/src/main/res/values-de/translations.xml +++ b/features/analytics/impl/src/main/res/values-de/translations.xml @@ -1,10 +1,10 @@ "Wir zeichnen keine persönlichen Daten auf und erstellen keine Profile." - "Teilen Sie anonyme Nutzungsdaten, um uns bei der Identifizierung von Problemen zu helfen." - "Sie können alle unsere Bedingungen lesen%1$s." + "Teile anonyme Nutzungsdaten, um uns bei der Identifizierung von Problemen zu helfen." + "Du kannst alle unsere Bedingungen lesen %1$s." "hier" - "Sie können diese Funktion jederzeit deaktivieren" + "Du kannst diese Funktion jederzeit deaktivieren" "Wir geben Ihre Daten nicht an Dritte weiter" "Hilf uns %1$s zu verbessern" diff --git a/features/analytics/impl/src/main/res/values-fr/translations.xml b/features/analytics/impl/src/main/res/values-fr/translations.xml index 63a97dc905..e18657cf98 100644 --- a/features/analytics/impl/src/main/res/values-fr/translations.xml +++ b/features/analytics/impl/src/main/res/values-fr/translations.xml @@ -1,7 +1,7 @@ - "Nous n\'enregistrerons ni ne profilerons aucune donnée personnelle" - "Partagez des données d\'utilisation anonymes pour nous aider à identifier les problèmes." + "Nous n’enregistrerons ni ne profilerons aucune donnée personnelle" + "Partagez des données d’utilisation anonymes pour nous aider à identifier les problèmes." "Vous pouvez lire toutes nos conditions %1$s." "ici" "Vous pouvez le désactiver à tout moment" diff --git a/features/call/src/main/res/values-fr/translations.xml b/features/call/src/main/res/values-fr/translations.xml index e35473b31b..eecf771031 100644 --- a/features/call/src/main/res/values-fr/translations.xml +++ b/features/call/src/main/res/values-fr/translations.xml @@ -1,6 +1,6 @@ "Appel en cours" - "Appuyez pour retourner à l\'appel." + "Cliquez pour retourner à l’appel." "☎️ Appel en cours" diff --git a/features/createroom/impl/src/main/res/values-fr/translations.xml b/features/createroom/impl/src/main/res/values-fr/translations.xml index 289fb3f50d..e060b99ed8 100644 --- a/features/createroom/impl/src/main/res/values-fr/translations.xml +++ b/features/createroom/impl/src/main/res/values-fr/translations.xml @@ -1,15 +1,15 @@ - "Nouvelle salle" + "Nouveau salon" "Inviter des amis sur Element" "Inviter des personnes" - "Une erreur s\'est produite lors de la création de la salle" - "Les messages dans cette pièce sont cryptés. Le cryptage ne peut pas être désactivé par la suite." - "Salle privée (sur invitation seulement)" - "Les messages ne sont pas cryptés et n\'importe qui peut les lire. Vous pouvez activer le chiffrement ultérieurement." - "Salle publique (tout le monde)" - "Nom de la salle" + "Une erreur s’est produite lors de la création du salon" + "Les messages dans ce salon sont chiffrés. Le chiffrement ne pourra pas être désactivé par la suite." + "Salon privé (sur invitation seulement)" + "Les messages ne sont pas chiffrés et n’importe qui peut les lire. Vous pouvez activer le chiffrement ultérieurement." + "Salon public (tout le monde)" + "Nom du salon" "Sujet (facultatif)" - "Une erreur s\'est produite lors de la tentative de démarrage d\'une discussion" - "Créer une salle" + "Une erreur s’est produite lors de la tentative de création de la discussion" + "Créer un salon" diff --git a/features/ftue/impl/src/main/res/values-de/translations.xml b/features/ftue/impl/src/main/res/values-de/translations.xml index 8df01adc45..9ee1113fdb 100644 --- a/features/ftue/impl/src/main/res/values-de/translations.xml +++ b/features/ftue/impl/src/main/res/values-de/translations.xml @@ -1,8 +1,8 @@ "Dies ist ein einmaliger Vorgang, danke fürs Warten." - "Richten Sie Ihr Konto ein." - "Sie können Ihre Einstellungen später ändern." + "Richte dein Konto ein." + "Du kannst deine Einstellungen später ändern." "Erlaube Benachrichtigungen und verpasse keine Nachricht" "Anrufe, Umfragen, Suchfunktionen und mehr werden im Laufe des Jahres hinzugefügt." "Der Nachrichtenverlauf für verschlüsselte Räume wird in diesem Update nicht verfügbar sein." diff --git a/features/ftue/impl/src/main/res/values-fr/translations.xml b/features/ftue/impl/src/main/res/values-fr/translations.xml index 68345265d4..864a887f20 100644 --- a/features/ftue/impl/src/main/res/values-fr/translations.xml +++ b/features/ftue/impl/src/main/res/values-fr/translations.xml @@ -1,13 +1,13 @@ - "Il s\'agit d\'un processus unique, merci d\'avoir attendu." + "Il s’agit d’une opération ponctuelle, merci d’attendre quelques instants." "Configuration de votre compte." "Vous pourrez modifier vos paramètres ultérieurement." "Autorisez les notifications et ne manquez aucun message" "Les appels, les sondages, les recherches et plus encore seront ajoutés plus tard cette année." - "L\'historique des messages pour les salles cryptées ne sera pas disponible dans cette mise à jour." - "N\'hésitez pas à nous faire part de vos commentaires via la page des paramètres." - "C\'est parti !" + "L’historique des messages pour les salons chiffrés ne sera pas disponible dans cette mise à jour." + "N’hésitez pas à nous faire part de vos commentaires via l’écran des paramètres." + "C’est parti !" "Voici ce que vous devez savoir :" - "Bienvenue à %1$s !" + "Bienvenue dans %1$s !" diff --git a/features/invitelist/impl/src/main/res/values-de/translations.xml b/features/invitelist/impl/src/main/res/values-de/translations.xml index 245634a971..97f4aa91f7 100644 --- a/features/invitelist/impl/src/main/res/values-de/translations.xml +++ b/features/invitelist/impl/src/main/res/values-de/translations.xml @@ -1,8 +1,8 @@ - "Möchten Sie die Einladung zum Betreten von %1$s wirklich ablehnen?" + "Möchtest du die Einladung zum Betreten von %1$s wirklich ablehnen?" "Einladung ablehnen" - "Sind Sie sicher, dass Sie diesen privaten Chat mit %1$s ablehnen möchten?" + "Bist du sicher, dass du diesen privaten Chat mit %1$s ablehnen möchtest?" "Chat ablehnen" "Keine Einladungen" "%1$s (%2$s) hat dich eingeladen" diff --git a/features/invitelist/impl/src/main/res/values-fr/translations.xml b/features/invitelist/impl/src/main/res/values-fr/translations.xml index 55606b100d..45c29b3572 100644 --- a/features/invitelist/impl/src/main/res/values-fr/translations.xml +++ b/features/invitelist/impl/src/main/res/values-fr/translations.xml @@ -1,9 +1,9 @@ - "Êtes-vous sûr de vouloir décliner l\'invitation à participer %1$s ?" - "Refuser l\'invitation" + "Êtes-vous sûr de vouloir décliner l’invitation à rejoindre %1$s ?" + "Refuser l’invitation" "Êtes-vous sûr de vouloir refuser cette discussion privée avec %1$s ?" - "Refuser le chat" + "Refuser l’invitation" "Aucune invitation" - "%1$s (%2$s) vous a invité" + "%1$s (%2$s) vous a invité(e)" diff --git a/features/login/impl/src/main/res/values-de/translations.xml b/features/login/impl/src/main/res/values-de/translations.xml index ba012e8082..cf247877fe 100644 --- a/features/login/impl/src/main/res/values-de/translations.xml +++ b/features/login/impl/src/main/res/values-de/translations.xml @@ -2,27 +2,27 @@ "Kontoanbieter ändern" "Homeserver-Adresse" - "Geben Sie einen Suchbegriff oder eine Domainadresse ein." - "Suchen Sie nach einem Unternehmen, einer Community oder einem privaten Server." + "Gib einen Suchbegriff oder eine Domainadresse ein." + "Suche nach einem Unternehmen, einer Community oder einem privaten Server." "Kontoanbieter finden" - "Hier werden Ihre Gespräche gespeichert – genau so, wie Sie einen E-Mail-Anbieter nutzen würden, um Ihre E-Mails aufzubewahren." - "Sie sind dabei, sich bei %s anzumelden" - "Hier werden Ihre Gespräche gespeichert – genau so, wie Sie einen E-Mail-Anbieter nutzen würden, um Ihre E-Mails aufzubewahren." - "Sie sind dabei, ein Konto bei %s zu erstellen" + "Hier werden Ihre Gespräche gespeichert – genau so, wie du einen E-Mail-Anbieter nutzen würdest, um deine E-Mails aufzubewahren." + "Du bist dabei, dich bei %s anzumelden" + "Hier werden deine Gespräche gespeichert – genau so, wie du einen E-Mail-Anbieter nutzen würdest, um deine E-Mails aufzubewahren." + "Du bist dabei, ein Konto bei %s zu erstellen" "Matrix.org ist ein großer, kostenloser Server im öffentlichen Matrix-Netzwerk für eine sichere, dezentralisierte Kommunikation, der von der Matrix.org Foundation betrieben wird." "Sonstige" - "Verwenden Sie einen anderen Kontoanbieter, z. B. Ihren eigenen privaten Server oder ein Geschäftskonto." + "Verwende einen anderen Kontoanbieter, z. B. deinen eigenen privaten Server oder ein Geschäftskonto." "Kontoanbieter wechseln" - "Wir konnten diesen Homeserver nicht erreichen. Bitte überprüfen Sie, ob Sie die Homeserver-URL korrekt eingegeben haben. Wenn die URL korrekt ist, wenden Sie sich an Ihren Homeserver-Administrator, um weitere Hilfe zu erhalten." + "Wir konnten diesen Homeserver nicht erreichen. Bitte überprüfe, ob du die Homeserver-URL korrekt eingegeben hast. Wenn die URL korrekt ist, wende dich an deinen Homeserver-Administrator, um weitere Hilfe zu erhalten." "Dieser Server unterstützt derzeit kein Sliding Sync." "Homeserver-URL" - "Sie können nur eine Verbindung zu einem vorhandenen Server herstellen, der Sliding Sync unterstützt. Ihr Homeserver-Administrator muss das konfigurieren. %1$s" + "Du kannst nur eine Verbindung zu einem vorhandenen Server herstellen, der Sliding Sync unterstützt. Dein Homeserver-Administrator muss das konfigurieren. %1$s" "Wie lautet die Adresse Ihres Servers?" "Dieses Konto wurde deaktiviert." "Falscher Benutzername und/oder Passwort" "Dies ist keine gültige Benutzerkennung. Erwartetes Format: \'@user:homeserver.org\'" - "Der ausgewählte Homeserver unterstützt weder den Login per Passwort noch per OIDC. Bitte kontaktieren Sie Ihren Admin oder wählen Sie einen anderen Homeserver." - "Geben Sie Ihre Daten ein" + "Der ausgewählte Homeserver unterstützt weder den Login per Passwort noch per OIDC. Bitte kontaktiere deinen Administrator oder wähle einen anderen Homeserver." + "Gebe deine Daten ein" "Willkommen zurück!" "Anmelden bei %1$s" "Kontoanbieter wechseln" @@ -39,7 +39,7 @@ Danke für Ihre Geduld!" "Sie sind dabei." "Weiter" "Weiter" - "Wählen Sie Ihren Server aus" + "Wähle deinen Server aus" "Passwort" "Weiter" "Matrix ist ein offenes Netzwerk für eine sichere, dezentrale Kommunikation." diff --git a/features/login/impl/src/main/res/values-fr/translations.xml b/features/login/impl/src/main/res/values-fr/translations.xml index 41be63cb2c..a566198a45 100644 --- a/features/login/impl/src/main/res/values-fr/translations.xml +++ b/features/login/impl/src/main/res/values-fr/translations.xml @@ -1,40 +1,40 @@ "Changer de fournisseur de compte" - "Adresse du serveur d\'accueil" + "Adresse du serveur d’accueil" "Entrez un terme de recherche ou une adresse de domaine." "Recherchez une entreprise, une communauté ou un serveur privé." "Trouver un fournisseur de comptes" - "C\'est ici que vos conversations seront enregistrées, comme vous le feriez avec un fournisseur de messagerie pour conserver vos e-mails." + "C’est ici que vos conversations seront enregistrées, comme vous le feriez avec un fournisseur de messagerie pour conserver vos e-mails." "Vous êtes sur le point de vous connecter à %s" - "C\'est ici que vos conversations seront enregistrées, comme vous le feriez avec un fournisseur de messagerie pour conserver vos e-mails." + "C’est ici que vos conversations seront enregistrées, comme vous le feriez avec un fournisseur de messagerie pour conserver vos e-mails." "Vous êtes sur le point de créer un compte sur %s" "Matrix.org est un grand serveur gratuit sur le réseau public Matrix pour une communication sécurisée et décentralisée, géré par la Fondation Matrix.org." "Autres" - "Utilisez un autre fournisseur de compte, tel que votre propre serveur privé ou un compte professionnel." + "Utilisez un autre fournisseur de compte, tel que votre propre serveur privé ou un serveur professionnel." "Changer de fournisseur de compte" - "Nous n\'avons pas pu atteindre ce serveur d\'accueil. Vérifiez que vous avez correctement saisi l\'URL du serveur d\'accueil. Si l\'URL est correcte, contactez l\'administrateur de votre serveur d\'accueil pour obtenir de l\'aide." + "Nous n’avons pas pu atteindre ce serveur d’accueil. Vérifiez que vous avez correctement saisi l’URL du serveur d’accueil. Si l’URL est correcte, contactez l’administrateur de votre serveur d’accueil pour obtenir de l’aide." "Ce serveur ne prend actuellement pas en charge la synchronisation glissante." - "URL du serveur d\'accueil" - "Vous ne pouvez vous connecter qu\'à un serveur existant qui prend en charge la synchronisation par glissement. L\'administrateur de votre serveur d\'accueil devra le configurer. %1$s" - "Quelle est l\'adresse de votre serveur ?" + "URL du serveur d’accueil" + "Vous ne pouvez vous connecter qu’à un serveur existant qui prend en charge le sliding sync. L’administrateur de votre serveur d’accueil devra le configurer. %1$s" + "Quelle est l’adresse de votre serveur ?" "Ce compte a été désactivé." - "Nom d\'utilisateur et/ou mot de passe incorrects" - "Il ne s\'agit pas d\'un identifiant utilisateur valide. Format attendu : « @user:homeserver.org »" - "Le serveur d\'accueil sélectionné ne prend pas en charge le mot de passe ou la connexion OIDC. Contactez votre administrateur ou choisissez un autre serveur d\'accueil." - "Saisir vos informations personnelles" - "Bienvenue !" + "Nom d’utilisateur et/ou mot de passe incorrects" + "Il ne s’agit pas d’un identifiant utilisateur valide. Format attendu : « @user:homeserver.org »" + "Le serveur d’accueil sélectionné ne prend pas en charge le mot de passe ou la connexion OIDC. Contactez votre administrateur ou choisissez un autre serveur d’accueil." + "Saisissez vos identifiants" + "Content de vous revoir !" "Connectez-vous à %1$s" "Changer de fournisseur de compte" - "Un serveur privé pour les employés d\'Element." + "Un serveur privé pour les employés d’Element." "Matrix est un réseau ouvert pour une communication sécurisée et décentralisée." - "C\'est ici que vos conversations seront enregistrées, comme vous le feriez avec un fournisseur de messagerie pour conserver vos e-mails." + "C’est ici que vos conversations seront enregistrées, comme vous le feriez avec un fournisseur de messagerie pour conserver vos e-mails." "Vous êtes sur le point de vous connecter à %1$s" "Vous êtes sur le point de créer un compte sur %1$s" - "Il y a une forte demande pour %1$s sur %2$s à l\'heure actuelle. Revenez sur l\'application dans quelques jours et réessayez. + "Il y a une forte demande pour %1$s sur %2$s à l’heure actuelle. Revenez sur l’application dans quelques jours et réessayez. -Merci pour votre patience !" - "Bienvenue à %1$s !" +Merci pour votre patience !" + "Bienvenue dans %1$s !" "Vous y êtes presque." "Vous y êtes." "Continuer" @@ -43,5 +43,5 @@ Merci pour votre patience !" "Mot de passe" "Continuer" "Matrix est un réseau ouvert pour une communication sécurisée et décentralisée." - "Nom d\'utilisateur" + "Nom d’utilisateur" diff --git a/features/logout/api/src/main/res/values-fr/translations.xml b/features/logout/api/src/main/res/values-fr/translations.xml index d4d8b8477b..16c9d3717e 100644 --- a/features/logout/api/src/main/res/values-fr/translations.xml +++ b/features/logout/api/src/main/res/values-fr/translations.xml @@ -1,6 +1,6 @@ - "Êtes-vous sûr de vouloir vous déconnecter ?" + "Êtes-vous sûr de vouloir vous déconnecter ?" "Se déconnecter" "Déconnexion…" "Se déconnecter" diff --git a/features/messages/impl/src/main/res/values-de/translations.xml b/features/messages/impl/src/main/res/values-de/translations.xml index 8208418e34..7127196056 100644 --- a/features/messages/impl/src/main/res/values-de/translations.xml +++ b/features/messages/impl/src/main/res/values-de/translations.xml @@ -14,29 +14,29 @@ "Textformatierung" "Der Nachrichtenverlauf ist derzeit in diesem Raum nicht verfügbar" "Benutzerdetails konnten nicht abgerufen werden" - "Möchten Sie sie wieder einladen?" - "Sie sind allein in diesem Chat" + "Möchtest du sie wieder einladen?" + "Du bist allein in diesem Chat" "Nachricht wurde kopiert" - "Sie sind nicht berechtigt, in diesem Raum zu posten" + "Du bist nicht berechtigt, in diesem Raum zu posten" "Benutzerdefinierte Einstellung zulassen" - "Wenn Sie diese Option aktivieren, wird Ihre Standardeinstellung außer Kraft gesetzt." - "Benachrichtigen Sie mich in diesem Chat bei" - "Sie können das in Ihrem %1$s ändern." + "Wenn du diese Option aktivierst, wird deine Standardeinstellung außer Kraft gesetzt." + "Benachrichtige mich in diesem Chat bei" + "Du kannst das in deinem %1$s ändern." "Globale Einstellungen" "Standardeinstellung" "Benutzerdefinierte Einstellung entfernen" "Beim Laden der Benachrichtigungseinstellungen ist ein Fehler aufgetreten." - "Fehler beim Wiederherstellen des Standardmodus. Bitte versuchen Sie es erneut." - "Fehler beim Einstellen des Modus. Bitte versuchen Sie es erneut." + "Fehler beim Wiederherstellen des Standardmodus. Bitte versuche es erneut." + "Fehler beim Einstellen des Modus. Bitte versuche es erneut." "Alle Nachrichten" "Nur Erwähnungen und Schlüsselwörter" - "Benachrichtigen Sie mich in diesem Raum bei" + "Benachrichtige mich in diesem Raum bei" "Weniger anzeigen" "Mehr anzeigen" "Erneut senden" "Ihre Nachricht konnte nicht gesendet werden" "Emoji hinzufügen" "Weniger anzeigen" - "Fehler beim Verarbeiten des hochgeladenen Mediums. Bitte versuchen Sie es erneut." + "Fehler beim Verarbeiten des hochgeladenen Mediums. Bitte versuche es erneut." "Entfernen" diff --git a/features/messages/impl/src/main/res/values-fr/translations.xml b/features/messages/impl/src/main/res/values-fr/translations.xml index 5bbd8e85b8..5ae43b98d7 100644 --- a/features/messages/impl/src/main/res/values-fr/translations.xml +++ b/features/messages/impl/src/main/res/values-fr/translations.xml @@ -1,42 +1,42 @@ - "%1$d changement de salle" - "%1$d changements de salle" + "%1$d changement dans le salon" + "%1$d changements dans le salon" "Appareil photo" "Prendre une photo" "Enregistrer une vidéo" "Pièce jointe" - "Photothèque et vidéothèque" - "Emplacement" + "Gallerie Photo et Vidéo" + "Position" "Sondage" "Formatage du texte" - "L\'historique des messages n\'est actuellement pas disponible dans cette salle" - "Impossible de récupérer les détails de l\'utilisateur" - "Aimeriez-vous les inviter à revenir ?" - "Vous êtes seul dans ce chat" + "L’historique des messages n’est actuellement pas disponible dans ce salon" + "Impossible de récupérer les détails de l’utilisateur" + "Souaitez-vous inviter l\'ancien membre à revenir ?" + "Vous êtes seul dans ce salon" "Message copié" - "Vous n\'êtes pas autorisé à publier dans cette salle" + "Vous n’êtes pas autorisé à publier dans ce salon" "Autoriser les paramètres personnalisés" - "L\'activation de cette option annulera votre paramètre par défaut" - "Prévenez-moi dans ce chat pour" + "L’activation de cette option annulera votre paramètre par défaut" + "Prévenez-moi dans ce salon pour" "Vous pouvez le modifier dans votre %1$s." "paramètres globaux" "Paramètre par défaut" "Supprimer le paramètre personnalisé" - "Une erreur s\'est produite lors du chargement des paramètres de notification." + "Une erreur s’est produite lors du chargement des paramètres de notification." "Échec de la restauration du mode par défaut, veuillez réessayer." "Échec de la configuration du mode, veuillez réessayer." "Tous les messages" "Mentions et mots clés uniquement" - "Dans cette salle, prévenez-moi pour" + "Dans ce salon, prévenez-moi pour" "Afficher moins" "Afficher plus" "Envoyer à nouveau" - "Votre message n\'a pas pu être envoyé" + "Votre message n’a pas pu être envoyé" "Ajouter un émoji" "Afficher moins" "Échec du traitement des médias à télécharger, veuillez réessayer." - "Enlever" + "Supprimer" diff --git a/features/onboarding/impl/src/main/res/values-de/translations.xml b/features/onboarding/impl/src/main/res/values-de/translations.xml index 08bc2abeee..b7f231a32a 100644 --- a/features/onboarding/impl/src/main/res/values-de/translations.xml +++ b/features/onboarding/impl/src/main/res/values-de/translations.xml @@ -6,5 +6,5 @@ "Sicher kommunizieren und zusammenarbeiten" "Willkommen beim schnellsten Element aller Zeiten. Optimiert für Geschwindigkeit und Einfachheit." "Willkommen zu %1$s. Aufgeladen, für Geschwindigkeit und Einfachheit." - "Seien Sie in Ihrem Element" + "Sei in deinem Element" diff --git a/features/onboarding/impl/src/main/res/values-fr/translations.xml b/features/onboarding/impl/src/main/res/values-fr/translations.xml index cbcfd477f0..789b29c5b8 100644 --- a/features/onboarding/impl/src/main/res/values-fr/translations.xml +++ b/features/onboarding/impl/src/main/res/values-fr/translations.xml @@ -1,10 +1,10 @@ - "Connectez-vous manuellement" - "Connectez-vous avec le code QR" + "Se connecter manuellement" + "Se connecter avec un QR code" "Créer un compte" "Communiquez et collaborez en toute sécurité" - "Bienvenue dans l\'Element le plus rapide de tous les temps. Boosté pour plus de rapidité et de simplicité." - "Bienvenue sur %1$s. Boosté, pour rapidité et simplicité." + "Bienvenue dans l’Element le plus rapide de tous les temps. Boosté pour plus de rapidité et de simplicité." + "Bienvenue sur %1$s. Boosté, pour plus de rapidité et de simplicité." "Soyez dans votre Element" diff --git a/features/poll/impl/src/main/res/values-de/translations.xml b/features/poll/impl/src/main/res/values-de/translations.xml index c2b07baf16..bd43eb8337 100644 --- a/features/poll/impl/src/main/res/values-de/translations.xml +++ b/features/poll/impl/src/main/res/values-de/translations.xml @@ -4,7 +4,7 @@ "Ergebnisse erst nach Ende der Umfrage anzeigen" "Anonyme Umfrage" "Option %1$d" - "Sind Sie sicher, dass Sie diese Umfrage verwerfen wollen?" + "Bist du sicher, dass du diese Umfrage verwerfen willst?" "Umfrage verwerfen" "Frage oder Thema" "Worum geht es bei der Umfrage?" diff --git a/features/preferences/impl/src/main/res/values-de/translations.xml b/features/preferences/impl/src/main/res/values-de/translations.xml new file mode 100644 index 0000000000..787bba6087 --- /dev/null +++ b/features/preferences/impl/src/main/res/values-de/translations.xml @@ -0,0 +1,9 @@ + + + "Anzeigename" + "Ihr Anzeigename" + "Ein unbekannter Fehler ist aufgetreten und die Informationen konnten nicht geändert werden." + "Profil kann nicht aktualisiert werden" + "Profil bearbeiten" + "Profil wird aktualisiert…" + diff --git a/features/preferences/impl/src/main/res/values-fr/translations.xml b/features/preferences/impl/src/main/res/values-fr/translations.xml new file mode 100644 index 0000000000..392b28c785 --- /dev/null +++ b/features/preferences/impl/src/main/res/values-fr/translations.xml @@ -0,0 +1,9 @@ + + + "Pseudonyme" + "Votre pseudonyme" + "Une erreur inconnue s’est produite et les informations n’ont pas pu être modifiées." + "Impossible de mettre à jour le profil" + "Modifier le profil" + "Mise à jour du profil…" + diff --git a/features/preferences/impl/src/main/res/values-sk/translations.xml b/features/preferences/impl/src/main/res/values-sk/translations.xml new file mode 100644 index 0000000000..46631c4eb3 --- /dev/null +++ b/features/preferences/impl/src/main/res/values-sk/translations.xml @@ -0,0 +1,9 @@ + + + "Zobrazované meno" + "Vaše zobrazované meno" + "Vyskytla sa neznáma chyba a informácie nebolo možné zmeniť." + "Nepodarilo sa aktualizovať profil" + "Upraviť profil" + "Aktualizácia profilu…" + diff --git a/features/rageshake/api/src/main/res/values-de/translations.xml b/features/rageshake/api/src/main/res/values-de/translations.xml index 7c49bf6225..468ac44491 100644 --- a/features/rageshake/api/src/main/res/values-de/translations.xml +++ b/features/rageshake/api/src/main/res/values-de/translations.xml @@ -1,5 +1,5 @@ - "%1$s ist bei der letzten Nutzung abgestürzt. Möchten Sie einen Absturzbericht mit uns teilen?" - "Sie scheinen das Telefon aus Frustration zu schütteln. Möchten Sie den Bildschirm für den Fehlerbericht öffnen?" + "%1$s ist bei der letzten Nutzung abgestürzt. Möchtest du einen Absturzbericht mit uns teilen?" + "Du scheinst das Telefon aus Frustration zu schütteln. Möchtest du den Bildschirm für den Fehlerbericht öffnen?" diff --git a/features/rageshake/api/src/main/res/values-fr/translations.xml b/features/rageshake/api/src/main/res/values-fr/translations.xml index 8d57edb3e1..5c3571e443 100644 --- a/features/rageshake/api/src/main/res/values-fr/translations.xml +++ b/features/rageshake/api/src/main/res/values-fr/translations.xml @@ -1,5 +1,5 @@ - "%1$s s\'est arrêté la dernière fois qu\'il a été utilisé. Souhaitez-vous partager un rapport d\'incident avec nous ?" - "Vous semblez secouer le téléphone de frustration. Voulez-vous ouvrir le formulaire de rapport de problème ?" + "%1$s s’est arrêté la dernière fois qu’il a été utilisé. Souhaitez-vous partager un rapport d’incident avec nous ?" + "Vous semblez secouer le téléphone avec frustration. Voulez-vous ouvrir le formulaire de rapport de problème ?" diff --git a/features/rageshake/impl/src/main/res/values-de/translations.xml b/features/rageshake/impl/src/main/res/values-de/translations.xml index f1a25237bf..63564615b8 100644 --- a/features/rageshake/impl/src/main/res/values-de/translations.xml +++ b/features/rageshake/impl/src/main/res/values-de/translations.xml @@ -4,12 +4,12 @@ "Sie können mich kontaktieren, wenn Sie weitere Fragen haben." "Kontaktieren Sie mich" "Bildschirmfoto bearbeiten" - "Bitte beschreiben Sie den Fehler. Was haben Sie getan? Was haben Sie erwartet, was passiert? Was ist tatsächlich passiert. Bitte gehen Sie so detailliert wie möglich vor." - "Beschreiben Sie den Fehler…" - "Wenn möglich, verfassen Sie die Beschreibung bitte auf Englisch." + "Bitte beschreibe den Fehler. Was hast du getan? Was hast du erwartet, was passiert? Was ist tatsächlich passiert. Bitte gehe so detailliert wie möglich vor." + "Beschreibe den Fehler…" + "Wenn möglich, verfasse die Beschreibung bitte auf Englisch." "Absturzprotokolle senden" "Protokolle zulassen" "Bildschirmfoto senden" - "Die Protokolle werden Ihrer Nachricht beigefügt, um sicherzustellen, dass alles ordnungsgemäß funktioniert. Um Ihre Nachricht ohne Protokolle zu senden, deaktivieren Sie diese Einstellung." - "%1$s ist bei der letzten Nutzung abgestürzt. Möchten Sie einen Absturzbericht mit uns teilen?" + "Die Protokolle werden Ihrer Nachricht beigefügt, um sicherzustellen, dass alles ordnungsgemäß funktioniert. Um deine Nachricht ohne Protokolle zu senden, deaktiviere diese Einstellung." + "%1$s ist bei der letzten Nutzung abgestürzt. Möchtest du einen Absturzbericht mit uns teilen?" diff --git a/features/rageshake/impl/src/main/res/values-fr/translations.xml b/features/rageshake/impl/src/main/res/values-fr/translations.xml index cd800881dc..ed2d9f7e96 100644 --- a/features/rageshake/impl/src/main/res/values-fr/translations.xml +++ b/features/rageshake/impl/src/main/res/values-fr/translations.xml @@ -3,13 +3,13 @@ "Joindre une capture d’écran" "Vous pouvez me contacter si vous avez des questions complémentaires." "Contactez-moi" - "Modifier la capture d\'écran" - "S\'il vous plait, veuillez décrire le bogue. Qu\'avez-vous fait ? À quoi vous attendiez-vous ? Que s\'est-il réellement passé. Veuillez ajouter le plus de détails possible." - "Décrire le bogue" + "Modifier la capture d’écran" + "S’il vous plait, veuillez décrire le problème. Qu’avez-vous fait ? À quoi vous attendiez-vous ? Que s’est-il réellement passé ? Veuillez ajouter le plus de détails possible." + "Décrire le problème" "Si possible, veuillez rédiger la description en anglais." "Envoyer des journaux d’incident" "Autoriser à inclure les journaux techniques" "Envoyer une capture d’écran" - "Pour vérifier que les choses fonctionnent comme prévu, des journaux techniques seront envoyés avec votre message. Pour l’envoyer sans ces journaux, désactivez ce paramètre." - "%1$s s\'est arrêté la dernière fois qu\'il a été utilisé. Souhaitez-vous partager un rapport d\'incident avec nous ?" + "Pour vérifier que les choses fonctionnent comme prévu, des journaux techniques seront envoyés avec votre message. Pour ne pas envoyer ces journaux, désactivez ce paramètre." + "%1$s s’est arrêté la dernière fois qu’il a été utilisé. Souhaitez-vous partager un rapport d’incident avec nous ?" diff --git a/features/roomdetails/impl/src/main/res/values-de/translations.xml b/features/roomdetails/impl/src/main/res/values-de/translations.xml index e4f43c1ffe..1495840415 100644 --- a/features/roomdetails/impl/src/main/res/values-de/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-de/translations.xml @@ -10,11 +10,11 @@ "Raum bearbeiten" "Es ist ein unbekannter Fehler aufgetreten und die Informationen konnten nicht geändert werden." "Raum kann nicht aktualisiert werden" - "Nachrichten sind mit Schlössern gesichert. Nur Sie und die Empfänger haben die eindeutigen Schlüssel, um sie zu entsperren." + "Nachrichten sind mit Schlössern gesichert. Nur du und die Empfänger haben die eindeutigen Schlüssel, um sie zu entsperren." "Nachrichtenverschlüsselung aktiviert" "Beim Laden der Benachrichtigungseinstellungen ist ein Fehler aufgetreten." - "Die Stummschaltung dieses Raums ist fehlgeschlagen, bitte versuchen Sie es erneut." - "Die Deaktivierung der Stummschaltung dieses Raums ist fehlgeschlagen, bitte versuchen Sie es erneut." + "Die Stummschaltung dieses Raums ist fehlgeschlagen, bitte versuche es erneut." + "Die Deaktivierung der Stummschaltung dieses Raums ist fehlgeschlagen, bitte versuche es erneut." "Personen einladen" "Benutzerdefiniert" "Standard" @@ -25,23 +25,23 @@ "Ausstehend" "Raummitglieder" "Benutzerdefinierte Einstellung zulassen" - "Wenn Sie diese Option aktivieren, wird Ihre Standardeinstellung außer Kraft gesetzt." - "Benachrichtigen Sie mich in diesem Chat bei" - "Sie können das in Ihrem %1$s ändern." + "Wenn du diese Option aktivierst, wird deine Standardeinstellung außer Kraft gesetzt." + "Benachrichtige mich in diesem Chat bei" + "Du kannst das in deinem %1$s ändern." "Globale Einstellungen" "Standardeinstellung" "Benutzerdefinierte Einstellung entfernen" "Beim Laden der Benachrichtigungseinstellungen ist ein Fehler aufgetreten." - "Fehler beim Wiederherstellen des Standardmodus. Bitte versuchen Sie es erneut." - "Fehler beim Einstellen des Modus. Bitte versuchen Sie es erneut." + "Fehler beim Wiederherstellen des Standardmodus. Bitte versuche es erneut." + "Fehler beim Einstellen des Modus. Bitte versuche es erneut." "Alle Nachrichten" "Nur Erwähnungen und Schlüsselwörter" - "Benachrichtigen Sie mich in diesem Raum bei" + "Benachrichtige mich in diesem Raum bei" "Sperren" - "Gesperrte Benutzer können Ihnen keine Nachrichten senden und alle ihre Nachrichten werden ausgeblendet. Sie können sie jederzeit entsperren." + "Gesperrte Benutzer können dir keine Nachrichten senden und alle ihre Nachrichten werden ausgeblendet. Du kannst sie jederzeit entsperren." "Benutzer sperren" "Entsperren" - "Sie können dann wieder alle Nachrichten von ihnen sehen." + "Du kannst dann wieder alle Nachrichten von ihnen sehen." "Benutzer entsperren" "Raum verlassen" "Personen" diff --git a/features/roomdetails/impl/src/main/res/values-fr/translations.xml b/features/roomdetails/impl/src/main/res/values-fr/translations.xml index d8dbd878d4..7efbe4c1f7 100644 --- a/features/roomdetails/impl/src/main/res/values-fr/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-fr/translations.xml @@ -6,44 +6,44 @@ "Ajouter un sujet" "Déjà membre" - "Déjà invité" - "Modifier la salle" - "Une erreur inconnue s\'est produite et les informations n\'ont pas pu être modifiées." - "Impossible de mettre à jour la salle" - "Les messages sont sécurisés par des verrous. Seuls vous et les destinataires possédez les clés uniques pour les déverrouiller." - "Cryptage des messages activé" - "Une erreur s\'est produite lors du chargement des paramètres de notification." - "Échec de la mise en sourdine de cette salle, veuillez réessayer." - "Échec de la désactivation de la mise en sourdine de cette salle, veuillez réessayer." + "Déjà invité(e)" + "Modifier le salon" + "Une erreur inconnue s’est produite et les informations n’ont pas pu être modifiées." + "Impossible de mettre à jour le salon" + "Les messages sont sécurisés par des clés de chiffrement. Seuls vous et les destinataires possédez les clés uniques pour les déverrouiller." + "Chiffrement des messages activé" + "Une erreur s’est produite lors du chargement des paramètres de notification." + "Échec de la mise en sourdine de ce salon, veuillez réessayer." + "Échec de la désactivation de la mise en sourdine de ce salon, veuillez réessayer." "Inviter des personnes" "Personnalisé" "Défaut" "Notifications" - "Nom de la salle" - "Partager la salle" - "Mise à jour de la salle…" + "Nom du salon" + "Partager le salon" + "Mise à jour du salon…" "En attente" - "Membres de la salle" + "Membres du salon" "Autoriser les paramètres personnalisés" - "L\'activation de cette option annulera votre paramètre par défaut" - "Prévenez-moi dans ce chat pour" + "L’activation de cette option annulera votre paramètre par défaut" + "Prévenez-moi dans ce salon pour" "Vous pouvez le modifier dans votre %1$s." "paramètres globaux" "Paramètre par défaut" "Supprimer le paramètre personnalisé" - "Une erreur s\'est produite lors du chargement des paramètres de notification." + "Une erreur s’est produite lors du chargement des paramètres de notification." "Échec de la restauration du mode par défaut, veuillez réessayer." "Échec de la configuration du mode, veuillez réessayer." "Tous les messages" "Mentions et mots clés uniquement" - "Dans cette salle, prévenez-moi pour" + "Dans ce salon, prévenez-moi pour" "Bloquer" "Les utilisateurs bloqués ne pourront pas vous envoyer de messages et tous leurs messages seront masqués. Vous pouvez les débloquer à tout moment." - "Bloquer l\'utilisateur" + "Bloquer l’utilisateur" "Débloquer" - "Vous pourrez à nouveau voir tous leurs messages." - "Débloquer un utilisateur" - "Quitter la salle" + "Vous pourrez à nouveau voir tous ses messages." + "Débloquer l’utilisateur" + "Quitter le salon" "Personnes" "Sécurité" "Sujet" diff --git a/features/roomlist/impl/src/main/res/values-de/translations.xml b/features/roomlist/impl/src/main/res/values-de/translations.xml index 8ce40240ae..c24d2146a4 100644 --- a/features/roomlist/impl/src/main/res/values-de/translations.xml +++ b/features/roomlist/impl/src/main/res/values-de/translations.xml @@ -1,7 +1,7 @@ "Eine neue Unterhaltung oder einen neuen Raum erstellen" - "Beginnen Sie, indem Sie jemandem eine Nachricht senden." + "Beginne, indem du jemandem eine Nachricht sendest." "Noch keine Chats." "Alle Chats" "Es sieht aus, als würden Sie ein neues Gerät verwenden. Verifizieren Sie es mit einem anderen Gerät, damit Sie auf Ihre verschlüsselten Nachrichten zugreifen können." diff --git a/features/roomlist/impl/src/main/res/values-fr/translations.xml b/features/roomlist/impl/src/main/res/values-fr/translations.xml index 0380971724..2a14d1f4f4 100644 --- a/features/roomlist/impl/src/main/res/values-fr/translations.xml +++ b/features/roomlist/impl/src/main/res/values-fr/translations.xml @@ -1,9 +1,9 @@ - "Créer une nouvelle conversation ou une nouvelle salle" - "Commencez par envoyer un message à quelqu\'un." + "Créer une nouvelle discussion ou un nouveau salon" + "Commencez par envoyer un message à quelqu’un." "Aucune discussion pour le moment." - "Tous les chats" - "Il semblerait que vous utilisiez un nouvel appareil. Vérifiez que vous êtes bien autorisé à accéder à vos messages cryptés." + "Conversations" + "Il semblerait que vous utilisiez un nouvel appareil. Vérifiez la session avec un autre de vos appareils pour accéder à vos messages chiffrés." "Vérifier que c’est bien vous" diff --git a/features/verifysession/impl/src/main/res/values-fr/translations.xml b/features/verifysession/impl/src/main/res/values-fr/translations.xml index 83de83146f..9339d6c760 100644 --- a/features/verifysession/impl/src/main/res/values-fr/translations.xml +++ b/features/verifysession/impl/src/main/res/values-fr/translations.xml @@ -3,17 +3,17 @@ "Quelque chose ne va pas. Soit la demande a expiré, soit elle a été refusée." "Confirmez que les emojis ci-dessous correspondent à ceux affichés sur votre autre session." "Comparez les émojis" - "Votre nouvelle session est désormais vérifiée. Elle a accès à vos messages cryptés et les autres utilisateurs la verront identifiée comme fiable." - "Prouvez qu\'il s\'agit bien de vous pour accéder à l\'historique de vos messages cryptés." + "Votre nouvelle session est désormais vérifiée. Elle a accès à vos messages chiffrés et les autres utilisateurs la verront identifiée comme fiable." + "Prouvez qu’il s’agit bien de vous pour accéder à l’historique de vos messages chiffrés." "Ouvrir une session existante" "Réessayer la vérification" "Je suis prêt.e" "En attente de correspondance" - "Comparez les emoji uniques en veillant à ce qu\'ils apparaissent dans le même ordre." + "Comparez les emoji uniques en veillant à ce qu’ils apparaissent dans le même ordre." "Ils ne correspondent pas" "Ils correspondent" "Pour continuer, acceptez la demande de lancement de la procédure de vérification dans votre autre session." - "En attente d\'acceptation de la demande" + "En attente d’acceptation de la demande" "Vérification annulée" "Démarrer" diff --git a/libraries/androidutils/src/main/res/values-fr/translations.xml b/libraries/androidutils/src/main/res/values-fr/translations.xml index b974766fce..a575424b39 100644 --- a/libraries/androidutils/src/main/res/values-fr/translations.xml +++ b/libraries/androidutils/src/main/res/values-fr/translations.xml @@ -1,4 +1,4 @@ - "Aucune application compatible n\'a été trouvée pour gérer cette action." + "Aucune application compatible n’a été trouvée pour gérer cette action." diff --git a/libraries/eventformatter/impl/src/main/res/values-fr/translations.xml b/libraries/eventformatter/impl/src/main/res/values-fr/translations.xml index b81dc80c0d..f7c12a2028 100644 --- a/libraries/eventformatter/impl/src/main/res/values-fr/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-fr/translations.xml @@ -1,29 +1,29 @@ - "(l\'avatar a aussi été modifié)" + "(l’avatar a aussi été modifié)" "%1$s a changé son avatar" - "Vous avez changé d\'avatar" - "%1$s a changé son nom d\'affichage de %2$s à %3$s" - "Vous avez changé votre nom d\'affichage de %1$s à %2$s" - "%1$s a supprimé leur nom d\'affichage (c\'était %2$s)" - "Vous avez supprimé votre nom d\'affichage (c\'était %1$s)" - "%1$s a défini son nom d\'affichage en tant que %2$s" - "Vous avez défini votre nom d\'affichage comme %1$s" - "%1$s a changé l\'avatar de la salle" - "Vous avez changé l\'avatar de la salle" - "%1$s a supprimé l\'avatar de la salle" - "Vous avez supprimé l\'avatar de la salle" + "Vous avez changé d’avatar" + "%1$s a changé son pseudonyme de %2$s à %3$s" + "Vous avez changé votre pseudonyme de %1$s à %2$s" + "%1$s a supprimé son pseudonyme (c’était %2$s)" + "Vous avez supprimé votre pseudonyme (c’était %1$s)" + "%1$s a défini son pseudonyme en tant que %2$s" + "Vous avez défini votre pseudonyme comme %1$s" + "%1$s a changé l’avatar du salon" + "Vous avez changé l’avatar du salon" + "%1$s a supprimé l’avatar du salon" + "Vous avez supprimé l’avatar du salon" "%1$s a banni %2$s" "Vous avez banni %1$s" - "%1$s a créé la salle" - "Vous avez créé la salle" + "%1$s a créé le salon" + "Vous avez créé le salon" "%1$s a invité %2$s" - "%1$s a accepté l\'invitation" - "Vous avez accepté l\'invitation" + "%1$s a accepté l’invitation" + "Vous avez accepté l’invitation" "Vous avez invité %1$s" - "%1$s vous a invité" - "%1$s a rejoint la salle" - "Vous avez rejoint la salle" + "%1$s vous a invité(e)" + "%1$s a rejoint le salon" + "Vous avez rejoint le salon" "%1$s a demandé à rejoindre" "%1$s a autorisé %2$s à rejoindre" "%1$s vous a autorisé à rejoindre" @@ -32,25 +32,25 @@ "Vous avez rejeté la demande de %1$s pour rejoindre" "%1$s a rejeté votre demande pour rejoindre" "%1$s n’est plus intéressé à rejoindre" - "Vous avez annulé votre demande d\'adhésion" - "%1$s a quitté la salle" - "Vous avez quitté la salle" - "%1$s a changé le nom de la salle en : %2$s" - "Vous avez changé le nom de la salle en : %1$s" - "%1$s a supprimé le nom de la salle" - "Vous avez supprimé le nom de la salle" - "%1$s a rejeté l\'invitation" - "Vous avez refusé l\'invitation" + "Vous avez annulé votre demande d’adhésion" + "%1$s a quitté le salon" + "Vous avez quitté le salon" + "%1$s a changé le nom du salon en : %2$s" + "Vous avez changé le nom du salon en : %1$s" + "%1$s a supprimé le nom du salon" + "Vous avez supprimé le nom du salon" + "%1$s a rejeté l’invitation" + "Vous avez refusé l’invitation" "%1$s a supprimé %2$s" "Vous avez supprimé %1$s" - "%1$s a envoyé une invitation à %2$s à rejoindre le salle" - "Vous avez envoyé une invitation à %1$s pour rejoindre la salle" - "%1$s a révoqué l\'invitation de %2$s à rejoindre la salle" - "Vous avez révoqué l\'invitation de %1$s à rejoindre la salle" - "%1$s a changé le sujet pour : %2$s" - "Vous avez changé le sujet pour : %1$s" - "%1$s a supprimé le sujet de la salle" - "Vous avez supprimé le sujet de la salle" + "%1$s a envoyé une invitation à %2$s à rejoindre le salon" + "Vous avez envoyé une invitation à %1$s pour rejoindre le salon" + "%1$s a révoqué l’invitation de %2$s à rejoindre le salon" + "Vous avez révoqué l’invitation de %1$s à rejoindre le salon" + "%1$s a changé le sujet pour : %2$s" + "Vous avez changé le sujet pour : %1$s" + "%1$s a supprimé le sujet du salon" + "Vous avez supprimé le sujet du salon" "%1$s a débanni %2$s" "Vous avez débanni %1$s" "%1$s a effectué un changement inconnu à son adhésion" diff --git a/libraries/push/impl/src/main/res/values-de/translations.xml b/libraries/push/impl/src/main/res/values-de/translations.xml index 48c14e8247..1f05b0f171 100644 --- a/libraries/push/impl/src/main/res/values-de/translations.xml +++ b/libraries/push/impl/src/main/res/values-de/translations.xml @@ -7,13 +7,13 @@ "** Fehler beim Senden - bitte Raum öffnen" "Beitreten" "Ablehnen" - "Sie wurden zu einem Chat eingeladen" + "Du wurdest zu einem Chat eingeladen" "Neue Nachrichten" "Reagiert mit %1$s" "Als gelesen markieren" - "Sie wurden eingeladen, den Raum zu betreten" + "Du wurdest eingeladen, den Raum zu betreten" "Ich" - "Sie sehen sich die Benachrichtigung an! Klicken Sie hier!" + "Du siehst dir die Benachrichtigung an! Klicke hier!" "%1$s: %2$s" "%1$s: %2$s %3$s" "%1$s und %2$s" @@ -43,7 +43,7 @@ "%d Raum" "%d Räume" - "Wählen Sie aus, wie Sie Benachrichtigungen erhalten möchten" + "Wähle aus, wie du Benachrichtigungen erhalten möchtest" "Hintergrundsynchronisation" "Google-Dienste" "Keine gültigen Google Play-Dienste gefunden. Benachrichtigungen funktionieren möglicherweise nicht richtig." diff --git a/libraries/push/impl/src/main/res/values-fr/translations.xml b/libraries/push/impl/src/main/res/values-fr/translations.xml index 67309cfc27..8ba38a31c3 100644 --- a/libraries/push/impl/src/main/res/values-fr/translations.xml +++ b/libraries/push/impl/src/main/res/values-fr/translations.xml @@ -1,27 +1,27 @@ "Appel" - "À l\'écoute des événements" + "À l’écoute des événements" "Notifications bruyantes" "Notifications silencieuses" - "** Échec de l\'envoi - veuillez ouvrir la salle" + "** Échec de l’envoi - veuillez ouvrir le salon" "Rejoindre" "Rejeter" - "Vous a invité à discuter" + "Vous a invité(e) à discuter" "Nouveaux messages" "A réagi avec %1$s" "Marquer comme lu" - "Vous a invité à rejoindre la salle" + "Vous a invité(e) à rejoindre le salon" "Moi" - "Vous êtes en train de consulter la notification ! Cliquez sur moi !" - "%1$s : %2$s" - "%1$s : %2$s %3$s" + "Vous êtes en train de voir la notification ! Cliquez-moi !" + "%1$s : %2$s" + "%1$s : %2$s %3$s" "%1$s et %2$s" "%1$s dans %2$s" "%1$s dans %2$s et %3$s" - "%1$s : %2$d message" - "%1$s : %2$d messages" + "%1$s : %2$d message" + "%1$s : %2$d messages" "%d notification" @@ -40,13 +40,13 @@ "%d messages notifiés non lus" - "%d salle" - "%d salles" + "%d salon" + "%d salons" "Choisissez le mode de réception des notifications" "Synchronisation en arrière-plan" "Services Google" - "Aucun service Google Play valide n\'a été trouvé. Les notifications peuvent ne pas fonctionner correctement." + "Aucun service Google Play valide n’a été trouvé. Les notifications peuvent ne pas fonctionner correctement." "Notification" "Réponse rapide" diff --git a/libraries/ui-strings/src/main/res/values-de/translations.xml b/libraries/ui-strings/src/main/res/values-de/translations.xml index d1af3b9cd1..9bf32a2cc6 100644 --- a/libraries/ui-strings/src/main/res/values-de/translations.xml +++ b/libraries/ui-strings/src/main/res/values-de/translations.xml @@ -33,7 +33,7 @@ "Einladen" "Freunde einladen" "Freunde einladen %1$s" - "Laden Sie Personen in %1$s ein" + "Lade Personen in %1$s ein" "Einladungen" "Mehr erfahren" "Verlassen" @@ -65,7 +65,7 @@ "Start" "Chat starten" "Verifizierung starten" - "Tippen Sie, um die Karte zu laden" + "Tippe, um die Karte zu laden" "Foto machen" "Quelle anzeigen" "Ja" @@ -120,7 +120,7 @@ "Nach jemandem suchen" "Suchergebnisse" "Sicherheit" - "Wählen Sie Ihren Server aus" + "Wähle deinen Server aus" "Wird gesendet…" "Server wird nicht unterstützt" "Server-URL" @@ -157,18 +157,18 @@ "Reisen & Orte" "Symbole" "Fehler beim Erstellen des Permalinks" - "%1$s konnte die Karte nicht laden. Bitte versuchen Sie es später erneut." + "%1$s konnte die Karte nicht laden. Bitte versuche es später erneut." "Fehler beim Laden der Nachrichten" - "%1$s konnte nicht auf Ihren Standort zugreifen. Bitte versuchen Sie es später erneut." - "%1$s hat keine Erlaubnis, auf Ihren Standort zuzugreifen. Sie können den Zugriff in den Einstellungen aktivieren." - "%1$s hat keine Erlaubnis, auf Ihren Standort zuzugreifen. Aktivieren Sie unten den Zugriff." + "%1$s konnte nicht auf Ihren Standort zugreifen. Bitte versuche es später erneut." + "%1$s hat keine Erlaubnis, auf Ihren Standort zuzugreifen. Du kannst den Zugriff in den Einstellungen aktivieren." + "%1$s hat keine Erlaubnis, auf Ihren Standort zuzugreifen. Aktiviere unten den Zugriff." "Einige Nachrichten wurden nicht gesendet" "Entschuldigung, es ist ein Fehler aufgetreten" "🔐️ Begleite mich auf %1$s" - "Hey, sprechen Sie mit mir auf %1$s: %2$s" - "Sind Sie sicher, dass Sie diesen Raum verlassen möchten? Sie sind die einzige Person hier. Wenn Sie austreten, kann in Zukunft niemand mehr eintreten, auch Sie nicht." - "Sind Sie sicher, dass Sie diesen Raum verlassen möchten? Dieser Raum ist nicht öffentlich und Sie können ihm ohne Einladung nicht erneut beitreten." - "Sind Sie sicher, dass Sie den Raum verlassen wollen?" + "Hey, sprich mit mir auf %1$s: %2$s" + "Bist du sicher, dass du diesen Raum verlassen möchtest? Du bist die einzige Person hier. Wenn du austritst, kann in Zukunft niemand mehr eintreten, auch du nicht." + "Bist du sicher, dass du diesen Raum verlassen möchtest? Dieser Raum ist nicht öffentlich und du kannst ihm ohne Einladung nicht erneut beitreten." + "Bist du sicher, dass du den Raum verlassen willst?" "%1$s Android" "%1$d Mitglied" @@ -178,8 +178,8 @@ "%d Stimme" "%d Stimmen" - "Schütteln Sie heftig zum Melden von Fehlern" - "Sie scheinen das Telefon aus Frustration zu schütteln. Möchten Sie den Bildschirm für den Fehlerbericht öffnen?" + "Schüttel heftig zum Melden von Fehlern" + "Du scheinst das Telefon aus Frustration zu schütteln. Möchtest du den Bildschirm für den Fehlerbericht öffnen?" "Diese Meldung wird an den Administrator Ihres Homeservers weitergeleitet. Dieser kann keine verschlüsselten Nachrichten lesen." "Grund für die Meldung dieses Inhalts" "Aufzählungsliste umschalten" @@ -206,43 +206,33 @@ "Dies ist der Anfang dieses Gesprächs." "Neu" "Analysedaten teilen" - "Anzeigename" - "Ihr Anzeigename" - "Ein unbekannter Fehler ist aufgetreten und die Informationen konnten nicht geändert werden." - "Profil kann nicht aktualisiert werden" - "Profil bearbeiten" - "Profil wird aktualisiert…" - "Medienauswahl fehlgeschlagen, bitte versuchen Sie es erneut." - "Fehler beim Verarbeiten des hochgeladenen Mediums. Bitte versuchen Sie es erneut." - "Das Hochladen der Medien ist fehlgeschlagen. Bitte versuchen Sie es erneut." + "Medienauswahl fehlgeschlagen, bitte versuche es erneut." + "Fehler beim Verarbeiten des hochgeladenen Mediums. Bitte versuche es erneut." + "Das Hochladen der Medien ist fehlgeschlagen. Bitte versuche es erneut." "Zusätzliche Einstellungen" "Audio- und Videoanrufe" "Konfiguration stimmt nicht überein" - "Wir haben die Einstellungen für Benachrichtigungen vereinfacht, damit die Optionen leichter zu finden sind. - -Einige benutzerdefinierte Einstellungen, die Sie in der Vergangenheit gewählt haben, werden hier nicht angezeigt, sind aber immer noch aktiv. - -Wenn Sie fortfahren, können sich einige Ihrer Einstellungen ändern." + "Wir haben die Einstellungen für Benachrichtigungen vereinfacht, damit die Optionen leichter zu finden sind. Einige benutzerdefinierte Einstellungen, die du in der Vergangenheit gewählt hast, werden hier nicht angezeigt, sind aber immer noch aktiv. Wenn du fortfährst, können sich einige deiner Einstellungen ändern." "Direkte Chats" "Benutzerdefinierte Einstellung pro Chat" "Beim Aktualisieren der Benachrichtigungseinstellungen ist ein Fehler aufgetreten." "Alle Nachrichten" "Nur Erwähnungen und Schlüsselwörter" - "Bei direkten Chats, benachrichtigen Sie mich bei" - "Bei Gruppenchats benachrichtigen Sie mich bei" + "Bei direkten Chats, benachrichtige mich bei" + "Bei Gruppenchats benachrichtige mich bei" "Benachrichtigungen auf diesem Gerät aktivieren" - "Die Konfiguration wurde nicht korrigiert, bitte versuchen Sie es erneut." + "Die Konfiguration wurde nicht korrigiert, bitte versuche es erneut." "Gruppenchats" "Erwähnungen" "Alle" "Erwähnungen" "Benachrichtige mich bei" "Benachrichtige mich bei @room" - "Um Benachrichtigungen zu erhalten, ändern Sie bitte Ihre %1$s." + "Um Benachrichtigungen zu erhalten, ändere bitte deine %1$s." "Systemeinstellungen" "Systembenachrichtigungen deaktiviert" "Benachrichtigungen" - "Prüfen Sie, ob Sie alle aktuellen und zukünftigen Nachrichten dieses Benutzers ausblenden möchten" + "Prüfe, ob du alle aktuellen und zukünftigen Nachrichten dieses Benutzers ausblenden möchtest" "Konto und Geräte" "Standort teilen" "Meinen Standort teilen" @@ -258,8 +248,8 @@ Wenn Sie fortfahren, können sich einige Ihrer Einstellungen ändern." "en" "Fehler" "Erfolg" - "Teilen Sie anonyme Nutzungsdaten, um uns bei der Identifizierung von Problemen zu helfen." - "Sie können alle unsere Bedingungen lesen%1$s." + "Teile anonyme Nutzungsdaten, um uns bei der Identifizierung von Problemen zu helfen." + "Du kannst alle unsere Bedingungen lesen %1$s." "hier" "Benutzer sperren" diff --git a/libraries/ui-strings/src/main/res/values-fr/translations.xml b/libraries/ui-strings/src/main/res/values-fr/translations.xml index f6dc4f5ac0..e014230a00 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -21,7 +21,7 @@ "Copier le lien" "Copier le lien vers le message" "Créer" - "Créer une salle" + "Créer un salon" "Refuser" "Désactiver" "Terminé" @@ -37,53 +37,53 @@ "Invitations" "En savoir plus" "Quitter" - "Quitter la salle" + "Quitter le salon" "Gérer le compte" - "Gérez les appareils" + "Gérez les sessions" "Suivant" "Non" "Pas maintenant" "OK" - "Ouvrez avec" + "Ouvrir avec" "Réponse rapide" "Citer" "Réagissez" - "Enlever" + "Supprimer" "Répondre" "Répondre dans le fil de discussion" - "Signaler un bogue" + "Signaler un problème" "Signaler le contenu" "Réessayer" - "Réessayer le décryptage" + "Réessayer le déchiffrement" "Enregistrer" "Rechercher" "Envoyer" "Envoyer un message" "Partager" "Partager le lien" - "Sauter" + "Passer" "Démarrer" - "Démarrer la discussion" + "Démarrer une discussion" "Commencer la vérification" - "Appuyez pour charger la carte" + "Cliquez pour charger la carte" "Prendre une photo" "Afficher la source" "Oui" "À propos" - "Politique d\'utilisation acceptable" + "Politique d’utilisation acceptable" "Paramètres avancés" - "Statistiques d\'utilisation" + "Statistiques d’utilisation" "Audio" "Bulles" - "Droits d\'auteur" - "Création de salle…" - "Quitter la salle" - "Erreur de décryptage" + "Droits d’auteur" + "Création du salon…" + "Quitter le salon" + "Erreur de déchiffrement" "Options pour les développeurs" "(modifié)" "Édition" "* %1$s %2$s" - "Cryptage activé" + "Chiffrement activé" "Erreur" "Fichier" "Fichier enregistré dans Téléchargements" @@ -91,12 +91,12 @@ "GIF" "Image" "En réponse à %1$s" - "Cet identifiant Matrix est introuvable, il est donc possible que l\'invitation ne soit pas reçue." - "Quitter la salle" + "Cet identifiant Matrix est introuvable, il est donc possible que l’invitation ne soit pas reçue." + "Quitter le salon…" "Lien copié dans le presse-papiers" "Chargement…" "Message" - "Mode d\'affichage des messages" + "Mode d’affichage des messages" "Message supprimé" "Moderne" "Mettre en sourdine" @@ -106,18 +106,18 @@ "Personnes" "Permalien" "Nombre total de votes : %1$s" - "Les résultats s\'afficheront une fois le sondage terminé" + "Les résultats s’afficheront une fois le sondage terminé" "Politique de confidentialité" "Réaction" "Réactions" "Actualisation…" "En réponse à %1$s" - "Signaler un bogue" + "Signaler un problème" "Rapport soumis" "Éditeur de texte enrichi" - "Nom de la salle" + "Nom du salon" "par exemple, le nom de votre projet" - "Rechercher quelqu\'un" + "Rechercher quelqu’un" "Résultats de la recherche" "Sécurité" "Sélectionnez votre serveur" @@ -125,8 +125,8 @@ "Serveur non pris en charge" "URL du serveur" "Paramètres" - "Emplacement partagé" - "Démarrer le chat…" + "Position partagée" + "Création de la discussion…" "Autocollant" "Succès" "Suggestions" @@ -135,13 +135,13 @@ "Avis de tiers" "Fil de discussion" "Sujet" - "De quoi s\'agit-il dans cette salle ?" + "De quoi s’agit-il dans ce salon ?" "Échec de déchiffrement" - "Les invitations n\'ont pas pu être envoyées à un ou plusieurs utilisateurs." - "Impossible d\'envoyer une ou plusieurs invitations" + "Les invitations n’ont pas pu être envoyées à un ou plusieurs utilisateurs." + "Impossible d’envoyer une ou plusieurs invitations" "Annuler la sourdine" "Événement non pris en charge" - "Nom d\'utilisateur" + "Nom d’utilisateur" "Vérification annulée" "Vérification terminée" "Vidéo" @@ -157,18 +157,18 @@ "Voyages & lieux" "Symboles" "Échec de la création du permalien" - "%1$s n\'a pas pu charger la carte. Veuillez réessayer ultérieurement." + "%1$s n’a pas pu charger la carte. Veuillez réessayer ultérieurement." "Échec du chargement des messages" - "%1$s n\'a pas pu accéder à votre emplacement. Veuillez réessayer ultérieurement." - "%1$s n\'est pas autorisé à accéder à votre position. Vous pouvez activer l\'accès dans les Paramètres." - "%1$s n\'est pas autorisé à accéder à votre position. Activez l\'accès ci-dessous." - "Certains messages n\'ont pas été envoyés" - "Désolé, une erreur s\'est produite" + "%1$s n’a pas pu accéder à votre position. Veuillez réessayer ultérieurement." + "%1$s n’est pas autorisé à accéder à votre position. Vous pouvez activer l’accès dans les Paramètres." + "%1$s n’est pas autorisé à accéder à votre position. Activez l’accès ci-dessous." + "Certains messages n’ont pas été envoyés" + "Désolé, une erreur s’est produite" "🔐️ Rejoignez-moi sur %1$s" "Salut, parle-moi sur %1$s : %2$s" - "Êtes-vous sûr de vouloir quitter cette salle ? Vous êtes la seule personne ici. Si vous partez, personne ne pourra rejoindre la salle à l\'avenir, y compris vous." - "Êtes-vous sûr de vouloir quitter cette salle ? Cette salle n\'est pas publique et vous ne pourrez pas la rejoindre sans invitation." - "Êtes-vous sûr de vouloir quitter la salle ?" + "Êtes-vous sûr de vouloir quitter ce salon ? Vous êtes la seule personne ici. Si vous partez, personne ne pourra rejoindre le salon à l’avenir, y compris vous." + "Êtes-vous sûr de vouloir quitter ce salon ? Ce salon n’est pas public et vous ne pourrez pas le rejoindre sans invitation." + "Êtes-vous sûr de vouloir quitter le salon ?" "%1$s Android" "%1$d membre" @@ -178,9 +178,9 @@ "%d vote" "%d votes" - "Rageshake pour signaler un bogue" - "Vous semblez secouer le téléphone de frustration. Voulez-vous ouvrir le formulaire de rapport de problème ?" - "Ce message sera signalé à l’administrateur de votre serveur d\'accueil. Ils ne pourront lire aucun message crypté." + "Rageshake pour signaler un problème" + "Vous semblez secouer le téléphone avec frustration. Voulez-vous ouvrir le formulaire de rapport de problème ?" + "Ce message sera signalé à l’administrateur de votre serveur d’accueil. Il ne pourra lire aucun message chiffré." "Raison du signalement de ce contenu" "Afficher une liste à puces" "Fermer les options de formatage" @@ -205,13 +205,7 @@ "Ceci est le début de %1$s." "Ceci est le début de cette conversation." "Nouveau" - "Partagez des données de statistiques d\'utilisation" - "Nom d\'affichage" - "Votre nom d\'affichage" - "Une erreur inconnue s\'est produite et les informations n\'ont pas pu être modifiées." - "Impossible de mettre à jour le profil" - "Modifier le profil" - "Mise à jour du profil…" + "Partagez des données de statistiques d’utilisation" "Échec de la sélection du média, veuillez réessayer." "Échec du traitement des médias à télécharger, veuillez réessayer." "Échec du téléchargement du média, veuillez réessayer." @@ -224,42 +218,42 @@ Certains paramètres personnalisés que vous avez choisis par le passé ne sont Si vous continuez, il est possible que certains de vos paramètres soient modifiés." "Discussions directes" - "Paramétrage personnalisé par chat" - "Une erreur s\'est produite lors de la mise à jour du paramètre de notification." + "Paramétrage personnalisé par salon" + "Une erreur s’est produite lors de la mise à jour du paramètre de notification." "Tous les messages" "Mentions et mots clés uniquement" - "Sur les chats directs, prévenez-moi pour" + "Sur les discussions directes, prévenez-moi pour" "Lors de discussions de groupe, prévenez-moi pour" "Activer les notifications sur cet appareil" - "La configuration n\'a pas été corrigée, veuillez réessayer." + "La configuration n’a pas été corrigée, veuillez réessayer." "Discussions de groupe" "Mentions" "Tous" "Mentions" "Prévenez-moi pour" - "Prévenez-moi sur @salle" + "Prévenez-moi si un message contient \"@room\"" "Pour recevoir des notifications, veuillez modifier votre %1$s." "paramètres du système" "Les notifications du système sont désactivées" "Notifications" "Cochez si vous souhaitez masquer tous les messages actuels et futurs de cet utilisateur." - "Compte et appareils" - "Emplacement partagé" - "Partager mon emplacement" + "Compte et sessions" + "Partage de position" + "Partager ma position" "Ouvrir dans Apple Maps" "Ouvrir dans Google Maps" "Ouvrir dans OpenStreetMap" - "Partager cet emplacement" - "Emplacement" + "Partager cet position" + "Position" "Rageshake" "Seuil de détection" "Général" - "Version : %1$s ( %2$s )" + "Version : %1$s ( %2$s )" "Ang." "Erreur" "Succès" - "Partagez des données d\'utilisation anonymes pour nous aider à identifier les problèmes." + "Partagez des données d’utilisation anonymes pour nous aider à identifier les problèmes." "Vous pouvez lire toutes nos conditions %1$s." "ici" - "Bloquer l\'utilisateur" + "Bloquer l’utilisateur" diff --git a/libraries/ui-strings/src/main/res/values-sk/translations.xml b/libraries/ui-strings/src/main/res/values-sk/translations.xml index 53fc0a1045..b5cf4f97e9 100644 --- a/libraries/ui-strings/src/main/res/values-sk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml @@ -208,12 +208,6 @@ "Toto je začiatok tejto konverzácie." "Nové" "Zdieľať analytické údaje" - "Zobrazované meno" - "Vaše zobrazované meno" - "Vyskytla sa neznáma chyba a informácie nebolo možné zmeniť." - "Nepodarilo sa aktualizovať profil" - "Upraviť profil" - "Aktualizácia profilu…" "Nepodarilo sa vybrať médium, skúste to prosím znova." "Nepodarilo sa spracovať médiá na odoslanie, skúste to prosím znova." "Nepodarilo sa nahrať médiá, skúste to prosím znova." diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 6509f3787e..a6908484b1 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -206,21 +206,13 @@ "This is the beginning of this conversation." "New" "Share analytics data" - "Display name" - "Your display name" - "An unknown error was encountered and the information couldn\'t be changed." - "Unable to update profile" - "Edit profile" - "Updating profile…" "Failed selecting media, please try again." "Failed processing media to upload, please try again." "Failed uploading media, please try again." "Additional settings" "Audio and video calls" "Configuration mismatch" - "We’ve simplified Notifications Settings to make options easier to find. - -Some custom settings you’ve chosen in the past are not shown here, but they’re still active. + "We’ve simplified Notifications Settings to make options easier to find. Some custom settings you’ve chosen in the past are not shown here, but they’re still active. If you proceed, some of your settings may change." "Direct chats" From 6497d2184fc4539c495bd0d5f31a68d9db3451e3 Mon Sep 17 00:00:00 2001 From: David Langley Date: Mon, 18 Sep 2023 16:03:30 +0100 Subject: [PATCH 223/234] Add test. --- .../roomlist/impl/RoomListPresenterTests.kt | 35 +++++++++++++++++-- .../matrix/test/room/RoomSummaryFixture.kt | 5 +++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt index a9327f64df..9b10a55461 100644 --- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt @@ -38,6 +38,7 @@ import io.element.android.libraries.designsystem.utils.SnackbarDispatcher import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter import io.element.android.libraries.eventformatter.test.FakeRoomLastMessageFormatter import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.verification.SessionVerificationService import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus import io.element.android.libraries.matrix.test.AN_AVATAR_URL @@ -47,6 +48,7 @@ import io.element.android.libraries.matrix.test.A_ROOM_NAME import io.element.android.libraries.matrix.test.A_USER_ID 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.notificationsettings.FakeNotificationSettingsService import io.element.android.libraries.matrix.test.room.aRoomSummaryFilled import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService @@ -61,6 +63,7 @@ import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test +import kotlin.time.Duration.Companion.milliseconds class RoomListPresenterTests { @@ -153,7 +156,7 @@ class RoomListPresenterTests { roomListService = roomListService ) val scope = CoroutineScope(coroutineContext + SupervisorJob()) - val presenter = createRoomListPresenter(matrixClient, coroutineScope = scope) + val presenter = createRoomListPresenter(client = matrixClient, coroutineScope = scope) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -328,6 +331,34 @@ class RoomListPresenterTests { } } + @Test + fun `present - change in notification settings updates the summary for decorations`() = runTest { + val userDefinedMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY + val notificationSettingsService = FakeNotificationSettingsService() + val roomListService = FakeRoomListService() + roomListService.postAllRooms(listOf(aRoomSummaryFilled(notificationMode = userDefinedMode))) + val matrixClient = FakeMatrixClient( + roomListService = roomListService, + notificationSettingsService = notificationSettingsService + ) + val scope = CoroutineScope(coroutineContext + SupervisorJob()) + val presenter = createRoomListPresenter(client = matrixClient , coroutineScope = scope) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + notificationSettingsService.setRoomNotificationMode(A_ROOM_ID, userDefinedMode) + + val updatedState = consumeItemsUntilPredicate { state -> + state.roomList.any { it.id == A_ROOM_ID.value && it.notificationMode == userDefinedMode } + }.last() + + val room = updatedState.roomList.find { it.id == A_ROOM_ID.value } + Truth.assertThat(room?.notificationMode).isEqualTo(userDefinedMode) + cancelAndIgnoreRemainingEvents() + scope.cancel() + } + } + private fun TestScope.createRoomListPresenter( client: MatrixClient = FakeMatrixClient(), sessionVerificationService: SessionVerificationService = FakeSessionVerificationService(), @@ -339,7 +370,7 @@ class RoomListPresenterTests { givenFormat(A_FORMATTED_DATE) }, roomLastMessageFormatter: RoomLastMessageFormatter = FakeRoomLastMessageFormatter(), - coroutineScope: CoroutineScope = this + coroutineScope: CoroutineScope = this, ) = RoomListPresenter( client = client, sessionVerificationService = sessionVerificationService, diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt index 12b0325da5..d3b4dbc577 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt @@ -20,6 +20,7 @@ import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.TransactionId import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.roomlist.RoomSummary import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails import io.element.android.libraries.matrix.api.room.message.RoomMessage @@ -48,6 +49,7 @@ fun aRoomSummaryFilled( lastMessage: RoomMessage? = aRoomMessage(), lastMessageTimestamp: Long? = null, unreadNotificationCount: Int = 2, + notificationMode: RoomNotificationMode? = null, ) = RoomSummary.Filled( aRoomSummaryDetail( roomId = roomId, @@ -57,6 +59,7 @@ fun aRoomSummaryFilled( lastMessage = lastMessage, lastMessageTimestamp = lastMessageTimestamp, unreadNotificationCount = unreadNotificationCount, + notificationMode = notificationMode, ) ) @@ -68,6 +71,7 @@ fun aRoomSummaryDetail( lastMessage: RoomMessage? = aRoomMessage(), lastMessageTimestamp: Long? = null, unreadNotificationCount: Int = 2, + notificationMode: RoomNotificationMode? = null, ) = RoomSummaryDetails( roomId = roomId, name = name, @@ -76,6 +80,7 @@ fun aRoomSummaryDetail( lastMessage = lastMessage, lastMessageTimestamp = lastMessageTimestamp, unreadNotificationCount = unreadNotificationCount, + notificationMode = notificationMode ) fun aRoomMessage( From b80366692c99d009f4d2a7c2f9d7bfbcc967e8aa Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 18 Sep 2023 17:06:35 +0200 Subject: [PATCH 224/234] Ignore false positive on monochrome icon. --- tools/lint/lint.xml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/lint/lint.xml b/tools/lint/lint.xml index ce49e50a7a..715131226a 100644 --- a/tools/lint/lint.xml +++ b/tools/lint/lint.xml @@ -1,5 +1,4 @@ - - From f7ae97f126ce5e8ac73fb6be528453153da57683 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Mon, 18 Sep 2023 15:20:45 +0000 Subject: [PATCH 225/234] Update screenshots --- ...lidNotificationSettingsViewDark_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...lidNotificationSettingsViewight_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...imepickers_TimePickerHorizontal_0_null,NEXUS_5,1.0,en].png | 4 ++-- ...s_TimePickerVerticalPreviewDark_0_null,NEXUS_5,1.0,en].png | 4 ++-- ..._TimePickerVerticalPreviewLight_0_null,NEXUS_5,1.0,en].png | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_InvalidNotificationSettingsViewDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_InvalidNotificationSettingsViewDark_0_null,NEXUS_5,1.0,en].png index f7d27ba4c0..c95a41feee 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_InvalidNotificationSettingsViewDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_InvalidNotificationSettingsViewDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fbece1a3764a140e2e8218d34517461809acf67ea87715140fa22b81ffa9d7c0 -size 42771 +oid sha256:ef2654539817251b9580fbf1d4fd0f581eb5800a60f8986d04d94c6785b2fd9f +size 42012 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_InvalidNotificationSettingsViewight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_InvalidNotificationSettingsViewight_0_null,NEXUS_5,1.0,en].png index eee59588f1..e39ff5329b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_InvalidNotificationSettingsViewight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.preferences.impl.notifications_null_InvalidNotificationSettingsViewight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a6c2719db95641bd6c2b613c65008ebecb8f8989d74d76c8070da0d741be3e7d -size 43506 +oid sha256:f99b8193089b4719c75acdee6339cc89307fb16255cf6e7deaf4486b03c42505 +size 42728 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_TimePickerHorizontal_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_TimePickerHorizontal_0_null,NEXUS_5,1.0,en].png index 10ce5f04d2..ff1a6cdeb9 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_TimePickerHorizontal_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_TimePickerHorizontal_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:678b668924c4caf77efe31bd15bf7f913e61aad0f90c645972cf9b6b32655321 -size 36710 +oid sha256:3b223d67c600c32363c53c1c7bbf7c4c10f8b7fa209a72ead71b9939768c0b9b +size 36363 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalPreviewDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalPreviewDark_0_null,NEXUS_5,1.0,en].png index d51b5f5dca..7d042ae2fd 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalPreviewDark_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalPreviewDark_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b49e0d05c9cc99cd8ddac92915f3a1e4512cc74871fee9800212dac26f23183a -size 25484 +oid sha256:370400027756777a5240d8f2bb3dd422980c850676ef6b88c6c4e8fd712f26a2 +size 25421 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalPreviewLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalPreviewLight_0_null,NEXUS_5,1.0,en].png index 4449d071e9..c7a2dc0082 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalPreviewLight_0_null,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalPreviewLight_0_null,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6b1a400702bc068f95af12f725392d51ed3b81389e480b9b28acbb48822e2029 -size 26312 +oid sha256:559c4cf12e91b924ef9fd45dce6645f1fcbafc603fc834b1ba0ab9af6387a227 +size 26253 From 67b9e94e195d0a383431a201082c58aa7dce3f7a Mon Sep 17 00:00:00 2001 From: David Langley Date: Mon, 18 Sep 2023 16:24:54 +0100 Subject: [PATCH 226/234] Fix unused import. --- .../android/features/roomlist/impl/RoomListPresenterTests.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt index 9b10a55461..db2f7027c4 100644 --- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt @@ -63,7 +63,6 @@ import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test -import kotlin.time.Duration.Companion.milliseconds class RoomListPresenterTests { From 6947fb1ba1cfa39b91b9ed180b46047e9994920d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 18 Sep 2023 19:48:30 +0200 Subject: [PATCH 227/234] Iterate on onboarding and welcome screens. --- .../atomic/atoms/ElementLogoAtom.kt | 26 ++++++++++++++++-- .../drawable-night-xxhdpi/element_logo.png | Bin 0 -> 72919 bytes .../main/res/drawable-night/onboarding_bg.png | Bin 397677 -> 413555 bytes .../main/res/drawable-xxhdpi/element_logo.png | Bin 0 -> 72689 bytes .../src/main/res/drawable/onboarding_bg.png | Bin 227910 -> 233286 bytes 5 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 libraries/designsystem/src/main/res/drawable-night-xxhdpi/element_logo.png create mode 100644 libraries/designsystem/src/main/res/drawable-xxhdpi/element_logo.png diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/ElementLogoAtom.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/ElementLogoAtom.kt index 5edc527821..2460d61b49 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/ElementLogoAtom.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/ElementLogoAtom.kt @@ -22,6 +22,7 @@ import androidx.compose.foundation.border import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -50,8 +51,9 @@ fun ElementLogoAtom( val blur = if (darkTheme) 160.dp else 24.dp //box-shadow: 0px 6.075949668884277px 24.30379867553711px 0px #1B1D2280; val shadowColor = if (darkTheme) size.shadowColorDark else size.shadowColorLight + val logoShadowColor = if (darkTheme) size.logoShadowColorDark else size.logoShadowColorLight val backgroundColor = if (darkTheme) Color.White.copy(alpha = 0.2f) else Color.White.copy(alpha = 0.4f) - val borderColor = if (darkTheme) Color.White.copy(alpha = 0.8f) else Color.White.copy(alpha = 0.4f) + val borderColor = if (darkTheme) Color.White.copy(alpha = 0.89f) else Color.White Box( modifier = modifier .size(size.outerSize) @@ -89,7 +91,21 @@ fun ElementLogoAtom( .blurCompat(blur) ) Image( - modifier = Modifier.size(size.logoSize), + modifier = Modifier + .size(size.logoSize) + // Do the same double shadow than on Figma... + .shadow( + elevation = 25.dp, + clip = false, + shape = CircleShape, + ambientColor = logoShadowColor, + ) + .shadow( + elevation = 25.dp, + clip = false, + shape = CircleShape, + ambientColor = Color(0x80000000), + ), painter = painterResource(id = R.drawable.element_logo), contentDescription = null ) @@ -101,6 +117,8 @@ sealed class ElementLogoAtomSize( val logoSize: Dp, val cornerRadius: Dp, val borderWidth: Dp, + val logoShadowColorDark: Color, + val logoShadowColorLight: Color, val shadowColorDark: Color, val shadowColorLight: Color, val shadowRadius: Dp, @@ -110,6 +128,8 @@ sealed class ElementLogoAtomSize( logoSize = 83.5.dp, cornerRadius = 33.dp, borderWidth = 0.38.dp, + logoShadowColorDark = Color(0x4D000000), + logoShadowColorLight = Color(0x66000000), shadowColorDark = Color.Black.copy(alpha = 0.4f), shadowColorLight = Color(0x401B1D22), shadowRadius = 32.dp, @@ -120,6 +140,8 @@ sealed class ElementLogoAtomSize( logoSize = 110.dp, cornerRadius = 44.dp, borderWidth = 0.5.dp, + logoShadowColorDark = Color(0x4D000000), + logoShadowColorLight = Color(0x66000000), shadowColorDark = Color.Black, shadowColorLight = Color(0x801B1D22), shadowRadius = 60.dp, diff --git a/libraries/designsystem/src/main/res/drawable-night-xxhdpi/element_logo.png b/libraries/designsystem/src/main/res/drawable-night-xxhdpi/element_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..d65c54da178cff9e0f0425d82196c74d0ffdfe15 GIT binary patch literal 72919 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 literal 0 HcmV?d00001 diff --git a/libraries/designsystem/src/main/res/drawable-night/onboarding_bg.png b/libraries/designsystem/src/main/res/drawable-night/onboarding_bg.png index df307073175aa335d8c0caf4a73da582ee67d2e6..2f51442fd342f56845f38c9e6790bb88e3928679 100644 GIT binary patch literal 413555 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 ?+e(O5JjSI701TM6 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 z%0A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

    `=THeSaN01r~VC06TB=BR^G)o_PkiH%FHE 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®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

    r-UBAz zqnD8a(UTL1d94I7T#7N6>@i8KPrG8mayO7<7pnjqV$nPB%wzF)WZ((%yUwngwa+vZ zQsjm=Q2D&Ci9g}>X$|tG0NffLZl1K@GtUc3C}dO85G7yJ`peqy zKb@R$p4A$e%FD$W+}w^G-PX$IF1qmRSWBly04@d8G!EMQ&h#+(Z@RTng6J~B@nYeM zHyow2Bs#D2N*A~kiK(=JPNK+^rh(B@6Jljx9=}PtKlU>GaDfp<_rfFcJ28Q6lk7hF z?TtU9^)lYSfr1N7B}d|w%-rDBn>ra7JuqD1pDtLoQ}q8W`=+5Y(jcJ20Mg604KA8N z^UU;N5WI~8JPtzcS7Gx%x%ErD znTd&f0=UNN#t$|Q*4Z>6GcHrti#L5QDPlhYpF_{=LjPbjO+wG`l=R3UpJ4RdOHs;P zF>SsxU-EtE8(7o4jXq|6HUJ3^N$caSak{S`4E$%VIgVW$6^9Mz#xE6F-kfB;Ct>kp zRoBynq6;;Te{Fn-`o2$--%p>fY+9(<*yHn<7teVb3Ff7-k51CAnU}}E!umRP#4#EE zb@2AUS`#I14Nm=HBdC~i#`7}2=t#c`GR{Tj1Z}3H^xyn_9jp7u1~B{=)-$$HJv8hB z_>7l)U=DcZJTwe1`N!Php2vqa5UyA0b3hV7usjZ5gh)=gptQ`_>K1r^bcKCCL=P;h zQ^A3o5azY`lQBz{F7KgncCeR~@wiq;D!#bM(&xqbFDC2~p9yOfz+I0Kdfx3Yu#@#Cl+3|-&vH++b2S4W|ZM$!K@jbgJYR6`;6Og*Ays4=*q?m?B^c|X;CX9`2(Gm>=tL1a>#EV^xPM>++ zECHL}_EOeW&(s1t%>Tn}w^qi+H{$_rHtN}Y$1?>Z`2@qsdG9i<*b%gGF`pH<(^btt zJ$4l4lV6k+lZ3yvy(Bpd#bj<$$SyjR82eT51JlM#jnIUkCnzkNXYQ{&vRv>?fck}i zqr8|;gyHMKVLRz&Q!}eX~c>}T(Er|lRo{M zmKc>wrj>WiNDuwy7+%Y|Om`YBBvvwk(J5a)oRFlKGIpq8Qi#twE$P+Aej0QKxzqfX zvrcvg(u)|=3cLhBG?OA*UP%MbXmE$7YWo)9^oUBEmV*?|#Q1t}X(tgL%4a_{)* zkNboal|Gm3)%cWVfbjq#KjYQJU z4!rSbkS$EDQnHy*k(T`8#jJEcZj~NAn%vZ6)h*pU!}HFxb&~Xr}De#o)oM1 z%0EmG7SXVpH-gJ{E~iXjRVtne!Vi1Skl>lnno4@5i!jSc9E_NbPnNfx)PX^52nG^7r)6eNTID{Ff!Q<#h33N znA z0zNzeqi+u46&#of#>-5t*K@OzbTOUGGiDAoAzc(#@D1N(wc?C0g5~`m=7C|#We6w3 zz9z844oa@wjMZl-g7vR*%9HitLXe&oG5@Jw#TziLjh74W5vqF`J9N2hcB8X9<3Pfk8GXLA~uO#U^erxR4uppkwW|0PiB_&>f}Y#Lo0XUy>g^k34B( zvgl(Q2)n=TS)op}XXA$!IxdHT+y3(mT=m^NL*`YJNs({iW;Qw{5`SE@r59(lHfOGf zquTTl6I^<~@o={jQOQ+5N+a{GBANm&%x~-J!*ZbYj-Q(cKj}d7JX>pVar~9mEL?XQ zoR8f|V)NdwiHzgB#Lp)d9fNZV07%=9TNKIX^e8Qu(hBroUld5nekz!2Gj)d}Xi z-&0jEzl}mbGA}x~;Jk$yzBsNM{QE4-Z^a)eejz@^!6BL#!)dhMcwm2>#t~!lsn1wQ zjF2&kC*P|lQ|g^r$BziES6*z|u*zf*t>!~G<6<|(Q|`L0;g$HM7E5SzorHr>ju|!n zk*OBHGuIbA|NO4_$=f4c$_tlqvwnzU9e5KZe3V>P1C)cKXL{a`R9yzyBG1%Ioj_4{oOkUpy}V#uno#)L-bfVjhP_%ERjHw>kA3%kK&?Thp=0tb@jUO|K zaM^}$5E$;J5%Q|o85bSnRkkKe@}Icqd~6l+TTjoQG0JY7nBi2I&O^ceEV@4!|E=N2 zGd>spceyjqPe|E2@@>nolcLik74#bCoqlg_f^87-=Kk>F^V%5F#+}-c7K}GO80KqO z6gsA1TQ*4Rg2@iD34*}$zd9Wzh3Jr2O0qXRl2Vg=j`SdYS~U)ReJ#s|_FYUq>O*px zk+{54)~tg5VDAmtD-5W9h)-^?+7t}8JUT@5%oxc>NJyn8m7ip~h?ZWHO8oPPk}4{5 z;2ofJb1LS4^%!jp6ALBb4@Q~ z6&JOAoCQcQkzYn>LXTlOugrrNW7LSH&2L#-A^`>JG*}Bi&!vFhy0J0lDTs--ONT*` z@)ai8MY0$_n>O5JP}i2Q{A-Nk(9N&w*Y|#J934-j1~37&#dgO1nuXKBmhGMjm2?}c zxhKdy_*8x&JX9#Xz$q#&dKZ5JCVBN=vbaj}O-GF0gXJ)O^ja8C#c=|r`f@B8Hqm{L z!idZ*_@!%YJT&2iW@n`dE>o7_y~qODIy=#|xncfDXTkGj9r23sbAF5s$+nUL6CiB{ z>6&9!`_I7RcmyJ072&b{tMv%m;SQw>|N=o_xwX{5Wix(T#ZYM zr0BFJi)F*~;le|r=N2&jvev4e`cF2o@TNhE_JgnJ9eha* z%rx)=6C!_UID|LV(@)*wN6!vC$CDx_$3uS;*JkX*;7>k0+*t^5})ef z2_$28And_5MmQ?DDZL;=QTZzaxB0nc9dVs6g--Be5)_}KC!b{^z@|H`(b74gNjbcb zEt<7RY#Ss#xWFEJ#eCD%=L7N9&}OLZ4tw|7eOQQz;iK&&Nv|=B)t}Co8Ej$-ztRt< z1ChDmh$Zi#Ors3#jbX4>gia6i$wF z#63D{3C}4r=EX80c?!|>sL_b>sCn>9Fy3{Ge%PE?3DaE*jOMbBKwnQ`KXi_|Nk3st zFzzq5VWz0zl3jPc&J@`(jjf40eM1R`~8M-dG%Wi|EgH6wM$CgVqnTp%}=(hUbq+X*G3qCp1K8s6FFnZOhaH@1gNl z)GN+tyA^ySnnHeYr|yK?_0889zXJR)PpC?Hb)LvW8rqnMcGB~5f>S_KMPEdENC3e zM;h7+qWoZ^GYWWY^?Yw1GgMA1NHnGn78jhw~ve&9m;ZwAYhGCaXS=OSK)DxB&n^^Wd+V#xyQ=3Ot zdB`bzKO*asizAZ*?g};ZBF{9No%_Yq3Q&)5NWG8aeQJ#cFg_(2!##|XVHPc5dO~;1 zZ;uvvH!6ieDTI;_ZjK${u8ixhea%e`ZY;}QOYG|XX_9~~``hOrRGaat+SWcM z5+OaoqT0V3s$nFI?(do#y@Kk}oE$lZ`P{uYC;1KGLmSTK6Kq0+ZghIzx+8WsZ&5g>IgX2MN%1Oj zI?zS#=Bswiw%~MP(MY-e$p1EHz4A7eB$Y+cxTz7`l4_BI6qmJ*4YN2sCf(EQBv=x=0Rw+A^>;w&A)C zCKt$yo5gJ}{Pr?0SQdPmF!pB<^#jawUr;*_Z3?lcINjB_Io*}$&o9@5@d|t|Xp6~I z8DLH`!gAe`321%Mo4Msk%<-myx(?Y2jXk48W4X*)d$9r7wc+sjAM=I7j=4nO#Y8Eb zlpFxz2jc_M)HH+?+i94;^U1I0F&2ni*dFR@y^De7=O^Xcv_c3Uy4c@z%Ek8a=%^m& zV*LppDxQZXB_6)fWT`{01#S-9!g144@tiMoO`@*pOcNLBG&w0gu>cZE6b$~_O;zL! z205S0(4sV1e2lnh;m7oQO=&GvhK2a~oWpJeqTff4tND?DTRaZ|T@(MP612ggvBScx za7VMAO8Y71rP;|;`uhGq8XcL>#O-m$qcHLU2hyZ`uj$03aK!gR=vB0sVfM?c{>!Kv z)-SwJSA)HuYl4-z63uD=n66U@I;lZ)_UBokcB_p?HXa;))?-Tta^+?)EMPfT9vUFy*{aA=FqkivO;9wY(-3O7I>fQhWAAMCz1YE)gL=gm%FYCrY(`RAY8hx08^r%qJd$pZ$uNjSLBEm*#*>`uT6rADg zy8d|{N#VjJX9Aw5RgOGkcKU~vP#nVR;5YzAJ|UA%@uxbc+m|sB1lsn?ropn^w1q!f z#05a8O+LwmXmQ%EIvsnt7JW3<@!X2W<2(_@6{B|yVM$x;gb!U>F>*IN2*6*B+6{{T>a<#Aq2vs|TlH8zE}KzwKXh`5^9<}o%r z(EWya=#cpO@!Sp7h?u|^iad=KgMhAeN{3uUCbHmCLKR*92{p6yJ z+l%r`!7Yl5djqm(H?nqgLfKUK|x26d$2 zRs&L2uu-Du-hrF@G)co{;rv?R|78Ceht!J6=0o2T|EN(*w0F&d_rTz9q-6KQ>d{FrL(0UG>3TXIsLa9pu0SUhl{-+R31t9TF)QXzn>5& z-72?{SI<2{^G1+qlGsMoLbx3Smj8EH5k0jhpifRHP;%ir4P)U97z&chGgqGJZ_-p2 z++YRy*B!p{>S}lRBZCxtY^T+b#EmAzE}{bK9=8ESmp3Rd`>4k#{0|LFiPRnI z@sV5wt^7_#+w*h%L3p@dvgF1_#2Lf4=wV2~ZW!L=qlM_8b3S8@@%7CP#MSAYWrdbu z*xYGIVDn913qJ%~vxoQQtW_-bICc)&sFbGgl?JDp8>>y@|EKI-6lLd8=Fp-uIeGsV zUYuzgs4Ar1f6_DGUbZZ82Z7|v>+dP}o2Zglx*t7%H7Hq5;X4?*h&8N0?6G0yWHnH` zkn{#ibr5q=l8tYG_7;Pq`T7$mX@8WrIa&Doda67|1|aU~nv6SuC;0-?c0aV;Xw)&} zv+;j@{4bs0UAUz@M`Qftowi*tXqzVY{FBDdjQKnH)dDJi6fG(Ip8ashdKVxq!zrp3 z?avO#b1+U;;~wM5e?M#tHzn({XUl5a+gUFz*b4VUXvnGv=py(ijJ>uM!%VvTRL_#swynRNPxfvdUvATT?lnJ(x0+= zFMj3mSGPztE-l)A(^PVU%J1d(823H?8^WsB=aXZQ4Nzt)Gk$VNIkb_c)Y5wb#nAms zCC~qB;tu-a=*g1h5s#T4CfV&GK=4SosN=Lq`HpK|6-OElF@MA1*M%0q|5mccL9!ZT zG?UJRM=lA?B6Dw7TKJYCp)WCo2Ukld6V>@7>T#Djmb|B84`1z7w$GOUP~K4bLo^V| zaTLyUJB;{UD975J68_9qhF>VB%CvTd%*WHl+n`*or2T#z8cTyo^384<>-V;lSvj-k zQo=~B%#8vUSb_VPreo8qGIg3D$y^>V_YT8x8(6q(c^G0Rf)`>tHZ;VS7q6irIQ8p1 z0f;mCZ$FDIU&R@a^BdjfwC6R63nX8>{KD@xGwo-5DbA#Q?m|NGI)1Dq?4u|zB2gP4 z5x1i9XEM8V&LX7cnB$MT|M&M%naXt*Eo^sv7p>60LPxCKgzzG0aKKCo&TX2VjjS7v zvjR)jmt2XM%D zym^!{gFBqZ7_KbJyIfWx;PL>>-X+1qrp@NfJf;rPM3~JlK)AkJ0?ap9hELj#^~L&m z2%0v_iBfMbYO_t}TOnJ<4NJb9JYW3}!99@WTBc?{4VnW6rO5xb;;)(4&{s5DAtZ!6 zw>`Do=bY>|Q^YTS;kyHaIU#Y$X>7TxypQ5Q|4GVX7e*?hT~IU*>u*Iw?_lj~%CEFx z-HMedMNf(I`3{H%)k*y6AcAqudxF(*+E;v>0ak@?0pKtrXnHF2TCje4PXemOWDHUu zAv7h{$~+DF-H{RaiyxynE(vWLz;$vHS_G&)*D!66aH#afTKOkMd6}q&;#lWJ<13H+ z`8KHt^Tz9|ct;lLiN;lalMD<3sJZQ(kXUpm%m!q^>!y=K9$3-dtW{=}Fj;9A&Vn^S zj}4YFF-@WqoAg>5ep=a?p6eOe|--MtAhV)yd}2TWSMSQ8#X z?E{Fd2dL~A{C81gDzaoQpnl@&3K;1jK3e*Zf6yX<3|34);Huu!aXrI7r`}@uYz&XC zww=*dC@R(#<*8I;3H3Qxr2-gdhYM4mFv zixCo|w4JZwW&h2?e$&+GCNwB4eQN>;oO-~8{%H$N0!r8LCY~PuE<7M~Vowll5Bs;1 zs?TQ}Zr%*DZJ>$m;2Ck)x53r%ay;e|dMq+JV2EVnhNpBi9|fdMP&a{N_8xp}R(`&J zpAQk~w>uioUVK=$aD~{j%58Vjm!0&9~`yhhdTz!c?<1nvw`2Mw?nBsJfssg zoc{MX7#}h(;bxSFy`Z78w&@?Pf3=-Xp!FEBd?$VPO!Y%*PJ7(pzUk-6x9AJHGved1 zQW^CvlPPul*jbUc5hP{>@nA5e zM;+vuZGcq~bYe%+VwjC}EiI7mD2K(1S@BCZcni>gS&7+(8w)>!TEoNyid3gvlYq;W zw6W;$Roc8vLOm{(u15#;h@>T2qVq5IEbGnQ;( zt*s0Wq4AQSjjW>syY^Kc!~WpL3oc_;Vm4Dqz>~{8>(=n$JqTp9FEh<^xL*~l{liz5 z+vpA*%Qg0A;+23TK5GXhjHsbI*SYg}*H2u&7c+Q=&m3DDIfRdiATP=z6Ox!eSs`XR z&Gl7~oBaYuGJlc(mMiUTtrW+))kxZ#tBA8O>6j^Gjh@FBgI?V=n3Q2cW2M7&zIBm6W*CqEdE1H0_w8CUpImfovM_dz zzC&jTJLKCed%Vi^;9YSqo?aA!W1&Cj#ll(RO}1)}2IaC7AnnI(SIQS?BYkW>4ch1p zXD*&K7aM&8EAv?mzyZg`PjIQ8Vk6KbS@0dm|eDS`W`XhwLj>_hdf^e(-thcxu3IrX=;r0{sa>{gQ z#JE`pCT=N*<;cnGVHDL9AeOtwI-#pc@}4%^i6g^gw|79+Tm4?1W|DV$ptL}7vd=tJ zu6Dyg9Evc$NM<#}+SL#qujew3ti=4wb}6!!O^xHsLq)<_N;a`E0ty=Up$vp)i?_Z z;J55{0b)D~T_N<{iaxci(6;pJN@E|#lEvu?LHk+BW+&Tm;}fFFSVb75z#1CgYtqH! zuwl_BV7xj0K3_#1woFc*JGAAIU^fiH{)qp-w3X!;{W3VcNFh9qQ(ABQ-PRhEMo)14 z)wYdS3lF`0wUbGgbDe1{78*@vkX-<^!D9<~wS1e{0kspi{F;jW}OoaN{5b4Ng`wWQI}HhV2Hgw{Un z0)b|!F!IJGZpBC2!H^@x1Whl6Hz^V>-zb@)DqwHS(qhYs5Q9&?zrR1hGkl6nwD5Uf z!;4W#9lWC`bpJ*7QD)^@N*~>N!e!hr`kc?^*j!DC1Yv!NkVfW{>m#fVd>ZYmcfwZ% zGA?{J!pj?0HV+6EJ-Q1(c)kKLZ>^fRE|a_jP9~0U*#Ov+L0Y0x`Uu4jOA>8f#6_0| zKkQo^bGw|1Rwm;eD6<1B;JVa4J=xbkiADSO-)E&3C+(`2U_!f-a^6m|cAG*9z!~!5 z^;>EDZ>#DtlYU4XYX&e`hZ{~Tq3Cr>l-xs}HvKM6xGe9PjLHKN!P(ZyfXd((eY*NQ zO8aSVfE7LpQ=`7Z-MmD}adZn7sK)v(3SED3!1cH`w6!_Z?L^yNY4-#YIO)N*eX$9X z4VG=by+lsVqk>l2qTtW%E=udB6YCdTaBSQ=%TrfNGergA|>+V}v^u9cQM3y5v zl?8N+@PEknBBz2xopKRmNPyd{iFy1#c}+rs6%`SOjZ+?8T?cfCaR0a!H-HvTlJJQ=$C?vhZuv!)!dvr_6YK(NE9Z*3?{cKjFK|mgOZ^a2 z8@enZuQ>7%9yu8DofFd4x@^BX5^JH)mbrfDxmY^-3_Wq-%XoBqu$>x>R|-=ylQ<*} zm>uMazx!KZDD<-k%GJ1Z7s14N%L`PUQXHF1ByKqnWTB&zNb9!}PKT*v6AmP)jvx3o zoErS{$($ILmqUCNr#A(P62^0JZ8kf)|>Bygi{6{OPH-_ zdn4b-p?MPr9X=sMt7C;Gbi>68H6lZJ;L-6>w7zp!2P_D^N>pPKe2Yv=I9f-+P-r-Z z&VVKnnCoFXO%qN7i~qe-M452bj#K~3uC`7f?fbkZAjmANNoE<-{Cdo&@t759p?wPh zMlPM?VTw>2^JZ40L;c1kFWny_$%`Oav z`Sa$(c*5vpL{t|JKbt<^1n6&UZxX~MS9_~m;=pgd4NZ7|$i!#}`e5pcEe_Z^{F;2P zvAZqCr&kiL$MR)%CWdz&^w=J(U-mc@7z~LBA#xnsevc1TH(hNl7yft5p$t2r^spZn zdn27Y(%#`&kgY%F8{hwnn|F9uxw)%|9Epy8`ImE>8+UF>qPhB;+(_H(&ZzCpIJfz> z?v5SJaPI(E-@qZW;Q??y;j-=>9o6#|uO^H$>`s#icEs_YKRl2hD13Jc9b&G<46MCrLrHX*7bQ zXxLrPO#jlZhxucN=n9twWiDCW3j}TNhDCJAb!?y}EZqfqVHE!2ou=Gl1*G1pv}oga zJ`d8kd)(ij`VN7o@Va*-HXhRbKeuZ^(_fOGwlX4~1OA-ITa1hy&JM^U>oV88S-$+_ zn%Y&|+7!-8wr?2h8I(+4O<$G5#b1GPGkaBQ7Ci#1Y17HH6J6&=cWT}%!7>ng)F86AFHxa_+Z;X6?&lVOuXIB^&H;>&b-@UBT@(-oc+0e0ILh7QqXc!D&% z4NRU>K7^PvN#frhB!t*tx2Gqc?~Em1ASaOprytM-WG0oqLZ!-qhIUOF4bE}B1|N8^ zU=$zF)p1dfC6c0paCs<=W1d1&#JQUh+aHv6qYtBR;M5099O1ih(zjP&iLb6JovUr! zGypFcTwbgm;|5FUZrB=%M%2rP zh{pAQGhvR^>w)bSO4m*-EsTyRzb78koc_{h_ts8^t5`2x>#b9}FnDQJ7$3nwp`8VV zU*m05aQbn|&x~6dFTNUi%h>|*#Fdoxese2vQ zd^3T5d&&;Lwoe78vK|5*cArn&EP0t6DtRC-w<#79En|V7n|{)5Ni+a1A*qyL{ONh( zl=Fo9x3Zb;7le*<}FXrIc0%Y>Tplp&N^F3AcEdqBqmIwTUb{;UA2ut)kNFJAd+BNY{xfglsQ$gW3|K+oW$aw9nY&A-(OyABE{}=_!xd8ZX~i_IDYe$HJ)a(?LhrN<;m;Qe$WyIW6O@o z6+pea3{;Qdz@Oiz?XD)n2o|_zhdoT%C>GVN_ka3K7!GVxzOGs?GP&{!*NMucCsv_l z7p3t7_ry!!xBJ8Orb*ANJK^i!CVUqL7q~T{j9*S@s>E~CG_tAIguLyF z`dH>UC*gMq-A zzjjh@34f|Wt35lKNwXyWn#?PA2V5-6Oh9*F!|Mj1=Y7Dq4>G`##)$#5N?I(Qx-@rX?_4*f%Z{vps zV@~!sY+cidqae*hr3KES_W_|wDvP(IXYt2@?*;uZB9?53lQa#SP0I|s!@`9Qf90z1 zIzt53(Ce#Os?Yk*6fx zsOx#Xj&q#Id&}l5E~qnp!(b)Pai{B8rSFME^pk>@stTiJ{Gw>bbq0=u*G}ed^6P|F zaW{-mxm@6LCo0_iFCXU{n4XpOKa-r=qDqfla!~v?SoiBMtZUH--;IKi(&PHuKnhRY zp%y(fNr;BslS9ytMWiYG8$4(M1i{_D;;Zy3tMTRlj)GuBaFa>H6P|Im8z!V`6XfZ$ zY;=ikguIKY*vZyb^P2}W!kHg|KrR^^v1 zKxRzf+!5QyLfRUy@>%lQatAInFPT^}oiKZ{_V>3RX5X~%Hb)&B2iyl1#CP(<6&Kyd z1#jcZ-2Sh6$a`A^(ybUVLLCwYe~%kH1v>`^>RsYwL=#bz5wYs^AgnXN4w*l1B@nvwYw!Wkxf|YB z9>u8E-tEbULv>KJ02r9bT!f~2NW~v(#oWL*ucXA309^5Oz?yxc6|{V{H~9R9%CBUg za$G)Ke6D~JVY*QpxZ2j&)?*htcO7EU`Jns6x+Hr}o+T`RTi&sdd7QKP&JIK5mP5nf z2nGu#-*sIQtkzkjjn%~y-+`?>1rA?uwqC-gfEc)t-=<=5uL=^T}ac`=o8*)f*gv<{ant#FE-*6YBSV9`g6 z9=8Z5pvk4i5iUMJ+@oapsZL6#z-T||d3~NEfsU)g*a~e{l3`NxMwZB@`+t^egpCcg z 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�% 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�k7Q$(ANC{-9jSxnVa2W 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 z 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 diff --git a/libraries/designsystem/src/main/res/drawable-xxhdpi/element_logo.png b/libraries/designsystem/src/main/res/drawable-xxhdpi/element_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..a5e24f328be1222949fb32cc4f3ce2f69a25191e GIT binary patch literal 72689 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%0Aq*!&vKLcNmipGZ$p2 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

    B>D1M;(5Dztzgq`oC6db{H>164M(Q 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 i3tc?GAXHM6)x^Mf!ua39!+G3+y5ZPAKAyQL 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
    Z_Nm(ikR(Ytf>j3xEMxg~`aFf~g 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