Merge branch 'develop' into julioromano/poll_history_entry_point
This commit is contained in:
commit
8f286c8ce6
54 changed files with 220 additions and 153 deletions
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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:954c763c082f8e4016247643408a61a038a221bb84643ba7e80f3389818528ba
|
||||
size 15587
|
||||
oid sha256:decba5aecbaf17385c6b92396b48ba7e8cb1d68c8319bef3334415cd42fee828
|
||||
size 36034
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:30886fbb00695077a80e046cd6c6c134375be8ecb8c3962e72fdc0dff60d7069
|
||||
size 14194
|
||||
oid sha256:97aec529c58486f1686e6c15f0cb9ed5286ed169115d8053b734bc491f724a28
|
||||
size 33309
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d7d9e27ba7e11c0bb8ccbc79ad1a0f36bfa9dcbd32de930fe7c5daddba9fdd23
|
||||
size 35942
|
||||
oid sha256:b927c63f95092c5345ceb35506e160c9ce6ce0348bba33d258c390cd8bd158de
|
||||
size 35825
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:15107ee39b3e1ea4d3a21b7b1abadaf8ebf2b0487073790ceefff5c02581d193
|
||||
size 35869
|
||||
oid sha256:6886af0b4f9e674aafd2674c6b77e707a08fb4a0f626169581ed3245b4241972
|
||||
size 35751
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a8c45197aff11763468432a96e6870c022398d26560629e7f84ea643506044f0
|
||||
size 32283
|
||||
oid sha256:ef4a2ee8e94f57164b5834fa331c37a3bf7bee15aae17fa3c5fb2a9c82e3e3a9
|
||||
size 33508
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9db4f92f89959facb236f9e4f8c64fae0daba27fcab8351a93511a68c2906810
|
||||
size 36825
|
||||
oid sha256:c1acca39f67a574b9b467827515b2f3442b4bb532a6d2cf3ad611ae79098815d
|
||||
size 36659
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:78eab361860e4b4153a680fad703dc61c69c80a28af0a90b0a6add85178eea4f
|
||||
size 49828
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4d286e663c1c3969ce66304064c5e1c54bde8488b5f71076e3056d00c7fe2d1c
|
||||
size 33108
|
||||
oid sha256:99b99dd9caaecaf34f5a354251833375456c43e4c31bb2dc020b8caa396fe7e3
|
||||
size 33088
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fd4758ac4bb9c62815b33f726f0c8e7183e0474224e9dbd9225e78793a67b1c7
|
||||
size 33068
|
||||
oid sha256:c427f18e4dcb5539069bcb6cb2d81160208a21fa5d1ca0c4086aed27b92013e8
|
||||
size 33043
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:076fc1b1f9d0a23e639f86ca191cbc3e14603ba0f2dd1beffb5519e710247e49
|
||||
size 29047
|
||||
oid sha256:5d3d53b374e9b59ec860951fbcd1ddb566c90b3debe335c5cba8f2d9e55f508d
|
||||
size 30346
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:be15f96a3c48b5ea7ddb30919ff5dab2afd3780fa792dda9a4b4a266d2d5c8b8
|
||||
size 32310
|
||||
oid sha256:0c85782934a98034a75e507f9c4e8316c1aa00e5628ae7fe3092b7f58ae3540c
|
||||
size 32286
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:29160e672d2bda2cdb69b7a2c2357316696637db23dc1de0665cc80308303399
|
||||
size 47051
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:99c766b057e9a18cb0126af3da9a921fc3c3f85d0c7bb7ce5bab8d3c684be640
|
||||
size 33829
|
||||
oid sha256:695a934529456a82e99371e9b53231ac02f6d235174927fbb346bf2a5375aceb
|
||||
size 33962
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4d79ba52e50a3bab13633c83a4196c229f8b40e10c4f00ff4469b68c5bbbdcc2
|
||||
size 38018
|
||||
oid sha256:4e406c5e173add3b29c3ad7a10e968d3bffc4627c7895bd2080826b832652ce1
|
||||
size 37783
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:13c58f6fb3d875d31d2c72e67f859bf5b4e1496a05de36ea1dc2601fe882f7f6
|
||||
size 33868
|
||||
oid sha256:52fe76d305e114d5eeab85b608c5d86307ccd6fa0f283f4a806d64163d17c7b0
|
||||
size 33985
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:60dbf7ac48dc77b79f80c15ea811381ee5885e2c5f702e522e789f16672c694b
|
||||
size 41164
|
||||
oid sha256:6e91c8c83e1a793bb8e0d306b98a4737187a5a5df7a47c67ac6a716696cff3fc
|
||||
size 41208
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:13c58f6fb3d875d31d2c72e67f859bf5b4e1496a05de36ea1dc2601fe882f7f6
|
||||
size 33868
|
||||
oid sha256:52fe76d305e114d5eeab85b608c5d86307ccd6fa0f283f4a806d64163d17c7b0
|
||||
size 33985
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:60dbf7ac48dc77b79f80c15ea811381ee5885e2c5f702e522e789f16672c694b
|
||||
size 41164
|
||||
oid sha256:6e91c8c83e1a793bb8e0d306b98a4737187a5a5df7a47c67ac6a716696cff3fc
|
||||
size 41208
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:695a934529456a82e99371e9b53231ac02f6d235174927fbb346bf2a5375aceb
|
||||
size 33962
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6992afacc7a2b2927258d9a8183c016df9f92c06616291eab2ffe55dddf3d149
|
||||
size 31451
|
||||
oid sha256:a128bd56c653706f65f20dac1e4110b21259e76821821057fe1e829044a1d36a
|
||||
size 31523
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:721a167934d333cac37e16c0114238ec80a56afa9eac04bd4ee96642f09a85e8
|
||||
size 35126
|
||||
oid sha256:65bd05d8176f7d65f10ee3183f221afc73a759962a2e6b95067d3830a93d876c
|
||||
size 34766
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2fe6a53eeb683a6e22ddef38481800489747ecd0d7875247f0014928e83a85f8
|
||||
size 30597
|
||||
oid sha256:f00202b17ca6c89dfdefc616888ceeb7272cfdb452745e8e034d556764983f7d
|
||||
size 30717
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:052a42e15095538d05231b73fd7f5259bd3782d1b280ef0726a0445a9dd719ad
|
||||
size 36640
|
||||
oid sha256:fec18df4d767d669a62d9adcef3d919332fb3af72f5bf2df349acc3e964fa78e
|
||||
size 36634
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2fe6a53eeb683a6e22ddef38481800489747ecd0d7875247f0014928e83a85f8
|
||||
size 30597
|
||||
oid sha256:f00202b17ca6c89dfdefc616888ceeb7272cfdb452745e8e034d556764983f7d
|
||||
size 30717
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:052a42e15095538d05231b73fd7f5259bd3782d1b280ef0726a0445a9dd719ad
|
||||
size 36640
|
||||
oid sha256:fec18df4d767d669a62d9adcef3d919332fb3af72f5bf2df349acc3e964fa78e
|
||||
size 36634
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a128bd56c653706f65f20dac1e4110b21259e76821821057fe1e829044a1d36a
|
||||
size 31523
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:62418ebe7afa2c1c7eda2b1251fb189a75527aa7a4289a9478c531fac7dee8bd
|
||||
size 10666
|
||||
oid sha256:aa7de6ce541afcabc79fc1554809c217fd4f8bc83ed2c324342a9d28b9f34717
|
||||
size 31001
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e5a32b1baaaad0bf266e190084a64b3d382a2d6d472a55b1c3653ee948e100c9
|
||||
size 9756
|
||||
oid sha256:9c7bdc732cc76ffcded6903e533ccb64d57d671f02a62093e63d0375fe0c680c
|
||||
size 29016
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f91d546db2397cb0fd90a200c916e4ff26db0de5c55d6c0eab4b25c3380377a6
|
||||
size 24070
|
||||
oid sha256:78cb940e6edfe0591071224fc7a8dcf32472633f56c38d55647dff40b042894b
|
||||
size 24303
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:16e46bb87e1f4ef3a71a2e64029075c26b2b6f9699a7b756492db2378f604152
|
||||
size 22643
|
||||
oid sha256:52992127004c26595f2bfeb50c657a5628b18ffc10b8e6b260203504f44756fa
|
||||
size 22787
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue