Merge pull request #4312 from element-hq/feature/bma/fixMultipleNtfy
Fix issues due to multiple ntfy applications with the same name.
This commit is contained in:
@@ -83,19 +83,19 @@ class NotificationSettingsPresenter @Inject constructor(
|
||||
}
|
||||
}
|
||||
}
|
||||
// List of Distributor names
|
||||
val distributorNames = remember {
|
||||
distributors.map { it.second.name }.toImmutableList()
|
||||
// List of Distributors
|
||||
val availableDistributors = remember {
|
||||
distributors.map { it.second }.toImmutableList()
|
||||
}
|
||||
|
||||
var currentDistributorName by remember { mutableStateOf<AsyncData<String>>(AsyncData.Uninitialized) }
|
||||
var currentDistributor by remember { mutableStateOf<AsyncData<Distributor>>(AsyncData.Uninitialized) }
|
||||
var refreshPushProvider by remember { mutableIntStateOf(0) }
|
||||
|
||||
LaunchedEffect(refreshPushProvider) {
|
||||
val p = pushService.getCurrentPushProvider()
|
||||
val name = p?.getCurrentDistributor(matrixClient.sessionId)?.name
|
||||
currentDistributorName = if (name != null) {
|
||||
AsyncData.Success(name)
|
||||
val distributor = p?.getCurrentDistributor(matrixClient.sessionId)
|
||||
currentDistributor = if (distributor != null) {
|
||||
AsyncData.Success(distributor)
|
||||
} else {
|
||||
AsyncData.Failure(Exception("Failed to get current push provider"))
|
||||
}
|
||||
@@ -108,24 +108,23 @@ class NotificationSettingsPresenter @Inject constructor(
|
||||
) = launch {
|
||||
showChangePushProviderDialog = false
|
||||
data ?: return@launch
|
||||
// No op if the value is the same.
|
||||
if (data.second.name == currentDistributorName.dataOrNull()) return@launch
|
||||
currentDistributorName = AsyncData.Loading(currentDistributorName.dataOrNull())
|
||||
data.let { (pushProvider, distributor) ->
|
||||
pushService.registerWith(
|
||||
matrixClient = matrixClient,
|
||||
pushProvider = pushProvider,
|
||||
distributor = distributor
|
||||
val (pushProvider, distributor) = data
|
||||
// No op if the distributor is the same.
|
||||
if (distributor == currentDistributor.dataOrNull()) return@launch
|
||||
currentDistributor = AsyncData.Loading(currentDistributor.dataOrNull())
|
||||
pushService.registerWith(
|
||||
matrixClient = matrixClient,
|
||||
pushProvider = pushProvider,
|
||||
distributor = distributor
|
||||
)
|
||||
.fold(
|
||||
{
|
||||
refreshPushProvider++
|
||||
},
|
||||
{
|
||||
currentDistributor = AsyncData.Failure(it)
|
||||
}
|
||||
)
|
||||
.fold(
|
||||
{
|
||||
refreshPushProvider++
|
||||
},
|
||||
{
|
||||
currentDistributorName = AsyncData.Failure(it)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun handleEvents(event: NotificationSettingsEvents) {
|
||||
@@ -162,8 +161,8 @@ class NotificationSettingsPresenter @Inject constructor(
|
||||
appNotificationsEnabled = appNotificationsEnabled.value
|
||||
),
|
||||
changeNotificationSettingAction = changeNotificationSettingAction.value,
|
||||
currentPushDistributor = currentDistributorName,
|
||||
availablePushDistributors = distributorNames,
|
||||
currentPushDistributor = currentDistributor,
|
||||
availablePushDistributors = availableDistributors,
|
||||
showChangePushProviderDialog = showChangePushProviderDialog,
|
||||
fullScreenIntentPermissionsState = key(refreshFullScreenIntentSettings) { fullScreenIntentPermissionsPresenter.present() },
|
||||
eventSink = ::handleEvents
|
||||
|
||||
@@ -12,6 +12,7 @@ import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState
|
||||
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
|
||||
import io.element.android.libraries.pushproviders.api.Distributor
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@Immutable
|
||||
@@ -19,8 +20,8 @@ data class NotificationSettingsState(
|
||||
val matrixSettings: MatrixSettings,
|
||||
val appSettings: AppSettings,
|
||||
val changeNotificationSettingAction: AsyncAction<Unit>,
|
||||
val currentPushDistributor: AsyncData<String>,
|
||||
val availablePushDistributors: ImmutableList<String>,
|
||||
val currentPushDistributor: AsyncData<Distributor>,
|
||||
val availablePushDistributors: ImmutableList<Distributor>,
|
||||
val showChangePushProviderDialog: Boolean,
|
||||
val fullScreenIntentPermissionsState: FullScreenIntentPermissionsState,
|
||||
val eventSink: (NotificationSettingsEvents) -> Unit,
|
||||
|
||||
@@ -13,6 +13,7 @@ import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState
|
||||
import io.element.android.libraries.fullscreenintent.api.aFullScreenIntentPermissionsState
|
||||
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
|
||||
import io.element.android.libraries.pushproviders.api.Distributor
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
@@ -24,11 +25,19 @@ open class NotificationSettingsStateProvider : PreviewParameterProvider<Notifica
|
||||
aValidNotificationSettingsState(changeNotificationSettingAction = AsyncAction.Loading),
|
||||
aValidNotificationSettingsState(changeNotificationSettingAction = AsyncAction.Failure(Throwable("error"))),
|
||||
aValidNotificationSettingsState(
|
||||
availablePushDistributors = listOf("Firebase"),
|
||||
availablePushDistributors = listOf(aDistributor("Firebase")),
|
||||
changeNotificationSettingAction = AsyncAction.Failure(Throwable("error")),
|
||||
),
|
||||
aValidNotificationSettingsState(availablePushDistributors = listOf("Firebase")),
|
||||
aValidNotificationSettingsState(availablePushDistributors = listOf(aDistributor("Firebase"))),
|
||||
aValidNotificationSettingsState(showChangePushProviderDialog = true),
|
||||
aValidNotificationSettingsState(
|
||||
availablePushDistributors = listOf(
|
||||
aDistributor("Firebase"),
|
||||
aDistributor("ntfy", "app.id1"),
|
||||
aDistributor("ntfy", "app.id2"),
|
||||
),
|
||||
showChangePushProviderDialog = true,
|
||||
),
|
||||
aValidNotificationSettingsState(currentPushDistributor = AsyncData.Loading()),
|
||||
aValidNotificationSettingsState(currentPushDistributor = AsyncData.Failure(Exception("Failed to change distributor"))),
|
||||
aInvalidNotificationSettingsState(),
|
||||
@@ -45,8 +54,11 @@ fun aValidNotificationSettingsState(
|
||||
inviteForMeNotificationsEnabled: Boolean = true,
|
||||
systemNotificationsEnabled: Boolean = true,
|
||||
appNotificationEnabled: Boolean = true,
|
||||
currentPushDistributor: AsyncData<String> = AsyncData.Success("Firebase"),
|
||||
availablePushDistributors: List<String> = listOf("Firebase", "ntfy"),
|
||||
currentPushDistributor: AsyncData<Distributor> = AsyncData.Success(aDistributor("Firebase")),
|
||||
availablePushDistributors: List<Distributor> = listOf(
|
||||
aDistributor("Firebase"),
|
||||
aDistributor("ntfy"),
|
||||
),
|
||||
showChangePushProviderDialog: Boolean = false,
|
||||
fullScreenIntentPermissionsState: FullScreenIntentPermissionsState = aFullScreenIntentPermissionsState(),
|
||||
eventSink: (NotificationSettingsEvents) -> Unit = {},
|
||||
@@ -88,3 +100,11 @@ fun aInvalidNotificationSettingsState(
|
||||
fullScreenIntentPermissionsState = aFullScreenIntentPermissionsState(),
|
||||
eventSink = eventSink,
|
||||
)
|
||||
|
||||
fun aDistributor(
|
||||
name: String = "Name",
|
||||
value: String = "$name Value",
|
||||
) = Distributor(
|
||||
value = value,
|
||||
name = name,
|
||||
)
|
||||
|
||||
@@ -206,7 +206,7 @@ private fun NotificationSettingsContentView(
|
||||
stringResource(id = CommonStrings.common_error)
|
||||
)
|
||||
is AsyncData.Success -> ListItemContent.Text(
|
||||
state.currentPushDistributor.dataOrNull() ?: ""
|
||||
state.currentPushDistributor.dataOrNull()?.name ?: ""
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
@@ -219,8 +219,14 @@ private fun NotificationSettingsContentView(
|
||||
if (state.showChangePushProviderDialog) {
|
||||
SingleSelectionDialog(
|
||||
title = stringResource(id = R.string.screen_advanced_settings_choose_distributor_dialog_title_android),
|
||||
options = state.availablePushDistributors.map {
|
||||
ListOption(title = it)
|
||||
options = state.availablePushDistributors.map { distributor ->
|
||||
// If there are several distributors with the same name, use the full name
|
||||
val title = if (state.availablePushDistributors.count { it.name == distributor.name } > 1) {
|
||||
distributor.fullName
|
||||
} else {
|
||||
distributor.name
|
||||
}
|
||||
ListOption(title = title)
|
||||
}.toImmutableList(),
|
||||
initialSelection = state.availablePushDistributors.indexOf(state.currentPushDistributor.dataOrNull()),
|
||||
onSelectOption = { index ->
|
||||
|
||||
@@ -240,8 +240,11 @@ class NotificationSettingsPresenterTest {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitLastSequentialItem()
|
||||
assertThat(initialState.currentPushDistributor).isEqualTo(AsyncData.Success("aDistributorName0"))
|
||||
assertThat(initialState.availablePushDistributors).containsExactly("aDistributorName0", "aDistributorName1")
|
||||
assertThat(initialState.currentPushDistributor).isEqualTo(AsyncData.Success(Distributor(value = "aDistributorValue0", name = "aDistributorName0")))
|
||||
assertThat(initialState.availablePushDistributors).containsExactly(
|
||||
Distributor(value = "aDistributorValue0", name = "aDistributorName0"),
|
||||
Distributor(value = "aDistributorValue1", name = "aDistributorName1"),
|
||||
)
|
||||
initialState.eventSink.invoke(NotificationSettingsEvents.ChangePushProvider)
|
||||
val withDialog = awaitItem()
|
||||
assertThat(withDialog.showChangePushProviderDialog).isTrue()
|
||||
@@ -257,11 +260,35 @@ class NotificationSettingsPresenterTest {
|
||||
assertThat(withNewProvider.currentPushDistributor).isInstanceOf(AsyncData.Loading::class.java)
|
||||
skipItems(1)
|
||||
val lastItem = awaitItem()
|
||||
assertThat(lastItem.currentPushDistributor).isEqualTo(AsyncData.Success("aDistributorName1"))
|
||||
assertThat(lastItem.currentPushDistributor).isEqualTo(AsyncData.Success(Distributor(value = "aDistributorValue1", name = "aDistributorName1")))
|
||||
cancelAndIgnoreRemainingEvents()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - change push provider to the same value is no op`() = runTest {
|
||||
val presenter = createNotificationSettingsPresenter(
|
||||
pushService = createFakePushService(),
|
||||
)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitLastSequentialItem()
|
||||
assertThat(initialState.currentPushDistributor).isEqualTo(AsyncData.Success(Distributor(value = "aDistributorValue0", name = "aDistributorName0")))
|
||||
assertThat(initialState.availablePushDistributors).containsExactly(
|
||||
Distributor(value = "aDistributorValue0", name = "aDistributorName0"),
|
||||
Distributor(value = "aDistributorValue1", name = "aDistributorName1"),
|
||||
)
|
||||
initialState.eventSink.invoke(NotificationSettingsEvents.ChangePushProvider)
|
||||
assertThat(awaitItem().showChangePushProviderDialog).isTrue()
|
||||
// Choose the same value (index 0)
|
||||
initialState.eventSink(NotificationSettingsEvents.SetPushProvider(0))
|
||||
val withNewProvider = awaitItem()
|
||||
assertThat(withNewProvider.showChangePushProviderDialog).isFalse()
|
||||
expectNoEvents()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - RefreshSystemNotificationsEnabled also refreshes fullScreenIntentState`() = runTest {
|
||||
var lambdaResult = aFullScreenIntentPermissionsState(permissionGranted = false)
|
||||
|
||||
@@ -267,7 +267,7 @@ class NotificationSettingsViewTest {
|
||||
state = aValidNotificationSettingsState(
|
||||
eventSink = eventsRecorder,
|
||||
showChangePushProviderDialog = true,
|
||||
availablePushDistributors = listOf("P1", "P2")
|
||||
availablePushDistributors = listOf(aDistributor("P1"), aDistributor("P2"))
|
||||
),
|
||||
)
|
||||
rule.onNodeWithText("P2").performClick()
|
||||
|
||||
@@ -18,4 +18,6 @@ package io.element.android.libraries.pushproviders.api
|
||||
data class Distributor(
|
||||
val value: String,
|
||||
val name: String,
|
||||
)
|
||||
) {
|
||||
val fullName = "$name ($value)"
|
||||
}
|
||||
|
||||
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.
Reference in New Issue
Block a user