parent
95ac835b9c
commit
9c99e5ac80
|
@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.Arrangement
|
|||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
|
@ -46,7 +47,7 @@ fun RadioButton(
|
|||
modifier: Modifier = Modifier,
|
||||
checkedContent: @Composable () -> Unit = { RadioButtonCheckedContent(state) },
|
||||
uncheckedContent: @Composable () -> Unit = { RadioButtonUncheckedContent(state) },
|
||||
trailingContent: @Composable (() -> Unit)? = null,
|
||||
trailingContent: @Composable (RowScope.() -> Unit)? = null,
|
||||
testTag: String? = null,
|
||||
) {
|
||||
Row(
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package co.electriccoin.zcash.di
|
||||
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetPersistableWalletUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetSelectedEndpointUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetSynchronizerUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.ObserveFastestServersUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.ObserveSelectedEndpointUseCase
|
||||
|
@ -21,4 +22,5 @@ val useCaseModule =
|
|||
singleOf(::PersistEndpointUseCase)
|
||||
singleOf(::ValidateEndpointUseCase)
|
||||
singleOf(::GetPersistableWalletUseCase)
|
||||
singleOf(::GetSelectedEndpointUseCase)
|
||||
}
|
||||
|
|
|
@ -131,7 +131,7 @@ class WalletRepositoryImpl(
|
|||
.withIndex()
|
||||
.flatMapLatest { (_, synchronizer) ->
|
||||
synchronizer
|
||||
?.getFastestServers(application, getAllServers())
|
||||
?.getFastestServers(application, getDefaultServers())
|
||||
?.map {
|
||||
when (it) {
|
||||
FastestServersResult.Measuring ->
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package co.electriccoin.zcash.ui.common.usecase
|
||||
|
||||
import co.electriccoin.zcash.ui.common.repository.WalletRepository
|
||||
|
||||
class GetSelectedEndpointUseCase(
|
||||
private val walletRepository: WalletRepository
|
||||
) {
|
||||
suspend operator fun invoke() = walletRepository.getSelectedServer()
|
||||
}
|
|
@ -43,6 +43,8 @@ sealed interface ServerState : Itemizable {
|
|||
data class Custom(
|
||||
val radioButtonState: RadioButtonState,
|
||||
val newServerTextFieldState: TextFieldState,
|
||||
val badge: StringResource?,
|
||||
val isExpanded: Boolean,
|
||||
) : ServerState {
|
||||
override val contentType: Any = "Custom"
|
||||
override val key: Any = contentType
|
||||
|
|
|
@ -35,6 +35,7 @@ import androidx.compose.runtime.setValue
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.res.painterResource
|
||||
|
@ -324,7 +325,8 @@ private fun FastestServersHeader(state: ServerListState.Fastest) {
|
|||
} else {
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.ic_retry),
|
||||
contentDescription = state.retryButton.text.getValue()
|
||||
contentDescription = state.retryButton.text.getValue(),
|
||||
colorFilter = ColorFilter.tint(ZcashTheme.zashiColors.textPrimary)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -353,6 +355,7 @@ private fun ServerHeader(text: StringResource) {
|
|||
)
|
||||
}
|
||||
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
private fun CustomServerRadioButton(
|
||||
state: ServerState.Custom,
|
||||
|
@ -362,21 +365,50 @@ private fun CustomServerRadioButton(
|
|||
RadioButton(
|
||||
state = state.radioButtonState,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
checkedContent = {
|
||||
if (state.badge == null) {
|
||||
RadioButtonCheckedContent(state.radioButtonState)
|
||||
} else {
|
||||
Image(
|
||||
painter =
|
||||
painterResource(
|
||||
id =
|
||||
if (isSystemInDarkTheme()) {
|
||||
drawable.ic_radio_button_checked_variant_dark
|
||||
} else {
|
||||
drawable.ic_radio_button_checked_variant
|
||||
}
|
||||
),
|
||||
contentDescription = state.radioButtonState.text.getValue(),
|
||||
)
|
||||
}
|
||||
},
|
||||
trailingContent = {
|
||||
if (state.badge != null) {
|
||||
Badge(
|
||||
text = state.badge,
|
||||
)
|
||||
Spacer(
|
||||
modifier = Modifier.width(8.dp),
|
||||
)
|
||||
}
|
||||
val iconAngle =
|
||||
animateFloatAsState(
|
||||
targetValue = if (state.radioButtonState.isChecked) 180f else 0f,
|
||||
targetValue = if (state.isExpanded) 180f else 0f,
|
||||
label = "iconAngle"
|
||||
)
|
||||
Image(
|
||||
modifier = Modifier.rotate(iconAngle.value),
|
||||
modifier =
|
||||
Modifier
|
||||
.align(Alignment.CenterVertically)
|
||||
.rotate(iconAngle.value),
|
||||
painter = painterResource(id = R.drawable.ic_expand),
|
||||
contentDescription = state.radioButtonState.text.getValue()
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
AnimatedVisibility(visible = state.radioButtonState.isChecked) {
|
||||
AnimatedVisibility(visible = state.isExpanded) {
|
||||
val focusManager = LocalFocusManager.current
|
||||
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall))
|
||||
ZashiTextField(
|
||||
|
@ -459,6 +491,8 @@ private fun ChooseServerPreview(
|
|||
isEnabled = true,
|
||||
onValueChange = { },
|
||||
),
|
||||
badge = null,
|
||||
isExpanded = true
|
||||
)
|
||||
} else {
|
||||
ServerState.Default(
|
||||
|
|
|
@ -42,6 +42,8 @@ class ChooseServerViewModel(
|
|||
|
||||
private val dialogState = MutableStateFlow<ServerDialogState?>(null)
|
||||
|
||||
private val isCustomEndpointExpanded = MutableStateFlow(false)
|
||||
|
||||
private val fastest =
|
||||
combine(
|
||||
observeSelectedEndpoint(),
|
||||
|
@ -71,7 +73,8 @@ class ChooseServerViewModel(
|
|||
observeFastestServers(),
|
||||
userCustomEndpointText,
|
||||
userEndpointSelection,
|
||||
) { selectedEndpoint, fastest, userCustomEndpointText, userEndpointSelection ->
|
||||
isCustomEndpointExpanded
|
||||
) { selectedEndpoint, fastest, userCustomEndpointText, userEndpointSelection, isCustomEndpointExpanded ->
|
||||
if (selectedEndpoint == null) return@combine null
|
||||
|
||||
val isSelectedEndpointCustom = !getAvailableServers().contains(selectedEndpoint)
|
||||
|
@ -81,7 +84,8 @@ class ChooseServerViewModel(
|
|||
userEndpointSelection = userEndpointSelection,
|
||||
isSelectedEndpointCustom = isSelectedEndpointCustom,
|
||||
userCustomEndpointText = userCustomEndpointText,
|
||||
selectedEndpoint = selectedEndpoint
|
||||
selectedEndpoint = selectedEndpoint,
|
||||
isCustomEndpointExpanded = isCustomEndpointExpanded
|
||||
)
|
||||
|
||||
ServerListState.Other(
|
||||
|
@ -109,7 +113,15 @@ class ChooseServerViewModel(
|
|||
userEndpointSelection,
|
||||
isSaveInProgress
|
||||
) { selectedEndpoint, userEndpointSelection, isSaveInProgress ->
|
||||
val userSelectedEndpoint = (userEndpointSelection as? Selection.Endpoint)?.endpoint
|
||||
val userSelectedEndpoint =
|
||||
when (userEndpointSelection) {
|
||||
Selection.Custom -> {
|
||||
val isSelectedEndpointCustom = !getAvailableServers().contains(selectedEndpoint)
|
||||
if (isSelectedEndpointCustom) selectedEndpoint else null
|
||||
}
|
||||
is Selection.Endpoint -> userEndpointSelection.endpoint
|
||||
null -> null
|
||||
}
|
||||
ButtonState(
|
||||
text = stringRes(R.string.choose_server_save),
|
||||
isEnabled = userEndpointSelection != null && selectedEndpoint != userSelectedEndpoint,
|
||||
|
@ -139,11 +151,17 @@ class ChooseServerViewModel(
|
|||
userEndpointSelection: Selection?,
|
||||
isSelectedEndpointCustom: Boolean,
|
||||
userCustomEndpointText: String?,
|
||||
selectedEndpoint: LightWalletEndpoint
|
||||
selectedEndpoint: LightWalletEndpoint,
|
||||
isCustomEndpointExpanded: Boolean,
|
||||
) = ServerState.Custom(
|
||||
radioButtonState =
|
||||
RadioButtonState(
|
||||
text = stringRes(R.string.choose_server_custom),
|
||||
text =
|
||||
if (isSelectedEndpointCustom) {
|
||||
stringRes(R.string.choose_server_full_server_name, selectedEndpoint.host, selectedEndpoint.port)
|
||||
} else {
|
||||
stringRes(R.string.choose_server_custom)
|
||||
},
|
||||
isChecked =
|
||||
userEndpointSelection is Selection.Custom ||
|
||||
(userEndpointSelection == null && isSelectedEndpointCustom),
|
||||
|
@ -163,6 +181,8 @@ class ChooseServerViewModel(
|
|||
},
|
||||
onValueChange = ::onCustomEndpointTextChanged,
|
||||
),
|
||||
badge = if (isSelectedEndpointCustom) stringRes(R.string.choose_server_active) else null,
|
||||
isExpanded = isCustomEndpointExpanded
|
||||
)
|
||||
|
||||
private fun createDefaultServerState(
|
||||
|
@ -195,10 +215,12 @@ class ChooseServerViewModel(
|
|||
}
|
||||
|
||||
private fun onEndpointClicked(endpoint: LightWalletEndpoint) {
|
||||
isCustomEndpointExpanded.update { false }
|
||||
userEndpointSelection.update { Selection.Endpoint(endpoint) }
|
||||
}
|
||||
|
||||
private fun onCustomEndpointClicked() {
|
||||
isCustomEndpointExpanded.update { true }
|
||||
userEndpointSelection.update { Selection.Custom }
|
||||
}
|
||||
|
||||
|
@ -210,6 +232,7 @@ class ChooseServerViewModel(
|
|||
val selection = getUserEndpointSelectionOrShowError() ?: return@launch
|
||||
try {
|
||||
persistEndpoint(selection)
|
||||
isCustomEndpointExpanded.update { false }
|
||||
} catch (e: PersistEndpointException) {
|
||||
showValidationErrorDialog(e.message)
|
||||
}
|
||||
|
@ -228,7 +251,7 @@ class ChooseServerViewModel(
|
|||
*/
|
||||
private fun getUserEndpointSelectionOrShowError(): LightWalletEndpoint? {
|
||||
return when (val selection = userEndpointSelection.value) {
|
||||
Selection.Custom -> {
|
||||
is Selection.Custom -> {
|
||||
val endpoint = userCustomEndpointText.value
|
||||
val validated = validateEndpoint(endpoint.orEmpty())
|
||||
if (validated == null) {
|
||||
|
|
Loading…
Reference in New Issue