Merge branch 'develop' into julioromano/poll_history_entry_point
This commit is contained in:
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
|
||||
1
changelog.d/2031.misc
Normal file
1
changelog.d/2031.misc
Normal file
@@ -0,0 +1 @@
|
||||
Only process content.json from Localazy.
|
||||
@@ -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))
|
||||
},
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
</plurals>
|
||||
<string name="screen_notification_settings_edit_failed_updating_default_mode">"An error occurred while updating the notification setting."</string>
|
||||
<string name="screen_polls_history_title">"Polls"</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.
@@ -117,6 +117,7 @@
|
||||
"screen_room_notification_settings_.*",
|
||||
"screen_notification_settings_edit_failed_updating_default_mode",
|
||||
"screen_polls_history_title",
|
||||
"screen_notification_settings_mentions_only_disclaimer",
|
||||
"screen_start_chat_error_starting_chat"
|
||||
]
|
||||
},
|
||||
|
||||
@@ -47,7 +47,7 @@ for entry in config["modules"]:
|
||||
"includeKeys": list(map(lambda i: "REGEX:" + i, entry["includeRegex"])),
|
||||
"excludeKeys": list(map(lambda i: "REGEX:" + i, excludeRegex)),
|
||||
"conditions": [
|
||||
"equals: ${languageCode}, en"
|
||||
"equals: ${languageCode}, en | equals: ${file}, content.json"
|
||||
]
|
||||
}
|
||||
# print(action)
|
||||
@@ -59,7 +59,7 @@ for entry in config["modules"]:
|
||||
"includeKeys": list(map(lambda i: "REGEX:" + i, entry["includeRegex"])),
|
||||
"excludeKeys": list(map(lambda i: "REGEX:" + i, excludeRegex)),
|
||||
"conditions": [
|
||||
"!equals: ${languageCode}, en"
|
||||
"!equals: ${languageCode}, en | equals: ${file}, content.json"
|
||||
]
|
||||
}
|
||||
allActions.append(actionTranslation)
|
||||
@@ -70,7 +70,7 @@ mainAction = baseAction | {
|
||||
"output": "libraries/ui-strings/src/main/res/values/localazy.xml",
|
||||
"excludeKeys": list(map(lambda i: "REGEX:" + i, allRegexToExcludeFromMainModule + regexToAlwaysExclude)),
|
||||
"conditions": [
|
||||
"equals: ${languageCode}, en"
|
||||
"equals: ${languageCode}, en | equals: ${file}, content.json"
|
||||
]
|
||||
}
|
||||
# print(mainAction)
|
||||
@@ -82,7 +82,7 @@ if allFiles:
|
||||
"output": "libraries/ui-strings/src/main/res/values-${langAndroidResNoScript}/translations.xml",
|
||||
"excludeKeys": list(map(lambda i: "REGEX:" + i, allRegexToExcludeFromMainModule + regexToAlwaysExclude)),
|
||||
"conditions": [
|
||||
"!equals: ${languageCode}, en"
|
||||
"!equals: ${languageCode}, en | equals: ${file}, content.json"
|
||||
]
|
||||
}
|
||||
allActions.append(mainActionTranslation)
|
||||
|
||||
Reference in New Issue
Block a user