Merge pull request #2873 from element-hq/feature/bma/pushProviderSwitch
Push provider switch
This commit is contained in:
commit
d67c1c6fb9
50 changed files with 782 additions and 154 deletions
|
|
@ -24,4 +24,7 @@ sealed interface AdvancedSettingsEvents {
|
|||
data object ChangeTheme : AdvancedSettingsEvents
|
||||
data object CancelChangeTheme : AdvancedSettingsEvents
|
||||
data class SetTheme(val theme: Theme) : AdvancedSettingsEvents
|
||||
data object ChangePushProvider : AdvancedSettingsEvents
|
||||
data object CancelChangePushProvider : AdvancedSettingsEvents
|
||||
data class SetPushProvider(val index: Int) : AdvancedSettingsEvents
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,10 @@
|
|||
package io.element.android.features.preferences.impl.advanced
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
|
|
@ -27,13 +29,22 @@ import io.element.android.compound.theme.Theme
|
|||
import io.element.android.compound.theme.mapToTheme
|
||||
import io.element.android.features.preferences.api.store.AppPreferencesStore
|
||||
import io.element.android.features.preferences.api.store.SessionPreferencesStore
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.push.api.PushService
|
||||
import io.element.android.libraries.pushproviders.api.Distributor
|
||||
import io.element.android.libraries.pushproviders.api.PushProvider
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
class AdvancedSettingsPresenter @Inject constructor(
|
||||
private val appPreferencesStore: AppPreferencesStore,
|
||||
private val sessionPreferencesStore: SessionPreferencesStore,
|
||||
private val matrixClient: MatrixClient,
|
||||
private val pushService: PushService,
|
||||
) : Presenter<AdvancedSettingsState> {
|
||||
@Composable
|
||||
override fun present(): AdvancedSettingsState {
|
||||
|
|
@ -49,6 +60,62 @@ class AdvancedSettingsPresenter @Inject constructor(
|
|||
}
|
||||
.collectAsState(initial = Theme.System)
|
||||
var showChangeThemeDialog by remember { mutableStateOf(false) }
|
||||
|
||||
// List of PushProvider -> Distributor
|
||||
val distributors = remember {
|
||||
pushService.getAvailablePushProviders()
|
||||
.flatMap { pushProvider ->
|
||||
pushProvider.getDistributors().map { distributor ->
|
||||
pushProvider to distributor
|
||||
}
|
||||
}
|
||||
}
|
||||
// List of Distributor names
|
||||
val distributorNames = remember {
|
||||
distributors.map { it.second.name }
|
||||
}
|
||||
|
||||
var currentDistributorName by remember { mutableStateOf<AsyncAction<String>>(AsyncAction.Uninitialized) }
|
||||
var refreshPushProvider by remember { mutableIntStateOf(0) }
|
||||
|
||||
LaunchedEffect(refreshPushProvider) {
|
||||
val p = pushService.getCurrentPushProvider()
|
||||
val name = p?.getCurrentDistributor(matrixClient)?.name
|
||||
currentDistributorName = if (name != null) {
|
||||
AsyncAction.Success(name)
|
||||
} else {
|
||||
AsyncAction.Failure(Exception("Failed to get current push provider"))
|
||||
}
|
||||
}
|
||||
|
||||
var showChangePushProviderDialog by remember { mutableStateOf(false) }
|
||||
|
||||
fun CoroutineScope.changePushProvider(
|
||||
data: Pair<PushProvider, Distributor>?
|
||||
) = launch {
|
||||
showChangePushProviderDialog = false
|
||||
data ?: return@launch
|
||||
// No op if the value is the same.
|
||||
if (data.second.name == currentDistributorName.dataOrNull()) return@launch
|
||||
currentDistributorName = AsyncAction.Loading
|
||||
data.let { (pushProvider, distributor) ->
|
||||
pushService.registerWith(
|
||||
matrixClient = matrixClient,
|
||||
pushProvider = pushProvider,
|
||||
distributor = distributor
|
||||
)
|
||||
.fold(
|
||||
{
|
||||
currentDistributorName = AsyncAction.Success(distributor.name)
|
||||
refreshPushProvider++
|
||||
},
|
||||
{
|
||||
currentDistributorName = AsyncAction.Failure(it)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun handleEvents(event: AdvancedSettingsEvents) {
|
||||
when (event) {
|
||||
is AdvancedSettingsEvents.SetDeveloperModeEnabled -> localCoroutineScope.launch {
|
||||
|
|
@ -63,6 +130,9 @@ class AdvancedSettingsPresenter @Inject constructor(
|
|||
appPreferencesStore.setTheme(event.theme.name)
|
||||
showChangeThemeDialog = false
|
||||
}
|
||||
AdvancedSettingsEvents.ChangePushProvider -> showChangePushProviderDialog = true
|
||||
AdvancedSettingsEvents.CancelChangePushProvider -> showChangePushProviderDialog = false
|
||||
is AdvancedSettingsEvents.SetPushProvider -> localCoroutineScope.changePushProvider(distributors.getOrNull(event.index))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -71,6 +141,9 @@ class AdvancedSettingsPresenter @Inject constructor(
|
|||
isSharePresenceEnabled = isSharePresenceEnabled,
|
||||
theme = theme,
|
||||
showChangeThemeDialog = showChangeThemeDialog,
|
||||
currentPushDistributor = currentDistributorName,
|
||||
availablePushDistributors = distributorNames.toImmutableList(),
|
||||
showChangePushProviderDialog = showChangePushProviderDialog,
|
||||
eventSink = { handleEvents(it) }
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,11 +17,16 @@
|
|||
package io.element.android.features.preferences.impl.advanced
|
||||
|
||||
import io.element.android.compound.theme.Theme
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
data class AdvancedSettingsState(
|
||||
val isDeveloperModeEnabled: Boolean,
|
||||
val isSharePresenceEnabled: Boolean,
|
||||
val theme: Theme,
|
||||
val showChangeThemeDialog: Boolean,
|
||||
val currentPushDistributor: AsyncAction<String>,
|
||||
val availablePushDistributors: ImmutableList<String>,
|
||||
val showChangePushProviderDialog: Boolean,
|
||||
val eventSink: (AdvancedSettingsEvents) -> Unit
|
||||
)
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ package io.element.android.features.preferences.impl.advanced
|
|||
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import io.element.android.compound.theme.Theme
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
open class AdvancedSettingsStateProvider : PreviewParameterProvider<AdvancedSettingsState> {
|
||||
override val values: Sequence<AdvancedSettingsState>
|
||||
|
|
@ -26,6 +28,9 @@ open class AdvancedSettingsStateProvider : PreviewParameterProvider<AdvancedSett
|
|||
aAdvancedSettingsState(isDeveloperModeEnabled = true),
|
||||
aAdvancedSettingsState(showChangeThemeDialog = true),
|
||||
aAdvancedSettingsState(isSendPublicReadReceiptsEnabled = true),
|
||||
aAdvancedSettingsState(showChangePushProviderDialog = true),
|
||||
aAdvancedSettingsState(currentPushDistributor = AsyncAction.Loading),
|
||||
aAdvancedSettingsState(currentPushDistributor = AsyncAction.Failure(Exception("Failed to change distributor"))),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -33,10 +38,17 @@ fun aAdvancedSettingsState(
|
|||
isDeveloperModeEnabled: Boolean = false,
|
||||
isSendPublicReadReceiptsEnabled: Boolean = false,
|
||||
showChangeThemeDialog: Boolean = false,
|
||||
currentPushDistributor: AsyncAction<String> = AsyncAction.Success("Firebase"),
|
||||
availablePushDistributors: List<String> = listOf("Firebase", "ntfy"),
|
||||
showChangePushProviderDialog: Boolean = false,
|
||||
eventSink: (AdvancedSettingsEvents) -> Unit = {},
|
||||
) = AdvancedSettingsState(
|
||||
isDeveloperModeEnabled = isDeveloperModeEnabled,
|
||||
isSharePresenceEnabled = isSendPublicReadReceiptsEnabled,
|
||||
theme = Theme.System,
|
||||
showChangeThemeDialog = showChangeThemeDialog,
|
||||
eventSink = {}
|
||||
currentPushDistributor = currentPushDistributor,
|
||||
availablePushDistributors = availablePushDistributors.toImmutableList(),
|
||||
showChangePushProviderDialog = showChangePushProviderDialog,
|
||||
eventSink = eventSink
|
||||
)
|
||||
|
|
|
|||
|
|
@ -16,19 +16,24 @@
|
|||
|
||||
package io.element.android.features.preferences.impl.advanced
|
||||
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.progressSemantics
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.Theme
|
||||
import io.element.android.compound.theme.themes
|
||||
import io.element.android.features.preferences.impl.R
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.designsystem.components.dialogs.ListOption
|
||||
import io.element.android.libraries.designsystem.components.dialogs.SingleSelectionDialog
|
||||
import io.element.android.libraries.designsystem.components.list.ListItemContent
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
|
||||
import io.element.android.libraries.designsystem.theme.components.ListItem
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
|
@ -81,6 +86,34 @@ fun AdvancedSettingsView(
|
|||
),
|
||||
onClick = { state.eventSink(AdvancedSettingsEvents.SetSharePresenceEnabled(!state.isSharePresenceEnabled)) }
|
||||
)
|
||||
ListItem(
|
||||
headlineContent = {
|
||||
Text(text = stringResource(id = R.string.screen_advanced_settings_push_provider_android))
|
||||
},
|
||||
trailingContent = when (state.currentPushDistributor) {
|
||||
AsyncAction.Uninitialized,
|
||||
AsyncAction.Confirming,
|
||||
AsyncAction.Loading -> ListItemContent.Custom {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier
|
||||
.progressSemantics()
|
||||
.size(20.dp),
|
||||
strokeWidth = 2.dp
|
||||
)
|
||||
}
|
||||
is AsyncAction.Failure -> ListItemContent.Text(
|
||||
stringResource(id = CommonStrings.common_error)
|
||||
)
|
||||
is AsyncAction.Success -> ListItemContent.Text(
|
||||
state.currentPushDistributor.dataOrNull() ?: ""
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
if (state.currentPushDistributor.isReady()) {
|
||||
state.eventSink(AdvancedSettingsEvents.ChangePushProvider)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (state.showChangeThemeDialog) {
|
||||
|
|
@ -97,6 +130,22 @@ fun AdvancedSettingsView(
|
|||
onDismissRequest = { state.eventSink(AdvancedSettingsEvents.CancelChangeTheme) },
|
||||
)
|
||||
}
|
||||
|
||||
if (state.showChangePushProviderDialog) {
|
||||
SingleSelectionDialog(
|
||||
title = stringResource(id = R.string.screen_advanced_settings_choose_distributor_dialog_title_android),
|
||||
options = state.availablePushDistributors.map {
|
||||
ListOption(title = it)
|
||||
}.toImmutableList(),
|
||||
initialSelection = state.availablePushDistributors.indexOf(state.currentPushDistributor.dataOrNull()),
|
||||
onOptionSelected = { index ->
|
||||
state.eventSink(
|
||||
AdvancedSettingsEvents.SetPushProvider(index)
|
||||
)
|
||||
},
|
||||
onDismissRequest = { state.eventSink(AdvancedSettingsEvents.CancelChangePushProvider) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue