#1420 Design hotfixes

Closes #1420
This commit is contained in:
Milan Cerovsky 2024-09-05 13:19:31 +02:00
parent 95ac835b9c
commit 9c99e5ac80
7 changed files with 83 additions and 12 deletions

View File

@ -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(

View File

@ -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)
}

View File

@ -131,7 +131,7 @@ class WalletRepositoryImpl(
.withIndex()
.flatMapLatest { (_, synchronizer) ->
synchronizer
?.getFastestServers(application, getAllServers())
?.getFastestServers(application, getDefaultServers())
?.map {
when (it) {
FastestServersResult.Measuring ->

View File

@ -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()
}

View File

@ -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

View File

@ -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(

View File

@ -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) {