Updated on 2026-08-14

This commit is contained in:
Tangem 2024-01-25 15:39:56 +03:00
parent 0450ce9906
commit b14caba3cf
9 changed files with 677 additions and 43 deletions

View file

@ -0,0 +1,154 @@
package com.tangem.core.ui.components.fields
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment.Companion.TopCenter
import androidx.compose.ui.Alignment.Companion.TopStart
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import com.tangem.core.ui.components.fields.visualtransformations.AmountVisualTransformation
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.utils.*
import java.text.DecimalFormat
@Composable
fun AmountTextField(
value: String,
decimals: Int,
onValueChange: (String) -> Unit,
textStyle: TextStyle,
modifier: Modifier = Modifier,
symbol: String? = null,
color: Color = TangemTheme.colors.text.primary1,
placeholderAlignment: Alignment = TopStart,
showPlaceholder: Boolean = true,
keyboardOptions: KeyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Number,
),
) {
val decimalFormat = rememberDecimalFormat()
val placeholderTextAlign = if (placeholderAlignment == TopCenter) {
TextAlign.Center
} else {
TextAlign.Start
}
SimpleTextField(
value = value,
onValueChange = { newText ->
if (decimalFormat.isValidSymbols(newText)) {
val trimmed = decimalFormat.getValidatedNumberWithFixedDecimals(newText, decimals)
onValueChange(trimmed)
}
},
modifier = modifier
.background(TangemTheme.colors.background.action),
textStyle = textStyle,
color = color,
keyboardOptions = keyboardOptions,
singleLine = true,
visualTransformation = AmountVisualTransformation(decimals, symbol, decimalFormat),
decorationBox = { innerTextField ->
Box {
if (value.isBlank() && showPlaceholder) {
val placeholder = if (symbol != null) {
decimalFormat.defaultFormat().plus(" $symbol")
} else {
decimalFormat.defaultFormat()
}
Text(
text = placeholder,
style = textStyle,
color = TangemTheme.colors.text.disabled,
textAlign = placeholderTextAlign,
modifier = Modifier
.align(placeholderAlignment),
)
}
innerTextField()
}
},
)
}
private fun DecimalFormat.isValidSymbols(text: String): Boolean {
return checkDecimalSeparatorDuplicate(text) && checkGroupingSeparator(text)
}
// region preview
@Preview(locale = "en", showBackground = true, name = "English")
@Preview(locale = "ru", showBackground = true, name = "Russian")
@Composable
private fun AmountTextFieldPreview(
@PreviewParameter(AmountTextFieldPreviewProvider::class) amount: AmountTextFieldPreviewData,
) {
var text by remember { mutableStateOf(amount.value.orEmpty()) }
TangemTheme {
AmountTextField(
value = text,
decimals = amount.decimals,
symbol = amount.symbol,
placeholderAlignment = amount.placeholderAlignment,
showPlaceholder = amount.showPlaceholder,
onValueChange = { text = it },
textStyle = TangemTheme.typography.h2.copy(
color = TangemTheme.colors.text.primary1,
textAlign = TextAlign.Center,
),
modifier = Modifier.fillMaxWidth(),
)
}
}
private class AmountTextFieldPreviewProvider : PreviewParameterProvider<AmountTextFieldPreviewData> {
override val values = sequenceOf(
AmountTextFieldPreviewData(
symbol = "USD",
value = "1000000,123123",
decimals = 3,
placeholderAlignment = TopStart,
showPlaceholder = true,
),
AmountTextFieldPreviewData(
symbol = null,
value = "1000000.123123",
decimals = 6,
placeholderAlignment = TopStart,
showPlaceholder = false,
),
AmountTextFieldPreviewData(
symbol = "$",
value = null,
decimals = 2,
showPlaceholder = true,
placeholderAlignment = TopCenter,
),
AmountTextFieldPreviewData(
symbol = null,
value = null,
decimals = 2,
showPlaceholder = true,
placeholderAlignment = TopStart,
),
)
}
private data class AmountTextFieldPreviewData(
val symbol: String? = "$",
val value: String? = null,
val decimals: Int = 2,
val showPlaceholder: Boolean,
val placeholderAlignment: Alignment,
)
// endregion

View file

