Updated on 2026-08-14
This commit is contained in:
parent
a2b3c22e53
commit
64e6a7609f
14 changed files with 380 additions and 234 deletions
|
|
@ -3,6 +3,10 @@ package com.tangem.tap.features.wallet.ui
|
|||
import androidx.annotation.IdRes
|
||||
import com.tangem.tap.common.extensions.hide
|
||||
import com.tangem.tap.common.extensions.show
|
||||
import com.tangem.tap.domain.model.WalletDataModel
|
||||
import com.tangem.tap.features.wallet.ui.utils.getFormattedAmount
|
||||
import com.tangem.tap.features.wallet.ui.utils.getFormattedFiatAmount
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
import com.tangem.wallet.databinding.CardBalanceBinding
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -36,36 +40,37 @@ data class BalanceWidgetData(
|
|||
class BalanceWidget(
|
||||
private val binding: CardBalanceBinding,
|
||||
private val fragment: WalletFragment,
|
||||
private val data: BalanceWidgetData,
|
||||
private val token: BalanceWidgetData?,
|
||||
private val isTwinCard: Boolean,
|
||||
private val blockchainWalletData: WalletDataModel,
|
||||
private val tokenWalletData: WalletDataModel?,
|
||||
) {
|
||||
|
||||
@Suppress("LongMethod", "ComplexMethod")
|
||||
fun setup() {
|
||||
when (data.status) {
|
||||
BalanceStatus.Loading -> {
|
||||
when (blockchainWalletData.status) {
|
||||
is WalletDataModel.Loading -> {
|
||||
with(binding) {
|
||||
lBalance.root.show()
|
||||
lBalanceError.root.hide()
|
||||
lBalance.tvFiatAmount.hide()
|
||||
|
||||
lBalance.tvCurrency.text = data.currency
|
||||
lBalance.tvCurrency.text = blockchainWalletData.currency.currencyName
|
||||
lBalance.tvAmount.text = ""
|
||||
}
|
||||
|
||||
showStatus(R.id.tv_status_loading)
|
||||
|
||||
if (token != null) {
|
||||
showBalanceWithToken(data, false)
|
||||
if (tokenWalletData != null) {
|
||||
showBalanceWithToken(blockchainWalletData, false)
|
||||
} else {
|
||||
showBalanceWithoutToken(data, false)
|
||||
showBalanceWithoutToken(blockchainWalletData, false)
|
||||
}
|
||||
}
|
||||
BalanceStatus.VerifiedOnline, BalanceStatus.TransactionInProgress -> with(binding.lBalance) {
|
||||
is WalletDataModel.VerifiedOnline,
|
||||
is WalletDataModel.TransactionInProgress,
|
||||
-> with(binding.lBalance) {
|
||||
root.show()
|
||||
binding.lBalanceError.root.hide()
|
||||
val statusView = if (data.status == BalanceStatus.VerifiedOnline) {
|
||||
val statusView = if (blockchainWalletData.status is WalletDataModel.VerifiedOnline) {
|
||||
R.id.tv_status_verified
|
||||
} else {
|
||||
tvStatusError.text =
|
||||
|
|
@ -75,61 +80,62 @@ class BalanceWidget(
|
|||
showStatus(statusView)
|
||||
tvStatusErrorMessage.hide()
|
||||
|
||||
if (token != null) {
|
||||
showBalanceWithToken(data, true)
|
||||
if (tokenWalletData != null) {
|
||||
showBalanceWithToken(blockchainWalletData, true)
|
||||
} else {
|
||||
showBalanceWithoutToken(data, true)
|
||||
showBalanceWithoutToken(blockchainWalletData, true)
|
||||
}
|
||||
}
|
||||
BalanceStatus.Unreachable -> with(binding.lBalance) {
|
||||
is WalletDataModel.Unreachable -> with(binding.lBalance) {
|
||||
root.show()
|
||||
binding.lBalanceError.root.hide()
|
||||
tvFiatAmount.hide()
|
||||
groupBaseCurrency.hide()
|
||||
|
||||
val currency = if (token != null) token.currencySymbol else data.currency
|
||||
val currency = tokenWalletData?.currency?.currencySymbol
|
||||
?: blockchainWalletData.currency.currencyName
|
||||
tvCurrency.text = currency
|
||||
tvAmount.text = ""
|
||||
|
||||
tvStatusErrorMessage.text = data.errorMessage
|
||||
tvStatusErrorMessage.text = blockchainWalletData.status.errorMessage
|
||||
tvStatusError.text =
|
||||
fragment.getString(R.string.wallet_balance_blockchain_unreachable)
|
||||
|
||||
showStatus(R.id.group_error)
|
||||
tvStatusErrorMessage.show(!data.errorMessage.isNullOrBlank())
|
||||
tvStatusErrorMessage.show(!blockchainWalletData.status.errorMessage.isNullOrBlank())
|
||||
}
|
||||
BalanceStatus.EmptyCard -> with(binding.lBalanceError) {
|
||||
binding.lBalance.root.hide()
|
||||
binding.lBalanceError.root.show()
|
||||
if (isTwinCard) {
|
||||
tvErrorTitle.text = fragment.getText(R.string.wallet_error_empty_twin_card)
|
||||
tvErrorDescriptions.text =
|
||||
fragment.getText(R.string.wallet_error_empty_twin_card_subtitle)
|
||||
} else {
|
||||
tvErrorTitle.text = fragment.getText(R.string.wallet_error_empty_card)
|
||||
tvErrorDescriptions.text =
|
||||
fragment.getText(R.string.wallet_error_empty_card_subtitle)
|
||||
}
|
||||
}
|
||||
BalanceStatus.NoAccount -> with(binding.lBalanceError) {
|
||||
// BalanceStatus.EmptyCard -> with(binding.lBalanceError) {
|
||||
// binding.lBalance.root.hide()
|
||||
// binding.lBalanceError.root.show()
|
||||
// if (isTwinCard) {
|
||||
// tvErrorTitle.text = fragment.getText(R.string.wallet_error_empty_twin_card)
|
||||
// tvErrorDescriptions.text =
|
||||
// fragment.getText(R.string.wallet_error_empty_twin_card_subtitle)
|
||||
// } else {
|
||||
// tvErrorTitle.text = fragment.getText(R.string.wallet_error_empty_card)
|
||||
// tvErrorDescriptions.text =
|
||||
// fragment.getText(R.string.wallet_error_empty_card_subtitle)
|
||||
// }
|
||||
// }
|
||||
is WalletDataModel.NoAccount -> with(binding.lBalanceError) {
|
||||
binding.lBalance.root.hide()
|
||||
binding.lBalanceError.root.show()
|
||||
tvErrorTitle.text = fragment.getText(R.string.wallet_error_no_account)
|
||||
tvErrorDescriptions.text =
|
||||
fragment.getString(
|
||||
R.string.no_account_generic,
|
||||
data.amountToCreateAccount,
|
||||
data.currencySymbol,
|
||||
blockchainWalletData.status.amountToCreateAccount,
|
||||
blockchainWalletData.currency.currencySymbol,
|
||||
)
|
||||
}
|
||||
BalanceStatus.UnknownBlockchain -> with(binding.lBalanceError) {
|
||||
binding.lBalance.root.hide()
|
||||
binding.lBalanceError.root.show()
|
||||
tvErrorTitle.text =
|
||||
fragment.getText(R.string.wallet_error_unsupported_blockchain)
|
||||
tvErrorDescriptions.text =
|
||||
fragment.getString(R.string.wallet_error_unsupported_blockchain_subtitle)
|
||||
}
|
||||
// BalanceStatus.UnknownBlockchain -> with(binding.lBalanceError) {
|
||||
// binding.lBalance.root.hide()
|
||||
// binding.lBalanceError.root.show()
|
||||
// tvErrorTitle.text =
|
||||
// fragment.getText(R.string.wallet_error_unsupported_blockchain)
|
||||
// tvErrorDescriptions.text =
|
||||
// fragment.getString(R.string.wallet_error_unsupported_blockchain_subtitle)
|
||||
// }
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
|
@ -140,25 +146,25 @@ class BalanceWidget(
|
|||
tvStatusVerified.show(viewRes == R.id.tv_status_verified)
|
||||
}
|
||||
|
||||
private fun showBalanceWithToken(data: BalanceWidgetData, showAmount: Boolean) = with(binding.lBalance) {
|
||||
private fun showBalanceWithToken(data: WalletDataModel, showAmount: Boolean) = with(binding.lBalance) {
|
||||
groupBaseCurrency.show()
|
||||
tvCurrency.text = token?.currencySymbol
|
||||
tvBaseCurrency.text = data.currency
|
||||
tvAmount.text = if (showAmount) token?.amountFormatted else ""
|
||||
tvBaseAmount.text = if (showAmount) data.amountFormatted else ""
|
||||
tvCurrency.text = tokenWalletData?.currency?.currencySymbol
|
||||
tvBaseCurrency.text = data.currency.currencyName
|
||||
tvAmount.text = if (showAmount) tokenWalletData?.getFormattedAmount() else ""
|
||||
tvBaseAmount.text = if (showAmount) data.getFormattedAmount() else ""
|
||||
if (showAmount) {
|
||||
tvFiatAmount.show()
|
||||
tvFiatAmount.text = token?.fiatAmountFormatted
|
||||
tvFiatAmount.text = tokenWalletData?.getFormattedFiatAmount(store.state.globalState.appCurrency)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showBalanceWithoutToken(data: BalanceWidgetData, showAmount: Boolean) = with(binding.lBalance) {
|
||||
private fun showBalanceWithoutToken(data: WalletDataModel, showAmount: Boolean) = with(binding.lBalance) {
|
||||
groupBaseCurrency.hide()
|
||||
tvCurrency.text = data.currency
|
||||
tvAmount.text = if (showAmount) data.amountFormatted else ""
|
||||
tvCurrency.text = data.currency.currencyName
|
||||
tvAmount.text = if (showAmount) data.getFormattedAmount() else ""
|
||||
if (showAmount) {
|
||||
tvFiatAmount.show()
|
||||
tvFiatAmount.text = data.fiatAmountFormatted
|
||||
tvFiatAmount.text = data.getFormattedFiatAmount(store.state.globalState.appCurrency)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -41,21 +41,29 @@ import com.tangem.tap.common.extensions.show
|
|||
import com.tangem.tap.common.extensions.toQrCode
|
||||
import com.tangem.tap.common.recyclerView.SpaceItemDecoration
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.domain.model.WalletDataModel
|
||||
import com.tangem.tap.features.wallet.models.Currency
|
||||
import com.tangem.tap.features.wallet.models.PendingTransaction
|
||||
import com.tangem.tap.features.wallet.models.PendingTransactionType
|
||||
import com.tangem.tap.features.wallet.models.WalletWarning
|
||||
import com.tangem.tap.features.wallet.redux.AddressData
|
||||
import com.tangem.tap.features.wallet.redux.ErrorType
|
||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.features.wallet.redux.WalletData
|
||||
import com.tangem.tap.features.wallet.redux.WalletState
|
||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN
|
||||
import com.tangem.tap.features.wallet.redux.utils.UNKNOWN_AMOUNT_SIGN
|
||||
import com.tangem.tap.features.wallet.ui.adapters.PendingTransactionsAdapter
|
||||
import com.tangem.tap.features.wallet.ui.adapters.WalletDetailWarningMessagesAdapter
|
||||
import com.tangem.tap.features.wallet.ui.images.load
|
||||
import com.tangem.tap.features.wallet.ui.test.TestWallet
|
||||
import com.tangem.tap.features.wallet.ui.utils.assembleWarnings
|
||||
import com.tangem.tap.features.wallet.ui.utils.getAvailableActions
|
||||
import com.tangem.tap.features.wallet.ui.utils.getFormattedAmount
|
||||
import com.tangem.tap.features.wallet.ui.utils.getFormattedFiatAmount
|
||||
import com.tangem.tap.features.wallet.ui.utils.isAvailableToBuy
|
||||
import com.tangem.tap.features.wallet.ui.utils.isAvailableToSell
|
||||
import com.tangem.tap.features.wallet.ui.utils.isAvailableToSwap
|
||||
import com.tangem.tap.features.wallet.ui.utils.mainButton
|
||||
import com.tangem.tap.features.wallet.ui.utils.shouldShowMultipleAddress
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.tap.userWalletsListManagerSafe
|
||||
import com.tangem.tap.walletCurrenciesManager
|
||||
|
|
@ -85,31 +93,19 @@ class WalletDetailsFragment :
|
|||
|
||||
private val binding: FragmentWalletDetailsBinding by viewBinding(FragmentWalletDetailsBinding::bind)
|
||||
|
||||
private val walletDataWatcher: ModelWatcher<WalletData> = modelWatcher {
|
||||
val addressCardStrategy: DiffStrategy<WalletData> = { old, new ->
|
||||
old.currency != new.currency ||
|
||||
old.walletAddresses?.selectedAddress != new.walletAddresses?.selectedAddress ||
|
||||
old.shouldShowMultipleAddress() != new.shouldShowMultipleAddress()
|
||||
private val walletDataWatcher: ModelWatcher<WalletDataModel> = modelWatcher {
|
||||
val addressCardStrategy: DiffStrategy<WalletDataModel> = { old, new ->
|
||||
old.currency != new.currency || old.walletAddresses != new.walletAddresses
|
||||
}
|
||||
|
||||
WalletData::pendingTransactions {
|
||||
showPendingTransactionsIfPresent(it)
|
||||
}
|
||||
WalletData::currency {
|
||||
WalletDataModel::currency {
|
||||
handleCurrencyIcon(it)
|
||||
}
|
||||
WalletData::currencyData {
|
||||
setupBalanceData(it)
|
||||
}
|
||||
WalletData::walletAddresses { walletAddresses ->
|
||||
WalletDataModel::walletAddresses { walletAddresses ->
|
||||
setupCopyAndShareButtons(walletAddresses?.selectedAddress?.address)
|
||||
}
|
||||
WalletData::assembleWarnings { warnings ->
|
||||
handleWarnings(warnings)
|
||||
}
|
||||
(WalletData::currencyData or WalletData::currency) { walletData ->
|
||||
setupCurrency(walletData.currencyData, walletData.currency)
|
||||
setupSwipeRefresh(walletData.currencyData, walletData.currency)
|
||||
WalletDataModel::currency { currency ->
|
||||
setupCurrency(currency)
|
||||
}
|
||||
watch({ it }, addressCardStrategy) { walletData ->
|
||||
setupAddressCard(
|
||||
|
|
@ -121,9 +117,28 @@ class WalletDetailsFragment :
|
|||
}
|
||||
|
||||
private val walletStateWatcher: ModelWatcher<WalletState> = modelWatcher {
|
||||
WalletState::selectedWalletData { selectedWallet ->
|
||||
val walletDataStrategy: DiffStrategy<WalletState> = { old, new ->
|
||||
new.walletsStores.isNotEmpty() &&
|
||||
new.selectedCurrency != null &&
|
||||
(old.selectedCurrency != new.selectedCurrency || old.walletsStores != new.walletsStores)
|
||||
}
|
||||
|
||||
watch({ it }, walletDataStrategy) { state ->
|
||||
val selectedWallet = state.selectedWalletData
|
||||
if (selectedWallet != null) {
|
||||
setupBalanceData(selectedWallet)
|
||||
setupSwipeRefresh(selectedWallet)
|
||||
walletDataWatcher.invoke(selectedWallet)
|
||||
|
||||
val walletStore = state.getWalletStore(state.selectedCurrency)
|
||||
if (walletStore != null) {
|
||||
handleWarnings(
|
||||
selectedWallet.assembleWarnings(
|
||||
blockchainAmount = walletStore.blockchainWalletData.status.amount,
|
||||
blockchainWalletRent = walletStore.walletRent,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
(WalletState::selectedWalletData or WalletState::isExchangeServiceFeatureOn) { state ->
|
||||
|
|
@ -234,8 +249,8 @@ class WalletDetailsFragment :
|
|||
)
|
||||
}
|
||||
|
||||
private fun setupCurrency(currencyData: BalanceWidgetData, currency: Currency) = with(binding) {
|
||||
tvCurrencyTitle.text = currencyData.currency
|
||||
private fun setupCurrency(currency: Currency) = with(binding) {
|
||||
tvCurrencyTitle.text = currency.currencyName
|
||||
|
||||
if (currency is Currency.Token) {
|
||||
tvCurrencySubtitle.text = tvCurrencySubtitle.getString(
|
||||
|
|
@ -248,16 +263,17 @@ class WalletDetailsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun setupSwipeRefresh(currencyData: BalanceWidgetData, currency: Currency) {
|
||||
private fun setupSwipeRefresh(walletData: WalletDataModel) {
|
||||
binding.srlWalletDetails.setOnRefreshListener {
|
||||
if (currencyData.status != BalanceStatus.Loading && currencyData.status != BalanceStatus.Refreshing) {
|
||||
if (walletData.status !is WalletDataModel.Loading) {
|
||||
Analytics.send(Token.Refreshed())
|
||||
val selectedUserWallet = userWalletsListManagerSafe?.selectedUserWalletSync.guard {
|
||||
Timber.e("Unable to refresh wallet details screen, no user wallet selected")
|
||||
return@setOnRefreshListener
|
||||
}
|
||||
binding.srlWalletDetails.isRefreshing = true
|
||||
lifecycleScope.launch(Dispatchers.Default) {
|
||||
val selectedUserWallet = userWalletsListManagerSafe?.selectedUserWalletSync.guard {
|
||||
Timber.e("Unable to refresh wallet details screen, no user wallet selected")
|
||||
return@launch
|
||||
}
|
||||
walletCurrenciesManager.update(selectedUserWallet, currency)
|
||||
walletCurrenciesManager.update(selectedUserWallet, walletData.currency)
|
||||
.doOnResult {
|
||||
withMainContext {
|
||||
binding.srlWalletDetails.isRefreshing = false
|
||||
|
|
@ -266,9 +282,6 @@ class WalletDetailsFragment :
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.srlWalletDetails.isRefreshing = currencyData.status == BalanceStatus.Loading ||
|
||||
currencyData.status == BalanceStatus.Refreshing
|
||||
}
|
||||
|
||||
private fun setupCopyAndShareButtons(walletAddress: String?) {
|
||||
|
|
@ -284,7 +297,7 @@ class WalletDetailsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun setupButtonsRow(selectedWallet: WalletData, isExchangeServiceFeatureOn: Boolean) {
|
||||
private fun setupButtonsRow(selectedWallet: WalletDataModel, isExchangeServiceFeatureOn: Boolean) {
|
||||
val exchangeManager = store.state.globalState.exchangeManager
|
||||
binding.rowButtons.apply {
|
||||
onBuyClick = { store.dispatch(WalletAction.TradeCryptoAction.Buy()) }
|
||||
|
|
@ -340,7 +353,7 @@ class WalletDetailsFragment :
|
|||
|
||||
private fun setupAddressCard(
|
||||
shouldShowMultipleAddress: Boolean,
|
||||
selectedAddress: AddressData?,
|
||||
selectedAddress: WalletDataModel.AddressData?,
|
||||
currency: Currency,
|
||||
) = with(binding.lWalletDetails) {
|
||||
if (selectedAddress == null) return@with
|
||||
|
|
@ -371,7 +384,7 @@ class WalletDetailsFragment :
|
|||
|
||||
private fun setupAddressTypeChips(
|
||||
shouldShowMultipleAddress: Boolean,
|
||||
selectedAddress: AddressData,
|
||||
selectedAddress: WalletDataModel.AddressData,
|
||||
currency: Currency,
|
||||
) = with(binding.lWalletDetails) {
|
||||
if (shouldShowMultipleAddress && currency is Currency.Blockchain) {
|
||||
|
|
@ -408,54 +421,58 @@ class WalletDetailsFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun setupBalanceData(data: BalanceWidgetData) = with(binding.lWalletDetails) {
|
||||
when (data.status) {
|
||||
BalanceStatus.Loading -> {
|
||||
private fun setupBalanceData(walletData: WalletDataModel) = with(binding.lWalletDetails) {
|
||||
when (val status = walletData.status) {
|
||||
is WalletDataModel.Loading -> {
|
||||
lBalanceError.root.hide()
|
||||
lBalance.root.show()
|
||||
lBalance.groupBalance.show()
|
||||
lBalance.tvError.hide()
|
||||
lBalance.tvAmount.text = data.amountFormatted
|
||||
lBalance.tvFiatAmount.text = data.fiatAmountFormatted ?: UNKNOWN_AMOUNT_SIGN
|
||||
lBalance.tvAmount.text = walletData.getFormattedAmount()
|
||||
lBalance.tvFiatAmount.text = walletData.getFormattedFiatAmount(store.state.globalState.appCurrency)
|
||||
lBalance.tvStatus.setLoadingStatus(R.string.wallet_balance_loading)
|
||||
}
|
||||
BalanceStatus.VerifiedOnline, BalanceStatus.SameCurrencyTransactionInProgress,
|
||||
BalanceStatus.TransactionInProgress,
|
||||
is WalletDataModel.VerifiedOnline,
|
||||
is WalletDataModel.SameCurrencyTransactionInProgress,
|
||||
is WalletDataModel.TransactionInProgress,
|
||||
-> {
|
||||
lBalanceError.root.hide()
|
||||
lBalance.root.show()
|
||||
lBalance.groupBalance.show()
|
||||
lBalance.tvError.hide()
|
||||
lBalance.tvAmount.text = data.amountFormatted
|
||||
lBalance.tvFiatAmount.text = data.fiatAmountFormatted ?: UNKNOWN_AMOUNT_SIGN
|
||||
when (data.status) {
|
||||
BalanceStatus.VerifiedOnline, BalanceStatus.SameCurrencyTransactionInProgress -> {
|
||||
lBalance.tvAmount.text = walletData.getFormattedAmount()
|
||||
lBalance.tvFiatAmount.text = walletData.getFormattedFiatAmount(store.state.globalState.appCurrency)
|
||||
when (status) {
|
||||
is WalletDataModel.VerifiedOnline,
|
||||
is WalletDataModel.SameCurrencyTransactionInProgress,
|
||||
-> {
|
||||
lBalance.tvStatus.setVerifiedBalanceStatus(R.string.wallet_balance_verified)
|
||||
}
|
||||
else -> {
|
||||
lBalance.tvStatus.setWarningStatus(R.string.wallet_balance_tx_in_progress)
|
||||
}
|
||||
}
|
||||
showPendingTransactionsIfPresent(status.pendingTransactions)
|
||||
}
|
||||
BalanceStatus.Unreachable -> {
|
||||
is WalletDataModel.Unreachable -> {
|
||||
lBalanceError.root.hide()
|
||||
lBalance.root.show()
|
||||
lBalance.groupBalance.hide()
|
||||
lBalance.tvError.show()
|
||||
lBalance.tvError.setWarningStatus(
|
||||
R.string.wallet_balance_blockchain_unreachable,
|
||||
data.errorMessage,
|
||||
status.errorMessage,
|
||||
)
|
||||
}
|
||||
BalanceStatus.NoAccount -> {
|
||||
is WalletDataModel.NoAccount -> {
|
||||
lBalance.root.hide()
|
||||
lBalanceError.root.show()
|
||||
lBalanceError.tvErrorTitle.text = getText(R.string.wallet_error_no_account)
|
||||
lBalanceError.tvErrorDescriptions.text =
|
||||
getString(
|
||||
R.string.no_account_generic,
|
||||
data.amountToCreateAccount,
|
||||
data.currencySymbol,
|
||||
status.amountToCreateAccount,
|
||||
walletData.currency.currencySymbol,
|
||||
)
|
||||
}
|
||||
else -> {}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
|||
|
||||
private val totalBalanceWatcher = modelWatcher {
|
||||
(WalletState::totalBalance) { totalBalance ->
|
||||
totalBalance?.state?.let {
|
||||
totalBalance?.let {
|
||||
viewModel.onBalanceLoaded(totalBalance)
|
||||
store.state.globalState.topUpController?.totalBalanceStateChanged(it)
|
||||
}
|
||||
|
|
@ -159,8 +159,7 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
|||
walletView = SaltPayWalletView()
|
||||
walletView.changeWalletView(this, binding)
|
||||
}
|
||||
state.isMultiwalletAllowed && state.primaryWalletData?.currencyData?.status != BalanceStatus.EmptyCard &&
|
||||
walletView !is MultiWalletView -> {
|
||||
state.isMultiwalletAllowed && walletView !is MultiWalletView -> {
|
||||
walletView.onViewDestroy()
|
||||
walletView = MultiWalletView()
|
||||
walletView.changeWalletView(this, binding)
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ import com.tangem.tap.common.analytics.converters.ParamCardCurrencyConverter
|
|||
import com.tangem.tap.common.analytics.events.Basic
|
||||
import com.tangem.tap.common.analytics.events.MainScreen
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.domain.model.TotalFiatBalance
|
||||
import com.tangem.tap.domain.userWalletList.UserWalletsListManager
|
||||
import com.tangem.tap.features.wallet.models.TotalBalance
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.features.wallet.ui.analytics.WalletAnalyticsEventsMapper
|
||||
import com.tangem.tap.store
|
||||
|
|
@ -88,7 +88,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
bootstrapShowSaveWalletIfNeeded()
|
||||
}
|
||||
|
||||
fun onBalanceLoaded(totalBalance: TotalBalance?) {
|
||||
fun onBalanceLoaded(totalBalance: TotalFiatBalance?) {
|
||||
if (totalBalance != null) {
|
||||
walletAnalyticsEventsMapper.convert(totalBalance)?.let { balanceParam ->
|
||||
analyticsEventHandler.send(
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ class WalletWarningConverter(
|
|||
is WalletWarning.Rent -> {
|
||||
context.getString(
|
||||
R.string.solana_rent_warning,
|
||||
message.walletRent.minRentValue,
|
||||
message.walletRent.rentExemptValue,
|
||||
message.walletRent.rent,
|
||||
message.walletRent.exemptionAmount,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,18 +12,20 @@ import com.tangem.tap.common.analytics.events.Portfolio
|
|||
import com.tangem.tap.common.extensions.getString
|
||||
import com.tangem.tap.common.extensions.hide
|
||||
import com.tangem.tap.common.extensions.show
|
||||
import com.tangem.tap.domain.model.WalletDataModel
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.features.wallet.redux.WalletData
|
||||
import com.tangem.tap.features.wallet.ui.BalanceStatus
|
||||
import com.tangem.tap.features.wallet.ui.utils.getFormattedAmount
|
||||
import com.tangem.tap.features.wallet.ui.utils.getFormattedFiatAmount
|
||||
import com.tangem.tap.features.wallet.ui.utils.getFormattedFiatRate
|
||||
import com.tangem.tap.features.wallet.ui.images.load
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
import com.tangem.wallet.databinding.ItemCurrencyWalletBinding
|
||||
|
||||
class WalletAdapter : ListAdapter<WalletData, WalletAdapter.WalletsViewHolder>(DiffUtilCallback) {
|
||||
class WalletAdapter : ListAdapter<WalletDataModel, WalletAdapter.WalletsViewHolder>(DiffUtilCallback) {
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
return currentList[position].currencyData.currencySymbol?.hashCode()?.toLong() ?: 0
|
||||
return currentList[position].currency.currencySymbol.hashCode().toLong()
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WalletsViewHolder {
|
||||
|
|
@ -39,34 +41,33 @@ class WalletAdapter : ListAdapter<WalletData, WalletAdapter.WalletsViewHolder>(D
|
|||
holder.bind(currentList[position])
|
||||
}
|
||||
|
||||
object DiffUtilCallback : DiffUtil.ItemCallback<WalletData>() {
|
||||
override fun areContentsTheSame(oldItem: WalletData, newItem: WalletData) = oldItem == newItem
|
||||
object DiffUtilCallback : DiffUtil.ItemCallback<WalletDataModel>() {
|
||||
override fun areContentsTheSame(oldItem: WalletDataModel, newItem: WalletDataModel) = oldItem == newItem
|
||||
|
||||
override fun areItemsTheSame(oldItem: WalletData, newItem: WalletData) = oldItem == newItem
|
||||
override fun areItemsTheSame(oldItem: WalletDataModel, newItem: WalletDataModel) = oldItem == newItem
|
||||
}
|
||||
|
||||
class WalletsViewHolder(val binding: ItemCurrencyWalletBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(wallet: WalletData) = with(binding) {
|
||||
val status = wallet.currencyData.status
|
||||
// Skip changes when on refreshing status
|
||||
if (status == BalanceStatus.Refreshing) return@with
|
||||
fun bind(wallet: WalletDataModel) = with(binding) {
|
||||
val status = wallet.status
|
||||
val fiatCurrency = store.state.globalState.appCurrency
|
||||
|
||||
val statusMessage = when (status) {
|
||||
BalanceStatus.TransactionInProgress -> {
|
||||
is WalletDataModel.TransactionInProgress -> {
|
||||
root.getString(R.string.wallet_balance_tx_in_progress)
|
||||
}
|
||||
BalanceStatus.Unreachable -> {
|
||||
is WalletDataModel.Unreachable -> {
|
||||
root.getString(R.string.wallet_balance_blockchain_unreachable)
|
||||
}
|
||||
BalanceStatus.MissedDerivation -> {
|
||||
is WalletDataModel.MissedDerivation -> {
|
||||
root.getString(R.string.wallet_balance_missing_derivation)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (status == null || status == BalanceStatus.Loading) {
|
||||
if (status is WalletDataModel.Loading) {
|
||||
lContent.root.hide()
|
||||
lShimmer.root.veil()
|
||||
} else {
|
||||
|
|
@ -82,24 +83,22 @@ class WalletAdapter : ListAdapter<WalletData, WalletAdapter.WalletsViewHolder>(D
|
|||
?.derivationStyle,
|
||||
)
|
||||
|
||||
lContent.tvCurrency.text = wallet.currencyData.currency
|
||||
lContent.tvAmountFiat.text = wallet.currencyData.fiatAmountFormatted ?: "—"
|
||||
lContent.tvAmount.text = wallet.currencyData.amountFormatted ?: "—"
|
||||
lContent.tvCurrency.text = wallet.currency.currencyName
|
||||
lContent.tvAmountFiat.text = wallet.getFormattedFiatAmount(fiatCurrency)
|
||||
lContent.tvAmount.text = wallet.getFormattedAmount()
|
||||
|
||||
lContent.tvStatus.isVisible = statusMessage != null
|
||||
lContent.tvStatus.text = statusMessage
|
||||
|
||||
lContent.tvExchangeRate.isVisible = statusMessage == null
|
||||
lContent.tvExchangeRate.text = wallet.fiatRateString
|
||||
?: root.getString(id = R.string.token_item_no_rate)
|
||||
lContent.tvExchangeRate.text = wallet.getFormattedFiatRate(
|
||||
fiatCurrency = fiatCurrency,
|
||||
noRateValue = root.getString(id = R.string.token_item_no_rate),
|
||||
)
|
||||
|
||||
if (wallet.walletAddresses != null) {
|
||||
cardWallet.setOnClickListener {
|
||||
Analytics.send(Portfolio.TokenTapped())
|
||||
store.dispatch(WalletAction.MultiWallet.SelectWallet(wallet.currency))
|
||||
}
|
||||
} else {
|
||||
cardWallet.setOnClickListener(null)
|
||||
cardWallet.setOnClickListener {
|
||||
Analytics.send(Portfolio.TokenTapped())
|
||||
store.dispatch(WalletAction.MultiWallet.SelectWallet(wallet.currency))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,22 +2,16 @@ package com.tangem.tap.features.wallet.ui.analytics
|
|||
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.extensions.isGreaterThan
|
||||
import com.tangem.tap.features.wallet.models.TotalBalance
|
||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||
import com.tangem.tap.domain.model.TotalFiatBalance
|
||||
import com.tangem.utils.converter.Converter
|
||||
import java.math.BigDecimal
|
||||
|
||||
class WalletAnalyticsEventsMapper : Converter<TotalBalance, AnalyticsParam.CardBalanceState?> {
|
||||
class WalletAnalyticsEventsMapper : Converter<TotalFiatBalance, AnalyticsParam.CardBalanceState?> {
|
||||
|
||||
override fun convert(value: TotalBalance): AnalyticsParam.CardBalanceState? {
|
||||
return when (value.state) {
|
||||
ProgressState.Done -> if (value.fiatAmount?.isGreaterThan(BigDecimal.ZERO) == true) {
|
||||
AnalyticsParam.CardBalanceState.Full
|
||||
} else {
|
||||
AnalyticsParam.CardBalanceState.Empty
|
||||
}
|
||||
ProgressState.Error -> {
|
||||
if (value.fiatAmount == null) {
|
||||
override fun convert(value: TotalFiatBalance): AnalyticsParam.CardBalanceState? {
|
||||
return when (value) {
|
||||
is TotalFiatBalance.Error -> {
|
||||
if (value.amount == null) {
|
||||
// if fiatAmount is null while ProgressState.Error it means error occurs when loading blockchain
|
||||
AnalyticsParam.CardBalanceState.BlockchainError
|
||||
} else {
|
||||
|
|
@ -25,7 +19,14 @@ class WalletAnalyticsEventsMapper : Converter<TotalBalance, AnalyticsParam.CardB
|
|||
AnalyticsParam.CardBalanceState.CustomToken
|
||||
}
|
||||
}
|
||||
else -> null
|
||||
is TotalFiatBalance.Loaded -> {
|
||||
if (value.amount.isGreaterThan(BigDecimal.ZERO)) {
|
||||
AnalyticsParam.CardBalanceState.Full
|
||||
} else {
|
||||
AnalyticsParam.CardBalanceState.Empty
|
||||
}
|
||||
}
|
||||
is TotalFiatBalance.Loading -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
package com.tangem.tap.features.wallet.ui.utils
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.domain.common.extensions.toNetworkId
|
||||
import com.tangem.feature.swap.api.SwapFeatureToggleManager
|
||||
import com.tangem.feature.swap.domain.SwapInteractor
|
||||
import com.tangem.tap.common.entities.FiatCurrency
|
||||
import com.tangem.tap.common.extensions.toFiatRateString
|
||||
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.domain.model.WalletDataModel
|
||||
import com.tangem.tap.domain.model.WalletStoreModel
|
||||
import com.tangem.tap.features.wallet.models.WalletWarning
|
||||
import com.tangem.tap.features.wallet.redux.WalletMainButton
|
||||
import com.tangem.tap.features.wallet.redux.utils.UNKNOWN_AMOUNT_SIGN
|
||||
import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager
|
||||
import java.math.BigDecimal
|
||||
|
||||
internal val WalletDataModel.mainButton: WalletMainButton
|
||||
get() = WalletMainButton.SendButton(
|
||||
enabled = !status.amount.isZero() && status.pendingTransactions.isEmpty(),
|
||||
)
|
||||
|
||||
internal fun WalletDataModel.getFormattedAmount(): String {
|
||||
return status.amount.toFormattedCurrencyString(
|
||||
decimals = currency.decimals,
|
||||
currency = currency.currencySymbol,
|
||||
)
|
||||
}
|
||||
|
||||
internal fun WalletDataModel.getFormattedFiatAmount(
|
||||
fiatCurrency: FiatCurrency,
|
||||
unknownAmountSign: String = UNKNOWN_AMOUNT_SIGN,
|
||||
): String {
|
||||
return this.fiatRate?.let { status.amount.toFiatValue(it) }
|
||||
?.takeIf { !status.isErrorStatus }
|
||||
?.toFormattedFiatValue(fiatCurrency.symbol)
|
||||
?: unknownAmountSign
|
||||
}
|
||||
|
||||
internal fun WalletDataModel.getFormattedFiatRate(fiatCurrency: FiatCurrency, noRateValue: String): String {
|
||||
return fiatRate?.toFiatRateString(fiatCurrency.symbol)
|
||||
?: noRateValue
|
||||
}
|
||||
|
||||
internal fun WalletDataModel.isAvailableToBuy(exchangeManager: CurrencyExchangeManager): Boolean {
|
||||
return exchangeManager.availableForBuy(currency)
|
||||
}
|
||||
|
||||
internal fun WalletDataModel.isAvailableToSell(exchangeManager: CurrencyExchangeManager): Boolean {
|
||||
return exchangeManager.availableForSell(currency)
|
||||
}
|
||||
|
||||
internal fun WalletDataModel.isAvailableToSwap(
|
||||
swapFeatureToggleManager: SwapFeatureToggleManager,
|
||||
swapInteractor: SwapInteractor,
|
||||
): Boolean {
|
||||
if (currency.blockchain.id == Blockchain.Optimism.id && !swapFeatureToggleManager.isOptimismSwapEnabled) {
|
||||
return false
|
||||
}
|
||||
return swapInteractor.isAvailableToSwap(currency.blockchain.toNetworkId()) &&
|
||||
!currency.isCustomCurrency(null)
|
||||
}
|
||||
|
||||
internal fun WalletDataModel.getAvailableActions(
|
||||
swapInteractor: SwapInteractor,
|
||||
exchangeManager: CurrencyExchangeManager,
|
||||
swapFeatureToggleManager: SwapFeatureToggleManager,
|
||||
): Set<CurrencyAction> {
|
||||
return setOfNotNull(
|
||||
if (isAvailableToBuy(exchangeManager)) CurrencyAction.Buy else null,
|
||||
if (isAvailableToSell(exchangeManager)) CurrencyAction.Sell else null,
|
||||
if (isAvailableToSwap(swapFeatureToggleManager, swapInteractor)) CurrencyAction.Swap else null,
|
||||
)
|
||||
}
|
||||
|
||||
internal fun WalletDataModel.shouldShowMultipleAddress(): Boolean {
|
||||
val listOfAddresses = walletAddresses?.list.orEmpty()
|
||||
return listOfAddresses.size > 1
|
||||
}
|
||||
|
||||
internal fun WalletDataModel.assembleWarnings(
|
||||
blockchainAmount: BigDecimal,
|
||||
blockchainWalletRent: WalletStoreModel.WalletRent?,
|
||||
): List<WalletWarning> {
|
||||
val walletWarnings = mutableListOf<WalletWarning>()
|
||||
assembleNonTypedWarnings(walletWarnings, blockchainWalletRent)
|
||||
assembleBlockchainWarnings(walletWarnings)
|
||||
assembleTokenWarnings(walletWarnings, blockchainAmount)
|
||||
|
||||
return walletWarnings.sortedBy { it.showingPosition }
|
||||
}
|
||||
|
||||
private fun WalletDataModel.assembleNonTypedWarnings(
|
||||
walletWarnings: MutableList<WalletWarning>,
|
||||
walletRent: WalletStoreModel.WalletRent?,
|
||||
) {
|
||||
if (this.status is WalletDataModel.SameCurrencyTransactionInProgress) {
|
||||
walletWarnings.add(WalletWarning.TransactionInProgress(currency.currencyName))
|
||||
}
|
||||
if (walletRent != null) {
|
||||
walletWarnings.add(WalletWarning.Rent(walletRent))
|
||||
}
|
||||
}
|
||||
|
||||
private fun WalletDataModel.assembleBlockchainWarnings(walletWarnings: MutableList<WalletWarning>) {
|
||||
with(currency) {
|
||||
if (!isBlockchain()) return
|
||||
|
||||
if (existentialDeposit != null) {
|
||||
val warning = WalletWarning.ExistentialDeposit(
|
||||
currencyName = currencyName,
|
||||
edStringValueWithSymbol = "${existentialDeposit.toPlainString()} $currencySymbol",
|
||||
)
|
||||
walletWarnings.add(warning)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun WalletDataModel.assembleTokenWarnings(
|
||||
walletWarnings: MutableList<WalletWarning>,
|
||||
blockchainAmount: BigDecimal,
|
||||
) {
|
||||
if (!currency.isToken()) return
|
||||
|
||||
if (!this.isEmptyAmount && blockchainAmount.isZero()) {
|
||||
walletWarnings.add(
|
||||
WalletWarning.BalanceNotEnoughForFee(
|
||||
currencyName = currency.currencyName,
|
||||
blockchainFullName = currency.blockchain.fullName,
|
||||
blockchainSymbol = currency.blockchain.currency,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private val WalletDataModel.isEmptyAmount: Boolean
|
||||
get() = this.status.amount.isZero()
|
||||
|
||||
enum class CurrencyAction {
|
||||
Buy, Sell, Swap
|
||||
}
|
||||
|
|
@ -35,9 +35,8 @@ import com.tangem.core.ui.components.SpacerW4
|
|||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.tap.common.entities.FiatCurrency
|
||||
import com.tangem.tap.common.extensions.formatWithSpaces
|
||||
import com.tangem.tap.features.wallet.models.TotalBalance
|
||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN
|
||||
import com.tangem.tap.domain.model.TotalFiatBalance
|
||||
import com.tangem.tap.features.wallet.redux.utils.UNKNOWN_AMOUNT_SIGN
|
||||
import com.tangem.wallet.R
|
||||
import com.valentinilk.shimmer.shimmer
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -52,18 +51,25 @@ internal class TotalBalanceCard @JvmOverloads constructor(
|
|||
) : AbstractComposeView(context, attrs, defStyleAttr) {
|
||||
private var state by mutableStateOf<TotalBalanceCardState>(TotalBalanceCardState.Empty)
|
||||
|
||||
var status: TotalBalance? = null
|
||||
var status: TotalFiatBalance? = null
|
||||
set(value) {
|
||||
if (field == value) return
|
||||
field = value
|
||||
updateState(value, onChangeFiatCurrencyClick)
|
||||
updateState(value, fiatCurrency, onChangeFiatCurrencyClick)
|
||||
}
|
||||
|
||||
var onChangeFiatCurrencyClick: () -> Unit = { /* no-op */ }
|
||||
set(value) {
|
||||
if (field == value) return
|
||||
field = value
|
||||
updateState(status, value)
|
||||
updateState(status, fiatCurrency, value)
|
||||
}
|
||||
|
||||
var fiatCurrency: FiatCurrency = FiatCurrency.Default
|
||||
set(value) {
|
||||
if (field == value) return
|
||||
field = value
|
||||
updateState(status, value, onChangeFiatCurrencyClick)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
@ -77,23 +83,21 @@ internal class TotalBalanceCard @JvmOverloads constructor(
|
|||
return javaClass.name
|
||||
}
|
||||
|
||||
private fun updateState(status: TotalBalance?, onChangeCurrencyClick: () -> Unit) {
|
||||
state = when (status?.state) {
|
||||
private fun updateState(status: TotalFiatBalance?, fiatCurrency: FiatCurrency, onChangeCurrencyClick: () -> Unit) {
|
||||
state = when (status) {
|
||||
null -> TotalBalanceCardState.Empty
|
||||
ProgressState.Loading -> TotalBalanceCardState.Loading(
|
||||
fiatCurrency = status.fiatCurrency,
|
||||
is TotalFiatBalance.Error -> TotalBalanceCardState.Failure(
|
||||
amount = status.amount,
|
||||
fiatCurrency = fiatCurrency,
|
||||
onChangeFiatCurrencyClick = onChangeCurrencyClick,
|
||||
)
|
||||
ProgressState.Error -> TotalBalanceCardState.Failure(
|
||||
amount = status.fiatAmount,
|
||||
fiatCurrency = status.fiatCurrency,
|
||||
is TotalFiatBalance.Loading -> TotalBalanceCardState.Loading(
|
||||
fiatCurrency = fiatCurrency,
|
||||
onChangeFiatCurrencyClick = onChangeCurrencyClick,
|
||||
)
|
||||
ProgressState.Refreshing,
|
||||
ProgressState.Done,
|
||||
-> TotalBalanceCardState.Success(
|
||||
amount = status.fiatAmount ?: BigDecimal.ZERO,
|
||||
fiatCurrency = status.fiatCurrency,
|
||||
is TotalFiatBalance.Loaded -> TotalBalanceCardState.Success(
|
||||
amount = status.amount,
|
||||
fiatCurrency = fiatCurrency,
|
||||
onChangeFiatCurrencyClick = onChangeCurrencyClick,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import androidx.core.view.isVisible
|
|||
import com.google.android.material.button.MaterialButton
|
||||
import com.tangem.tap.common.extensions.hide
|
||||
import com.tangem.tap.common.extensions.show
|
||||
import com.tangem.tap.features.wallet.redux.CurrencyAction
|
||||
import com.tangem.tap.features.wallet.ui.utils.CurrencyAction
|
||||
import com.tangem.wallet.databinding.ViewWalletDetailsButtonsRowBinding
|
||||
|
||||
internal class WalletDetailsButtonsRow @JvmOverloads constructor(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.tangem.tap.features.wallet.ui.wallet
|
||||
|
||||
import android.widget.Button
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.badoo.mvicore.modelWatcher
|
||||
|
|
@ -14,14 +13,13 @@ import com.tangem.tap.common.extensions.hide
|
|||
import com.tangem.tap.common.extensions.show
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.domain.model.TotalFiatBalance
|
||||
import com.tangem.tap.features.tokens.redux.TokensAction
|
||||
import com.tangem.tap.features.wallet.models.TotalBalance
|
||||
import com.tangem.tap.features.wallet.redux.ErrorType
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.features.wallet.redux.WalletState
|
||||
import com.tangem.tap.features.wallet.ui.BalanceStatus
|
||||
import com.tangem.tap.features.wallet.ui.WalletFragment
|
||||
import com.tangem.tap.features.wallet.ui.adapters.WalletAdapter
|
||||
import com.tangem.tap.features.wallet.ui.view.WalletDetailsButtonsRow
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
import com.tangem.wallet.databinding.FragmentWalletBinding
|
||||
|
|
@ -151,35 +149,29 @@ class MultiWalletView : WalletView() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun handleTotalBalance(binding: FragmentWalletBinding, totalBalance: TotalBalance?, walletsCount: Int) =
|
||||
with(binding.lCardTotalBalance) {
|
||||
isVisible = walletsCount > 0
|
||||
private fun handleTotalBalance(
|
||||
binding: FragmentWalletBinding,
|
||||
totalBalance: TotalFiatBalance?,
|
||||
walletsCount: Int,
|
||||
) = with(binding.lCardTotalBalance) {
|
||||
isVisible = walletsCount > 0
|
||||
|
||||
onChangeFiatCurrencyClick = {
|
||||
store.dispatch(WalletAction.AppCurrencyAction.ChooseAppCurrency)
|
||||
}
|
||||
status = totalBalance
|
||||
onChangeFiatCurrencyClick = {
|
||||
store.dispatch(WalletAction.AppCurrencyAction.ChooseAppCurrency)
|
||||
}
|
||||
status = totalBalance
|
||||
}
|
||||
|
||||
private fun handleErrorStates(state: WalletState, binding: FragmentWalletBinding, fragment: WalletFragment) {
|
||||
when (state.primaryWalletData?.currencyData?.status) {
|
||||
BalanceStatus.EmptyCard -> {
|
||||
showErrorState(
|
||||
binding,
|
||||
fragment.getText(R.string.wallet_error_empty_card),
|
||||
fragment.getString(R.string.wallet_error_empty_card_subtitle),
|
||||
)
|
||||
configureButtonsForEmptyWalletState(binding)
|
||||
}
|
||||
BalanceStatus.UnknownBlockchain -> {
|
||||
when (state.error) {
|
||||
ErrorType.UnknownBlockchain -> {
|
||||
showErrorState(
|
||||
binding,
|
||||
fragment.getText(R.string.wallet_error_unsupported_blockchain),
|
||||
fragment.getString(R.string.wallet_error_unsupported_blockchain_subtitle),
|
||||
)
|
||||
}
|
||||
else -> { /* no-op */
|
||||
}
|
||||
else -> { /* no-op */ }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -199,27 +191,8 @@ class MultiWalletView : WalletView() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun configureButtonsForEmptyWalletState(binding: FragmentWalletBinding) = with(binding) {
|
||||
rowButtons.btnBuy.hide()
|
||||
rowButtons.btnSell.hide()
|
||||
rowButtons.btnTrade.hide()
|
||||
rowButtons.show()
|
||||
|
||||
rowButtons.btnSend.text = fragment?.getText(R.string.wallet_button_create_wallet)
|
||||
rowButtons.onSendClick = { store.dispatch(WalletAction.CreateWallet) }
|
||||
}
|
||||
|
||||
override fun onDestroyFragment() {
|
||||
super.onDestroyFragment()
|
||||
watcher.clear()
|
||||
}
|
||||
}
|
||||
|
||||
private val WalletDetailsButtonsRow.btnBuy: Button
|
||||
get() = this.findViewById(R.id.btn_buy)
|
||||
private val WalletDetailsButtonsRow.btnSell: Button
|
||||
get() = this.findViewById(R.id.btn_sell)
|
||||
private val WalletDetailsButtonsRow.btnTrade: Button
|
||||
get() = this.findViewById(R.id.btn_trade)
|
||||
private val WalletDetailsButtonsRow.btnSend: Button
|
||||
get() = this.findViewById(R.id.btn_send)
|
||||
}
|
||||
|
|
@ -11,14 +11,19 @@ import com.tangem.tap.common.extensions.getQuantityString
|
|||
import com.tangem.tap.common.extensions.getString
|
||||
import com.tangem.tap.common.extensions.hide
|
||||
import com.tangem.tap.common.extensions.show
|
||||
import com.tangem.tap.domain.model.WalletDataModel
|
||||
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsState
|
||||
import com.tangem.tap.features.wallet.models.Currency
|
||||
import com.tangem.tap.features.wallet.models.PendingTransaction
|
||||
import com.tangem.tap.features.wallet.models.PendingTransactionType
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.features.wallet.redux.WalletData
|
||||
import com.tangem.tap.features.wallet.redux.WalletMainButton
|
||||
import com.tangem.tap.features.wallet.redux.WalletState
|
||||
import com.tangem.tap.features.wallet.ui.utils.getAvailableActions
|
||||
import com.tangem.tap.features.wallet.ui.utils.isAvailableToBuy
|
||||
import com.tangem.tap.features.wallet.ui.utils.isAvailableToSell
|
||||
import com.tangem.tap.features.wallet.ui.utils.mainButton
|
||||
import com.tangem.tap.features.wallet.ui.utils.shouldShowMultipleAddress
|
||||
import com.tangem.tap.features.wallet.ui.BalanceWidget
|
||||
import com.tangem.tap.features.wallet.ui.MultipleAddressUiHelper
|
||||
import com.tangem.tap.features.wallet.ui.WalletFragment
|
||||
|
|
@ -71,7 +76,7 @@ class SingleWalletView : WalletView() {
|
|||
setupTwinCards(state.twinCardsState, binding)
|
||||
setupButtons(primaryWalletData, binding, state.isExchangeServiceFeatureOn)
|
||||
setupAddressCard(state, binding)
|
||||
showPendingTransactionsIfPresent(primaryWalletData.pendingTransactions)
|
||||
showPendingTransactionsIfPresent(primaryWalletData.status.pendingTransactions)
|
||||
setupBalance(state, primaryWalletData)
|
||||
}
|
||||
|
||||
|
|
@ -83,32 +88,30 @@ class SingleWalletView : WalletView() {
|
|||
binding?.rvPendingTransaction?.show(knownTransactions.isNotEmpty())
|
||||
}
|
||||
|
||||
private fun setupBalance(state: WalletState, primaryWallet: WalletData) {
|
||||
private fun setupBalance(state: WalletState, primaryWallet: WalletDataModel) {
|
||||
val fragment = fragment ?: return
|
||||
binding?.apply {
|
||||
lCardBalance.lBalance.root.show()
|
||||
BalanceWidget(
|
||||
binding = this.lCardBalance,
|
||||
fragment = fragment,
|
||||
data = primaryWallet.currencyData,
|
||||
token = state.primaryTokenData?.currencyData,
|
||||
isTwinCard = state.isTangemTwins,
|
||||
blockchainWalletData = primaryWallet,
|
||||
tokenWalletData = state.primaryTokenData,
|
||||
).setup()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupTwinCards(twinCardsState: TwinCardsState?, binding: FragmentWalletBinding) = with(binding) {
|
||||
twinCardsState?.cardNumber?.let { cardNumber ->
|
||||
tvTwinCardNumber.show()
|
||||
tvTwinCardNumber.text = tvTwinCardNumber.getQuantityString(R.plurals.card_label_card_count, 2)
|
||||
}
|
||||
if (twinCardsState?.cardNumber == null) {
|
||||
tvTwinCardNumber.hide()
|
||||
} else {
|
||||
tvTwinCardNumber.show()
|
||||
tvTwinCardNumber.text = tvTwinCardNumber.getQuantityString(R.plurals.card_label_card_count, 2)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupButtons(
|
||||
walletData: WalletData,
|
||||
walletData: WalletDataModel,
|
||||
binding: FragmentWalletBinding,
|
||||
isExchangeServiceFeatureEnabled: Boolean,
|
||||
) = with(binding) {
|
||||
|
|
@ -134,7 +137,7 @@ class SingleWalletView : WalletView() {
|
|||
}
|
||||
|
||||
private fun setupRowButtons(
|
||||
walletData: WalletData,
|
||||
walletData: WalletDataModel,
|
||||
rowButtons: WalletDetailsButtonsRow,
|
||||
isExchangeServiceFeatureEnabled: Boolean,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -8,13 +8,15 @@ import com.tangem.tap.common.ShimmerData
|
|||
import com.tangem.tap.common.ShimmerRecyclerAdapter
|
||||
import com.tangem.tap.common.analytics.events.MainScreen
|
||||
import com.tangem.tap.common.extensions.animateVisibility
|
||||
import com.tangem.tap.common.extensions.formatAmountAsSpannedString
|
||||
import com.tangem.tap.common.extensions.hide
|
||||
import com.tangem.tap.common.extensions.show
|
||||
import com.tangem.tap.common.recyclerView.SpaceItemDecoration
|
||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.features.wallet.redux.WalletState
|
||||
import com.tangem.tap.features.wallet.ui.utils.getFormattedAmount
|
||||
import com.tangem.tap.features.wallet.ui.utils.getFormattedFiatAmount
|
||||
import com.tangem.tap.features.wallet.ui.utils.isAvailableToBuy
|
||||
import com.tangem.tap.features.wallet.ui.WalletFragment
|
||||
import com.tangem.tap.features.wallet.ui.wallet.WalletView
|
||||
import com.tangem.tap.features.wallet.ui.wallet.saltPay.rv.HistoryItemData
|
||||
|
|
@ -124,16 +126,14 @@ class SaltPayWalletView : WalletView() {
|
|||
tvUnreachable.animateVisibility(show = mainProgressState == ProgressState.Error)
|
||||
veilBalanceCrypto.animateVisibility(show = mainProgressState != ProgressState.Error)
|
||||
|
||||
if (tokenData.currencyData.fiatAmount == null) {
|
||||
if (tokenData.fiatRate == null) {
|
||||
veilBalance.veil()
|
||||
} else {
|
||||
veilBalance.unVeil()
|
||||
tvBalance.text = tokenData.currencyData.fiatAmount.formatAmountAsSpannedString(
|
||||
currencySymbol = appCurrency.symbol,
|
||||
)
|
||||
tvBalance.text = tokenData.getFormattedFiatAmount(appCurrency)
|
||||
}
|
||||
|
||||
tvBalanceCrypto.text = tokenData.currencyData.amountFormatted
|
||||
tvBalanceCrypto.text = tokenData.getFormattedAmount()
|
||||
|
||||
tvCurrencyName.text = appCurrency.code
|
||||
tvCurrencyName.setOnClickListener {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package com.tangem.tap.features.walletSelector.ui
|
|||
import com.tangem.tap.common.entities.FiatCurrency
|
||||
import com.tangem.tap.common.extensions.toFormattedFiatValue
|
||||
import com.tangem.tap.domain.model.TotalFiatBalance
|
||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN
|
||||
import com.tangem.tap.features.wallet.redux.utils.UNKNOWN_AMOUNT_SIGN
|
||||
import com.tangem.tap.features.walletSelector.redux.UserWalletModel
|
||||
import com.tangem.tap.features.walletSelector.ui.model.MultiCurrencyUserWalletItem
|
||||
import com.tangem.tap.features.walletSelector.ui.model.SingleCurrencyUserWalletItem
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue