From 0b32fcb92580bee99ea7d657927e524246ddd7a7 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 8 Apr 2024 11:30:31 +0500 Subject: [PATCH 1/2] Updated on 2026-08-14 --- .../send/impl/presentation/state/SendUiState.kt | 1 + .../presentation/state/fee/FeeStateFactory.kt | 16 +++++++++++++--- .../state/fee/SendFeeStateConverter.kt | 1 + .../state/previewdata/FeeStatePreviewData.kt | 1 + 4 files changed, 16 insertions(+), 3 deletions(-) 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 a4306da4f4..c8e1d05950 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 @@ -77,6 +77,7 @@ internal sealed class SendStates { val rate: BigDecimal?, val appCurrency: AppCurrency, val isFeeApproximate: Boolean, + val isCustomSelected: Boolean, val notifications: ImmutableList, ) : SendStates() diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeStateFactory.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeStateFactory.kt index 997c39d2f1..5ef07bb664 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeStateFactory.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeStateFactory.kt @@ -56,18 +56,26 @@ internal class FeeStateFactory( fun onFeeOnLoadedState(fees: TransactionFee): SendUiState { val state = currentStateProvider() val feeState = state.feeState ?: return state - val feeSelectorState = (feeState.feeSelectorState as? FeeSelectorState.Content)?.copy( + val feeSelectorState = feeState.feeSelectorState as? FeeSelectorState.Content + + val isCustomWasSelected = if (feeState.isCustomSelected) { + feeSelectorState?.customValues ?: persistentListOf() + } else { + customFeeFieldConverter.convert(fees.normal) + } + val updatedFeeSelectorState = feeSelectorState?.copy( fees = fees, + customValues = isCustomWasSelected, ) ?: FeeSelectorState.Content( fees = fees, customValues = customFeeFieldConverter.convert(fees.normal), ) - val fee = feeConverter.convert(feeSelectorState) + val fee = feeConverter.convert(updatedFeeSelectorState) return state.copy( amountState = state.amountState?.copy(isFeeLoading = false), feeState = feeState.copy( - feeSelectorState = feeSelectorState, + feeSelectorState = updatedFeeSelectorState, fee = fee, isFeeApproximate = isFeeApproximate(fee), ), @@ -91,9 +99,11 @@ internal class FeeStateFactory( val updatedFeeSelectorState = feeSelectorState.copy(selectedFee = feeType) val fee = feeConverter.convert(updatedFeeSelectorState) + val isCustomFeeWasSelected = feeState.isCustomSelected || updatedFeeSelectorState.selectedFee == FeeType.Custom return state.copy( feeState = feeState.copy( fee = fee, + isCustomSelected = isCustomFeeWasSelected, feeSelectorState = updatedFeeSelectorState, ), ) diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/SendFeeStateConverter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/SendFeeStateConverter.kt index caf0ee5683..8bab03a2c8 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/SendFeeStateConverter.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/SendFeeStateConverter.kt @@ -20,6 +20,7 @@ internal class SendFeeStateConverter( rate = feeCryptoCurrencyStatusProvider().value.fiatRate, appCurrency = appCurrencyProvider(), isFeeApproximate = false, + isCustomSelected = false, ) } } \ No newline at end of file diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/previewdata/FeeStatePreviewData.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/previewdata/FeeStatePreviewData.kt index c07c45a39b..766380d826 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/previewdata/FeeStatePreviewData.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/previewdata/FeeStatePreviewData.kt @@ -48,6 +48,7 @@ internal object FeeStatePreviewData { ), isFeeApproximate = false, notifications = persistentListOf(), + isCustomSelected = false, ) val errorFeeState = feeState.copy( From 38d95a7a9cbc82b346dc1a45a80375745944b0bd Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 8 Apr 2024 11:33:39 +0500 Subject: [PATCH 2/2] Updated on 2026-08-14 --- .../AmountVisualTransformation.kt | 12 ++--- .../core/ui/utils/BigDecimalFormatter.kt | 48 +++++++++---------- .../fields/SendAmountFieldChangeConverter.kt | 9 +++- .../impl/presentation/ui/send/AmountBlock.kt | 10 ++-- 4 files changed, 38 insertions(+), 41 deletions(-) diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/fields/visualtransformations/AmountVisualTransformation.kt b/core/ui/src/main/java/com/tangem/core/ui/components/fields/visualtransformations/AmountVisualTransformation.kt index 5ef8a2c4e3..8f10352030 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/fields/visualtransformations/AmountVisualTransformation.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/fields/visualtransformations/AmountVisualTransformation.kt @@ -7,7 +7,6 @@ import androidx.compose.ui.text.input.VisualTransformation import com.tangem.core.ui.utils.BigDecimalFormatter import com.tangem.core.ui.utils.defaultFormat import com.tangem.core.ui.utils.formatWithThousands -import com.tangem.core.ui.utils.parseToBigDecimal import java.text.DecimalFormat class AmountVisualTransformation( @@ -23,21 +22,16 @@ class AmountVisualTransformation( decimals, ) formattedAmount = formattedAmount.ifEmpty { decimalFormat.defaultFormat() } - val decimalValue = text.text.parseToBigDecimal(decimals) val formattedText = if (formattedAmount.isNotEmpty() && symbol != null) { AnnotatedString( if (currencyCode != null) { - BigDecimalFormatter.formatFiatAmount( - fiatAmount = decimalValue, + BigDecimalFormatter.formatFiatEditableAmount( + fiatAmount = formattedAmount, fiatCurrencyCode = currencyCode, fiatCurrencySymbol = symbol, ) } else { - BigDecimalFormatter.formatCryptoAmountUncapped( - cryptoAmount = decimalValue, - cryptoSymbol = symbol, - decimals = decimals, - ) + BigDecimalFormatter.formatWithSymbol(formattedAmount, symbol) }, ) } else { 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 3ca0b57adf..42309223b1 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 @@ -1,8 +1,10 @@ package com.tangem.core.ui.utils import com.tangem.domain.tokens.model.CryptoCurrency +import timber.log.Timber import java.math.BigDecimal import java.math.RoundingMode +import java.text.DecimalFormat import java.text.NumberFormat import java.util.Currency import java.util.Locale @@ -38,30 +40,6 @@ 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, @@ -90,6 +68,26 @@ object BigDecimalFormatter { .replace(formatterCurrency.getSymbol(locale), fiatCurrencySymbol) } + fun formatFiatEditableAmount( + fiatAmount: String?, + fiatCurrencyCode: String, + fiatCurrencySymbol: String, + locale: Locale = Locale.getDefault(), + ): String { + if (fiatAmount == null) return EMPTY_BALANCE_SIGN + + val formatterCurrency = getCurrency(fiatCurrencyCode) + val numberFormatter = NumberFormat.getCurrencyInstance(locale).apply { + currency = formatterCurrency + } + val formatter = requireNotNull(numberFormatter as? DecimalFormat) { + Timber.e("NumberFormat is null") + return EMPTY_BALANCE_SIGN + } + return "${formatter.positivePrefix}$fiatAmount${formatter.positiveSuffix}" + .replace(formatterCurrency.getSymbol(locale), fiatCurrencySymbol) + } + fun formatPercent( percent: BigDecimal, useAbsoluteValue: Boolean, @@ -107,6 +105,8 @@ object BigDecimalFormatter { return formatter.format(value) } + fun formatWithSymbol(amount: String, symbol: String) = "$amount\u2009$symbol" + private fun getCurrency(code: String): Currency { return runCatching { Currency.getInstance(code) } .getOrElse { e -> 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 273e457783..a1fc8fbe25 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 @@ -45,7 +45,7 @@ internal class SendAmountFieldChangeConverter( cryptoAmount = amountTextField.cryptoAmount.copy(value = decimalCryptoValue), fiatAmount = amountTextField.fiatAmount.copy(value = decimalFiatValue), keyboardOptions = KeyboardOptions( - imeAction = if (!isExceedBalance) ImeAction.Done else ImeAction.None, + imeAction = getKeyboardAction(isExceedBalance, decimalCryptoValue), keyboardType = KeyboardType.Number, ), ), @@ -103,4 +103,11 @@ internal class SendAmountFieldChangeConverter( cryptoDecimal > currencyCryptoAmount } } + + private fun getKeyboardAction(isExceedBalance: Boolean, decimalCryptoValue: BigDecimal) = + if (!isExceedBalance && !decimalCryptoValue.isZero()) { + ImeAction.Done + } else { + ImeAction.None + } } \ No newline at end of file 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 528cdfea00..85ff055ed6 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 @@ -30,13 +30,9 @@ internal fun AmountBlock( ) { val amount = amountState.amountTextField - val cryptoAmount = BigDecimalFormatter.formatCryptoAmount( - cryptoAmount = amount.cryptoAmount.value, - cryptoCurrency = amount.cryptoAmount.currencySymbol, - decimals = amount.cryptoAmount.decimals, - ) - val fiatAmount = BigDecimalFormatter.formatFiatAmount( - fiatAmount = amount.fiatAmount.value, + val cryptoAmount = BigDecimalFormatter.formatWithSymbol(amount.value, amount.cryptoAmount.currencySymbol) + val fiatAmount = BigDecimalFormatter.formatFiatEditableAmount( + fiatAmount = amount.fiatValue, fiatCurrencySymbol = amount.fiatAmount.currencySymbol, fiatCurrencyCode = amountState.appCurrencyCode, )