@ -3,14 +3,18 @@ package com.tangem.core.ui.components.fields
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.selection.LocalTextSelectionColors
import androidx.compose.foundation.text.selection.TextSelectionColors
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.input.VisualTransformation
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
@ -19,6 +23,7 @@ import com.tangem.core.ui.res.TangemTheme
/**
* Simple text field with placeholder
*/
@Suppress("ReusedModifierInstance")
@Composable
fun SimpleTextField(
value: String,
@ -29,32 +34,72 @@ fun SimpleTextField(
visualTransformation: VisualTransformation = VisualTransformation.None,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
color: Color = TangemTheme.colors.text.primary1,
textStyle: TextStyle = TangemTheme.typography.body2.copy(color = color),
readOnly: Boolean = false,
decorationBox: (@Composable (innerTextField: @Composable () -> Unit) -> Unit)? = null,
) {
val focusRequester = remember { FocusRequester() }
BasicTextField(
value = value,
onValueChange = onValueChange,
textStyle = TangemTheme.typography.body2.copy(color = color),
cursorBrush = SolidColor(TangemTheme.colors.text.primary1),
singleLine = singleLine,
readOnly = readOnly,
visualTransformation = visualTransformation,
keyboardOptions = keyboardOptions,
decorationBox = { textValue ->
Box {
if (value.isBlank() && placeholder != null) {
Text(
text = placeholder.resolveReference(),
style = TangemTheme.typography.body2,
color = TangemTheme.colors.text.disabled,
modifier = Modifier,
)
}
textValue()
}
},
modifier = modifier
.focusRequester(focusRequester),
var textFieldValueState by remember {
mutableStateOf(
TextFieldValue(
text = value,
selection = when {
value.isEmpty() -> TextRange.Zero
else -> TextRange(value.length, value.length)
},
),
)
}
val focusRequester = remember { FocusRequester.Default }
val customTextSelectionColors = TextSelectionColors(
handleColor = TangemTheme.colors.text.secondary,
backgroundColor = TangemTheme.colors.text.secondary.copy(alpha = 0.4f),
)
val textFieldValue = textFieldValueState.copy(text = value)
SideEffect {
if (textFieldValue.selection != textFieldValueState.selection ||
textFieldValue.composition != textFieldValueState.composition
) {
textFieldValueState = textFieldValue
}
}
var lastTextValue by remember(value) { mutableStateOf(value) }
CompositionLocalProvider(LocalTextSelectionColors provides customTextSelectionColors) {
BasicTextField(
value = textFieldValue,
onValueChange = { newTextFieldValueState ->
textFieldValueState = newTextFieldValueState
val stringChangedSinceLastInvocation = lastTextValue != newTextFieldValueState.text
lastTextValue = newTextFieldValueState.text
if (stringChangedSinceLastInvocation) {
onValueChange(newTextFieldValueState.text)
}
},
textStyle = textStyle.copy(color = color),
cursorBrush = SolidColor(TangemTheme.colors.text.primary1),
singleLine = singleLine,
readOnly = readOnly,
visualTransformation = visualTransformation,
keyboardOptions = keyboardOptions,
decorationBox = decorationBox ?: { textValue ->
Box {
if (value.isBlank() && placeholder != null) {
Text(
text = placeholder.resolveReference(),
style = textStyle,
color = TangemTheme.colors.text.disabled,
)
}
textValue()
}
},
modifier = modifier
.focusRequester(focusRequester),
)
}
}

View file

@ -5,28 +5,49 @@ import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.input.OffsetMapping
import androidx.compose.ui.text.input.TransformedText
import androidx.compose.ui.text.input.VisualTransformation
import com.tangem.core.ui.utils.formatWithThousands
import java.text.DecimalFormat
class AmountVisualTransformation(
private val symbol: String,
private val decimals: Int,
private val symbol: String? = null,
private val decimalFormat: DecimalFormat = DecimalFormat(),
) : VisualTransformation {
override fun filter(text: AnnotatedString): TransformedText {
return TransformedText(
buildAnnotatedString {
append(text)
if (text.isNotBlank()) {
append(" ")
append(symbol)
}
},
object : OffsetMapping {
override fun originalToTransformed(offset: Int): Int {
return text.length
}
override fun transformedToOriginal(offset: Int): Int {
return text.length
override fun filter(text: AnnotatedString): TransformedText {
val formattedText = decimalFormat.formatWithThousands(
text.text,
decimals,
)
val groupingSymbol = decimalFormat.decimalFormatSymbols.groupingSeparator
return TransformedText(
text = buildAnnotatedString {
append(formattedText)
if (formattedText.isNotEmpty() && symbol != null) {
append(" $symbol")
}
},
offsetMapping = OffsetMappingImpl(text.text, formattedText, groupingSymbol),
)
}
private class OffsetMappingImpl(
private val text: String,
private val formattedText: String,
private val gropingSymbol: Char,
) : OffsetMapping {
override fun originalToTransformed(offset: Int): Int {
var noneDigitCount = 0
var i = 0
while (i < offset + noneDigitCount) {
if (formattedText.getOrNull(i++) == gropingSymbol) noneDigitCount++
}
return (offset + noneDigitCount).coerceIn(0, formattedText.length)
}
override fun transformedToOriginal(offset: Int): Int {
val noneDigitCount = formattedText.take(offset).count { it == gropingSymbol }
return (offset - noneDigitCount).coerceIn(0, text.length)
}
}
}

View file

@ -0,0 +1,104 @@
package com.tangem.core.ui.components.inputrow
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import com.tangem.core.ui.components.fields.AmountTextField
import com.tangem.core.ui.components.inputrow.inner.DividerContainer
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
/**
* Input row for entering amount. Manages correct amount format and validation
*
* @param title title reference
* @param text primary text reference
* @param onValueChange text change callback
* @param modifier modifier
* @param titleColor title color
* @param textColor text color
* @param keyboardOptions keyboard options for field
* @param iconRes action icon
* @param iconTint action icon tint
* @param onIconClick click on action icon
* @param showDivider show divider
*
* @see [InputRowDefault] for read only version
* @see <a href=https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?type=design&node-id=2100-799&mode=design&
* t=IQ5lBJEkFGU4WSvi-4>InputRowEnter</a>
*/
@Composable
fun InputRowEnterAmount(
title: TextReference,
text: String,
decimals: Int,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier,
symbol: String? = null,
titleColor: Color = TangemTheme.colors.text.secondary,
textColor: Color = TangemTheme.colors.text.primary1,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
iconRes: Int? = null,
iconTint: Color = TangemTheme.colors.icon.informative,
onIconClick: (() -> Unit)? = null,
showDivider: Boolean = false,
) {
DividerContainer(
modifier = modifier,
showDivider = showDivider,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(TangemTheme.dimens.spacing12),
) {
Column(modifier = Modifier.weight(1f)) {
Text(
text = title.resolveReference(),
style = TangemTheme.typography.caption2,
color = titleColor,
)
AmountTextField(
value = text,
decimals = decimals,
symbol = symbol,
onValueChange = onValueChange,
color = textColor,
textStyle = TangemTheme.typography.body2,
keyboardOptions = keyboardOptions,
modifier = Modifier
.padding(top = TangemTheme.dimens.spacing8),
)
}
iconRes?.let {
Icon(
painter = painterResource(id = iconRes),
contentDescription = null,
tint = iconTint,
modifier = Modifier
.padding(
top = TangemTheme.dimens.spacing10,
bottom = TangemTheme.dimens.spacing10,
)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(bounded = false),
) { onIconClick?.invoke() },
)
}
}
}
}

View file

@ -0,0 +1,94 @@
package com.tangem.core.ui.components.inputrow
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import com.tangem.core.ui.components.fields.AmountTextField
import com.tangem.core.ui.components.inputrow.inner.DividerContainer
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
/**
* `Input Row Enter Info` for entering amount. Manages correct amount format and validation
* @param title title reference
* @param text primary text reference
* @param onValueChange text change callback
* @param modifier modifier
* @param titleColor title color
* @param textColor text color
* @param isSingleLine text
* @param visualTransformation applied transformation to text
* @param keyboardOptions keyboard options for field
* @param showDivider show divider
*
* @see [InputRowEnterInfo]
* @see <a href=https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?type=design&node-id=2100-799&mode
* =design&t=IQ5lBJEkFGU4WSvi-4>Input Row Enter</a>
* @see <a href=https://www.figma.com/file/Vs6SkVsFnUPsSCNwlnVf5U/Android-%E2%80%93-UI?type=design&node
* * -id=7854-33577&mode=design&t=6o23sqF8fDQdn4C5-4>Input Row Enter Info</a>
*/
@Composable
fun InputRowEnterInfoAmount(
title: TextReference,
text: String,
decimals: Int,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier,
symbol: String? = null,
info: TextReference? = null,
titleColor: Color = TangemTheme.colors.text.secondary,
textColor: Color = TangemTheme.colors.text.primary1,
infoColor: Color = TangemTheme.colors.text.tertiary,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
showDivider: Boolean = false,
) {
DividerContainer(
modifier = modifier,
showDivider = showDivider,
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(TangemTheme.dimens.spacing12),
) {
Text(
text = title.resolveReference(),
style = TangemTheme.typography.caption2,
color = titleColor,
)
Row {
AmountTextField(
value = text,
decimals = decimals,
symbol = symbol,
onValueChange = onValueChange,
color = textColor,
textStyle = TangemTheme.typography.body2,
keyboardOptions = keyboardOptions,
modifier = Modifier
.padding(top = TangemTheme.dimens.spacing8)
.weight(1f),
)
info?.let {
Text(
text = it.resolveReference(),
style = TangemTheme.typography.body2,
color = infoColor,
modifier = Modifier
.padding(start = TangemTheme.dimens.spacing8)
.align(Alignment.Bottom),
)
}
}
}
}
}

View file

@ -0,0 +1,153 @@
package com.tangem.core.ui.utils
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalConfiguration
import java.math.BigDecimal
import java.math.RoundingMode
import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
import java.util.Locale
private const val TEXT_CHUNK_THOUSAND = 3
private const val POINT_SEPARATOR = '.'
@Composable
fun rememberDecimalFormat(): DecimalFormat {
val locale = LocalConfiguration.current.locale
val decimalSymbols = remember { DecimalFormatSymbols.getInstance(locale) }
return remember {
DecimalFormat().apply {
decimalFormatSymbols = decimalSymbols
isParseBigDecimal = true
}
}
}
/**
* Formats input [String] for InputField, to remove wrong symbols, letters etc
* Use [decimals] for cut this number symbols after floating point
*
* Example (with 8 decimals):
* input string - ab123.46377372ab53
* result string 123.46377372
*/
fun DecimalFormat.getValidatedNumberWithFixedDecimals(text: String, decimals: Int): String {
val thousandsSeparator = decimalFormatSymbols.groupingSeparator
val decimalSeparator = decimalFormatSymbols.decimalSeparator
val lastChar = text.lastOrNull()
val trimmedText = if (text.isNotEmpty() && (lastChar == thousandsSeparator || lastChar == POINT_SEPARATOR)) {
text.dropLast(1) + decimalSeparator
} else {
text
}
if (trimmedText.startsWith("0") && trimmedText.length > 1 && trimmedText[1] != decimalSeparator) {
return "0"
}
val filteredChars = trimmedText.replace(thousandsSeparator.toString(), "").filterIndexed { index, c ->
val isOneOrZeroPoint =
c == decimalSeparator && index != 0 && trimmedText.count { it == decimalSeparator } <= 1
val isIndexPointIndex =
c == decimalSeparator && index != 0 && trimmedText.indexOf(decimalSeparator) == index
c.isDigit() || isIndexPointIndex || isOneOrZeroPoint
}
// If dot is present, take first digits before decimal and first decimals digits after decimal
return if (filteredChars.count { it == decimalSeparator } == 1) {
val beforeDecimal = filteredChars.substringBefore(decimalSeparator)
val afterDecimal = filteredChars.substringAfter(decimalSeparator)
beforeDecimal + decimalSeparator + afterDecimal.take(decimals)
}
// If there is no dot, just take all digits
else {
filteredChars
}
}
/**
* Formats input [text] with grouping and decimal separators.
* Takes into account [decimals] number of digits after floating point.
*/
fun DecimalFormat.formatWithThousands(text: String, decimals: Int): String {
val thousandsSeparator = decimalFormatSymbols.groupingSeparator
val decimalSeparator = decimalFormatSymbols.decimalSeparator
val localizedText = text.replace("[,.]".toRegex(), decimalSeparator.toString())
return if (localizedText.count { it == decimalSeparator } == 1) {
val beforeDecimal = localizedText.substringBefore(decimalSeparator)
.reversed()
.chunked(TEXT_CHUNK_THOUSAND)
.joinToString(thousandsSeparator.toString())
.reversed()
val afterDecimal = localizedText.substringAfter(decimalSeparator)
beforeDecimal + decimalSeparator + afterDecimal.take(decimals)
}
// If there is no dot, just take all digits
else {
localizedText.reversed()
.chunked(TEXT_CHUNK_THOUSAND)
.joinToString(thousandsSeparator.toString())
.reversed()
}
}
fun DecimalFormat.defaultFormat(): String {
return "0${decimalFormatSymbols.decimalSeparator}00"
}
/**
* Checks if text input contains extra decimal separators.
* If so, it will return false, otherwise true.
*
* Note: number can contain only one decimal separator.
*/
fun DecimalFormat.checkDecimalSeparatorDuplicate(text: String): Boolean {
val regex = "[${decimalFormatSymbols.decimalSeparator}]".toRegex()
val decimalSeparatorCount = regex.findAll(text).count()
return decimalSeparatorCount <= 1 // only one decimal separator
}
/**
* Checks if text input contains grouping separators.
* If so, it will return false, otherwise true.
*
* Note: grouping separators are used only for VisualTransformations.
*/
fun DecimalFormat.checkGroupingSeparator(text: String): Boolean {
val regex = "[${decimalFormatSymbols.groupingSeparator}]".toRegex()
val decimalSeparatorCount = regex.findAll(text).count()
return decimalSeparatorCount == 0 // no grouping separator
}
fun String.parseToBigDecimal(decimals: Int): BigDecimal {
val decimalFormat = DecimalFormat().apply {
decimalFormatSymbols = DecimalFormatSymbols(Locale.getDefault())
isParseBigDecimal = true
maximumFractionDigits = decimals
minimumFractionDigits = decimals
}
return try {
decimalFormat.parse(this) as? BigDecimal ?: BigDecimal.ZERO
} catch (e: Exception) {
BigDecimal.ZERO
}
}
fun BigDecimal.parseBigDecimal(decimals: Int, roundingMode: RoundingMode = RoundingMode.DOWN): String {
val decimalFormat = DecimalFormat().apply {
decimalFormatSymbols = DecimalFormatSymbols(Locale.getDefault())
isParseBigDecimal = true
isGroupingUsed = false
maximumFractionDigits = decimals
minimumFractionDigits = 0
this.roundingMode = roundingMode
}
return try {
decimalFormat.format(this)
} catch (e: Exception) {
""
}
}

View file

@ -2,6 +2,7 @@ package com.tangem.core.ui.utils
import java.text.DecimalFormat
@Deprecated("Deprecated due to unnecessary abstraction. Use methods from DecimalFormatterExt")
class InputNumberFormatter(
numberFormat: DecimalFormat,
) {

View file

@ -0,0 +1,30 @@
package com.tangem.domain.tokens.model
import java.math.BigDecimal
data class Amount(
val currencySymbol: String,
val value: BigDecimal? = null,
val decimals: Int,
val type: AmountType = AmountType.CoinType,
)
sealed class AmountType {
object CoinType : AmountType()
object ReserveType : AmountType()
data class TokenType(val token: CryptoCurrency.Token) : AmountType()
data class FiatType(val code: String) : AmountType()
}
/** Converts `BigDecimal` [cryptoCurrency] to [Amount] */
fun BigDecimal.convertToAmount(cryptoCurrency: CryptoCurrency) = Amount(
currencySymbol = cryptoCurrency.symbol,
value = this,
decimals = cryptoCurrency.decimals,
type = when (cryptoCurrency) {
is CryptoCurrency.Coin -> AmountType.CoinType
is CryptoCurrency.Token -> AmountType.TokenType(
token = cryptoCurrency,
)
},
)

View file

@ -0,0 +1,32 @@
package com.tangem.features.send.impl.presentation.state.amount
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.features.send.impl.presentation.state.SendUiState
import com.tangem.utils.Provider
import com.tangem.utils.converter.Converter
import com.tangem.utils.isNullOrZero
internal class SendAmountCurrencyConverter(
private val currentStateProvider: Provider<SendUiState>,
private val cryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus>,
) : Converter<Boolean, SendUiState> {
override fun convert(value: Boolean): SendUiState {
val state = currentStateProvider()
val amountState = state.amountState ?: return state
val amountTextField = amountState.amountTextField
val cryptoCurrencyStatus = cryptoCurrencyStatusProvider()
val isValidFiatRate = cryptoCurrencyStatus.value.fiatRate.isNullOrZero()
return if (amountTextField.isFiatValue == value && !isValidFiatRate) {
state
} else {
return state.copy(
amountState = amountState.copy(
amountTextField = amountTextField.copy(
isFiatValue = value,
),
),
)
}
}
}