From 25824ca6140d6a2b83e0b352a48fcdc129d8b8a5 Mon Sep 17 00:00:00 2001 From: yostyle Date: Tue, 8 Aug 2023 15:22:49 +0200 Subject: [PATCH 01/56] 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 175ccd95b24a3aa02d3b65961a923e168299dcd1 Mon Sep 17 00:00:00 2001 From: yostyle Date: Tue, 8 Aug 2023 16:02:08 +0200 Subject: [PATCH 02/56] 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 fdea1913cca8eaf3c29d2be5f23fd1ab3affe7dc Mon Sep 17 00:00:00 2001 From: yostyle Date: Tue, 8 Aug 2023 16:18:38 +0200 Subject: [PATCH 03/56] 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 b55f4be739b22af94779f5359c9be20287300f6b Mon Sep 17 00:00:00 2001 From: yostyle Date: Tue, 8 Aug 2023 16:46:11 +0200 Subject: [PATCH 04/56] 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 dd192cb647a3a071d97fb77737686eea51b69a28 Mon Sep 17 00:00:00 2001 From: yostyle Date: Tue, 8 Aug 2023 18:10:00 +0200 Subject: [PATCH 05/56] 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 d930f4130e47b418d57fd3e92290012c65b6f90b Mon Sep 17 00:00:00 2001 From: yostyle Date: Thu, 6 Jul 2023 18:49:14 +0200 Subject: [PATCH 06/56] 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 ad6f772a62661bcdfe9f3948bb7fb7664795d47d Mon Sep 17 00:00:00 2001 From: yostyle Date: Tue, 18 Jul 2023 11:51:28 +0200 Subject: [PATCH 07/56] 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 3e8a536c0d69357a295f250524490c651f900af1 Mon Sep 17 00:00:00 2001 From: yostyle Date: Tue, 18 Jul 2023 13:49:51 +0200 Subject: [PATCH 08/56] 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 bfb6bd9d08bef0ce87e2863d5eec8a0b77e738e0 Mon Sep 17 00:00:00 2001 From: yostyle Date: Wed, 19 Jul 2023 15:12:20 +0200 Subject: [PATCH 09/56] 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 6895f8bcae69e47866c32b841e9211bb311d68ae Mon Sep 17 00:00:00 2001 From: yostyle Date: Tue, 1 Aug 2023 15:20:20 +0200 Subject: [PATCH 10/56] 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 9c3006a273df98a886fd16aa8b9732763c73056d Mon Sep 17 00:00:00 2001 From: yostyle Date: Mon, 7 Aug 2023 16:33:45 +0200 Subject: [PATCH 11/56] 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 36926f6f0b00aea67612d0ae0f84c2c8dd8d57a5 Mon Sep 17 00:00:00 2001 From: yostyle Date: Mon, 7 Aug 2023 17:54:05 +0200 Subject: [PATCH 12/56] 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 8bf5b57c5615a6750fb84a2a93a6f612eda28ce3 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 8 Aug 2023 08:12:28 +0000 Subject: [PATCH 13/56] 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 4ce6f3d4adfdf11842090baddd1d67f49e629827 Mon Sep 17 00:00:00 2001 From: yostyle Date: Tue, 8 Aug 2023 10:46:17 +0200 Subject: [PATCH 14/56] 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 28291b99fe2b8a373726a584ee67e0ab1c1ee551 Mon Sep 17 00:00:00 2001 From: yostyle Date: Fri, 11 Aug 2023 14:07:59 +0200 Subject: [PATCH 15/56] 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 683eb778dcc57795140e4d85e0a942bfc110f0cb Mon Sep 17 00:00:00 2001 From: ElementBot Date: Mon, 14 Aug 2023 06:28:14 +0000 Subject: [PATCH 16/56] 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 eea849d74c43f7d5349eef2a05e06eb44231ae13 Mon Sep 17 00:00:00 2001 From: yostyle Date: Thu, 17 Aug 2023 09:32:06 +0200 Subject: [PATCH 17/56] 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 ba06c158093773f15115ec729be3c401356834e7 Mon Sep 17 00:00:00 2001 From: yostyle Date: Thu, 17 Aug 2023 09:46:59 +0200 Subject: [PATCH 18/56] 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 7f06c321cc29c3094b59d8b4c138abab16f41a86 Mon Sep 17 00:00:00 2001 From: yostyle Date: Thu, 17 Aug 2023 09:55:05 +0200 Subject: [PATCH 19/56] 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 122d5e42397f833d3ded153bf7510b0f0b82a69f Mon Sep 17 00:00:00 2001 From: yostyle Date: Thu, 17 Aug 2023 11:38:41 +0200 Subject: [PATCH 20/56] 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 a78f3430e26dd1de4adf1b3212e86f0a87bcf985 Mon Sep 17 00:00:00 2001 From: yostyle Date: Thu, 17 Aug 2023 13:50:49 +0200 Subject: [PATCH 21/56] 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 e59d37fc0d9e49cc90801edaf607aed249a63d00 Mon Sep 17 00:00:00 2001 From: yostyle Date: Thu, 17 Aug 2023 14:12:23 +0200 Subject: [PATCH 22/56] 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 675b3ab3837e94bbe89447db9f40910ee186399e 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 23/56] 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 9fdeb81e50e979f4aa1852b8f6b8789edb692e00 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 24/56] 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 b0d0c2e5d28b0d20e402e8945f4a7c05224cdcb4 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 25/56] 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 5ba290ae352379987e97fb9dda1ed42959b320c4 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 17 Aug 2023 14:53:47 +0000 Subject: [PATCH 26/56] 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 a86ec1a8fa20f8c69bd7fe4a8c551f7a99f09acb Mon Sep 17 00:00:00 2001 From: yostyle Date: Thu, 24 Aug 2023 15:43:10 +0200 Subject: [PATCH 27/56] 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 604a528544a2b77c7dc0dd2c425a224168ed0605 Mon Sep 17 00:00:00 2001 From: David Langley Date: Wed, 30 Aug 2023 16:54:59 +0100 Subject: [PATCH 28/56] 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 9e27c2bdf01f3a373d532c12f700bec88f47f6c2 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 30 Aug 2023 16:08:13 +0000 Subject: [PATCH 29/56] 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 2f6f28bfbb1f2446548823ba594ace785b4c3a44 Mon Sep 17 00:00:00 2001 From: David Langley Date: Tue, 12 Sep 2023 01:11:13 +0100 Subject: [PATCH 30/56] 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(membersCount)) + notificationSettings.unmuteRoom(roomId.value, isEncrypted, isOneToOne) } } - /** - * 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 isRoomMentionEnabled(): Result = withContext(dispatchers.io) { + runCatching { + notificationSettings.isRoomMentionEnabled() + } + } + + 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 c3e595bf4fc0ef7b09a891f583b0e0d35f125c5b Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Wed, 13 Sep 2023 11:51:29 +0200 Subject: [PATCH 31/56] 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 47f030cffe5e3c8dd2dfec451c49c008a9bf64e4 Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Wed, 13 Sep 2023 13:43:17 +0200 Subject: [PATCH 32/56] 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 55f51a01a089aec7cd3a7210a36b456af5646466 Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Wed, 13 Sep 2023 10:25:30 +0200 Subject: [PATCH 33/56] 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 ccd684ea404e6850a94662c813373b1c0fd4ea36 Mon Sep 17 00:00:00 2001 From: David Langley Date: Wed, 13 Sep 2023 12:44:22 +0100 Subject: [PATCH 34/56] 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 7be1b8cc12a12b9f1e520ed629acf5a83da76a4b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 13 Sep 2023 13:49:08 +0200 Subject: [PATCH 35/56] 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 1144cee572455626a4cf883983403084d4bc77f5 Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Wed, 13 Sep 2023 11:02:25 +0200 Subject: [PATCH 36/56] 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 b9efaaa4307fb953f6793b5a4c9929f21e0428de Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 13 Sep 2023 12:14:40 +0000 Subject: [PATCH 37/56] 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 d7b820e4746f9396ee269f1500483a5eaefa7291 Mon Sep 17 00:00:00 2001 From: David Langley Date: Wed, 13 Sep 2023 13:22:05 +0100 Subject: [PATCH 38/56] 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 6702dc68952c5f790be722d51b98727fee4a164d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 13 Sep 2023 14:33:32 +0200 Subject: [PATCH 39/56] 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 827dd357915428bf23f53cef2ca03751d213d42f Mon Sep 17 00:00:00 2001 From: David Langley Date: Wed, 13 Sep 2023 14:18:28 +0100 Subject: [PATCH 40/56] 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 b860bd30bd0a38730d201e422eb4f166f0066644 Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Wed, 13 Sep 2023 15:19:26 +0200 Subject: [PATCH 41/56] 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 5d8666a507666ece5cb2327a0d4fc3a3f25d13be Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Wed, 13 Sep 2023 15:42:48 +0200 Subject: [PATCH 42/56] 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 dfdd8e59f7c1205982011e4eb2675b3f9cff605f 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 43/56] 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 a6b2a4af94469e4937736a33ba72bcc320fac2a8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 13 Sep 2023 16:39:24 +0200 Subject: [PATCH 44/56] 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 c1ae0ead3b558bbbbb9b68b4ba67d38e648e4976 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 13 Sep 2023 17:13:15 +0200 Subject: [PATCH 45/56] 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 6c3322875662587207028a8cb16520cc4cc2c67b Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 13 Sep 2023 15:48:14 +0000 Subject: [PATCH 46/56] 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 bd6b8ab6dff23b11e0effb8f69e5e14743272113 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 47/56] 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 a1a9b57df7a8350246d1b7d12c38012264c8b348 Mon Sep 17 00:00:00 2001 From: David Langley Date: Wed, 13 Sep 2023 21:03:52 +0100 Subject: [PATCH 48/56] 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 7b8a73096c4b8c119c6b567161f0a1060011c98a Mon Sep 17 00:00:00 2001 From: David Langley Date: Wed, 13 Sep 2023 21:12:16 +0100 Subject: [PATCH 49/56] - 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 ef84996ba3dea4adaac846d8232d7c2070d8e3a1 Mon Sep 17 00:00:00 2001 From: David Langley Date: Wed, 13 Sep 2023 21:14:37 +0100 Subject: [PATCH 50/56] 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 23118f0858c432bb108f4182dbfedb12efd1aeba Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 13 Sep 2023 20:28:48 +0000 Subject: [PATCH 51/56] 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 3699b516ea4bedc0e89c2879f6ceaf7cae1dd346 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Thu, 14 Sep 2023 08:30:41 +0200 Subject: [PATCH 52/56] 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 3c03bd7f71bfe39d720c76d3fb17e09e77a543c6 Mon Sep 17 00:00:00 2001 From: David Langley Date: Thu, 14 Sep 2023 09:51:45 +0100 Subject: [PATCH 53/56] 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 b7e0befc6a1555c9cbe4aa5942060d4b8720de7b Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Thu, 14 Sep 2023 11:51:10 +0200 Subject: [PATCH 54/56] 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 6d6a346369d7108b0ab6f0542678b4c16e956056 Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Thu, 14 Sep 2023 12:12:49 +0200 Subject: [PATCH 55/56] 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 455d39c629ad8afbaf5e860f1d78d086eb460aeb Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 14 Sep 2023 14:38:49 +0000 Subject: [PATCH 56/56] 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."