diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml
index bc227501e8..136cc2857f 100644
--- a/core/res/src/main/res/values-ru/strings.xml
+++ b/core/res/src/main/res/values-ru/strings.xml
@@ -431,7 +431,7 @@
Причина: %1$s\nКод: %2$s
Транзакция не выполнена
Сумма
- Подтвердить
+ Подтверждение
%1$s, %2$s
Адрес
Код назначения
@@ -456,6 +456,7 @@
Максимальная сумма
Комиссия не превысит
Комиссия, которая будет взята за вашу транзакцию. Вы можете выставить своё собственное значение.
+ Допустим ввод только цифр
Сумма отправки будет уменьшена на %1$s для покрытия выбранного уровня комиссии. Получателю будет отправлено %2$s.
Покрытие сетевой комиссии
Недостаточно средств для перевода, так как сумма комиссии и сумма перевода в совокупности больше имеющегося баланса
diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/appbar/AppBarWithBackButtonAndIconContent.kt b/core/ui/src/main/java/com/tangem/core/ui/components/appbar/AppBarWithBackButtonAndIconContent.kt
index 2bd0141ea1..09b6158abb 100644
--- a/core/ui/src/main/java/com/tangem/core/ui/components/appbar/AppBarWithBackButtonAndIconContent.kt
+++ b/core/ui/src/main/java/com/tangem/core/ui/components/appbar/AppBarWithBackButtonAndIconContent.kt
@@ -1,10 +1,7 @@
package com.tangem.core.ui.components.appbar
import androidx.annotation.DrawableRes
-import androidx.compose.animation.AnimatedVisibility
-import androidx.compose.animation.animateContentSize
-import androidx.compose.animation.fadeIn
-import androidx.compose.animation.fadeOut
+import androidx.compose.animation.*
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
@@ -66,8 +63,7 @@ fun AppBarWithBackButtonAndIconContent(
)
Column(
verticalArrangement = Arrangement.Center,
- modifier = Modifier.weight(1f)
- .animateContentSize(),
+ modifier = Modifier.weight(1f),
) {
AnimatedVisibility(
visible = !text.isNullOrBlank(),
@@ -84,8 +80,8 @@ fun AppBarWithBackButtonAndIconContent(
}
AnimatedVisibility(
visible = !subtitle.isNullOrBlank(),
- enter = fadeIn(),
- exit = fadeOut(),
+ enter = fadeIn().plus(expandVertically()),
+ exit = fadeOut().plus(shrinkVertically()),
label = "Toolbar subtitle change",
) {
Text(
@@ -93,6 +89,7 @@ fun AppBarWithBackButtonAndIconContent(
color = TangemTheme.colors.text.secondary,
maxLines = 1,
style = TangemTheme.typography.caption2,
+ modifier = Modifier.animateContentSize(),
)
}
}
diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/fields/AmountTextField.kt b/core/ui/src/main/java/com/tangem/core/ui/components/fields/AmountTextField.kt
index fb140e00d4..75836f873a 100644
--- a/core/ui/src/main/java/com/tangem/core/ui/components/fields/AmountTextField.kt
+++ b/core/ui/src/main/java/com/tangem/core/ui/components/fields/AmountTextField.kt
@@ -2,12 +2,10 @@ package com.tangem.core.ui.components.fields
import androidx.annotation.FloatRange
import androidx.compose.foundation.background
-import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.text.KeyboardActions
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
@@ -21,6 +19,7 @@ import androidx.compose.ui.text.ParagraphIntrinsics
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.createFontFamilyResolver
import androidx.compose.ui.text.input.KeyboardType
+import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextDirection
import androidx.compose.ui.tooling.preview.Preview
@@ -33,20 +32,21 @@ import java.text.DecimalFormat
/**
* Simple text field for amount input.
- * Validates and trims input text using [DecimalFormat]. Formats visual output using [AmountVisualTransformation].
- * Can display aligned placeholder and currency symbol [symbol].
+ * Validates and trims input text using [DecimalFormat]. Formats visual output using [visualTransformation].
+ * Can display aligned placeholder.
*
* @param value initial text
* @param decimals number of decimal places
* @param onValueChange callback
* @param textStyle text and placeholder styles
* @param modifier modifier
- * @param symbol currency symbol
* @param color text color
- * @param placeholderAlignment alignment of placeholder
- * @param showPlaceholder show placeholder
+ * @param visualTransformation text visual transformation
* @param keyboardOptions keyboard options
- *
+ * @param keyboardActions keyboard actions
+ * @param isEnabled is field editing enabled
+ * @param isAutoResize is text font auto resize
+ * @param reduceFactor font resize factor
* @see [SimpleTextField] for standard text field
*/
@Composable
@@ -56,10 +56,8 @@ fun AmountTextField(
onValueChange: (String) -> Unit,
textStyle: TextStyle,
modifier: Modifier = Modifier,
- symbol: String? = null,
color: Color = TangemTheme.colors.text.primary1,
- placeholderAlignment: Alignment = TopStart,
- showPlaceholder: Boolean = true,
+ visualTransformation: VisualTransformation = AmountVisualTransformation(decimals),
keyboardOptions: KeyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Number,
),
@@ -70,12 +68,6 @@ fun AmountTextField(
reduceFactor: Double = 0.9,
) {
val decimalFormat = rememberDecimalFormat()
- val visualTransformation = remember { AmountVisualTransformation(decimals, symbol, decimalFormat) }
- val placeholderTextAlign = if (placeholderAlignment == TopCenter) {
- TextAlign.Center
- } else {
- TextAlign.Start
- }
BoxWithConstraints(modifier = modifier) {
var fontSize = textStyle.fontSize
if (isAutoResize) {
@@ -96,6 +88,7 @@ fun AmountTextField(
}
}
}
+ val textColor = if (value.isBlank()) TangemTheme.colors.text.disabled else color
SimpleTextField(
value = value,
onValueChange = { newText ->
@@ -108,31 +101,13 @@ fun AmountTextField(
fontSize = fontSize,
textDirection = TextDirection.ContentOrLtr,
),
- color = color,
+ color = textColor,
keyboardOptions = keyboardOptions,
keyboardActions = keyboardActions,
singleLine = true,
readOnly = !isEnabled,
- visualTransformation = AmountVisualTransformation(decimals, symbol, decimalFormat),
+ visualTransformation = visualTransformation,
modifier = Modifier.background(TangemTheme.colors.background.action),
- decorationBox = { innerTextField ->
- Box {
- if (value.isBlank() && showPlaceholder) {
- var placeholder = decimalFormat.defaultFormat()
- if (symbol != null) {
- placeholder = placeholder.plus(" $symbol")
- }
- Text(
- text = placeholder,
- style = textStyle.copy(textDirection = TextDirection.ContentOrLtr),
- color = TangemTheme.colors.text.disabled,
- textAlign = placeholderTextAlign,
- modifier = Modifier.align(placeholderAlignment),
- )
- }
- innerTextField()
- }
- },
)
}
}
@@ -153,9 +128,6 @@ private fun AmountTextFieldPreview(
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,
@@ -169,28 +141,24 @@ private fun AmountTextFieldPreview(
private class AmountTextFieldPreviewProvider : PreviewParameterProvider {
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,
@@ -200,7 +168,6 @@ private class AmountTextFieldPreviewProvider : PreviewParameterProvider 0) {
+ transformedOffset.coerceIn(0, minOf(symbolOffset, formattedText.length))
+ } else {
+ transformedOffset.coerceIn(0, formattedText.length)
+ }
+ return transformedOffset
}
override fun transformedToOriginal(offset: Int): Int {
diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowEnterAmount.kt b/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowEnterAmount.kt
index dd7c375e77..28c9082f90 100644
--- a/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowEnterAmount.kt
+++ b/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowEnterAmount.kt
@@ -17,10 +17,12 @@ 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.fields.visualtransformations.AmountVisualTransformation
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
+import com.tangem.core.ui.utils.rememberDecimalFormat
/**
* Input row for entering amount. Manages correct amount format and validation
@@ -76,7 +78,11 @@ fun InputRowEnterAmount(
AmountTextField(
value = text,
decimals = decimals,
- symbol = symbol,
+ visualTransformation = AmountVisualTransformation(
+ decimals = decimals,
+ symbol = symbol,
+ decimalFormat = rememberDecimalFormat(),
+ ),
onValueChange = onValueChange,
color = textColor,
textStyle = TangemTheme.typography.body2,
diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowEnterInfoAmount.kt b/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowEnterInfoAmount.kt
index 40276abe7a..00d4221e37 100644
--- a/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowEnterInfoAmount.kt
+++ b/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowEnterInfoAmount.kt
@@ -12,23 +12,28 @@ 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.fields.visualtransformations.AmountVisualTransformation
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
+import com.tangem.core.ui.utils.rememberDecimalFormat
/**
* `Input Row Enter Info` for entering amount. Manages correct amount format and validation
* @param title title reference
* @param text primary text reference
+ * @param decimals amount text decimal count
* @param onValueChange text change callback
* @param modifier modifier
+ * @param symbol amount symbol
+ * @param info info text
* @param titleColor title color
* @param textColor text color
- * @param isSingleLine text
- * @param visualTransformation applied transformation to text
+ * @param infoColor info text color
* @param keyboardOptions keyboard options for field
+ * @param keyboardActions keyboard actions for field
* @param showDivider show divider
*
* @see [InputRowEnterInfo]
@@ -71,7 +76,11 @@ fun InputRowEnterInfoAmount(
AmountTextField(
value = text,
decimals = decimals,
- symbol = symbol,
+ visualTransformation = AmountVisualTransformation(
+ decimals = decimals,
+ symbol = symbol,
+ decimalFormat = rememberDecimalFormat(),
+ ),
onValueChange = onValueChange,
color = textColor,
textStyle = TangemTheme.typography.body2,
diff --git a/core/ui/src/main/java/com/tangem/core/ui/utils/BigDecimalFormatter.kt b/core/ui/src/main/java/com/tangem/core/ui/utils/BigDecimalFormatter.kt
index 020cc01c45..3ca0b57adf 100644
--- a/core/ui/src/main/java/com/tangem/core/ui/utils/BigDecimalFormatter.kt
+++ b/core/ui/src/main/java/com/tangem/core/ui/utils/BigDecimalFormatter.kt
@@ -38,6 +38,30 @@ object BigDecimalFormatter {
}
}
+ fun formatCryptoAmountUncapped(
+ cryptoAmount: BigDecimal?,
+ cryptoSymbol: String,
+ decimals: Int,
+ locale: Locale = Locale.getDefault(),
+ ): String {
+ if (cryptoAmount == null) return EMPTY_BALANCE_SIGN
+
+ val formatter = NumberFormat.getNumberInstance(locale).apply {
+ maximumFractionDigits = decimals
+ minimumFractionDigits = minOf(2, decimals)
+ isGroupingUsed = true
+ roundingMode = RoundingMode.DOWN
+ }
+
+ return formatter.format(cryptoAmount).let {
+ if (cryptoSymbol.isEmpty()) {
+ it
+ } else {
+ it + "\u2009$cryptoSymbol"
+ }
+ }
+ }
+
fun formatCryptoAmount(
cryptoAmount: BigDecimal?,
cryptoCurrency: CryptoCurrency,
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt
index d16f511bbd..a4306da4f4 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt
@@ -50,6 +50,7 @@ internal sealed class SendStates {
val segmentedButtonConfig: PersistentList,
val amountTextField: SendTextField.AmountField,
val notifications: ImmutableList,
+ val appCurrencyCode: String,
val isFeeLoading: Boolean,
) : SendStates()
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/amount/SendAmountStateConverter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/amount/SendAmountStateConverter.kt
index 9e393e8bae..d12d7d3c28 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/amount/SendAmountStateConverter.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/amount/SendAmountStateConverter.kt
@@ -40,6 +40,7 @@ internal class SendAmountStateConverter(
isPrimaryButtonEnabled = false,
notifications = persistentListOf(),
isFeeLoading = false,
+ appCurrencyCode = appCurrency.code,
segmentedButtonConfig = if (status.value.fiatRate.isNullOrZero()) {
persistentListOf()
} else {
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/EthereumCustomFeeConverter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/EthereumCustomFeeConverter.kt
index 950dd0b135..11dfc8f056 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/EthereumCustomFeeConverter.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/custom/EthereumCustomFeeConverter.kt
@@ -50,7 +50,7 @@ internal class EthereumCustomFeeConverter(
),
SendTextField.CustomFee(
value = value.gasPrice.toString(),
- decimals = ETHEREUM_GAS_DECIMALS,
+ decimals = GAS_DECIMALS,
symbol = ETHEREUM_GAS_UNIT,
title = resourceReference(R.string.send_gas_price),
footer = resourceReference(R.string.send_gas_price_footer),
@@ -64,7 +64,7 @@ internal class EthereumCustomFeeConverter(
SendTextField.CustomFee(
value = value.gasLimit.toString(),
decimals = GAS_DECIMALS,
- symbol = null,
+ symbol = "",
title = resourceReference(R.string.send_gas_limit),
footer = resourceReference(R.string.send_gas_limit_footer),
onValueChange = { clickIntents.onCustomFeeValueChange(GAS_LIMIT, it) },
@@ -95,57 +95,10 @@ internal class EthereumCustomFeeConverter(
): ImmutableList {
val mutableCustomValues = customValues.toMutableList()
return mutableCustomValues.apply {
- val gasLimit = this[GAS_LIMIT].value.parseToBigDecimal(this[GAS_LIMIT].decimals)
when (index) {
- FEE_AMOUNT -> {
- val newFeeAmountDecimal = value.parseToBigDecimal(this[FEE_AMOUNT].decimals)
- val newFeeAmount = newFeeAmountDecimal.movePointRight(this[FEE_AMOUNT].decimals)
- val newGasPrice = newFeeAmount.divide(gasLimit, GAS_DECIMALS, RoundingMode.HALF_UP)
- set(GAS_PRICE, this[GAS_PRICE].copy(value = newGasPrice.parseBigDecimal(GAS_DECIMALS)))
- set(
- index,
- this[index].copy(
- value = value,
- label = getFeeFormatted(newFeeAmountDecimal),
- ),
- )
- }
- GAS_PRICE -> {
- val newGasPrice = value.parseToBigDecimal(this[GAS_PRICE].decimals)
- .movePointLeft(this[GAS_PRICE].decimals)
- val newFeeAmount = gasLimit * newGasPrice
- set(
- FEE_AMOUNT,
- this[FEE_AMOUNT].copy(
- value = newFeeAmount.parseBigDecimal(this[FEE_AMOUNT].decimals),
- label = getFeeFormatted(newFeeAmount),
- ),
- )
- set(index, this[index].copy(value = value))
- }
- else -> {
- val newGasLimit = value.parseToBigDecimal(this[GAS_LIMIT].decimals)
- val gasPrice = this[GAS_PRICE].value.parseToBigDecimal(this[GAS_PRICE].decimals)
- .movePointLeft(this[FEE_AMOUNT].decimals)
- val newFeeAmount = newGasLimit * gasPrice
- set(
- FEE_AMOUNT,
- this[FEE_AMOUNT].copy(
- value = newFeeAmount.parseBigDecimal(this[FEE_AMOUNT].decimals),
- label = getFeeFormatted(newFeeAmount),
- ),
- )
- set(
- index,
- this[index].copy(
- value = value,
- keyboardOptions = KeyboardOptions(
- imeAction = if (!checkExceedBalance(newFeeAmount)) ImeAction.None else ImeAction.Done,
- keyboardType = KeyboardType.Number,
- ),
- ),
- )
- }
+ FEE_AMOUNT -> setOnAmountChange(value, index)
+ GAS_PRICE -> setOnGasPriceChange(value, index)
+ else -> setOnGasLimitChange(value, index)
}
}.toImmutableList()
}
@@ -170,9 +123,81 @@ internal class EthereumCustomFeeConverter(
return feeAmount == null || feeAmount.isZero() || feeAmount > currencyCryptoAmount
}
+ private fun MutableList.setEmpty(index: Int) {
+ set(index, this[index].copy(value = ""))
+ }
+
+ private fun MutableList.setOnAmountChange(value: String, index: Int) {
+ val gasLimit = this[GAS_LIMIT].value.parseToBigDecimal(this[GAS_LIMIT].decimals)
+ if (value.isBlank()) {
+ setEmpty(FEE_AMOUNT)
+ setEmpty(GAS_PRICE)
+ } else {
+ val newFeeAmountDecimal = value.parseToBigDecimal(this[FEE_AMOUNT].decimals)
+ val newFeeAmount = newFeeAmountDecimal.movePointRight(this[FEE_AMOUNT].decimals)
+ val newGasPrice = newFeeAmount.divide(gasLimit, GAS_DECIMALS, RoundingMode.HALF_UP)
+ set(GAS_PRICE, this[GAS_PRICE].copy(value = newGasPrice.parseBigDecimal(GAS_DECIMALS)))
+ set(
+ index,
+ this[index].copy(
+ value = value,
+ label = getFeeFormatted(newFeeAmountDecimal),
+ ),
+ )
+ }
+ }
+
+ private fun MutableList.setOnGasPriceChange(value: String, index: Int) {
+ val gasLimit = this[GAS_LIMIT].value.parseToBigDecimal(this[GAS_LIMIT].decimals)
+ if (value.isBlank()) {
+ setEmpty(FEE_AMOUNT)
+ setEmpty(GAS_PRICE)
+ } else {
+ val newGasPrice = value.parseToBigDecimal(this[GAS_PRICE].decimals)
+ .movePointLeft(this[GAS_PRICE].decimals)
+ val newFeeAmount = (gasLimit * newGasPrice).movePointLeft(this[FEE_AMOUNT].decimals)
+ set(
+ FEE_AMOUNT,
+ this[FEE_AMOUNT].copy(
+ value = newFeeAmount.parseBigDecimal(this[FEE_AMOUNT].decimals),
+ label = getFeeFormatted(newFeeAmount),
+ ),
+ )
+ set(index, this[index].copy(value = value))
+ }
+ }
+
+ private fun MutableList.setOnGasLimitChange(value: String, index: Int) {
+ if (value.isBlank()) {
+ setEmpty(FEE_AMOUNT)
+ setEmpty(GAS_LIMIT)
+ } else {
+ val newGasLimit = value.parseToBigDecimal(this[GAS_LIMIT].decimals)
+ val gasPrice = this[GAS_PRICE].value.parseToBigDecimal(this[GAS_PRICE].decimals)
+ .movePointLeft(this[FEE_AMOUNT].decimals)
+ val newFeeAmount = newGasLimit * gasPrice
+ set(
+ FEE_AMOUNT,
+ this[FEE_AMOUNT].copy(
+ value = newFeeAmount.parseBigDecimal(this[FEE_AMOUNT].decimals),
+ label = getFeeFormatted(newFeeAmount),
+ ),
+ )
+ set(
+ index,
+ this[index].copy(
+ value = value,
+ keyboardOptions = KeyboardOptions(
+ imeAction = if (!checkExceedBalance(newFeeAmount)) ImeAction.None else ImeAction.Done,
+ keyboardType = KeyboardType.Number,
+ ),
+ ),
+ )
+ }
+ }
+
companion object {
private const val ETHEREUM_GAS_UNIT = "GWEI"
- private const val ETHEREUM_GAS_DECIMALS = 18
private const val FEE_AMOUNT = 0
private const val GAS_PRICE = 1
private const val GAS_LIMIT = 2
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fields/SendAmountFieldChangeConverter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fields/SendAmountFieldChangeConverter.kt
index cd6254be4f..273e457783 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fields/SendAmountFieldChangeConverter.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fields/SendAmountFieldChangeConverter.kt
@@ -75,12 +75,16 @@ internal class SendAmountFieldChangeConverter(
}
private fun SendUiState.emptyState(): SendUiState {
+ if (amountState == null) return this
+ val amountTextField = amountState.amountTextField
return copy(
- amountState = amountState?.copy(
+ amountState = amountState.copy(
isPrimaryButtonEnabled = false,
- amountTextField = amountState.amountTextField.copy(
+ amountTextField = amountTextField.copy(
value = "",
fiatValue = "",
+ cryptoAmount = amountTextField.cryptoAmount.copy(value = BigDecimal.ZERO),
+ fiatAmount = amountTextField.fiatAmount.copy(value = BigDecimal.ZERO),
isError = false,
),
),
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/previewdata/AmountStatePreviewData.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/previewdata/AmountStatePreviewData.kt
index 43d0d75572..75e5ce97f4 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/previewdata/AmountStatePreviewData.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/previewdata/AmountStatePreviewData.kt
@@ -24,6 +24,7 @@ internal object AmountStatePreviewData {
segmentedButtonConfig = persistentListOf(),
notifications = persistentListOf(),
isFeeLoading = false,
+ appCurrencyCode = "usd",
amountTextField = SendTextField.AmountField(
value = "123.123123123123123123",
onValueChange = {},
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/amount/AmountField.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/amount/AmountField.kt
index 4c45622e33..5aa3ec82ac 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/amount/AmountField.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/amount/AmountField.kt
@@ -3,42 +3,49 @@ package com.tangem.features.send.impl.presentation.ui.amount
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
-import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.requiredHeightIn
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment.Companion.BottomCenter
-import androidx.compose.ui.Alignment.Companion.TopCenter
import androidx.compose.ui.Modifier
+import androidx.compose.ui.focus.FocusRequester
+import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextDirection
import com.tangem.core.ui.components.fields.AmountTextField
+import com.tangem.core.ui.components.fields.visualtransformations.AmountVisualTransformation
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.utils.BigDecimalFormatter
-import com.tangem.core.ui.utils.defaultFormat
import com.tangem.core.ui.utils.rememberDecimalFormat
import com.tangem.features.send.impl.presentation.state.fields.SendTextField
+import kotlinx.coroutines.job
@Composable
-internal fun AmountField(sendField: SendTextField.AmountField, isEnabled: Boolean) {
+internal fun AmountField(sendField: SendTextField.AmountField, isEnabled: Boolean, appCurrencyCode: String) {
val decimalFormat = rememberDecimalFormat()
- val (primaryValue, secondaryValue) = if (sendField.isFiatValue) {
- sendField.fiatValue to sendField.value
+ val isFiatValue = sendField.isFiatValue
+ val currencyCode = if (isFiatValue) appCurrencyCode else null
+ val (primaryAmount, primaryValue) = if (isFiatValue) {
+ sendField.fiatAmount to sendField.fiatValue
} else {
- sendField.value to sendField.fiatValue
+ sendField.cryptoAmount to sendField.value
}
-
- val (primaryAmount, secondaryAmount) = if (sendField.isFiatValue) {
- sendField.fiatAmount to sendField.cryptoAmount
- } else {
- sendField.cryptoAmount to sendField.fiatAmount
- }
-
+ val requester = remember { FocusRequester() }
AmountTextField(
value = primaryValue,
decimals = primaryAmount.decimals,
- symbol = primaryAmount.currencySymbol,
+ visualTransformation = AmountVisualTransformation(
+ decimals = primaryAmount.decimals,
+ symbol = primaryAmount.currencySymbol,
+ currencyCode = currencyCode,
+ decimalFormat = decimalFormat,
+ ),
onValueChange = sendField.onValueChange,
keyboardOptions = sendField.keyboardOptions,
keyboardActions = sendField.keyboardActions,
@@ -48,8 +55,8 @@ internal fun AmountField(sendField: SendTextField.AmountField, isEnabled: Boolea
),
isEnabled = isEnabled,
isAutoResize = true,
- placeholderAlignment = TopCenter,
modifier = Modifier
+ .focusRequester(requester)
.padding(
top = TangemTheme.dimens.spacing24,
start = TangemTheme.dimens.spacing12,
@@ -57,7 +64,18 @@ internal fun AmountField(sendField: SendTextField.AmountField, isEnabled: Boolea
)
.requiredHeightIn(min = TangemTheme.dimens.size32),
)
+ LaunchedEffect(key1 = Unit) {
+ this.coroutineContext.job.invokeOnCompletion {
+ requester.requestFocus()
+ }
+ }
+ AmountSecondary(sendField, appCurrencyCode)
+}
+
+@Composable
+private fun AmountSecondary(sendField: SendTextField.AmountField, appCurrencyCode: String) {
+ val secondaryAmount = if (sendField.isFiatValue) sendField.cryptoAmount else sendField.fiatAmount
Box(
modifier = Modifier
.padding(
@@ -66,10 +84,18 @@ internal fun AmountField(sendField: SendTextField.AmountField, isEnabled: Boolea
end = TangemTheme.dimens.spacing12,
),
) {
- val text = if (sendField.isFiatUnavailable) {
- BigDecimalFormatter.EMPTY_BALANCE_SIGN
+ val text = if (sendField.isFiatValue) {
+ BigDecimalFormatter.formatCryptoAmount(
+ cryptoAmount = secondaryAmount.value,
+ cryptoCurrency = secondaryAmount.currencySymbol,
+ decimals = secondaryAmount.decimals,
+ )
} else {
- "${secondaryValue.ifEmpty { decimalFormat.defaultFormat() }} ${secondaryAmount.currencySymbol}"
+ BigDecimalFormatter.formatFiatAmount(
+ fiatAmount = secondaryAmount.value,
+ fiatCurrencySymbol = secondaryAmount.currencySymbol,
+ fiatCurrencyCode = appCurrencyCode,
+ )
}
Text(
text = text,
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/amount/AmountFieldContainer.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/amount/AmountFieldContainer.kt
index 5cf940b41b..d9926e3f54 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/amount/AmountFieldContainer.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/amount/AmountFieldContainer.kt
@@ -63,6 +63,7 @@ internal fun LazyListScope.amountField(
AmountField(
sendField = amountState.amountTextField,
isEnabled = !amountState.isFeeLoading,
+ appCurrencyCode = amountState.appCurrencyCode,
)
}
}
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/AmountBlock.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/AmountBlock.kt
index 26c0380dd5..528cdfea00 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/AmountBlock.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/send/AmountBlock.kt
@@ -17,6 +17,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import com.tangem.core.ui.components.ResizableText
import com.tangem.core.ui.components.currency.tokenicon.TokenIcon
import com.tangem.core.ui.res.TangemTheme
+import com.tangem.core.ui.utils.BigDecimalFormatter
import com.tangem.features.send.impl.presentation.state.SendStates
import com.tangem.features.send.impl.presentation.state.previewdata.AmountStatePreviewData
@@ -29,8 +30,16 @@ internal fun AmountBlock(
) {
val amount = amountState.amountTextField
- val cryptoAmount = getAmountWithSymbol(amount.value, amount.cryptoAmount.currencySymbol)
- val fiatAmount = getAmountWithSymbol(amount.fiatValue, amount.fiatAmount.currencySymbol)
+ val cryptoAmount = BigDecimalFormatter.formatCryptoAmount(
+ cryptoAmount = amount.cryptoAmount.value,
+ cryptoCurrency = amount.cryptoAmount.currencySymbol,
+ decimals = amount.cryptoAmount.decimals,
+ )
+ val fiatAmount = BigDecimalFormatter.formatFiatAmount(
+ fiatAmount = amount.fiatAmount.value,
+ fiatCurrencySymbol = amount.fiatAmount.currencySymbol,
+ fiatCurrencyCode = amountState.appCurrencyCode,
+ )
val backgroundColor = if (isEditingDisabled) {
TangemTheme.colors.button.disabled
} else {
@@ -77,10 +86,6 @@ internal fun AmountBlock(
}
}
-private fun getAmountWithSymbol(amount: String, symbol: String): String {
- return "$amount $symbol"
-}
-
// region Preview
@Preview
@Composable