Add warning message to 'mentions and keywords only' notification option (#2028)
* Add warning message to 'mentions and keywords only' It should be displayed when it's not supported by the homeserver * Only display disclaimer in the room notification settings if the room is encrypted Co-authored-by: Benoit Marty <benoit@matrix.org> * Fix test and add another one --------- Co-authored-by: ElementBot <benoitm+elementbot@element.io> Co-authored-by: Benoit Marty <benoit@matrix.org>
This commit is contained in:
committed by
GitHub
parent
506f47630b
commit
3ba75962e6
1
changelog.d/1749.misc
Normal file
1
changelog.d/1749.misc
Normal file
@@ -0,0 +1 @@
|
||||
Add a warning for 'mentions and keywords only' notification option if your homeserver does not support it
|
||||
@@ -16,67 +16,43 @@
|
||||
|
||||
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.features.preferences.impl.R
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
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.compound.theme.ElementTheme
|
||||
import io.element.android.libraries.designsystem.components.list.ListItemContent
|
||||
import io.element.android.libraries.designsystem.theme.components.ListItem
|
||||
|
||||
@Composable
|
||||
fun DefaultNotificationSettingOption(
|
||||
mode: RoomNotificationMode,
|
||||
onOptionSelected: (RoomNotificationMode) -> Unit,
|
||||
displayMentionsOnlyDisclaimer: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
isSelected: Boolean = false,
|
||||
) {
|
||||
val subtitle = when(mode) {
|
||||
val title = 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,
|
||||
)
|
||||
val subtitle = when {
|
||||
mode == RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY && displayMentionsOnlyDisclaimer -> {
|
||||
stringResource(id = R.string.screen_notification_settings_mentions_only_disclaimer)
|
||||
}
|
||||
|
||||
RadioButton(
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterVertically)
|
||||
.size(48.dp),
|
||||
selected = isSelected,
|
||||
onClick = null // null recommended for accessibility with screenreaders
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
ListItem(
|
||||
modifier = modifier,
|
||||
headlineContent = { Text(title) },
|
||||
supportingContent = subtitle?.let { { Text(it) } },
|
||||
trailingContent = ListItemContent.RadioButton(selected = isSelected),
|
||||
onClick = { onOptionSelected(mode) },
|
||||
)
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
@@ -86,11 +62,19 @@ internal fun DefaultNotificationSettingOptionPreview() = ElementPreview {
|
||||
DefaultNotificationSettingOption(
|
||||
mode = RoomNotificationMode.ALL_MESSAGES,
|
||||
isSelected = true,
|
||||
displayMentionsOnlyDisclaimer = false,
|
||||
onOptionSelected = {},
|
||||
)
|
||||
DefaultNotificationSettingOption(
|
||||
mode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY,
|
||||
isSelected = false,
|
||||
displayMentionsOnlyDisclaimer = false,
|
||||
onOptionSelected = {},
|
||||
)
|
||||
DefaultNotificationSettingOption(
|
||||
mode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY,
|
||||
isSelected = false,
|
||||
displayMentionsOnlyDisclaimer = true,
|
||||
onOptionSelected = {},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -19,9 +19,11 @@ 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.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
@@ -55,6 +57,7 @@ class EditDefaultNotificationSettingPresenter @AssistedInject constructor(
|
||||
}
|
||||
@Composable
|
||||
override fun present(): EditDefaultNotificationSettingState {
|
||||
var displayMentionsOnlyDisclaimer by remember { mutableStateOf(false) }
|
||||
|
||||
val mode: MutableState<RoomNotificationMode?> = remember {
|
||||
mutableStateOf(null)
|
||||
@@ -71,6 +74,7 @@ class EditDefaultNotificationSettingPresenter @AssistedInject constructor(
|
||||
fetchSettings(mode)
|
||||
observeNotificationSettings(mode)
|
||||
observeRoomSummaries(roomsWithUserDefinedMode)
|
||||
displayMentionsOnlyDisclaimer = !notificationSettingsService.canHomeServerPushEncryptedEventsToDevice().getOrDefault(true)
|
||||
}
|
||||
|
||||
fun handleEvents(event: EditDefaultNotificationSettingStateEvents) {
|
||||
@@ -87,6 +91,7 @@ class EditDefaultNotificationSettingPresenter @AssistedInject constructor(
|
||||
mode = mode.value,
|
||||
roomsWithUserDefinedMode = roomsWithUserDefinedMode.value.toImmutableList(),
|
||||
changeNotificationSettingAction = changeNotificationSettingAction.value,
|
||||
displayMentionsOnlyDisclaimer = displayMentionsOnlyDisclaimer,
|
||||
eventSink = ::handleEvents
|
||||
)
|
||||
}
|
||||
|
||||
@@ -26,5 +26,6 @@ data class EditDefaultNotificationSettingState(
|
||||
val mode: RoomNotificationMode?,
|
||||
val roomsWithUserDefinedMode: ImmutableList<RoomSummary.Filled>,
|
||||
val changeNotificationSettingAction: Async<Unit>,
|
||||
val displayMentionsOnlyDisclaimer: Boolean,
|
||||
val eventSink: (EditDefaultNotificationSettingStateEvents) -> Unit,
|
||||
)
|
||||
|
||||
@@ -31,17 +31,20 @@ open class EditDefaultNotificationSettingStateProvider: PreviewParameterProvider
|
||||
anEditDefaultNotificationSettingsState(isOneToOne = true),
|
||||
anEditDefaultNotificationSettingsState(changeNotificationSettingAction = Async.Loading(Unit)),
|
||||
anEditDefaultNotificationSettingsState(changeNotificationSettingAction = Async.Failure(Throwable("error"))),
|
||||
anEditDefaultNotificationSettingsState(displayMentionsOnlyDisclaimer = true),
|
||||
)
|
||||
}
|
||||
|
||||
private fun anEditDefaultNotificationSettingsState(
|
||||
isOneToOne: Boolean = false,
|
||||
changeNotificationSettingAction: Async<Unit> = Async.Uninitialized
|
||||
changeNotificationSettingAction: Async<Unit> = Async.Uninitialized,
|
||||
displayMentionsOnlyDisclaimer: Boolean = false,
|
||||
) = EditDefaultNotificationSettingState(
|
||||
isOneToOne = isOneToOne,
|
||||
mode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY,
|
||||
roomsWithUserDefinedMode = persistentListOf(aRoomSummary()),
|
||||
changeNotificationSettingAction = changeNotificationSettingAction,
|
||||
displayMentionsOnlyDisclaimer = displayMentionsOnlyDisclaimer,
|
||||
eventSink = {}
|
||||
)
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ fun EditDefaultNotificationSettingView(
|
||||
DefaultNotificationSettingOption(
|
||||
mode = item,
|
||||
isSelected = state.mode == item,
|
||||
displayMentionsOnlyDisclaimer = state.displayMentionsOnlyDisclaimer,
|
||||
onOptionSelected = { state.eventSink(EditDefaultNotificationSettingStateEvents.SetNotificationMode(it)) }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import io.element.android.libraries.matrix.test.notificationsettings.FakeNotific
|
||||
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
|
||||
import io.element.android.libraries.matrix.test.room.aRoomSummaryDetail
|
||||
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
|
||||
import io.element.android.tests.testutils.awaitLastSequentialItem
|
||||
import io.element.android.tests.testutils.consumeItemsUntilPredicate
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
@@ -51,6 +52,8 @@ class EditDefaultNotificationSettingsPresenterTests {
|
||||
it.mode == RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY
|
||||
}.last()
|
||||
assertThat(loadedState.mode).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)
|
||||
|
||||
assertThat(loadedState.displayMentionsOnlyDisclaimer).isFalse()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +115,19 @@ class EditDefaultNotificationSettingsPresenterTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - display mentions only warning if homeserver does not support it`() = runTest {
|
||||
val notificationSettingsService = FakeNotificationSettingsService().apply {
|
||||
givenCanHomeServerPushEncryptedEventsToDeviceResult(Result.success(false))
|
||||
}
|
||||
val presenter = createEditDefaultNotificationSettingPresenter(notificationSettingsService)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
assertThat(awaitLastSequentialItem().displayMentionsOnlyDisclaimer).isTrue()
|
||||
}
|
||||
}
|
||||
|
||||
private fun createEditDefaultNotificationSettingPresenter(
|
||||
notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(),
|
||||
roomListService: FakeRoomListService = FakeRoomListService(),
|
||||
|
||||
@@ -31,7 +31,7 @@ data class RoomNotificationSettingsItem(
|
||||
|
||||
@Composable
|
||||
fun roomNotificationSettingsItems(): ImmutableList<RoomNotificationSettingsItem> {
|
||||
return RoomNotificationMode.values()
|
||||
return RoomNotificationMode.entries
|
||||
.map {
|
||||
when (it) {
|
||||
RoomNotificationMode.ALL_MESSAGES -> RoomNotificationSettingsItem(
|
||||
|
||||
@@ -17,80 +17,56 @@
|
||||
package io.element.android.features.roomdetails.impl.notificationsettings
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.selection.selectable
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import io.element.android.features.roomdetails.impl.R
|
||||
import io.element.android.libraries.designsystem.components.list.ListItemContent
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.theme.components.RadioButton
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.theme.components.ListItem
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.toEnabledColor
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
|
||||
|
||||
@Composable
|
||||
fun RoomNotificationSettingsOption(
|
||||
roomNotificationSettingsItem: RoomNotificationSettingsItem,
|
||||
onOptionSelected: (RoomNotificationSettingsItem) -> Unit,
|
||||
displayMentionsOnlyDisclaimer: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
isSelected: Boolean = false,
|
||||
) {
|
||||
Row(
|
||||
modifier
|
||||
.fillMaxWidth()
|
||||
.selectable(
|
||||
selected = isSelected,
|
||||
enabled = enabled,
|
||||
onClick = { onOptionSelected(roomNotificationSettingsItem) },
|
||||
role = Role.RadioButton,
|
||||
)
|
||||
.padding(8.dp),
|
||||
) {
|
||||
Column(
|
||||
Modifier
|
||||
.weight(1f)
|
||||
.padding(horizontal = 8.dp)
|
||||
.align(Alignment.CenterVertically)
|
||||
) {
|
||||
Text(
|
||||
text = roomNotificationSettingsItem.title,
|
||||
style = ElementTheme.typography.fontBodyLgRegular,
|
||||
color = enabled.toEnabledColor(),
|
||||
)
|
||||
val mode = roomNotificationSettingsItem.mode
|
||||
val title = roomNotificationSettingsItem.title
|
||||
val subtitle = when {
|
||||
mode == RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY && displayMentionsOnlyDisclaimer -> {
|
||||
stringResource(id = R.string.screen_notification_settings_mentions_only_disclaimer)
|
||||
}
|
||||
|
||||
RadioButton(
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterVertically)
|
||||
.size(48.dp),
|
||||
selected = isSelected,
|
||||
enabled = enabled,
|
||||
onClick = null // null recommended for accessibility with screenreaders
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
ListItem(
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
headlineContent = { Text(title) },
|
||||
supportingContent = subtitle?.let { { Text(it) } },
|
||||
trailingContent = ListItemContent.RadioButton(selected = isSelected),
|
||||
onClick = { onOptionSelected(roomNotificationSettingsItem) },
|
||||
)
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun RoomPrivacyOptionPreview() = ElementPreview {
|
||||
Column {
|
||||
RoomNotificationSettingsOption(
|
||||
roomNotificationSettingsItem = roomNotificationSettingsItems().first(),
|
||||
onOptionSelected = {},
|
||||
isSelected = true,
|
||||
)
|
||||
RoomNotificationSettingsOption(
|
||||
roomNotificationSettingsItem = roomNotificationSettingsItems().last(),
|
||||
onOptionSelected = {},
|
||||
isSelected = false,
|
||||
enabled = false,
|
||||
)
|
||||
for ((index, item) in roomNotificationSettingsItems().withIndex()) {
|
||||
RoomNotificationSettingsOption(
|
||||
roomNotificationSettingsItem = item,
|
||||
onOptionSelected = {},
|
||||
isSelected = index == 0,
|
||||
enabled = index != 2,
|
||||
displayMentionsOnlyDisclaimer = index == 1,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ fun RoomNotificationSettingsOptions(
|
||||
selected: RoomNotificationMode?,
|
||||
enabled: Boolean,
|
||||
onOptionSelected: (RoomNotificationSettingsItem) -> Unit,
|
||||
displayMentionsOnlyDisclaimer: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val items = roomNotificationSettingsItems()
|
||||
@@ -36,6 +37,7 @@ fun RoomNotificationSettingsOptions(
|
||||
roomNotificationSettingsItem = item,
|
||||
isSelected = selected == item.mode,
|
||||
onOptionSelected = onOptionSelected,
|
||||
displayMentionsOnlyDisclaimer = displayMentionsOnlyDisclaimer,
|
||||
enabled = enabled
|
||||
)
|
||||
}
|
||||
|
||||
@@ -19,10 +19,12 @@ 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.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
@@ -54,6 +56,7 @@ class RoomNotificationSettingsPresenter @AssistedInject constructor(
|
||||
|
||||
@Composable
|
||||
override fun present(): RoomNotificationSettingsState {
|
||||
var shouldDisplayMentionsOnlyDisclaimer by remember { mutableStateOf(false) }
|
||||
val defaultRoomNotificationMode: MutableState<RoomNotificationMode?> = rememberSaveable {
|
||||
mutableStateOf(null)
|
||||
}
|
||||
@@ -87,6 +90,7 @@ class RoomNotificationSettingsPresenter @AssistedInject constructor(
|
||||
getDefaultRoomNotificationMode(defaultRoomNotificationMode)
|
||||
fetchNotificationSettings(pendingRoomNotificationMode, roomNotificationSettings)
|
||||
observeNotificationSettings(pendingRoomNotificationMode, roomNotificationSettings)
|
||||
shouldDisplayMentionsOnlyDisclaimer = room.isEncrypted && !notificationSettingsService.canHomeServerPushEncryptedEventsToDevice().getOrDefault(true)
|
||||
}
|
||||
|
||||
fun handleEvents(event: RoomNotificationSettingsEvents) {
|
||||
@@ -124,6 +128,7 @@ class RoomNotificationSettingsPresenter @AssistedInject constructor(
|
||||
defaultRoomNotificationMode = defaultRoomNotificationMode.value,
|
||||
setNotificationSettingAction = setNotificationSettingAction.value,
|
||||
restoreDefaultAction = restoreDefaultAction.value,
|
||||
displayMentionsOnlyDisclaimer = shouldDisplayMentionsOnlyDisclaimer,
|
||||
eventSink = ::handleEvents,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ data class RoomNotificationSettingsState(
|
||||
val defaultRoomNotificationMode: RoomNotificationMode?,
|
||||
val setNotificationSettingAction: Async<Unit>,
|
||||
val restoreDefaultAction: Async<Unit>,
|
||||
val displayMentionsOnlyDisclaimer: Boolean,
|
||||
val eventSink: (RoomNotificationSettingsEvents) -> Unit
|
||||
)
|
||||
|
||||
|
||||
@@ -30,12 +30,14 @@ internal class RoomNotificationSettingsStateProvider : PreviewParameterProvider<
|
||||
aRoomNotificationSettingsState(setNotificationSettingAction = Async.Failure(Throwable("error"))),
|
||||
aRoomNotificationSettingsState(restoreDefaultAction = Async.Loading(Unit)),
|
||||
aRoomNotificationSettingsState(restoreDefaultAction = Async.Failure(Throwable("error"))),
|
||||
aRoomNotificationSettingsState(displayMentionsOnlyDisclaimer = true)
|
||||
)
|
||||
|
||||
private fun aRoomNotificationSettingsState(
|
||||
isDefault: Boolean = true,
|
||||
setNotificationSettingAction: Async<Unit> = Async.Uninitialized,
|
||||
restoreDefaultAction: Async<Unit> = Async.Uninitialized,
|
||||
displayMentionsOnlyDisclaimer: Boolean = false,
|
||||
): RoomNotificationSettingsState {
|
||||
return RoomNotificationSettingsState(
|
||||
showUserDefinedSettingStyle = false,
|
||||
@@ -48,6 +50,7 @@ internal class RoomNotificationSettingsStateProvider : PreviewParameterProvider<
|
||||
defaultRoomNotificationMode = RoomNotificationMode.ALL_MESSAGES,
|
||||
setNotificationSettingAction = setNotificationSettingAction,
|
||||
restoreDefaultAction = restoreDefaultAction,
|
||||
displayMentionsOnlyDisclaimer = displayMentionsOnlyDisclaimer,
|
||||
eventSink = { },
|
||||
)
|
||||
}
|
||||
|
||||
@@ -133,10 +133,13 @@ private fun RoomSpecificNotificationSettingsView(
|
||||
}
|
||||
RoomNotificationMode.MUTE -> stringResource(id = CommonStrings.common_mute)
|
||||
}
|
||||
val displayMentionsOnlyDisclaimer = state.displayMentionsOnlyDisclaimer
|
||||
&& state.defaultRoomNotificationMode == RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY
|
||||
RoomNotificationSettingsOption(
|
||||
roomNotificationSettingsItem = RoomNotificationSettingsItem(state.defaultRoomNotificationMode, defaultModeTitle),
|
||||
isSelected = true,
|
||||
onOptionSelected = { },
|
||||
displayMentionsOnlyDisclaimer = displayMentionsOnlyDisclaimer,
|
||||
enabled = true
|
||||
)
|
||||
}
|
||||
@@ -146,6 +149,7 @@ private fun RoomSpecificNotificationSettingsView(
|
||||
RoomNotificationSettingsOptions(
|
||||
selected = state.displayNotificationMode,
|
||||
enabled = !state.displayIsDefault.orTrue(),
|
||||
displayMentionsOnlyDisclaimer = state.displayMentionsOnlyDisclaimer,
|
||||
onOptionSelected = {
|
||||
state.eventSink(RoomNotificationSettingsEvents.RoomNotificationModeChanged(it.mode))
|
||||
},
|
||||
|
||||
@@ -37,6 +37,7 @@ internal class UserDefinedRoomNotificationSettingsStateProvider : PreviewParamet
|
||||
defaultRoomNotificationMode = RoomNotificationMode.ALL_MESSAGES,
|
||||
setNotificationSettingAction = Async.Uninitialized,
|
||||
restoreDefaultAction = Async.Uninitialized,
|
||||
displayMentionsOnlyDisclaimer = false,
|
||||
eventSink = { },
|
||||
),
|
||||
)
|
||||
|
||||
@@ -66,6 +66,7 @@ fun UserDefinedRoomNotificationSettingsView(
|
||||
RoomNotificationSettingsOptions(
|
||||
selected = state.displayNotificationMode,
|
||||
enabled = !state.displayIsDefault.orTrue(),
|
||||
displayMentionsOnlyDisclaimer = state.displayMentionsOnlyDisclaimer,
|
||||
onOptionSelected = {
|
||||
state.eventSink(RoomNotificationSettingsEvents.RoomNotificationModeChanged(it.mode))
|
||||
},
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<item quantity="other">"%1$d people"</item>
|
||||
</plurals>
|
||||
<string name="screen_notification_settings_edit_failed_updating_default_mode">"An error occurred while updating the notification setting."</string>
|
||||
<string name="screen_notification_settings_mentions_only_disclaimer">"Your homeserver does not support this option in encrypted rooms, you may not get notified in some rooms."</string>
|
||||
<string name="screen_room_details_add_topic_title">"Add topic"</string>
|
||||
<string name="screen_room_details_already_a_member">"Already a member"</string>
|
||||
<string name="screen_room_details_already_invited">"Already invited"</string>
|
||||
|
||||
@@ -27,6 +27,8 @@ import io.element.android.libraries.matrix.api.room.RoomNotificationMode
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.A_THROWABLE
|
||||
import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService
|
||||
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
|
||||
import io.element.android.tests.testutils.awaitLastSequentialItem
|
||||
import io.element.android.tests.testutils.consumeItemsUntilPredicate
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
@@ -41,6 +43,8 @@ class RoomNotificationSettingsPresenterTests {
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.roomNotificationSettings.dataOrNull()).isNull()
|
||||
assertThat(initialState.defaultRoomNotificationMode).isNull()
|
||||
val loadedState = awaitItem()
|
||||
assertThat(loadedState.displayMentionsOnlyDisclaimer).isFalse()
|
||||
cancelAndIgnoreRemainingEvents()
|
||||
}
|
||||
}
|
||||
@@ -159,10 +163,39 @@ class RoomNotificationSettingsPresenterTests {
|
||||
cancelAndIgnoreRemainingEvents()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - display mentions only warning for a room if homeserver does not support it and it's encrypted`() = runTest {
|
||||
val notificationService = FakeNotificationSettingsService().apply {
|
||||
givenCanHomeServerPushEncryptedEventsToDeviceResult(Result.success(false))
|
||||
}
|
||||
val room = aMatrixRoom(notificationSettingsService = notificationService, isEncrypted = true)
|
||||
val presenter = createRoomNotificationSettingsPresenter(notificationService, room)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
assertThat(awaitLastSequentialItem().displayMentionsOnlyDisclaimer).isTrue()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - do not display mentions only warning for a room it's not encrypted`() = runTest {
|
||||
val notificationService = FakeNotificationSettingsService().apply {
|
||||
givenCanHomeServerPushEncryptedEventsToDeviceResult(Result.success(false))
|
||||
}
|
||||
val room = aMatrixRoom(notificationSettingsService = notificationService, isEncrypted = false)
|
||||
val presenter = createRoomNotificationSettingsPresenter(notificationService, room)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
assertThat(awaitLastSequentialItem().displayMentionsOnlyDisclaimer).isFalse()
|
||||
}
|
||||
}
|
||||
|
||||
private fun createRoomNotificationSettingsPresenter(
|
||||
notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService()
|
||||
notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(),
|
||||
room: FakeMatrixRoom = aMatrixRoom(notificationSettingsService = notificationSettingsService),
|
||||
): RoomNotificationSettingsPresenter{
|
||||
val room = aMatrixRoom(notificationSettingsService = notificationSettingsService)
|
||||
return RoomNotificationSettingsPresenter(
|
||||
room = room,
|
||||
notificationSettingsService = notificationSettingsService,
|
||||
|
||||
@@ -41,4 +41,5 @@ interface NotificationSettingsService {
|
||||
suspend fun isInviteForMeEnabled(): Result<Boolean>
|
||||
suspend fun setInviteForMeEnabled(enabled: Boolean): Result<Unit>
|
||||
suspend fun getRoomsWithUserDefinedRules(): Result<List<String>>
|
||||
suspend fun canHomeServerPushEncryptedEventsToDevice(): Result<Boolean>
|
||||
}
|
||||
|
||||
@@ -140,4 +140,9 @@ class RustNotificationSettingsService(
|
||||
runCatching {
|
||||
notificationSettings.getRoomsWithUserDefinedRules(enabled = true)
|
||||
}
|
||||
|
||||
override suspend fun canHomeServerPushEncryptedEventsToDevice(): Result<Boolean> =
|
||||
runCatching {
|
||||
notificationSettings.canHomeserverPushEncryptedEventToDevice()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ class FakeNotificationSettingsService(
|
||||
private var restoreDefaultNotificationModeError: Throwable? = null
|
||||
private var setDefaultNotificationModeError: Throwable? = null
|
||||
private var setAtRoomError: Throwable? = null
|
||||
private var canHomeServerPushEncryptedEventsToDeviceResult = Result.success(true)
|
||||
override val notificationSettingsChangeFlow: SharedFlow<Unit>
|
||||
get() = _notificationSettingsStateFlow
|
||||
|
||||
@@ -163,6 +164,10 @@ class FakeNotificationSettingsService(
|
||||
return Result.success(if (roomNotificationModeIsDefault) listOf() else listOf(A_ROOM_ID.value))
|
||||
}
|
||||
|
||||
override suspend fun canHomeServerPushEncryptedEventsToDevice(): Result<Boolean> {
|
||||
return canHomeServerPushEncryptedEventsToDeviceResult
|
||||
}
|
||||
|
||||
fun givenSetNotificationModeError(throwable: Throwable?) {
|
||||
setNotificationModeError = throwable
|
||||
}
|
||||
@@ -178,4 +183,8 @@ class FakeNotificationSettingsService(
|
||||
fun givenSetDefaultNotificationModeError(throwable: Throwable?) {
|
||||
setDefaultNotificationModeError = throwable
|
||||
}
|
||||
|
||||
fun givenCanHomeServerPushEncryptedEventsToDeviceResult(result: Result<Boolean>) {
|
||||
canHomeServerPushEncryptedEventsToDeviceResult = result
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -116,6 +116,7 @@
|
||||
"screen_dm_details_.*",
|
||||
"screen_room_notification_settings_.*",
|
||||
"screen_notification_settings_edit_failed_updating_default_mode",
|
||||
"screen_notification_settings_mentions_only_disclaimer",
|
||||
"screen_start_chat_error_starting_chat"
|
||||
]
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user