Updated on 2026-08-14

This commit is contained in:
Tangem 2022-05-20 17:26:32 +03:00
parent fffd53dcf2
commit 598fa3b3ea
6 changed files with 215 additions and 218 deletions

View file

@ -39,10 +39,23 @@ fun BigDecimal.toFormattedCurrencyString(
return "$formattedAmount $currency"
}
fun BigDecimal.toFiatString(rateValue: BigDecimal, fiatCurrencyName: String): String {
fun BigDecimal.toFiatRateString(
fiatCurrencyName: String
): String {
val value = this
.setScale(2, RoundingMode.HALF_UP)
.formatWithSpaces()
return "$value $fiatCurrencyName"
}
fun BigDecimal.toFiatString(
rateValue: BigDecimal,
fiatCurrencyName: String,
formatWithSpaces: Boolean = false
): String {
var fiatValue = rateValue.multiply(this)
fiatValue = fiatValue.setScale(2, RoundingMode.HALF_UP)
return "≈ ${fiatCurrencyName} $fiatValue"
return fiatValue.toFormattedFiatValue(fiatCurrencyName, formatWithSpaces)
}
fun BigDecimal.toFiatValue(rateValue: BigDecimal): BigDecimal {
@ -50,8 +63,12 @@ fun BigDecimal.toFiatValue(rateValue: BigDecimal): BigDecimal {
return fiatValue.setScale(2, RoundingMode.HALF_UP)
}
fun BigDecimal.toFormattedFiatValue(fiatCurrencyName: String): String {
return "≈ ${fiatCurrencyName} $this"
fun BigDecimal.toFormattedFiatValue(
fiatCurrencyName: String,
formatWithSpaces: Boolean = false
): String {
val fiatValue = if (formatWithSpaces) this.formatWithSpaces() else this
return "${fiatValue} $fiatCurrencyName"
}
fun BigDecimal.stripZeroPlainString(): String = this.stripTrailingZeros().toPlainString()
@ -111,4 +128,33 @@ fun BigDecimal.formatAmountAsSpannedString(
append(' ')
append(currencySymbol)
}
}
fun BigDecimal.formatWithSpaces(): String {
val str = this.toString()
var integerStr = str.substringBefore('.')
val reminderStr = str.substringAfter('.')
val packets = arrayListOf<String>()
var index: Int = integerStr.length
while (0 < index) {
if (index <= 3) {
packets.add(0, integerStr)
break
}
index -= 3
packets.add(integerStr.substring(startIndex = index))
integerStr = integerStr.substring(startIndex = 0, endIndex = index)
}
return buildString {
packets.forEachIndexed { index, packet ->
append(packet)
if (index != packets.lastIndex) append(' ')
}
if (reminderStr.isNotBlank()) {
append('.')
append(reminderStr)
}
}
}

View file

@ -65,7 +65,7 @@ class OnWalletLoadedReducer {
amount = coinAmountValue,
amountFormatted = formattedAmount,
fiatAmount = fiatAmount,
fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(fiatCurrency.code)
fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(fiatCurrency.symbol)
),
pendingTransactions = pendingTransactions.removeUnknownTransactions(),
mainButton = WalletMainButton.SendButton(coinSendButton),

View file

@ -5,9 +5,9 @@ import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.Wallet
import com.tangem.domain.common.TwinCardNumber
import com.tangem.tap.common.entities.FiatCurrency
import com.tangem.tap.common.extensions.toFiatRateString
import com.tangem.tap.common.extensions.toFiatString
import com.tangem.tap.common.extensions.toFiatValue
import com.tangem.tap.common.extensions.toFormattedCurrencyString
import com.tangem.tap.common.extensions.toFormattedFiatValue
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.domain.TapError
@ -20,7 +20,6 @@ import com.tangem.tap.features.wallet.ui.BalanceWidgetData
import com.tangem.tap.store
import org.rekotlin.Action
import java.math.BigDecimal
import java.math.RoundingMode
class WalletReducer {
companion object {
@ -383,10 +382,8 @@ private fun setNewFiatRate(
state: WalletState
): WalletState {
val rate = fiatRate.second ?: return state
val rateFormatted = rate.toFormattedCurrencyString(
decimals = 2,
currency = appCurrency.code,
roundingMode = RoundingMode.HALF_UP
val rateFormatted = rate.toFiatRateString(
fiatCurrencyName = appCurrency.symbol
)
val currency = fiatRate.first
@ -415,7 +412,7 @@ private fun setMultiWalletFiatRate(
is Currency.Token ->
wallet?.getTokenAmount(currency.token)?.value?.toFiatValue(rate)
}
val fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(appCurrency.code)
val fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(appCurrency.symbol)
val newWalletData = state.getWalletData(currency)?.copy(
currencyData = walletData.currencyData.copy(
fiatAmountFormatted = fiatAmountFormatted,

View file

@ -10,7 +10,6 @@ import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.Token
import com.tangem.domain.common.TapWorkarounds.derivationStyle
import com.tangem.tap.common.extensions.getString
import com.tangem.tap.common.extensions.hide
import com.tangem.tap.common.extensions.loadCurrenciesIcon
import com.tangem.tap.common.extensions.show
import com.tangem.tap.features.wallet.redux.Currency
@ -63,9 +62,7 @@ class WalletAdapter
fun bind(wallet: WalletData) = with(binding) {
tvCurrency.text = wallet.currencyData.currency
tvAmount.text = wallet.currencyData.amountFormatted?.takeWhile { !it.isWhitespace() }
tvCurrencySymbol.text =
wallet.currencyData.amountFormatted?.takeLastWhile { !it.isWhitespace() }
tvAmount.text = wallet.currencyData.amountFormatted.orEmpty()
tvAmountFiat.text = wallet.currencyData.fiatAmountFormatted
tvExchangeRate.text = wallet.fiatRateString
cardWallet.setOnClickListener {
@ -74,8 +71,8 @@ class WalletAdapter
val blockchain = wallet.currency.blockchain
val token = (wallet.currency as? Currency.Token)?.token
val isCustom =
wallet.currency.isCustomCurrency(store.state.globalState.scanResponse?.card?.derivationStyle)
val isCustom = wallet.currency
.isCustomCurrency(store.state.globalState.scanResponse?.card?.derivationStyle)
tvExchangeRate.show(!isCustom)
tvCustomCurrency.show(isCustom)
@ -86,43 +83,35 @@ class WalletAdapter
)
when (wallet.currencyData.status) {
BalanceStatus.VerifiedOnline, BalanceStatus.SameCurrencyTransactionInProgress -> hideWarning(isCustom)
BalanceStatus.Loading -> {
hideWarning(isCustom)
if (wallet.currencyData.amountFormatted == null) {
tvExchangeRate.text = root.getString(R.string.wallet_balance_loading)
}
BalanceStatus.VerifiedOnline,
BalanceStatus.SameCurrencyTransactionInProgress -> hideMessage()
BalanceStatus.Loading -> if (wallet.currencyData.amountFormatted == null) {
showMessage(root.getString(R.string.wallet_balance_loading))
}
BalanceStatus.TransactionInProgress ->
showWarning(root.getString(R.string.wallet_balance_tx_in_progress), isCustom)
showMessage(root.getString(R.string.wallet_balance_tx_in_progress))
BalanceStatus.Unreachable ->
showWarning(root.getString(R.string.wallet_balance_blockchain_unreachable), isCustom)
showMessage(root.getString(R.string.wallet_balance_blockchain_unreachable))
BalanceStatus.NoAccount ->
showWarning(root.getString(R.string.wallet_error_no_account), isCustom)
showMessage(root.getString(R.string.wallet_error_no_account))
else -> {
}
}
}
private fun showWarning(message: String, isCustom: Boolean = false) {
toggleWarning(true, isCustom)
binding.tvStatusErrorMessage.text = message
private fun showMessage(message: String) {
toggleMessage(true)
binding.tvStatus.text = message
}
private fun hideWarning(isCustom: Boolean = false) {
toggleWarning(false, isCustom)
private fun hideMessage() {
toggleMessage(false)
}
private fun toggleWarning(show: Boolean, isCustom: Boolean = false) {
if (!show) {
binding.tvExchangeRate.show(!isCustom)
binding.tvCustomCurrency.show(isCustom)
} else {
binding.tvExchangeRate.hide()
binding.tvCustomCurrency.hide()
}
binding.tvStatusErrorMessage.show(show)
private fun toggleMessage(show: Boolean) {
binding.tvAmount.show(!show)
binding.tvStatus.show(show)
}
}
}

View file

@ -1,205 +1,165 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.card.MaterialCardView
android:id="@+id/card_wallet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:background="@android:color/white"
android:elevation="3dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/card_wallet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="76dp">
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:background="@android:color/white"
android:elevation="3dp">
<androidx.constraintlayout.utils.widget.ImageFilterView
android:id="@+id/iv_currency"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/shape_circle" />
<TextView
android:id="@+id/tv_token_letter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:textColor="@android:color/white"
android:textSize="25sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@id/iv_currency"
app:layout_constraintEnd_toEndOf="@id/iv_currency"
app:layout_constraintStart_toStartOf="@id/iv_currency"
app:layout_constraintTop_toTopOf="@id/iv_currency"
tools:text="J" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.5" />
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp">
<androidx.constraintlayout.utils.widget.ImageFilterView
android:id="@+id/iv_currency"
android:layout_width="40dp"
android:layout_height="40dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/shape_circle" />
<TextView
android:id="@+id/tv_currency"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:ellipsize="end"
android:maxLines="1"
android:paddingStart="16dp"
android:paddingEnd="2dp"
android:textColor="@color/darkGray6"
android:textSize="17sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@id/guideline"
app:layout_constraintEnd_toStartOf="@+id/tv_amount"
app:layout_constraintStart_toEndOf="@id/iv_currency"
app:layout_constraintTop_toTopOf="parent"
tools:text="Binance Smart Chain Optimal" />
android:id="@+id/tv_token_letter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:textColor="@android:color/white"
android:textSize="25sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@id/iv_currency"
app:layout_constraintEnd_toEndOf="@id/iv_currency"
app:layout_constraintStart_toStartOf="@id/iv_currency"
app:layout_constraintTop_toTopOf="@id/iv_currency"
tools:text="J" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintGuide_percent="0.45"
app:layout_constraintTop_toTopOf="parent" />
android:id="@+id/guideline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.5" />
<TextView
android:id="@+id/tv_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginEnd="4dp"
android:ellipsize="end"
android:gravity="end"
android:maxEms="12"
android:maxLength="12"
android:maxLines="1"
android:textColor="@color/darkGray6"
android:textSize="17sp"
android:textStyle="bold"
android:visibility="visible"
app:layout_constraintEnd_toStartOf="@+id/tv_currency_symbol"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="@+id/guideline2"
app:layout_constraintTop_toTopOf="parent"
tools:text="1234567890.1234567890" />
android:id="@+id/tv_currency"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:ellipsize="end"
android:maxLines="1"
android:textColor="@color/darkGray6"
android:textSize="16sp"
android:textStyle="bold"
app:lineHeight="24dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/guideline"
app:layout_constraintStart_toEndOf="@id/iv_currency"
app:layout_constraintEnd_toStartOf="@+id/tv_amount"
tools:text="Binance Smart Chain Optimal" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintGuide_percent="0.5"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_exchange_rate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:textColor="@color/darkGray2"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/iv_currency"
app:layout_constraintTop_toTopOf="@id/guideline"
tools:text="USD 3 588" />
android:id="@+id/tv_amount_fiat"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:maxEms="12"
android:maxLength="12"
android:maxLines="1"
android:textColor="@color/darkGray6"
android:textSize="16sp"
android:textStyle="bold"
android:textAlignment="viewEnd"
app:lineHeight="24dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/guideline"
app:layout_constraintStart_toEndOf="@+id/guideline2"
app:layout_constraintEnd_toEndOf="parent"
tools:text="12300.43 $" />
<TextView
android:id="@+id/tv_custom_currency"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:paddingStart="4dp"
android:paddingEnd="4dp"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:textColor="@color/darkGray2"
android:textSize="14sp"
android:background="@drawable/shape_rectangle_rounded_4"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/iv_currency"
app:layout_constraintTop_toTopOf="@id/guideline"
android:text="@string/common_custom" />
android:id="@+id/tv_amount"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:maxEms="12"
android:maxLength="12"
android:maxLines="1"
android:textColor="@color/darkGray2"
android:textSize="12sp"
android:textAlignment="viewEnd"
app:lineHeight="20dp"
app:layout_constraintTop_toBottomOf="@id/guideline"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/guideline2"
app:layout_constraintEnd_toEndOf="parent"
tools:text="2.002134 BTC" />
<TextView
android:id="@+id/tv_status_error_message"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:ellipsize="end"
android:maxLines="1"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:textColor="@color/warning"
android:textSize="14sp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/tv_amount_fiat"
app:layout_constraintStart_toEndOf="@id/iv_currency"
app:layout_constraintTop_toTopOf="@id/guideline"
tools:text="@string/lorem_ipsum" />
android:id="@+id/tv_status"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:visibility="gone"
android:maxLines="1"
android:ellipsize="end"
android:textColor="@color/darkGray2"
android:textSize="12sp"
android:textAlignment="viewEnd"
app:lineHeight="20dp"
app:layout_constraintTop_toBottomOf="@id/guideline"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/guideline2"
app:layout_constraintEnd_toEndOf="parent"
tools:text="Unreachable..." />
<TextView
android:id="@+id/tv_status_loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:drawablePadding="5dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:text="@string/wallet_balance_loading"
android:textColor="@color/darkGray6"
android:textSize="13sp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
android:id="@+id/tv_exchange_rate"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:maxLines="1"
android:textColor="@color/darkGray2"
android:textSize="12sp"
app:lineHeight="20dp"
app:layout_constraintTop_toBottomOf="@id/guideline"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/iv_currency"
app:layout_constraintEnd_toStartOf="@id/guideline2"
tools:text="46 908 $" />
<TextView
android:id="@+id/tv_currency_symbol"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:gravity="end"
android:maxLines="1"
android:textColor="@color/darkGray6"
android:textSize="17sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintTop_toTopOf="parent"
tools:text="BTC" />
<TextView
android:id="@+id/tv_amount_fiat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:paddingEnd="16dp"
android:textColor="@color/darkGray2"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/guideline"
tools:text="0.43 USD" />
android:id="@+id/tv_custom_currency"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:textColor="@color/darkGray2"
android:textSize="14sp"
android:text="@string/common_custom"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/guideline"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/iv_currency"
app:layout_constraintEnd_toStartOf="@id/guideline2" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
</FrameLayout>

View file

@ -11,6 +11,7 @@
<item name="android:windowContentOverlay">@null</item>
<item name="actionMenuTextColor">@color/menu_accent_color</item>
<item name="materialCardViewStyle">@style/Widget.AppTheme.CardView</item>
</style>
<style name="AppTheme" parent="BaseAppTheme" />
@ -156,6 +157,10 @@
<item name="android:textColor">@color/selector_chip_shop_text</item>
</style>
<style name="Widget.AppTheme.CardView" parent="Widget.MaterialComponents.CardView">
<item name="cardCornerRadius">8dp</item>
</style>
</resources>
<!-- android:fontFamily="sans-serif" // roboto regular -->
@ -163,4 +168,4 @@
<!-- android:fontFamily="sans-serif-condensed" // roboto condensed -->
<!-- android:fontFamily="sans-serif-black" // roboto black -->
<!-- android:fontFamily="sans-serif-thin" // roboto thin (android 4.2) -->
<!-- android:fontFamily="sans-serif-medium" // roboto medium (android 5.0) -->
<!-- android:fontFamily="sans-serif-medium" // roboto medium (android 5.0) -->