Improve code and display error.
This commit is contained in:
parent
4bd01b6f4f
commit
e64051f7bd
6 changed files with 94 additions and 38 deletions
|
|
@ -26,5 +26,5 @@ sealed interface AdvancedSettingsEvents {
|
||||||
data class SetTheme(val theme: Theme) : AdvancedSettingsEvents
|
data class SetTheme(val theme: Theme) : AdvancedSettingsEvents
|
||||||
data object ChangePushProvider : AdvancedSettingsEvents
|
data object ChangePushProvider : AdvancedSettingsEvents
|
||||||
data object CancelChangePushProvider : AdvancedSettingsEvents
|
data object CancelChangePushProvider : AdvancedSettingsEvents
|
||||||
data class SetPushProvider(val distributorName: String) : AdvancedSettingsEvents
|
data class SetPushProvider(val index: Int) : AdvancedSettingsEvents
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,10 +29,14 @@ import io.element.android.compound.theme.Theme
|
||||||
import io.element.android.compound.theme.mapToTheme
|
import io.element.android.compound.theme.mapToTheme
|
||||||
import io.element.android.features.preferences.api.store.AppPreferencesStore
|
import io.element.android.features.preferences.api.store.AppPreferencesStore
|
||||||
import io.element.android.features.preferences.api.store.SessionPreferencesStore
|
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.architecture.Presenter
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
import io.element.android.libraries.push.api.PushService
|
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.collections.immutable.toImmutableList
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
@ -57,20 +61,60 @@ class AdvancedSettingsPresenter @Inject constructor(
|
||||||
.collectAsState(initial = Theme.System)
|
.collectAsState(initial = Theme.System)
|
||||||
var showChangeThemeDialog by remember { mutableStateOf(false) }
|
var showChangeThemeDialog by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
var currentPushProvider by remember { mutableStateOf<String?>(null) }
|
// List of PushProvider -> Distributor
|
||||||
var distributors by remember { mutableStateOf<List<String>>(emptyList()) }
|
var distributors by remember { mutableStateOf<List<Pair<PushProvider, Distributor>>>(emptyList()) }
|
||||||
|
var distributorNames by remember { mutableStateOf<List<String>>(emptyList()) }
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
distributors = pushService.getAvailablePushProviders()
|
||||||
|
.flatMap { pushProvider ->
|
||||||
|
pushProvider.getDistributors().map { distributor ->
|
||||||
|
pushProvider to distributor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
distributorNames = distributors.map { it.second.name }
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentDistributorName by remember { mutableStateOf<AsyncAction<String>>(AsyncAction.Uninitialized) }
|
||||||
var refreshPushProvider by remember { mutableIntStateOf(0) }
|
var refreshPushProvider by remember { mutableIntStateOf(0) }
|
||||||
|
|
||||||
LaunchedEffect(refreshPushProvider) {
|
LaunchedEffect(refreshPushProvider) {
|
||||||
val p = pushService.getCurrentPushProvider()
|
val p = pushService.getCurrentPushProvider()
|
||||||
currentPushProvider = p?.getCurrentDistributor(matrixClient)?.name
|
val name = p?.getCurrentDistributor(matrixClient)?.name
|
||||||
distributors = pushService.getAvailablePushProviders()
|
currentDistributorName = if (name != null) {
|
||||||
.flatMap { pushProvider ->
|
AsyncAction.Success(name)
|
||||||
pushProvider.getDistributors().map { it.name }
|
} else {
|
||||||
|
AsyncAction.Failure(Exception("Failed to get current push provider"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var showChangePushProviderDialog by remember { mutableStateOf(false) }
|
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) {
|
fun handleEvents(event: AdvancedSettingsEvents) {
|
||||||
when (event) {
|
when (event) {
|
||||||
is AdvancedSettingsEvents.SetDeveloperModeEnabled -> localCoroutineScope.launch {
|
is AdvancedSettingsEvents.SetDeveloperModeEnabled -> localCoroutineScope.launch {
|
||||||
|
|
@ -87,23 +131,7 @@ class AdvancedSettingsPresenter @Inject constructor(
|
||||||
}
|
}
|
||||||
AdvancedSettingsEvents.ChangePushProvider -> showChangePushProviderDialog = true
|
AdvancedSettingsEvents.ChangePushProvider -> showChangePushProviderDialog = true
|
||||||
AdvancedSettingsEvents.CancelChangePushProvider -> showChangePushProviderDialog = false
|
AdvancedSettingsEvents.CancelChangePushProvider -> showChangePushProviderDialog = false
|
||||||
is AdvancedSettingsEvents.SetPushProvider -> {
|
is AdvancedSettingsEvents.SetPushProvider -> localCoroutineScope.changePushProvider(distributors.getOrNull(event.index))
|
||||||
localCoroutineScope.launch {
|
|
||||||
// Retrieve the push provider
|
|
||||||
// TODO rework this
|
|
||||||
val pushProvider = pushService.getAvailablePushProviders().firstOrNull { pushProvider ->
|
|
||||||
pushProvider.getDistributors().any { it.name == event.distributorName }
|
|
||||||
} ?: return@launch
|
|
||||||
val distributor = pushProvider.getDistributors().firstOrNull { it.name == event.distributorName } ?: return@launch
|
|
||||||
pushService.registerWith(
|
|
||||||
matrixClient,
|
|
||||||
pushProvider = pushProvider,
|
|
||||||
distributor = distributor
|
|
||||||
)
|
|
||||||
showChangePushProviderDialog = false
|
|
||||||
refreshPushProvider++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,10 +140,11 @@ class AdvancedSettingsPresenter @Inject constructor(
|
||||||
isSharePresenceEnabled = isSharePresenceEnabled,
|
isSharePresenceEnabled = isSharePresenceEnabled,
|
||||||
theme = theme,
|
theme = theme,
|
||||||
showChangeThemeDialog = showChangeThemeDialog,
|
showChangeThemeDialog = showChangeThemeDialog,
|
||||||
pushDistributor = currentPushProvider ?: "",
|
pushDistributor = currentDistributorName,
|
||||||
pushDistributors = distributors.toImmutableList(),
|
pushDistributors = distributorNames.toImmutableList(),
|
||||||
showChangePushProviderDialog = showChangePushProviderDialog,
|
showChangePushProviderDialog = showChangePushProviderDialog,
|
||||||
eventSink = { handleEvents(it) }
|
eventSink = { handleEvents(it) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package io.element.android.features.preferences.impl.advanced
|
package io.element.android.features.preferences.impl.advanced
|
||||||
|
|
||||||
import io.element.android.compound.theme.Theme
|
import io.element.android.compound.theme.Theme
|
||||||
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
data class AdvancedSettingsState(
|
data class AdvancedSettingsState(
|
||||||
|
|
@ -24,7 +25,7 @@ data class AdvancedSettingsState(
|
||||||
val isSharePresenceEnabled: Boolean,
|
val isSharePresenceEnabled: Boolean,
|
||||||
val theme: Theme,
|
val theme: Theme,
|
||||||
val showChangeThemeDialog: Boolean,
|
val showChangeThemeDialog: Boolean,
|
||||||
val pushDistributor: String,
|
val pushDistributor: AsyncAction<String>,
|
||||||
val pushDistributors: ImmutableList<String>,
|
val pushDistributors: ImmutableList<String>,
|
||||||
val showChangePushProviderDialog: Boolean,
|
val showChangePushProviderDialog: Boolean,
|
||||||
val eventSink: (AdvancedSettingsEvents) -> Unit
|
val eventSink: (AdvancedSettingsEvents) -> Unit
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package io.element.android.features.preferences.impl.advanced
|
||||||
|
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||||
import io.element.android.compound.theme.Theme
|
import io.element.android.compound.theme.Theme
|
||||||
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
|
|
||||||
open class AdvancedSettingsStateProvider : PreviewParameterProvider<AdvancedSettingsState> {
|
open class AdvancedSettingsStateProvider : PreviewParameterProvider<AdvancedSettingsState> {
|
||||||
|
|
@ -28,6 +29,8 @@ open class AdvancedSettingsStateProvider : PreviewParameterProvider<AdvancedSett
|
||||||
aAdvancedSettingsState(showChangeThemeDialog = true),
|
aAdvancedSettingsState(showChangeThemeDialog = true),
|
||||||
aAdvancedSettingsState(isSendPublicReadReceiptsEnabled = true),
|
aAdvancedSettingsState(isSendPublicReadReceiptsEnabled = true),
|
||||||
aAdvancedSettingsState(showChangePushProviderDialog = true),
|
aAdvancedSettingsState(showChangePushProviderDialog = true),
|
||||||
|
aAdvancedSettingsState(pushDistributor = AsyncAction.Loading),
|
||||||
|
aAdvancedSettingsState(pushDistributor = AsyncAction.Failure(Exception("Failed to change distributor"))),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,7 +38,7 @@ fun aAdvancedSettingsState(
|
||||||
isDeveloperModeEnabled: Boolean = false,
|
isDeveloperModeEnabled: Boolean = false,
|
||||||
isSendPublicReadReceiptsEnabled: Boolean = false,
|
isSendPublicReadReceiptsEnabled: Boolean = false,
|
||||||
showChangeThemeDialog: Boolean = false,
|
showChangeThemeDialog: Boolean = false,
|
||||||
pushDistributor: String = "Firebase",
|
pushDistributor: AsyncAction<String> = AsyncAction.Success("Firebase"),
|
||||||
pushDistributors: List<String> = listOf("Firebase", "ntfy"),
|
pushDistributors: List<String> = listOf("Firebase", "ntfy"),
|
||||||
showChangePushProviderDialog: Boolean = false,
|
showChangePushProviderDialog: Boolean = false,
|
||||||
) = AdvancedSettingsState(
|
) = AdvancedSettingsState(
|
||||||
|
|
|
||||||
|
|
@ -16,19 +16,24 @@
|
||||||
|
|
||||||
package io.element.android.features.preferences.impl.advanced
|
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.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
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.Theme
|
||||||
import io.element.android.compound.theme.themes
|
import io.element.android.compound.theme.themes
|
||||||
import io.element.android.features.preferences.impl.R
|
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.ListOption
|
||||||
import io.element.android.libraries.designsystem.components.dialogs.SingleSelectionDialog
|
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.list.ListItemContent
|
||||||
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
|
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
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.ListItem
|
||||||
import io.element.android.libraries.designsystem.theme.components.Text
|
import io.element.android.libraries.designsystem.theme.components.Text
|
||||||
import io.element.android.libraries.ui.strings.CommonStrings
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
|
|
@ -86,12 +91,29 @@ fun AdvancedSettingsView(
|
||||||
// TODO i18n
|
// TODO i18n
|
||||||
Text(text = "Push provider")
|
Text(text = "Push provider")
|
||||||
},
|
},
|
||||||
trailingContent = ListItemContent.Text(
|
trailingContent = when (state.pushDistributor) {
|
||||||
state.pushDistributor
|
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.pushDistributor.dataOrNull() ?: ""
|
||||||
|
)
|
||||||
|
},
|
||||||
onClick = {
|
onClick = {
|
||||||
|
if (state.pushDistributor.isReady()) {
|
||||||
state.eventSink(AdvancedSettingsEvents.ChangePushProvider)
|
state.eventSink(AdvancedSettingsEvents.ChangePushProvider)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,15 +134,14 @@ fun AdvancedSettingsView(
|
||||||
|
|
||||||
if (state.showChangePushProviderDialog) {
|
if (state.showChangePushProviderDialog) {
|
||||||
SingleSelectionDialog(
|
SingleSelectionDialog(
|
||||||
|
title = "Select Push provider",
|
||||||
options = state.pushDistributors.map {
|
options = state.pushDistributors.map {
|
||||||
ListOption(title = it)
|
ListOption(title = it)
|
||||||
}.toImmutableList(),
|
}.toImmutableList(),
|
||||||
initialSelection = state.pushDistributors.indexOf(state.pushDistributor),
|
initialSelection = state.pushDistributors.indexOf(state.pushDistributor.dataOrNull()),
|
||||||
onOptionSelected = {
|
onOptionSelected = { index ->
|
||||||
state.eventSink(
|
state.eventSink(
|
||||||
AdvancedSettingsEvents.SetPushProvider(
|
AdvancedSettingsEvents.SetPushProvider(index)
|
||||||
state.pushDistributors[it]
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onDismissRequest = { state.eventSink(AdvancedSettingsEvents.CancelChangePushProvider) },
|
onDismissRequest = { state.eventSink(AdvancedSettingsEvents.CancelChangePushProvider) },
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,8 @@ sealed interface AsyncAction<out T> {
|
||||||
fun isFailure(): Boolean = this is Failure
|
fun isFailure(): Boolean = this is Failure
|
||||||
|
|
||||||
fun isSuccess(): Boolean = this is Success
|
fun isSuccess(): Boolean = this is Success
|
||||||
|
|
||||||
|
fun isReady() = isSuccess() || isFailure()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend inline fun <T> MutableState<AsyncAction<T>>.runCatchingUpdatingState(
|
suspend inline fun <T> MutableState<AsyncAction<T>>.runCatchingUpdatingState(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue