Updated on 2026-08-14
This commit is contained in:
commit
333e9fa9cb
6 changed files with 99 additions and 46 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue