Updated on 2026-08-14
This commit is contained in:
parent
b153993f3c
commit
5a20f6d533
22 changed files with 387 additions and 429 deletions
|
|
@ -210,6 +210,7 @@ fun View.animateVisibility(
|
|||
hiddenVisibility: Int = View.GONE,
|
||||
) {
|
||||
if (show) {
|
||||
if (this.visibility == View.VISIBLE) return
|
||||
this.animate()
|
||||
.alpha(1f)
|
||||
.setDuration(durationMillis)
|
||||
|
|
@ -218,6 +219,7 @@ fun View.animateVisibility(
|
|||
this.isVisible = true
|
||||
}
|
||||
} else {
|
||||
if (this.visibility == hiddenVisibility) return
|
||||
this.animate()
|
||||
.alpha(0f)
|
||||
.setDuration(durationMillis)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.tap.domain
|
||||
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.BlockchainSdkConfig
|
||||
import com.tangem.blockchain.common.Token
|
||||
|
|
@ -39,6 +40,7 @@ import com.tangem.tap.userTokensRepository
|
|||
import com.tangem.tap.walletStoresManager
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.rekotlin.Action
|
||||
import timber.log.Timber
|
||||
|
||||
class TapWalletManager {
|
||||
|
|
@ -223,20 +225,20 @@ class TapWalletManager {
|
|||
val primaryWalletManager = walletManagerFactory.makePrimaryWalletManager(data)
|
||||
|
||||
if (blockchain != Blockchain.Unknown && primaryWalletManager != null) {
|
||||
val primaryToken = data.getPrimaryToken()
|
||||
|
||||
dispatchOnMain(WalletAction.MultiWallet.SetPrimaryBlockchain(blockchain))
|
||||
if (primaryToken != null) {
|
||||
primaryWalletManager.addToken(primaryToken)
|
||||
dispatchOnMain(WalletAction.MultiWallet.SetPrimaryToken(primaryToken))
|
||||
}
|
||||
dispatchOnMain(
|
||||
val blockchainNetwork = BlockchainNetwork.fromWalletManager(primaryWalletManager)
|
||||
val actionsList = listOfNotNull<Action>(
|
||||
WalletAction.MultiWallet.AddBlockchains(
|
||||
blockchains = listOf(BlockchainNetwork.fromWalletManager(primaryWalletManager)),
|
||||
walletManagers = listOf(primaryWalletManager),
|
||||
),
|
||||
data.getPrimaryToken()?.let {
|
||||
primaryWalletManager.addToken(it)
|
||||
primaryWalletManager.wallet.setAmount(Amount(it))
|
||||
WalletAction.MultiWallet.AddToken(it, blockchainNetwork, false)
|
||||
},
|
||||
WalletAction.LoadFiatRate(),
|
||||
)
|
||||
dispatchOnMain(*actionsList.toTypedArray())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package com.tangem.tap.features.wallet.redux
|
|||
|
||||
import android.content.Context
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.Token
|
||||
import com.tangem.blockchain.common.Wallet
|
||||
import com.tangem.blockchain.common.WalletManager
|
||||
|
|
@ -98,8 +97,6 @@ sealed class WalletAction : Action {
|
|||
data class RemoveWallet(val currency: Currency) : MultiWallet()
|
||||
data class RemoveWallets(val currencies: List<Currency>) : MultiWallet()
|
||||
|
||||
data class SetPrimaryBlockchain(val blockchain: Blockchain) : MultiWallet()
|
||||
data class SetPrimaryToken(val token: Token) : MultiWallet()
|
||||
data class ShowWalletBackupWarning(val show: Boolean) : MultiWallet()
|
||||
object BackupWallet : MultiWallet()
|
||||
object ScheduleCheckForMissingDerivation : MultiWallet()
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.tangem.tap.common.extensions.toQrCode
|
|||
import com.tangem.tap.common.redux.global.CryptoCurrencyName
|
||||
import com.tangem.tap.common.toggleWidget.WidgetState
|
||||
import com.tangem.tap.domain.configurable.warningMessage.WarningMessage
|
||||
import com.tangem.tap.domain.getFirstToken
|
||||
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
|
||||
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsState
|
||||
import com.tangem.tap.features.wallet.models.Currency
|
||||
|
|
@ -43,8 +44,6 @@ data class WalletState(
|
|||
val isMultiwalletAllowed: Boolean = false,
|
||||
val cardCurrency: CryptoCurrencyName? = null,
|
||||
val selectedCurrency: Currency? = null,
|
||||
val primaryBlockchain: Blockchain? = null,
|
||||
val primaryToken: Token? = null,
|
||||
val isTestnet: Boolean = false,
|
||||
val totalBalance: TotalBalance? = null,
|
||||
val showBackupWarning: Boolean = false,
|
||||
|
|
@ -81,13 +80,30 @@ data class WalletState(
|
|||
val walletManagers: List<WalletManager>
|
||||
get() = walletsStores.mapNotNull { it.walletManager }
|
||||
|
||||
val primaryWallet: WalletData? = walletsStores.firstOrNull()?.walletsData?.firstOrNull()
|
||||
private val primaryWalletStore: WalletStore?
|
||||
get() = if (isMultiwalletAllowed || walletsStores.isEmpty() || walletsStores.size > 1) null
|
||||
else walletsStores[0]
|
||||
|
||||
val primaryWalletManager: WalletManager? = if (walletsStores.isNotEmpty()) walletsStores[0].walletManager else null
|
||||
private val primaryWalletManager: WalletManager?
|
||||
get() = primaryWalletStore?.walletManager
|
||||
|
||||
val primaryWalletData: WalletData?
|
||||
get() = primaryWalletStore?.walletsData?.firstOrNull()
|
||||
|
||||
val primaryBlockchain: Blockchain?
|
||||
get() = primaryWalletManager?.wallet?.blockchain
|
||||
|
||||
val primaryToken: Token?
|
||||
get() = primaryWalletManager?.wallet?.getFirstToken()
|
||||
|
||||
val primaryTokenData: WalletData?
|
||||
get() = primaryWalletStore?.walletsData?.toMutableList()
|
||||
?.apply { remove(primaryWalletData) }
|
||||
?.firstOrNull()
|
||||
|
||||
val shouldShowDetails: Boolean =
|
||||
primaryWallet?.currencyData?.status != BalanceStatus.EmptyCard &&
|
||||
primaryWallet?.currencyData?.status != BalanceStatus.UnknownBlockchain
|
||||
primaryWalletData?.currencyData?.status != BalanceStatus.EmptyCard &&
|
||||
primaryWalletData?.currencyData?.status != BalanceStatus.UnknownBlockchain
|
||||
|
||||
val hasSavedWallets: Boolean
|
||||
get() = userWalletsListManager.hasSavedUserWallets
|
||||
|
|
@ -138,13 +154,6 @@ data class WalletState(
|
|||
return getWalletStore(currency)?.walletsData?.firstOrNull { it.currency == currency }
|
||||
}
|
||||
|
||||
private fun isPrimaryCurrency(walletData: WalletData): Boolean {
|
||||
return (walletData.currency is Currency.Blockchain &&
|
||||
walletData.currency.blockchain == store.state.walletState.primaryBlockchain)
|
||||
|| (walletData.currency is Currency.Token &&
|
||||
walletData.currency.token == store.state.walletState.primaryToken)
|
||||
}
|
||||
|
||||
fun replaceWalletStoreInWalletsStores(wallet: WalletStore?): List<WalletStore> {
|
||||
if (wallet == null) return walletsStores
|
||||
var changed = false
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.tangem.tap.features.wallet.redux.middlewares
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.tap.common.extensions.stripZeroPlainString
|
||||
import com.tangem.tap.common.extensions.toFiatRateString
|
||||
|
|
@ -19,7 +18,6 @@ import com.tangem.tap.features.wallet.redux.WalletMainButton
|
|||
import com.tangem.tap.features.wallet.redux.WalletStore
|
||||
import com.tangem.tap.features.wallet.ui.BalanceStatus
|
||||
import com.tangem.tap.features.wallet.ui.BalanceWidgetData
|
||||
import com.tangem.tap.features.wallet.ui.TokenData
|
||||
import com.tangem.tap.store
|
||||
import java.math.BigDecimal
|
||||
|
||||
|
|
@ -49,15 +47,6 @@ internal fun WalletStoreModel.mapToReduxModel(): WalletStore {
|
|||
walletsData = walletsData.mapToReduxModels(walletRent, appCurrencySymbol),
|
||||
)
|
||||
.updateTokenModels(blockchainWalletData.status.amount)
|
||||
.setupIfHadCardSingleToken(
|
||||
blockchain = blockchain,
|
||||
walletsDataModel = walletsData,
|
||||
appCurrencySymbol = appCurrencySymbol,
|
||||
blockchainWalletData = blockchainWalletData.mapToReduxModel(
|
||||
walletRent = walletRent,
|
||||
appCurrencySymbol = appCurrencySymbol,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun List<WalletDataModel>.mapToReduxModels(
|
||||
|
|
@ -122,7 +111,7 @@ private fun WalletDataModel.mapToReduxModel(
|
|||
amountFormatted = amountFormatted,
|
||||
fiatAmount = fiatAmount,
|
||||
fiatAmountFormatted = fiatAmountFormatted,
|
||||
token = null,
|
||||
// token = null,
|
||||
amountToCreateAccount = (status as? WalletDataModel.NoAccount)
|
||||
?.amountToCreateAccount
|
||||
?.toString(),
|
||||
|
|
@ -146,45 +135,4 @@ private fun WalletStore.updateTokenModels(blockchainAmount: BigDecimal): WalletS
|
|||
)
|
||||
}
|
||||
return updateWallets(updatedTokensWalletData)
|
||||
}
|
||||
|
||||
private fun WalletStore.setupIfHadCardSingleToken(
|
||||
blockchain: Blockchain,
|
||||
walletsDataModel: List<WalletDataModel>,
|
||||
appCurrencySymbol: String,
|
||||
blockchainWalletData: WalletData,
|
||||
): WalletStore {
|
||||
// Card with single token contains only 2 model - blockchain and token
|
||||
if (walletsData.size != 2) return this
|
||||
|
||||
val cardSingleTokenWalletData = walletsDataModel.firstOrNull {
|
||||
it.currency.isToken() && it.currency.blockchain == blockchain && it.isCardSingleToken
|
||||
} ?: return this
|
||||
|
||||
val blockchainWalletDataWithSingleToken = blockchainWalletData.copy(
|
||||
currencyData = blockchainWalletData.currencyData.copy(
|
||||
token = cardSingleTokenWalletData.toTokenData(appCurrencySymbol),
|
||||
),
|
||||
)
|
||||
return updateWallets(listOf(blockchainWalletDataWithSingleToken))
|
||||
}
|
||||
|
||||
private fun WalletDataModel.toTokenData(appCurrencySymbol: String): TokenData {
|
||||
val amount = status.amount
|
||||
val fiatAmount = fiatRate?.let { status.amount.toFiatValue(it) }
|
||||
|
||||
return TokenData(
|
||||
amount = amount,
|
||||
amountFormatted = amount.toFormattedCurrencyString(
|
||||
decimals = currency.decimals,
|
||||
currency = currency.currencySymbol,
|
||||
),
|
||||
fiatAmount = fiatAmount,
|
||||
fiatAmountFormatted = fiatAmount
|
||||
?.takeIf { !status.isErrorStatus }
|
||||
?.toFormattedFiatValue(appCurrencySymbol),
|
||||
tokenSymbol = currency.currencySymbol,
|
||||
fiatRate = fiatRate,
|
||||
fiatRateString = fiatRate?.toFiatRateString(appCurrencySymbol),
|
||||
)
|
||||
}
|
||||
|
|
@ -49,6 +49,7 @@ 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.WalletStore
|
||||
import com.tangem.tap.features.wallet.redux.reducers.findSelectedCurrency
|
||||
import com.tangem.tap.network.NetworkConnectivity
|
||||
import com.tangem.tap.network.NetworkStateChanged
|
||||
import com.tangem.tap.preferencesStorage
|
||||
|
|
@ -153,7 +154,7 @@ class WalletMiddleware {
|
|||
if (walletState.isMultiwalletAllowed) {
|
||||
walletState.walletsDataFromStores.map { it.currency }
|
||||
} else {
|
||||
val derivationPath = walletState.primaryWallet?.currency?.derivationPath
|
||||
val derivationPath = walletState.primaryWalletData?.currency?.derivationPath
|
||||
val primaryBlockchain = walletState.primaryBlockchain
|
||||
val primaryToken = walletState.primaryToken
|
||||
listOfNotNull(
|
||||
|
|
@ -310,15 +311,14 @@ class WalletMiddleware {
|
|||
}
|
||||
}
|
||||
|
||||
private fun updateWalletStores(wallStores: List<WalletStoreModel>, state: WalletState) {
|
||||
private fun updateWalletStores(walletsStores: List<WalletStoreModel>, state: WalletState) {
|
||||
scope.launch(Dispatchers.Default) {
|
||||
val reduxWalletStores = walletsStores.mapToReduxModels()
|
||||
if (!state.isMultiwalletAllowed) {
|
||||
wallStores.firstOrNull()?.walletsData?.firstOrNull()?.let {
|
||||
store.dispatchOnMain(WalletAction.MultiWallet.SetSingleWalletCurrency(it.currency))
|
||||
findSelectedCurrency(reduxWalletStores, null, false)?.let {
|
||||
store.dispatchOnMain(WalletAction.MultiWallet.SetSingleWalletCurrency(it))
|
||||
}
|
||||
}
|
||||
|
||||
val reduxWalletStores = wallStores.mapToReduxModels()
|
||||
store.dispatchOnMain(
|
||||
WalletAction.WalletStoresChanged.UpdateWalletStores(
|
||||
reduxWalletStores = reduxWalletStores,
|
||||
|
|
@ -438,11 +438,7 @@ class WalletMiddleware {
|
|||
walletStore: WalletStore?,
|
||||
): PrepareSendScreen {
|
||||
val coinRate = state?.getWalletData(walletStore?.blockchainNetwork)?.fiatRate
|
||||
val tokenRate = if (state?.isMultiwalletAllowed == true) {
|
||||
selectedWalletData?.fiatRate
|
||||
} else {
|
||||
selectedWalletData?.currencyData?.token?.fiatRate
|
||||
}
|
||||
val tokenRate = selectedWalletData?.fiatRate
|
||||
val coinAmount = walletStore?.walletManager?.wallet?.amounts?.get(AmountType.Coin)
|
||||
|
||||
return PrepareSendScreen(
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import com.tangem.tap.common.extensions.toFiatString
|
|||
import com.tangem.tap.common.extensions.toFormattedCurrencyString
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.domain.getFirstToken
|
||||
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
|
||||
import com.tangem.tap.features.wallet.models.Currency
|
||||
import com.tangem.tap.features.wallet.models.WalletRent
|
||||
|
|
@ -26,7 +25,6 @@ import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT
|
|||
import com.tangem.tap.features.wallet.redux.WalletStore
|
||||
import com.tangem.tap.features.wallet.ui.BalanceStatus
|
||||
import com.tangem.tap.features.wallet.ui.BalanceWidgetData
|
||||
import com.tangem.tap.features.wallet.ui.TokenData
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.tap.userWalletsListManager
|
||||
import com.tangem.wallet.R
|
||||
|
|
@ -42,17 +40,11 @@ class MultiWalletReducer {
|
|||
(it.wallet.publicKey.derivationPath?.rawPath == blockchain.derivationPath)
|
||||
}
|
||||
val wallet = walletManager?.wallet
|
||||
val cardToken = if (!state.isMultiwalletAllowed) {
|
||||
wallet?.getFirstToken()?.symbol?.let { TokenData("", tokenSymbol = it) }
|
||||
} else {
|
||||
null
|
||||
}
|
||||
val walletData = WalletData(
|
||||
currencyData = BalanceWidgetData(
|
||||
status = BalanceStatus.Loading,
|
||||
currency = blockchain.blockchain.fullName,
|
||||
currencySymbol = blockchain.blockchain.currency,
|
||||
token = cardToken,
|
||||
),
|
||||
walletAddresses = createAddressList(wallet),
|
||||
mainButton = WalletMainButton.SendButton(false),
|
||||
|
|
@ -66,18 +58,17 @@ class MultiWalletReducer {
|
|||
WalletStore(
|
||||
walletManager = walletManager,
|
||||
blockchainNetwork = blockchain,
|
||||
walletsData = listOf(walletData),
|
||||
walletsData = listOfNotNull(walletData),
|
||||
)
|
||||
}
|
||||
|
||||
val selectedCurrency = if (state.isMultiwalletAllowed) {
|
||||
state.selectedCurrency
|
||||
} else {
|
||||
walletStores.firstOrNull()?.walletsData?.firstOrNull()?.currency
|
||||
}
|
||||
state.copy(
|
||||
walletsStores = walletStores,
|
||||
selectedCurrency = selectedCurrency,
|
||||
selectedCurrency = findSelectedCurrency(
|
||||
walletsStores = walletStores,
|
||||
currentSelectedCurrency = state.selectedCurrency,
|
||||
isMultiWalletAllowed = state.isMultiwalletAllowed,
|
||||
),
|
||||
)
|
||||
}
|
||||
is WalletAction.MultiWallet.AddBlockchain -> {
|
||||
|
|
@ -181,8 +172,6 @@ class MultiWalletReducer {
|
|||
action.currencies.forEach { updatedState = updatedState.removeWalletData(state.getWalletData(it)) }
|
||||
updatedState
|
||||
}
|
||||
is WalletAction.MultiWallet.SetPrimaryBlockchain -> state.copy(primaryBlockchain = action.blockchain)
|
||||
is WalletAction.MultiWallet.SetPrimaryToken -> state.copy(primaryToken = action.token)
|
||||
is WalletAction.MultiWallet.SaveCurrencies -> state
|
||||
is WalletAction.MultiWallet.ShowWalletBackupWarning -> state.copy(showBackupWarning = action.show)
|
||||
is WalletAction.MultiWallet.ScheduleCheckForMissingDerivation -> state.copy(
|
||||
|
|
@ -190,7 +179,7 @@ class MultiWalletReducer {
|
|||
)
|
||||
is WalletAction.MultiWallet.AddMissingDerivations -> state.copy(
|
||||
missingDerivations = action.blockchains,
|
||||
derivationsCheckIsScheduled = false
|
||||
derivationsCheckIsScheduled = false,
|
||||
)
|
||||
is WalletAction.MultiWallet.BackupWallet -> state
|
||||
is WalletAction.MultiWallet.ScanToGetDerivations -> state.copy(state = ProgressState.Loading)
|
||||
|
|
@ -212,7 +201,6 @@ class MultiWalletReducer {
|
|||
}
|
||||
|
||||
fun Token.toWallet(state: WalletState, blockchain: BlockchainNetwork): WalletData? {
|
||||
if (!state.isMultiwalletAllowed) return null
|
||||
val currency = Currency.fromBlockchainNetwork(blockchain, this)
|
||||
if (state.currencies.contains(currency)) return null
|
||||
|
||||
|
|
|
|||
|
|
@ -3,11 +3,9 @@ package com.tangem.tap.features.wallet.redux.reducers
|
|||
import com.tangem.blockchain.common.AmountType
|
||||
import com.tangem.blockchain.common.Wallet
|
||||
import com.tangem.common.extensions.isZero
|
||||
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.domain.getFirstToken
|
||||
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
|
||||
import com.tangem.tap.features.wallet.models.Currency
|
||||
import com.tangem.tap.features.wallet.models.filterByToken
|
||||
|
|
@ -20,9 +18,7 @@ import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT
|
|||
import com.tangem.tap.features.wallet.redux.replaceSomeWalletsData
|
||||
import com.tangem.tap.features.wallet.ui.BalanceStatus
|
||||
import com.tangem.tap.features.wallet.ui.BalanceWidgetData
|
||||
import com.tangem.tap.features.wallet.ui.TokenData
|
||||
import com.tangem.tap.store
|
||||
import java.math.BigDecimal
|
||||
|
||||
class OnWalletLoadedReducer {
|
||||
|
||||
|
|
@ -37,7 +33,7 @@ class OnWalletLoadedReducer {
|
|||
private fun onMultiWalletLoaded(
|
||||
wallet: Wallet,
|
||||
blockchainNetwork: BlockchainNetwork,
|
||||
walletState: WalletState
|
||||
walletState: WalletState,
|
||||
): WalletState {
|
||||
val walletData = walletState.getWalletData(blockchainNetwork) ?: return walletState
|
||||
|
||||
|
|
@ -45,7 +41,7 @@ class OnWalletLoadedReducer {
|
|||
val coinAmountValue = wallet.amounts[AmountType.Coin]?.value
|
||||
val formattedAmount = coinAmountValue?.toFormattedCurrencyString(
|
||||
wallet.blockchain.decimals(),
|
||||
wallet.blockchain.currency
|
||||
wallet.blockchain.currency,
|
||||
)
|
||||
|
||||
val pendingTransactions = wallet.getPendingTransactions()
|
||||
|
|
@ -98,7 +94,7 @@ class OnWalletLoadedReducer {
|
|||
amount = tokenAmountValue,
|
||||
amountFormatted = tokenAmountValue?.toFormattedCurrencyString(
|
||||
token.decimals,
|
||||
token.symbol
|
||||
token.symbol,
|
||||
),
|
||||
fiatAmount = tokenFiatAmount,
|
||||
fiatAmountFormatted = tokenFiatAmountFormatted,
|
||||
|
|
@ -117,33 +113,12 @@ class OnWalletLoadedReducer {
|
|||
if (wallet.blockchain != walletState.primaryBlockchain) return walletState
|
||||
|
||||
val fiatCurrencyName = store.state.globalState.appCurrency.code
|
||||
val token = wallet.getFirstToken()
|
||||
val tokenData = if (token != null) {
|
||||
val tokenAmount = wallet.getTokenAmount(token)
|
||||
if (tokenAmount != null) {
|
||||
val tokenFiatRate = walletState.primaryWallet?.currencyData?.token?.fiatRate
|
||||
val tokenFiatAmount =
|
||||
tokenFiatRate?.let { tokenAmount.value?.toFiatString(it, fiatCurrencyName) }
|
||||
TokenData(
|
||||
amount = tokenAmount.value ?: BigDecimal.ZERO,
|
||||
tokenSymbol = tokenAmount.currencySymbol, fiatAmountFormatted = tokenFiatAmount,
|
||||
fiatAmount = tokenFiatRate?.let { tokenAmount.value?.toFiatValue(tokenFiatRate) },
|
||||
amountFormatted = tokenAmount.value?.toFormattedCurrencyString(
|
||||
token.decimals, token.symbol,
|
||||
) ?: "",
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
val amount = wallet.amounts[AmountType.Coin]?.value
|
||||
val formattedAmount = amount?.toFormattedCurrencyString(
|
||||
wallet.blockchain.decimals(),
|
||||
wallet.blockchain.currency
|
||||
wallet.blockchain.currency,
|
||||
)
|
||||
val fiatAmount = walletState.primaryWallet?.fiatRate?.let { amount?.toFiatValue(it) }
|
||||
val fiatAmount = walletState.primaryWalletData?.fiatRate?.let { amount?.toFiatValue(it) }
|
||||
val fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(fiatCurrencyName) ?: UNKNOWN_AMOUNT_SIGN
|
||||
|
||||
val pendingTransactions = wallet.getPendingTransactions()
|
||||
|
|
@ -153,16 +128,15 @@ class OnWalletLoadedReducer {
|
|||
} else {
|
||||
BalanceStatus.VerifiedOnline
|
||||
}
|
||||
val walletData = walletState.primaryWallet?.copy(
|
||||
val walletData = walletState.primaryWalletData?.copy(
|
||||
currencyData = BalanceWidgetData(
|
||||
balanceStatus, wallet.blockchain.fullName,
|
||||
currencySymbol = wallet.blockchain.currency,
|
||||
token = tokenData,
|
||||
blockchainAmount = amount,
|
||||
amount = amount,
|
||||
amountFormatted = formattedAmount,
|
||||
fiatAmount = fiatAmount,
|
||||
fiatAmountFormatted = fiatAmountFormatted
|
||||
fiatAmountFormatted = fiatAmountFormatted,
|
||||
),
|
||||
pendingTransactions = pendingTransactions.removeUnknownTransactions(),
|
||||
mainButton = WalletMainButton.SendButton(sendButtonEnabled),
|
||||
|
|
@ -171,7 +145,8 @@ class OnWalletLoadedReducer {
|
|||
val updatedStore = walletState.getWalletStore(walletData?.currency)?.updateWallets(wallets)
|
||||
|
||||
return walletState.updateWalletStore(updatedStore).copy(
|
||||
state = ProgressState.Done, error = null
|
||||
state = ProgressState.Done,
|
||||
error = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,6 @@ import com.tangem.domain.common.TapWorkarounds.isTestCard
|
|||
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
|
||||
|
|
@ -17,7 +16,6 @@ import com.tangem.tap.common.redux.AppState
|
|||
import com.tangem.tap.domain.TapError
|
||||
import com.tangem.tap.domain.extensions.getArtworkUrl
|
||||
import com.tangem.tap.domain.extensions.isMultiwalletAllowed
|
||||
import com.tangem.tap.domain.getFirstToken
|
||||
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
|
||||
import com.tangem.tap.features.wallet.models.Currency
|
||||
import com.tangem.tap.features.wallet.models.WalletRent
|
||||
|
|
@ -36,7 +34,6 @@ import com.tangem.tap.features.wallet.ui.BalanceStatus
|
|||
import com.tangem.tap.features.wallet.ui.BalanceWidgetData
|
||||
import com.tangem.tap.proxy.AppStateHolder
|
||||
import org.rekotlin.Action
|
||||
import timber.log.Timber
|
||||
import java.math.BigDecimal
|
||||
|
||||
class WalletReducer {
|
||||
|
|
@ -285,8 +282,9 @@ private fun internalReduce(action: Action, state: AppState, appStateHolder: AppS
|
|||
newState = newState.copy(cardImage = cardImage)
|
||||
}
|
||||
|
||||
is WalletAction.LoadFiatRate.Success ->
|
||||
is WalletAction.LoadFiatRate.Success -> {
|
||||
newState = setNewFiatRate(action.fiatRates, state.globalState.appCurrency, newState)
|
||||
}
|
||||
is WalletAction.LoadArtwork -> {
|
||||
val artworkUrl = action.card.getArtworkUrl(action.artworkId)
|
||||
?: when (state.twinCardsState.cardNumber) {
|
||||
|
|
@ -361,18 +359,13 @@ private fun internalReduce(action: Action, state: AppState, appStateHolder: AppS
|
|||
)
|
||||
}
|
||||
is WalletAction.LoadData.Success -> {
|
||||
val selectedCurrency = if (newState.isMultiwalletAllowed) {
|
||||
newState.selectedCurrency
|
||||
} else {
|
||||
newState.walletsStores.firstOrNull()
|
||||
?.walletsData
|
||||
?.firstOrNull()
|
||||
?.currency
|
||||
}
|
||||
|
||||
newState = newState.copy(
|
||||
state = ProgressState.Done,
|
||||
selectedCurrency = selectedCurrency,
|
||||
selectedCurrency = findSelectedCurrency(
|
||||
walletsStores = newState.walletsStores,
|
||||
currentSelectedCurrency = newState.selectedCurrency,
|
||||
isMultiWalletAllowed = newState.isMultiwalletAllowed,
|
||||
),
|
||||
)
|
||||
}
|
||||
else -> Unit
|
||||
|
|
@ -381,6 +374,19 @@ private fun internalReduce(action: Action, state: AppState, appStateHolder: AppS
|
|||
return newState
|
||||
}
|
||||
|
||||
fun findSelectedCurrency(
|
||||
walletsStores: List<WalletStore>,
|
||||
currentSelectedCurrency: Currency?,
|
||||
isMultiWalletAllowed: Boolean,
|
||||
): Currency? = if (isMultiWalletAllowed) {
|
||||
currentSelectedCurrency
|
||||
} else {
|
||||
walletsStores.firstOrNull()
|
||||
?.walletsData
|
||||
?.firstOrNull()
|
||||
?.currency
|
||||
}
|
||||
|
||||
private fun CardDTO.findCardsCount(): Int? {
|
||||
return (this.backupStatus as? CardDTO.BackupStatus.Active)?.cardCount?.inc()
|
||||
?.takeIf { this.isMultiwalletAllowed }
|
||||
|
|
@ -439,45 +445,18 @@ private fun setNewFiatRate(
|
|||
state: WalletState,
|
||||
): WalletState {
|
||||
val rateFormatter: (BigDecimal) -> String = { rate: BigDecimal ->
|
||||
rate.toFiatRateString(
|
||||
fiatCurrencyName = appCurrency.symbol,
|
||||
)
|
||||
rate.toFiatRateString(fiatCurrencyName = appCurrency.symbol)
|
||||
}
|
||||
|
||||
return if (state.isMultiwalletAllowed) {
|
||||
setMultiWalletFiatRate(
|
||||
fiatRates = fiatRates.mapNotNullValues { it.value },
|
||||
rateFormatter = rateFormatter,
|
||||
appCurrency = appCurrency,
|
||||
state = state,
|
||||
)
|
||||
} else {
|
||||
setSingleWalletFiatRates(
|
||||
fiatRates = fiatRates.mapNotNullValues { it.value },
|
||||
rateFormatter = rateFormatter,
|
||||
appCurrency = appCurrency,
|
||||
state = state,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setMultiWalletFiatRate(
|
||||
fiatRates: Map<Currency, BigDecimal>,
|
||||
rateFormatter: (BigDecimal) -> String,
|
||||
appCurrency: FiatCurrency,
|
||||
state: WalletState,
|
||||
): WalletState {
|
||||
val newWalletsData = fiatRates.mapNotNull { (currency, rate) ->
|
||||
val newWalletsData = fiatRates.mapNotNullValues { it.value }.mapNotNull { (currency, rate) ->
|
||||
val walletStore = state.getWalletStore(currency) ?: return@mapNotNull null
|
||||
val wallet = walletStore.walletManager?.wallet
|
||||
val walletData = state.getWalletData(currency) ?: return@mapNotNull null
|
||||
val currencyData = walletData.currencyData
|
||||
|
||||
var fiatAmount = when (currency) {
|
||||
is Currency.Blockchain ->
|
||||
wallet?.amounts?.get(AmountType.Coin)?.value?.toFiatValue(rate)
|
||||
is Currency.Token ->
|
||||
wallet?.getTokenAmount(currency.token)?.value?.toFiatValue(rate)
|
||||
is Currency.Blockchain -> wallet?.amounts?.get(AmountType.Coin)?.value?.toFiatValue(rate)
|
||||
is Currency.Token -> wallet?.getTokenAmount(currency.token)?.value?.toFiatValue(rate)
|
||||
}
|
||||
if (currencyData.status == BalanceStatus.NoAccount && fiatAmount == null) {
|
||||
fiatAmount = BigDecimal.ZERO.setScale(2)
|
||||
|
|
@ -494,96 +473,5 @@ private fun setMultiWalletFiatRate(
|
|||
)
|
||||
}
|
||||
|
||||
return state
|
||||
.updateWalletsData(newWalletsData)
|
||||
}
|
||||
|
||||
private fun setSingleWalletFiatRates(
|
||||
fiatRates: Map<Currency, BigDecimal>,
|
||||
appCurrency: FiatCurrency,
|
||||
rateFormatter: (BigDecimal) -> String,
|
||||
state: WalletState,
|
||||
): WalletState {
|
||||
val blockchainFiatRate = fiatRates.entries.firstOrNull { it.key.isBlockchain() }
|
||||
val tokenFiatRate = fiatRates.entries.firstOrNull { it.key.isToken() }
|
||||
Timber.e("Token Fiat Rate is ${tokenFiatRate ?: "NULL"}")
|
||||
val updatedState = updateStateWithFiatRate(blockchainFiatRate?.toPair(), appCurrency, rateFormatter, state)
|
||||
return updateStateWithFiatRate(tokenFiatRate?.toPair(), appCurrency, rateFormatter, updatedState)
|
||||
}
|
||||
|
||||
private fun updateStateWithFiatRate(
|
||||
fiatRate: Pair<Currency, BigDecimal>?,
|
||||
appCurrency: FiatCurrency,
|
||||
rateFormatter: (BigDecimal) -> String,
|
||||
state: WalletState,
|
||||
): WalletState {
|
||||
return if (fiatRate != null) {
|
||||
val currency = fiatRate.first
|
||||
val rate = fiatRate.second
|
||||
|
||||
setSingleWalletFiatRate(
|
||||
rate = rate,
|
||||
rateFormatted = rateFormatter(rate),
|
||||
currency = currency,
|
||||
appCurrency = appCurrency,
|
||||
state = state,
|
||||
)
|
||||
} else {
|
||||
state
|
||||
}
|
||||
}
|
||||
|
||||
private fun setSingleWalletFiatRate(
|
||||
rate: BigDecimal,
|
||||
rateFormatted: String,
|
||||
currency: Currency,
|
||||
appCurrency: FiatCurrency,
|
||||
state: WalletState,
|
||||
): WalletState {
|
||||
val wallet = state.primaryWalletManager?.wallet ?: return state
|
||||
val token = wallet.getFirstToken()
|
||||
Timber.e("Working with currency: ${currency.currencyName}")
|
||||
|
||||
if (currency == state.primaryWallet?.currency) {
|
||||
val fiatAmount = wallet.amounts[AmountType.Coin]?.value
|
||||
?.toFiatString(rate, appCurrency.code)
|
||||
val walletData = state.primaryWallet.copy(
|
||||
currencyData = state.primaryWallet.currencyData.copy(fiatAmountFormatted = fiatAmount),
|
||||
fiatRate = rate,
|
||||
fiatRateString = rateFormatted,
|
||||
)
|
||||
return state.updateWalletData(walletData)
|
||||
} else if (currency is Currency.Token && currency.token == token) {
|
||||
Timber.e("Working with token fiat rate")
|
||||
|
||||
val tokenFiatAmount = wallet.getTokenAmount(token)
|
||||
?.value
|
||||
val tokenAmountFormatted = tokenFiatAmount?.toFiatString(rate, appCurrency.code)
|
||||
|
||||
val tokenData = state.primaryWallet?.currencyData?.token?.copy(
|
||||
fiatAmountFormatted = tokenAmountFormatted,
|
||||
fiatAmount = tokenFiatAmount,
|
||||
fiatRate = rate,
|
||||
fiatRateString = rateFormatted,
|
||||
)
|
||||
// ?: TokenData(
|
||||
// fiatAmountFormatted = tokenAmountFormatted,
|
||||
// fiatAmount = tokenFiatAmount,
|
||||
// fiatRate = rate,
|
||||
// fiatRateString = rateFormatted,
|
||||
// amount = "",
|
||||
// tokenSymbol = currency.currencySymbol
|
||||
// )
|
||||
|
||||
Timber.e("Token Data is ${tokenData ?: "NULL"}")
|
||||
|
||||
val walletData = state.primaryWallet?.copy(
|
||||
currencyData = state.primaryWallet.currencyData.copy(
|
||||
token = tokenData,
|
||||
),
|
||||
)
|
||||
Timber.e("Wallet Data is ${walletData ?: "NULL"}")
|
||||
return state.updateWalletData(walletData)
|
||||
}
|
||||
return state
|
||||
return state.updateWalletsData(newWalletsData)
|
||||
}
|
||||
|
|
@ -24,31 +24,20 @@ data class BalanceWidgetData(
|
|||
val status: BalanceStatus? = null,
|
||||
val currency: String? = null,
|
||||
val currencySymbol: String? = null,
|
||||
val blockchainAmount: BigDecimal? = BigDecimal.ZERO,
|
||||
val amount: BigDecimal? = null,
|
||||
val amountFormatted: String? = null,
|
||||
val fiatAmount: BigDecimal? = null,
|
||||
val fiatAmountFormatted: String? = null,
|
||||
val token: TokenData? = null,
|
||||
val blockchainAmount: BigDecimal? = BigDecimal.ZERO,
|
||||
val amountToCreateAccount: String? = null,
|
||||
val errorMessage: String? = null
|
||||
val errorMessage: String? = null,
|
||||
)
|
||||
|
||||
data class TokenData(
|
||||
val amountFormatted: String?,
|
||||
val amount: BigDecimal? = null,
|
||||
val tokenSymbol: String,
|
||||
val fiatAmountFormatted: String? = null,
|
||||
val fiatAmount: BigDecimal? = null,
|
||||
val fiatRateString: String? = null,
|
||||
val fiatRate: BigDecimal? = null,
|
||||
)
|
||||
|
||||
|
||||
class BalanceWidget(
|
||||
private val binding: CardBalanceBinding,
|
||||
private val fragment: WalletFragment,
|
||||
private val data: BalanceWidgetData,
|
||||
private val token: BalanceWidgetData?,
|
||||
private val isTwinCard: Boolean,
|
||||
) {
|
||||
|
||||
|
|
@ -68,7 +57,7 @@ class BalanceWidget(
|
|||
|
||||
showStatus(R.id.tv_status_loading)
|
||||
|
||||
if (data.token != null) {
|
||||
if (token != null) {
|
||||
showBalanceWithToken(data, false)
|
||||
} else {
|
||||
showBalanceWithoutToken(data, false)
|
||||
|
|
@ -87,7 +76,7 @@ class BalanceWidget(
|
|||
showStatus(statusView)
|
||||
tvStatusErrorMessage.hide()
|
||||
|
||||
if (data.token != null) {
|
||||
if (token != null) {
|
||||
showBalanceWithToken(data, true)
|
||||
} else {
|
||||
showBalanceWithoutToken(data, true)
|
||||
|
|
@ -99,7 +88,7 @@ class BalanceWidget(
|
|||
tvFiatAmount.hide()
|
||||
groupBaseCurrency.hide()
|
||||
|
||||
val currency = if (data.token != null) data.token.tokenSymbol else data.currency
|
||||
val currency = if (token != null) token.currencySymbol else data.currency
|
||||
tvCurrency.text = currency
|
||||
tvAmount.text = ""
|
||||
|
||||
|
|
@ -130,7 +119,7 @@ class BalanceWidget(
|
|||
tvErrorDescriptions.text =
|
||||
fragment.getString(
|
||||
R.string.no_account_generic,
|
||||
data.amountToCreateAccount, data.currencySymbol
|
||||
data.amountToCreateAccount, data.currencySymbol,
|
||||
)
|
||||
}
|
||||
BalanceStatus.UnknownBlockchain -> with(binding.lBalanceError) {
|
||||
|
|
@ -152,13 +141,13 @@ class BalanceWidget(
|
|||
|
||||
private fun showBalanceWithToken(data: BalanceWidgetData, showAmount: Boolean) = with(binding.lBalance) {
|
||||
groupBaseCurrency.show()
|
||||
tvCurrency.text = data.token?.tokenSymbol
|
||||
tvCurrency.text = token?.currencySymbol
|
||||
tvBaseCurrency.text = data.currency
|
||||
tvAmount.text = if (showAmount) data.token?.amountFormatted else ""
|
||||
tvAmount.text = if (showAmount) token?.amountFormatted else ""
|
||||
tvBaseAmount.text = if (showAmount) data.amountFormatted else ""
|
||||
if (showAmount) {
|
||||
tvFiatAmount.show()
|
||||
tvFiatAmount.text = data.token?.fiatAmountFormatted
|
||||
tvFiatAmount.text = token?.fiatAmountFormatted
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ import com.tangem.tap.features.wallet.redux.WalletAction
|
|||
import com.tangem.tap.features.wallet.redux.WalletState
|
||||
import com.tangem.tap.features.wallet.ui.adapters.WarningMessagesAdapter
|
||||
import com.tangem.tap.features.wallet.ui.wallet.MultiWalletView
|
||||
import com.tangem.tap.features.wallet.ui.wallet.SaltPaySingleWalletView
|
||||
import com.tangem.tap.features.wallet.ui.wallet.SaltPayWalletView
|
||||
import com.tangem.tap.features.wallet.ui.wallet.SingleWalletView
|
||||
import com.tangem.tap.features.wallet.ui.wallet.WalletView
|
||||
import com.tangem.tap.store
|
||||
|
|
@ -149,11 +149,11 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
|||
val isSaltPay = store.state.globalState.scanResponse?.card?.isSaltPay == true
|
||||
|
||||
when {
|
||||
isSaltPay && (walletView !is SaltPaySingleWalletView) -> {
|
||||
walletView = SaltPaySingleWalletView()
|
||||
isSaltPay && (walletView !is SaltPayWalletView) -> {
|
||||
walletView = SaltPayWalletView()
|
||||
walletView.changeWalletView(this, binding)
|
||||
}
|
||||
state.isMultiwalletAllowed && state.primaryWallet?.currencyData?.status != BalanceStatus.EmptyCard &&
|
||||
state.isMultiwalletAllowed && state.primaryWalletData?.currencyData?.status != BalanceStatus.EmptyCard &&
|
||||
walletView !is MultiWalletView -> {
|
||||
walletView = MultiWalletView()
|
||||
walletView.changeWalletView(this, binding)
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ class MultiWalletView : WalletView() {
|
|||
|
||||
private fun showMultiWalletView(binding: FragmentWalletBinding) = with(binding) {
|
||||
watcher.clear()
|
||||
lSaltPayWallet.root.hide()
|
||||
tvTwinCardNumber.hide()
|
||||
rvPendingTransaction.hide()
|
||||
lCardBalance.root.hide()
|
||||
|
|
@ -220,7 +221,7 @@ class MultiWalletView : WalletView() {
|
|||
binding: FragmentWalletBinding,
|
||||
fragment: WalletFragment,
|
||||
) {
|
||||
when (state.primaryWallet?.currencyData?.status) {
|
||||
when (state.primaryWalletData?.currencyData?.status) {
|
||||
BalanceStatus.EmptyCard -> {
|
||||
showErrorState(
|
||||
binding,
|
||||
|
|
|
|||
|
|
@ -1,64 +0,0 @@
|
|||
package com.tangem.tap.features.wallet.ui.wallet
|
||||
|
||||
import com.tangem.domain.common.extensions.debounce
|
||||
import com.tangem.tap.common.entities.FiatCurrency
|
||||
import com.tangem.tap.common.extensions.animateVisibility
|
||||
import com.tangem.tap.common.extensions.formatAmountAsSpannedString
|
||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.mainScope
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.databinding.LayoutSingleWalletBalanceBinding
|
||||
import org.rekotlin.Action
|
||||
import java.math.BigDecimal
|
||||
|
||||
data class SaltPayBalanceWidgetData(
|
||||
val state: ProgressState? = null,
|
||||
val currencySymbol: String? = null,
|
||||
val currency: String? = null,
|
||||
val fiatAmount: BigDecimal? = null,
|
||||
val fiatCurrency: FiatCurrency? = null,
|
||||
)
|
||||
|
||||
class SaltPayBalanceWidget(
|
||||
private val binding: LayoutSingleWalletBalanceBinding,
|
||||
private val data: SaltPayBalanceWidgetData,
|
||||
) {
|
||||
fun setup(): Unit = with(binding) {
|
||||
if (data.state == ProgressState.Loading) {
|
||||
veilBalance.veil()
|
||||
veilBalanceCrypto.veil()
|
||||
} else {
|
||||
// veilBalance.unVeil()
|
||||
veilBalanceCrypto.unVeil()
|
||||
}
|
||||
tvProcessing.animateVisibility(
|
||||
show = data.state == ProgressState.Error,
|
||||
)
|
||||
veilBalanceCrypto.animateVisibility(
|
||||
show = data.state != ProgressState.Error,
|
||||
)
|
||||
if (data.fiatAmount == null) {
|
||||
//TODO: SaltPay: A tricky solution to the problem with displaying rates
|
||||
// If the rates are loaded after the walletManager.update() is completely updated,
|
||||
// then this problem can be avoided
|
||||
actionDebouncer(WalletAction.LoadFiatRate())
|
||||
} else {
|
||||
veilBalance.unVeil()
|
||||
tvBalance.text = data.fiatAmount?.formatAmountAsSpannedString(
|
||||
currencySymbol = data.fiatCurrency?.symbol ?: "",
|
||||
)
|
||||
}
|
||||
|
||||
tvBalanceCrypto.text = data.currency
|
||||
|
||||
tvCurrencyName.text = data.fiatCurrency?.code
|
||||
|
||||
tvCurrencyName.setOnClickListener {
|
||||
store.dispatch(WalletAction.AppCurrencyAction.ChooseAppCurrency)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val actionDebouncer = debounce<Action>(500, mainScope) { store.dispatch(it) }
|
||||
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
package com.tangem.tap.features.wallet.ui.wallet
|
||||
|
||||
import com.tangem.tap.common.extensions.hide
|
||||
import com.tangem.tap.common.extensions.show
|
||||
import com.tangem.tap.features.wallet.redux.WalletState
|
||||
import com.tangem.tap.features.wallet.ui.TokenData
|
||||
import com.tangem.tap.features.wallet.ui.WalletFragment
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.databinding.FragmentWalletBinding
|
||||
import timber.log.Timber
|
||||
|
||||
class SaltPaySingleWalletView : WalletView() {
|
||||
override fun changeWalletView(fragment: WalletFragment, binding: FragmentWalletBinding) {
|
||||
setFragment(fragment, binding)
|
||||
onViewCreated()
|
||||
showSingleWalletView(binding)
|
||||
}
|
||||
|
||||
private fun showSingleWalletView(binding: FragmentWalletBinding) = with(binding) {
|
||||
rvMultiwallet.hide()
|
||||
btnAddToken.hide()
|
||||
rowButtons.hide()
|
||||
rvPendingTransaction.hide()
|
||||
tvTwinCardNumber.hide()
|
||||
pbLoadingUserTokens.hide()
|
||||
lCardBalance.root.hide()
|
||||
lAddress.root.hide()
|
||||
lSingleWalletBalance.root.show()
|
||||
}
|
||||
|
||||
override fun onViewCreated() {
|
||||
}
|
||||
|
||||
override fun onNewState(state: WalletState) {
|
||||
val binding = binding ?: return
|
||||
val tokenData = state.primaryWallet?.currencyData?.token ?: return
|
||||
|
||||
setupBalance(state, tokenData, binding)
|
||||
}
|
||||
|
||||
private fun setupBalance(state: WalletState, tokenData: TokenData, binding: FragmentWalletBinding) {
|
||||
binding.lSingleWalletBalance.root.show()
|
||||
Timber.e("Current address is ${state.primaryWalletManager?.wallet?.address}")
|
||||
SaltPayBalanceWidget(
|
||||
binding = binding.lSingleWalletBalance,
|
||||
data = SaltPayBalanceWidgetData(
|
||||
state = state.state,
|
||||
currencySymbol = tokenData.tokenSymbol,
|
||||
currency = tokenData.amountFormatted,
|
||||
fiatAmount = tokenData.fiatAmount, // TODO: show fiatAmount
|
||||
fiatCurrency = store.state.globalState.appCurrency,
|
||||
),
|
||||
).setup()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
package com.tangem.tap.features.wallet.ui.wallet
|
||||
|
||||
import com.tangem.domain.common.extensions.debounce
|
||||
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.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.WalletFragment
|
||||
import com.tangem.tap.mainScope
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.databinding.FragmentWalletBinding
|
||||
import com.tangem.wallet.databinding.LayoutSaltPayWalletBinding
|
||||
import org.rekotlin.Action
|
||||
|
||||
class SaltPayWalletView : WalletView() {
|
||||
|
||||
private lateinit var saltPayBinding: LayoutSaltPayWalletBinding
|
||||
private val actionDebouncer = debounce<Action>(500, mainScope) { store.dispatch(it) }
|
||||
|
||||
override fun changeWalletView(fragment: WalletFragment, binding: FragmentWalletBinding) {
|
||||
saltPayBinding = binding.lSaltPayWallet
|
||||
setFragment(fragment, binding)
|
||||
onViewCreated()
|
||||
showSaltPayView(binding)
|
||||
}
|
||||
|
||||
private fun showSaltPayView(binding: FragmentWalletBinding) = with(binding) {
|
||||
rvWarningMessages.hide()
|
||||
rvPendingTransaction.hide()
|
||||
rvMultiwallet.hide()
|
||||
tvTwinCardNumber.hide()
|
||||
lCardBalance.root.hide()
|
||||
lSingleWalletBalance.root.hide()
|
||||
lAddress.root.hide()
|
||||
rowButtons.hide()
|
||||
btnAddToken.hide()
|
||||
pbLoadingUserTokens.hide()
|
||||
lSaltPayWallet.root.show()
|
||||
}
|
||||
|
||||
override fun onViewCreated() {
|
||||
}
|
||||
|
||||
override fun onNewState(state: WalletState) {
|
||||
setupBalanceWidget(state)
|
||||
}
|
||||
|
||||
private fun setupBalanceWidget(state: WalletState) = with(saltPayBinding.lSaltPayBalance) {
|
||||
val tokenData = state.primaryTokenData ?: return@with
|
||||
|
||||
val appCurrency = store.state.globalState.appCurrency
|
||||
val mainProgressState = state.state
|
||||
|
||||
if (mainProgressState == ProgressState.Loading) {
|
||||
veilBalance.veil()
|
||||
veilBalanceCrypto.veil()
|
||||
} else {
|
||||
veilBalanceCrypto.unVeil()
|
||||
}
|
||||
|
||||
tvProcessing.animateVisibility(show = mainProgressState == ProgressState.Error)
|
||||
veilBalanceCrypto.animateVisibility(show = mainProgressState != ProgressState.Error)
|
||||
|
||||
if (tokenData.currencyData.fiatAmount == null) {
|
||||
actionDebouncer(WalletAction.LoadFiatRate())
|
||||
} else {
|
||||
veilBalance.unVeil()
|
||||
tvBalance.text = tokenData.currencyData.fiatAmount.formatAmountAsSpannedString(
|
||||
currencySymbol = appCurrency.symbol,
|
||||
)
|
||||
}
|
||||
|
||||
tvBalanceCrypto.text = tokenData.currencyData.amountFormatted
|
||||
|
||||
tvCurrencyName.text = appCurrency.code
|
||||
tvCurrencyName.setOnClickListener {
|
||||
store.dispatch(WalletAction.AppCurrencyAction.ChooseAppCurrency)
|
||||
}
|
||||
|
||||
btnBuy.show(tokenData.isAvailableToBuy)
|
||||
btnBuy.setOnClickListener {
|
||||
store.dispatch(WalletAction.TradeCryptoAction.Buy(false))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -35,6 +35,7 @@ class SingleWalletView : WalletView() {
|
|||
}
|
||||
|
||||
private fun showSingleWalletView(binding: FragmentWalletBinding) = with(binding) {
|
||||
lSaltPayWallet.root.hide()
|
||||
tvTwinCardNumber.hide()
|
||||
rvMultiwallet.hide()
|
||||
btnAddToken.hide()
|
||||
|
|
@ -63,13 +64,13 @@ class SingleWalletView : WalletView() {
|
|||
|
||||
override fun onNewState(state: WalletState) {
|
||||
val binding = binding ?: return
|
||||
state.primaryWallet ?: return
|
||||
val primaryWalletData = state.primaryWalletData ?: return
|
||||
|
||||
setupTwinCards(state.twinCardsState, binding)
|
||||
setupButtons(state.primaryWallet, binding, state.isExchangeServiceFeatureOn)
|
||||
setupButtons(primaryWalletData, binding, state.isExchangeServiceFeatureOn)
|
||||
setupAddressCard(state, binding)
|
||||
showPendingTransactionsIfPresent(state.primaryWallet.pendingTransactions)
|
||||
setupBalance(state, state.primaryWallet)
|
||||
showPendingTransactionsIfPresent(primaryWalletData.pendingTransactions)
|
||||
setupBalance(state, primaryWalletData)
|
||||
}
|
||||
|
||||
private fun showPendingTransactionsIfPresent(pendingTransactions: List<PendingTransaction>) {
|
||||
|
|
@ -88,6 +89,7 @@ class SingleWalletView : WalletView() {
|
|||
binding = this.lCardBalance,
|
||||
fragment = fragment,
|
||||
data = primaryWallet.currencyData,
|
||||
token = state.primaryTokenData?.currencyData,
|
||||
isTwinCard = state.isTangemTwins,
|
||||
).setup()
|
||||
}
|
||||
|
|
@ -152,7 +154,7 @@ class SingleWalletView : WalletView() {
|
|||
}
|
||||
|
||||
private fun setupAddressCard(state: WalletState, binding: FragmentWalletBinding) = with(binding.lAddress) {
|
||||
val primaryWallet = state.primaryWallet
|
||||
val primaryWallet = state.primaryWalletData
|
||||
if (primaryWallet?.walletAddresses != null && primaryWallet.currency is Currency.Blockchain) {
|
||||
binding.lAddress.root.show()
|
||||
if (primaryWallet.shouldShowMultipleAddress()) {
|
||||
|
|
@ -187,7 +189,7 @@ class SingleWalletView : WalletView() {
|
|||
|
||||
private fun setupCardInfo(state: WalletState) {
|
||||
val textView = binding?.lAddress?.tvInfo
|
||||
val blockchain = state.primaryWallet?.currency?.blockchain
|
||||
val blockchain = state.primaryWalletData?.currency?.blockchain
|
||||
if (textView != null && blockchain != null) {
|
||||
textView.text = textView.getString(
|
||||
id = R.string.address_qr_code_message_format,
|
||||
|
|
|
|||
5
app/src/main/res/color/selector_saltpay_btn.xml
Normal file
5
app/src/main/res/color/selector_saltpay_btn.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/button_disabled" android:state_enabled="false" />
|
||||
<item android:color="@color/button_secondary" />
|
||||
</selector>
|
||||
5
app/src/main/res/color/selector_saltpay_btn_text.xml
Normal file
5
app/src/main/res/color/selector_saltpay_btn_text.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="#66FFFFFF" android:state_enabled="false" />
|
||||
<item android:color="@color/text_primary_1" />
|
||||
</selector>
|
||||
|
|
@ -177,6 +177,15 @@
|
|||
android:visibility="gone"
|
||||
app:layout_constraintTop_toBottomOf="@id/rv_pending_transaction" />
|
||||
|
||||
<include
|
||||
android:id="@+id/l_salt_pay_wallet"
|
||||
layout="@layout/layout_salt_pay_wallet"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:visibility="visible"
|
||||
app:layout_constraintTop_toBottomOf="@id/rv_pending_transaction" />
|
||||
|
||||
<include
|
||||
android:id="@+id/l_address"
|
||||
layout="@layout/layout_address"
|
||||
|
|
|
|||
138
app/src/main/res/layout/layout_salt_pay_balance.xml
Normal file
138
app/src/main/res/layout/layout_salt_pay_balance.xml
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.card.MaterialCardView 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:id="@+id/card_balance"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardCornerRadius="12dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:animateLayoutChanges="true"
|
||||
android:clipToPadding="false"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="@string/onboarding_balance_title"
|
||||
android:textColor="@color/text_tertiary"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toStartOf="@id/tv_currency_name"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.skydoves.androidveil.VeilLayout
|
||||
android:id="@+id/veil_balance"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
app:layout_constraintBottom_toTopOf="@id/tv_processing"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_title"
|
||||
app:veilLayout_baseColor="@color/lightGray0"
|
||||
app:veilLayout_highlightColor="@color/lightGray1"
|
||||
app:veilLayout_layout="@layout/card_total_balance_shimmer"
|
||||
app:veilLayout_radius="4dp"
|
||||
app:veilLayout_shimmerEnable="true"
|
||||
app:veilLayout_veiled="true"
|
||||
tools:veilLayout_veiled="false"
|
||||
tools:visibility="visible">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_balance"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:minWidth="152dp"
|
||||
android:textColor="@color/text_primary_1"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
tools:text="22 325.40 $" />
|
||||
|
||||
</com.skydoves.androidveil.VeilLayout>
|
||||
|
||||
<com.skydoves.androidveil.VeilLayout
|
||||
android:id="@+id/veil_balance_crypto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="18dp"
|
||||
android:layout_marginTop="4dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/veil_balance"
|
||||
app:veilLayout_baseColor="@color/lightGray0"
|
||||
app:veilLayout_highlightColor="@color/lightGray1"
|
||||
app:veilLayout_layout="@layout/card_total_balance_shimmer"
|
||||
app:veilLayout_radius="4dp"
|
||||
app:veilLayout_shimmerEnable="true"
|
||||
app:veilLayout_veiled="true"
|
||||
tools:veilLayout_veiled="false"
|
||||
tools:visibility="visible">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_balance_crypto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="2dp"
|
||||
android:maxLines="1"
|
||||
android:minWidth="152dp"
|
||||
android:textColor="@color/text_tertiary"
|
||||
android:textSize="12sp"
|
||||
tools:text="5.13123123123 ETH"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</com.skydoves.androidveil.VeilLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_processing"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:text="@string/wallet_balance_blockchain_unreachable"
|
||||
android:textColor="@color/warning"
|
||||
android:textSize="12sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/veil_balance" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_buy"
|
||||
style="@style/BaseSaltPayButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:text="@string/wallet_button_buy"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_add"
|
||||
app:iconGravity="textStart"
|
||||
app:iconTint="@color/selector_saltpay_btn_text"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/veil_balance_crypto"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_currency_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:textColor="@color/text_tertiary"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:drawableEndCompat="@drawable/ic_arrow_angle_down"
|
||||
app:drawableTint="@color/text_tertiary"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="USD" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
22
app/src/main/res/layout/layout_salt_pay_wallet.xml
Normal file
22
app/src/main/res/layout/layout_salt_pay_wallet.xml
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/cl_salt_pay_wallet_info"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="6dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<include
|
||||
android:id="@+id/l_salt_pay_balance"
|
||||
layout="@layout/layout_salt_pay_balance"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
@ -131,6 +131,19 @@
|
|||
<item name="android:lineSpacingExtra">4sp</item>
|
||||
</style>
|
||||
|
||||
<style name="BaseSaltPayButton">
|
||||
<item name="android:minHeight">40dp</item>
|
||||
<item name="android:insetTop">0dp</item>
|
||||
<item name="android:insetBottom">0dp</item>
|
||||
<item name="android:elevation">0dp</item>
|
||||
<item name="android:textColor">@color/selector_saltpay_btn_text</item>
|
||||
<item name="android:textAllCaps">false</item>
|
||||
<item name="android:letterSpacing">0</item>
|
||||
<item name="android:backgroundTint">@color/selector_saltpay_btn</item>
|
||||
<item name="cornerRadius">@dimen/btn_corner_radius_medium</item>
|
||||
<item name="android:stateListAnimator">@null</item>
|
||||
</style>
|
||||
|
||||
<style name="heading">
|
||||
<item name="android:textSize">24sp</item>
|
||||
<item name="android:textColor">#060606</item>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue