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 9e87675b3a..f38c211b67 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 @@ -17,11 +17,11 @@ package io.element.android.features.preferences.impl.notifications 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 SetInviteForMeNotificationsEnabled(val enabled: Boolean) : NotificationSettingsEvents data object FixConfigurationMismatch : NotificationSettingsEvents data object ClearConfigurationMismatchError : NotificationSettingsEvents data object ClearNotificationChangeError : NotificationSettingsEvents 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 689cca8f66..6252be1e5c 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 @@ -76,6 +76,9 @@ class NotificationSettingsPresenter @Inject constructor( is NotificationSettingsEvents.SetCallNotificationsEnabled -> { localCoroutineScope.setCallNotificationsEnabled(event.enabled, changeNotificationSettingAction) } + is NotificationSettingsEvents.SetInviteForMeNotificationsEnabled -> { + localCoroutineScope.setInviteForMeNotificationsEnabled(event.enabled, changeNotificationSettingAction) + } is NotificationSettingsEvents.SetNotificationsEnabled -> localCoroutineScope.setNotificationsEnabled(userPushStore, event.enabled) NotificationSettingsEvents.ClearConfigurationMismatchError -> { matrixSettings.value = NotificationSettingsState.MatrixSettings.Invalid(fixFailed = false) @@ -123,10 +126,12 @@ class NotificationSettingsPresenter @Inject constructor( val callNotificationsEnabled = notificationSettingsService.isCallEnabled().getOrThrow() val atRoomNotificationsEnabled = notificationSettingsService.isRoomMentionEnabled().getOrThrow() + val inviteForMeNotificationsEnabled = notificationSettingsService.isInviteForMeEnabled().getOrThrow() target.value = NotificationSettingsState.MatrixSettings.Valid( atRoomNotificationsEnabled = atRoomNotificationsEnabled, callNotificationsEnabled = callNotificationsEnabled, + inviteForMeNotificationsEnabled = inviteForMeNotificationsEnabled, defaultGroupNotificationMode = encryptedGroupDefaultMode, defaultOneToOneNotificationMode = encryptedOneToOneDefaultMode, ) @@ -175,6 +180,12 @@ class NotificationSettingsPresenter @Inject constructor( }.runCatchingUpdatingState(action) } + private fun CoroutineScope.setInviteForMeNotificationsEnabled(enabled: Boolean, action: MutableState>) = launch { + suspend { + notificationSettingsService.setInviteForMeEnabled(enabled).getOrThrow() + }.runCatchingUpdatingState(action) + } + private fun CoroutineScope.setNotificationsEnabled(userPushStore: UserPushStore, enabled: Boolean) = launch { userPushStore.setNotificationEnabledForDevice(enabled) } 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 2b0faa110c..581f0e8475 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 @@ -32,6 +32,7 @@ data class NotificationSettingsState( data class Valid( val atRoomNotificationsEnabled: Boolean, val callNotificationsEnabled: Boolean, + val inviteForMeNotificationsEnabled: Boolean, val defaultGroupNotificationMode: RoomNotificationMode?, val defaultOneToOneNotificationMode: RoomNotificationMode?, ) : MatrixSettings 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 9336857585..f121a2fe60 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 @@ -35,6 +35,7 @@ fun aNotificationSettingsState( matrixSettings = NotificationSettingsState.MatrixSettings.Valid( atRoomNotificationsEnabled = true, callNotificationsEnabled = true, + inviteForMeNotificationsEnabled = true, defaultGroupNotificationMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY, defaultOneToOneNotificationMode = RoomNotificationMode.ALL_MESSAGES, ), 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 c2c52a07c9..f1066b2e9d 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 @@ -77,6 +77,7 @@ fun NotificationSettingsView( onMentionNotificationsChanged = { state.eventSink(NotificationSettingsEvents.SetAtRoomNotificationsEnabled(it)) }, // TODO We are removing the call notification toggle until support for call notifications has been added // onCallsNotificationsChanged = { state.eventSink(NotificationSettingsEvents.SetCallNotificationsEnabled(it)) }, + onInviteForMeNotificationsChanged = { state.eventSink(NotificationSettingsEvents.SetInviteForMeNotificationsEnabled(it)) }, ) } AsyncView( @@ -98,6 +99,7 @@ private fun NotificationSettingsContentView( onMentionNotificationsChanged: (Boolean) -> Unit, // TODO We are removing the call notification toggle until support for call notifications has been added // onCallsNotificationsChanged: (Boolean) -> Unit, + onInviteForMeNotificationsChanged: (Boolean) -> Unit, modifier: Modifier = Modifier, ) { val context = LocalContext.current @@ -147,8 +149,8 @@ private fun NotificationSettingsContentView( onCheckedChange = onMentionNotificationsChanged ) } - // TODO We are removing the call notification toggle until support for call notifications has been added -// PreferenceCategory(title = stringResource(id = CommonStrings.screen_notification_settings_additional_settings_section_title)) { + PreferenceCategory(title = stringResource(id = R.string.screen_notification_settings_additional_settings_section_title)) { + // TODO We are removing the call notification toggle until support for call notifications has been added // PreferenceSwitch( // modifier = Modifier, // title = stringResource(id = CommonStrings.screen_notification_settings_calls_label), @@ -156,7 +158,14 @@ private fun NotificationSettingsContentView( // switchAlignment = Alignment.Top, // onCheckedChange = onCallsNotificationsChanged // ) -// } + PreferenceSwitch( + modifier = Modifier, + title = stringResource(id = R.string.screen_notification_settings_invite_for_me_label), + isChecked = matrixSettings.inviteForMeNotificationsEnabled, + switchAlignment = Alignment.Top, + onCheckedChange = onInviteForMeNotificationsChanged + ) + } } } diff --git a/features/preferences/impl/src/main/res/values/localazy.xml b/features/preferences/impl/src/main/res/values/localazy.xml index c76c647bba..55c43f05f4 100644 --- a/features/preferences/impl/src/main/res/values/localazy.xml +++ b/features/preferences/impl/src/main/res/values/localazy.xml @@ -29,6 +29,7 @@ If you proceed, some of your settings may change." "Enable notifications on this device" "The configuration has not been corrected, please try again." "Group chats" + "Invitations" "Your homeserver does not support this option in encrypted rooms, you may not get notified in some rooms." "Mentions" "All" 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 index 52b1108273..e55d7a1c80 100644 --- 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 @@ -50,6 +50,7 @@ class NotificationSettingsPresenterTests { val valid = loadedState.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid assertThat(valid?.atRoomNotificationsEnabled).isFalse() assertThat(valid?.callNotificationsEnabled).isFalse() + assertThat(valid?.inviteForMeNotificationsEnabled).isFalse() assertThat(valid?.defaultGroupNotificationMode).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY) assertThat(valid?.defaultOneToOneNotificationMode).isEqualTo(RoomNotificationMode.ALL_MESSAGES) cancelAndIgnoreRemainingEvents() @@ -166,6 +167,28 @@ class NotificationSettingsPresenterTests { } } + @Test + fun `present - set invite for me notifications enabled`() = runTest { + val presenter = createNotificationSettingsPresenter() + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val loadedState = consumeItemsUntilPredicate { + (it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid)?.inviteForMeNotificationsEnabled == false + }.last() + val validMatrixState = loadedState.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid + Truth.assertThat(validMatrixState?.inviteForMeNotificationsEnabled).isFalse() + + loadedState.eventSink(NotificationSettingsEvents.SetInviteForMeNotificationsEnabled(true)) + val updatedState = consumeItemsUntilPredicate { + (it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid)?.inviteForMeNotificationsEnabled == true + }.last() + val updatedMatrixState = updatedState.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid + Truth.assertThat(updatedMatrixState?.inviteForMeNotificationsEnabled).isTrue() + cancelAndIgnoreRemainingEvents() + } + } + @Test fun `present - set atRoom notifications enabled`() = runTest { val presenter = createNotificationSettingsPresenter() 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 71d46a2b8e..ca005e624a 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 @@ -38,5 +38,7 @@ interface NotificationSettingsService { suspend fun setRoomMentionEnabled(enabled: Boolean): Result suspend fun isCallEnabled(): Result suspend fun setCallEnabled(enabled: Boolean): Result + suspend fun isInviteForMeEnabled(): Result + suspend fun setInviteForMeEnabled(enabled: Boolean): Result suspend fun getRoomsWithUserDefinedRules(): 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 c857de56dd..6ddebfbe70 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 @@ -124,6 +124,18 @@ class RustNotificationSettingsService( } } + override suspend fun isInviteForMeEnabled(): Result = withContext(dispatchers.io) { + runCatching { + notificationSettings.isInviteForMeEnabled() + } + } + + override suspend fun setInviteForMeEnabled(enabled: Boolean): Result = withContext(dispatchers.io) { + runCatching { + notificationSettings.setInviteForMeEnabled(enabled) + } + } + override suspend fun getRoomsWithUserDefinedRules(): Result> = runCatching { notificationSettings.getRoomsWithUserDefinedRules(enabled = true) 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 039b855e7e..969acb9d25 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 @@ -41,6 +41,7 @@ class FakeNotificationSettingsService( private var roomNotificationMode: RoomNotificationMode = initialRoomMode private var roomNotificationModeIsDefault: Boolean = initialRoomModeIsDefault private var callNotificationsEnabled = false + private var inviteNotificationsEnabled = false private var atRoomNotificationsEnabled = false private var setNotificationModeError: Throwable? = null private var restoreDefaultNotificationModeError: Throwable? = null @@ -52,7 +53,7 @@ class FakeNotificationSettingsService( override suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, isOneToOne: Boolean): Result { return Result.success( RoomNotificationSettings( - mode = if(roomNotificationModeIsDefault) defaultEncryptedGroupRoomNotificationMode else roomNotificationMode, + mode = if (roomNotificationModeIsDefault) defaultEncryptedGroupRoomNotificationMode else roomNotificationMode, isDefault = roomNotificationModeIsDefault ) ) @@ -149,6 +150,15 @@ class FakeNotificationSettingsService( return Result.success(Unit) } + override suspend fun isInviteForMeEnabled(): Result { + return Result.success(inviteNotificationsEnabled) + } + + override suspend fun setInviteForMeEnabled(enabled: Boolean): Result { + inviteNotificationsEnabled = enabled + return Result.success(Unit) + } + override suspend fun getRoomsWithUserDefinedRules(): Result> { return Result.success(if (roomNotificationModeIsDefault) listOf() else listOf(A_ROOM_ID.value)) } @@ -168,5 +178,4 @@ class FakeNotificationSettingsService( fun givenSetDefaultNotificationModeError(throwable: Throwable?) { setDefaultNotificationModeError = throwable } - }