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:
parent
e725747ea3
commit
d27e9e5265
52 changed files with 215 additions and 149 deletions
|
|
@ -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(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue