Updated on 2026-08-14

This commit is contained in:
Tangem 2024-08-14 12:25:02 +05:00
commit 333e9fa9cb
6 changed files with 99 additions and 46 deletions

View file

@ -1,30 +1,12 @@
package com.tangem.common.ui.amountScreen.utils
import com.tangem.blockchain.common.Amount
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.combinedReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.utils.BigDecimalFormatter
import com.tangem.core.ui.utils.BigDecimalFormatter.EMPTY_BALANCE_SIGN
import com.tangem.domain.appcurrency.model.AppCurrency
import java.math.BigDecimal
private const val CRYPTO_FEE_DECIMALS = 6
fun getCryptoReference(amount: Amount?, isFeeApproximate: Boolean): TextReference? {
if (amount == null) return null
return combinedReference(
if (isFeeApproximate) stringReference("${BigDecimalFormatter.CAN_BE_LOWER_SIGN} ") else TextReference.EMPTY,
stringReference(
BigDecimalFormatter.formatCryptoAmount(
cryptoAmount = amount.value,
cryptoCurrency = amount.currencySymbol,
decimals = amount.decimals.coerceAtMost(CRYPTO_FEE_DECIMALS),
),
),
)
}
fun getFiatReference(value: BigDecimal?, rate: BigDecimal?, appCurrency: AppCurrency): TextReference? {
if (value == null || rate == null) return null
val formattedFiat = getFiatString(value = value, rate = rate, appCurrency = appCurrency)

View file

@ -13,15 +13,18 @@ import java.text.NumberFormat
import java.util.Currency
import java.util.Locale
@Suppress("LargeClass")
object BigDecimalFormatter {
const val EMPTY_BALANCE_SIGN = DASH_SIGN
const val CAN_BE_LOWER_SIGN = LOWER_SIGN
private const val CAN_BE_LOWER_SIGN = LOWER_SIGN
private val FORMAT_THRESHOLD = BigDecimal("0.01")
private const val TEMP_CURRENCY_CODE = "USD"
private val FIAT_FORMAT_THRESHOLD = BigDecimal("0.01")
private val CRYPTO_FEE_FORMAT_THRESHOLD = BigDecimal("0.000001")
private const val FIAT_MARKET_DEFAULT_DIGITS = 2
private const val FIAT_MARKET_EXTENDED_DIGITS = 6
@ -112,6 +115,45 @@ object BigDecimalFormatter {
}
}
fun formatCryptoFeeAmount(
cryptoAmount: BigDecimal?,
cryptoCurrency: String,
decimals: Int,
canBeLower: Boolean = false,
locale: Locale = Locale.getDefault(),
): String {
if (cryptoAmount == null) return EMPTY_BALANCE_SIGN
val formatter = NumberFormat.getNumberInstance(locale).apply {
maximumFractionDigits = decimals.coerceAtMost(maximumValue = 6)
minimumFractionDigits = 2
isGroupingUsed = true
roundingMode = RoundingMode.HALF_UP
}
val amountFormatted = if (cryptoAmount.checkCryptoThreshold()) {
buildString {
append(CAN_BE_LOWER_SIGN)
append(
formatter.format(CRYPTO_FEE_FORMAT_THRESHOLD),
)
}
} else {
buildString {
if (canBeLower) {
append(CAN_BE_LOWER_SIGN)
}
append(formatter.format(cryptoAmount))
}
}
return if (cryptoCurrency.isEmpty()) {
amountFormatted
} else {
amountFormatted + "\u2009$cryptoCurrency"
}
}
fun formatCryptoAmount(
cryptoAmount: BigDecimal?,
cryptoCurrency: CryptoCurrency,
@ -137,7 +179,7 @@ object BigDecimalFormatter {
roundingMode = RoundingMode.HALF_UP
}
return if (fiatAmount.isLessThanThreshold()) {
return if (fiatAmount.checkFiatThreshold()) {
buildString {
append(CAN_BE_LOWER_SIGN)
append(
@ -160,7 +202,7 @@ object BigDecimalFormatter {
if (fiatAmount == null) return EMPTY_BALANCE_SIGN
val formatterCurrency = getCurrency(fiatCurrencyCode)
val digits = if (fiatAmount.isLessThanThreshold()) {
val digits = if (fiatAmount.checkFiatThreshold()) {
FIAT_MARKET_EXTENDED_DIGITS
} else {
FIAT_MARKET_DEFAULT_DIGITS
@ -358,7 +400,9 @@ object BigDecimalFormatter {
}
}
private fun BigDecimal.isLessThanThreshold() = this > BigDecimal.ZERO && this < FIAT_FORMAT_THRESHOLD
private fun BigDecimal.checkFiatThreshold() = this > BigDecimal.ZERO && this < FIAT_FORMAT_THRESHOLD
private fun BigDecimal.checkCryptoThreshold() = this > BigDecimal.ZERO && this < CRYPTO_FEE_FORMAT_THRESHOLD
@Suppress("MagicNumber")
fun getProperFiatPriceDecimals(price: BigDecimal): Int {

View file

@ -22,7 +22,6 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import com.tangem.common.ui.amountScreen.models.AmountState
import com.tangem.common.ui.amountScreen.ui.SendDoneButtons
import com.tangem.common.ui.amountScreen.utils.getCryptoReference
import com.tangem.common.ui.amountScreen.utils.getFiatString
import com.tangem.core.ui.R
import com.tangem.core.ui.components.Keyboard
@ -34,6 +33,7 @@ import com.tangem.core.ui.components.keyboardAsState
import com.tangem.core.ui.extensions.*
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.SendUiCurrentScreen
import com.tangem.features.send.impl.presentation.state.SendUiState
import com.tangem.features.send.impl.presentation.state.SendUiStateType
@ -186,16 +186,6 @@ private fun SendingText(
fiatCurrencySymbol = feeState.appCurrency.symbol,
fiatCurrencyCode = feeState.appCurrency.code,
)
val feeValue = if (feeState.isFeeConvertibleToFiat) {
getFiatString(
value = feeState.fee?.amount?.value,
rate = feeState.rate,
appCurrency = feeState.appCurrency,
)
} else {
getCryptoReference(feeState.fee?.amount, feeState.isFeeApproximate)?.resolveReference().orEmpty()
}
val textResource = remember(uiState) {
resourceReference(
id = if (feeState.isFeeConvertibleToFiat) {
@ -203,7 +193,7 @@ private fun SendingText(
} else {
R.string.send_summary_transaction_description_no_fiat_fee
},
formatArgs = wrappedList(sendingValue, feeValue),
formatArgs = wrappedList(sendingValue, feeState.getFiatValue()),
)
}
Text(
@ -219,6 +209,22 @@ private fun SendingText(
}
}
private fun SendStates.FeeState.getFiatValue() = if (isFeeConvertibleToFiat) {
getFiatString(
value = fee?.amount?.value,
rate = rate,
appCurrency = appCurrency,
)
} else {
val amount = fee?.amount
BigDecimalFormatter.formatCryptoFeeAmount(
cryptoAmount = amount?.value,
cryptoCurrency = amount?.currencySymbol.orEmpty(),
decimals = amount?.decimals ?: 0,
canBeLower = isFeeApproximate,
)
}
private fun getButtonData(
uiState: SendUiState,
currentState: SendUiCurrentScreen,
@ -245,11 +251,11 @@ private fun getButtonData(
private fun isButtonEnabled(currentState: SendUiCurrentScreen, uiState: SendUiState): Boolean {
return when (currentState.type) {
SendUiStateType.Amount -> uiState.amountState?.isPrimaryButtonEnabled
SendUiStateType.Amount -> uiState.amountState.isPrimaryButtonEnabled
SendUiStateType.Recipient -> uiState.recipientState?.isPrimaryButtonEnabled
SendUiStateType.Fee -> uiState.feeState?.isPrimaryButtonEnabled
SendUiStateType.Send -> uiState.sendState?.isPrimaryButtonEnabled
SendUiStateType.EditAmount -> uiState.editAmountState?.isPrimaryButtonEnabled
SendUiStateType.EditAmount -> uiState.editAmountState.isPrimaryButtonEnabled
SendUiStateType.EditRecipient -> uiState.editRecipientState?.isPrimaryButtonEnabled
SendUiStateType.EditFee -> uiState.editFeeState?.isPrimaryButtonEnabled
else -> true

View file

@ -11,11 +11,11 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.tangem.blockchain.common.Amount
import com.tangem.blockchain.common.transaction.TransactionFee
import com.tangem.common.ui.amountScreen.utils.getCryptoReference
import com.tangem.common.ui.amountScreen.utils.getFiatReference
import com.tangem.core.ui.components.RectangleShimmer
import com.tangem.core.ui.components.SpacerWMax
import com.tangem.core.ui.components.rows.SelectorRowItem
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.utils.BigDecimalFormatter
import com.tangem.core.ui.utils.parseToBigDecimal
@ -52,7 +52,14 @@ internal fun SendSpeedSelectorItem(
iconRes = iconRes,
onSelect = onSelect,
modifier = modifier,
preDot = getCryptoReference(amount, state.isFeeApproximate),
preDot = stringReference(
BigDecimalFormatter.formatCryptoFeeAmount(
cryptoAmount = amount?.value,
cryptoCurrency = amount?.currencySymbol.orEmpty(),
decimals = amount?.decimals ?: 0,
canBeLower = state.isFeeApproximate,
),
),
postDot = if (state.isFeeConvertibleToFiat) {
getFiatReference(amount?.value, state.rate, state.appCurrency)
} else {

View file

@ -14,12 +14,12 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import com.tangem.common.ui.amountScreen.utils.getCryptoReference
import com.tangem.common.ui.amountScreen.utils.getFiatReference
import com.tangem.core.ui.components.RectangleShimmer
import com.tangem.core.ui.components.rows.SelectorRowItem
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.utils.BigDecimalFormatter
import com.tangem.features.send.impl.R
import com.tangem.features.send.impl.presentation.state.SendStates
@ -61,7 +61,14 @@ internal fun FeeBlock(feeState: SendStates.FeeState, isClickDisabled: Boolean, o
SelectorRowItem(
titleRes = title,
iconRes = icon,
preDot = getCryptoReference(feeAmount, feeState.isFeeApproximate),
preDot = stringReference(
BigDecimalFormatter.formatCryptoFeeAmount(
cryptoAmount = feeAmount?.value,
cryptoCurrency = feeAmount?.currencySymbol.orEmpty(),
decimals = feeAmount?.decimals ?: 0,
canBeLower = feeState.isFeeApproximate,
),
),
postDot = if (feeState.isFeeConvertibleToFiat) {
getFiatReference(feeAmount?.value, feeState.rate, feeState.appCurrency)
} else {

View file

@ -16,14 +16,14 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import com.tangem.blockchain.common.Amount
import com.tangem.blockchain.common.AmountType
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.common.ui.R
import com.tangem.common.ui.amountScreen.utils.getFiatReference
import com.tangem.core.ui.components.RectangleShimmer
import com.tangem.core.ui.components.rows.SelectorRowItem
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.utils.BigDecimalFormatter
import com.tangem.common.ui.R
import com.tangem.common.ui.amountScreen.utils.getCryptoReference
import com.tangem.common.ui.amountScreen.utils.getFiatReference
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.features.staking.impl.presentation.state.FeeState
import java.math.BigDecimal
@ -53,7 +53,14 @@ internal fun StakingFeeBlock(feeState: FeeState) {
SelectorRowItem(
titleRes = title,
iconRes = icon,
preDot = getCryptoReference(feeAmount, feeState.isFeeApproximate),
preDot = stringReference(
BigDecimalFormatter.formatCryptoFeeAmount(
cryptoAmount = feeAmount?.value,
cryptoCurrency = feeAmount?.currencySymbol.orEmpty(),
decimals = feeAmount?.decimals ?: 0,
canBeLower = feeState.isFeeApproximate,
),
),
postDot = if (feeState.isFeeConvertibleToFiat) {
getFiatReference(feeAmount?.value, feeState.rate, feeState.appCurrency)
} else {