Updated on 2026-08-14
This commit is contained in:
commit
5ee5b4f61b
563 changed files with 13917 additions and 4692 deletions
|
|
@ -175,6 +175,8 @@ internal class DefaultSendComponent @AssistedInject constructor(
|
|||
userWalletId = params.userWalletId,
|
||||
cryptoCurrency = params.currency,
|
||||
cryptoCurrencyStatusFlow = model.cryptoCurrencyStatusFlow,
|
||||
accountFlow = model.accountFlow,
|
||||
isAccountModeFlow = model.isAccountModeFlow,
|
||||
callback = model,
|
||||
predefinedValues = model.predefinedValues,
|
||||
analyticsSendSource = model.analyticsSendSource,
|
||||
|
|
@ -201,6 +203,8 @@ internal class DefaultSendComponent @AssistedInject constructor(
|
|||
feeCryptoCurrencyStatus = feeCryptoCurrencyStatus,
|
||||
cryptoCurrencyStatusFlow = model.cryptoCurrencyStatusFlow,
|
||||
feeCryptoCurrencyStatusFlow = model.feeCryptoCurrencyStatusFlow,
|
||||
accountFlow = model.accountFlow,
|
||||
isAccountModeFlow = model.isAccountModeFlow,
|
||||
appCurrency = model.appCurrency,
|
||||
callback = model,
|
||||
predefinedValues = model.predefinedValues,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import com.tangem.core.decompose.context.child
|
|||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.transaction.error.GetFeeError
|
||||
|
|
@ -73,6 +74,8 @@ internal class SendConfirmComponent(
|
|||
cryptoCurrencyStatusFlow = params.cryptoCurrencyStatusFlow,
|
||||
isBalanceHidingFlow = params.isBalanceHidingFlow,
|
||||
analyticsSendSource = params.analyticsSendSource,
|
||||
accountFlow = params.accountFlow,
|
||||
isAccountModeFlow = params.isAccountModeFlow,
|
||||
),
|
||||
onResult = model::onAmountResult,
|
||||
onClick = model::showEditAmount,
|
||||
|
|
@ -152,6 +155,8 @@ internal class SendConfirmComponent(
|
|||
val feeCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
|
||||
val feeCryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
|
||||
val accountFlow: StateFlow<Account.CryptoPortfolio?>,
|
||||
val isAccountModeFlow: StateFlow<Boolean>,
|
||||
val appCurrency: AppCurrency,
|
||||
val callback: ModelCallback,
|
||||
val currentRoute: Flow<CommonSendRoute>,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@ import com.tangem.core.decompose.model.ParamsContainer
|
|||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.ui.utils.parseBigDecimal
|
||||
import com.tangem.core.ui.utils.parseBigDecimalOrNull
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.account.status.usecase.GetAccountCurrencyStatusUseCase
|
||||
import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||
|
|
@ -23,6 +26,7 @@ import com.tangem.domain.feedback.SaveBlockchainErrorUseCase
|
|||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||
import com.tangem.domain.feedback.models.BlockchainErrorInfo
|
||||
import com.tangem.domain.feedback.models.FeedbackEmailType
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.isMultiCurrency
|
||||
|
|
@ -91,8 +95,11 @@ internal class SendModel @Inject constructor(
|
|||
private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
||||
private val createTransferTransactionUseCase: CreateTransferTransactionUseCase,
|
||||
private val getFeeUseCase: GetFeeUseCase,
|
||||
private val getAccountCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase,
|
||||
private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase,
|
||||
private val sendAmountUpdateTrigger: SendAmountUpdateTrigger,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
) : Model(), SendComponentCallback {
|
||||
|
||||
private val params: SendComponent.Params = paramsContainer.require()
|
||||
|
|
@ -115,21 +122,26 @@ internal class SendModel @Inject constructor(
|
|||
|
||||
val currentRoute = MutableStateFlow(initialRoute)
|
||||
|
||||
private val _cryptoCurrencyStatusFlow = MutableStateFlow(
|
||||
CryptoCurrencyStatus(
|
||||
params.currency,
|
||||
value = CryptoCurrencyStatus.Loading,
|
||||
),
|
||||
)
|
||||
val cryptoCurrencyStatusFlow = _cryptoCurrencyStatusFlow.asStateFlow()
|
||||
val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>
|
||||
field = MutableStateFlow(
|
||||
CryptoCurrencyStatus(
|
||||
params.currency,
|
||||
value = CryptoCurrencyStatus.Loading,
|
||||
),
|
||||
)
|
||||
|
||||
private val _feeCryptoCurrencyStatusFlow = MutableStateFlow(
|
||||
CryptoCurrencyStatus(
|
||||
params.currency,
|
||||
value = CryptoCurrencyStatus.Loading,
|
||||
),
|
||||
)
|
||||
val feeCryptoCurrencyStatusFlow = _feeCryptoCurrencyStatusFlow.asStateFlow()
|
||||
val feeCryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>
|
||||
field = MutableStateFlow(
|
||||
CryptoCurrencyStatus(
|
||||
params.currency,
|
||||
value = CryptoCurrencyStatus.Loading,
|
||||
),
|
||||
)
|
||||
|
||||
val accountFlow: StateFlow<Account.CryptoPortfolio?>
|
||||
field = MutableStateFlow(null)
|
||||
val isAccountModeFlow: StateFlow<Boolean>
|
||||
field = MutableStateFlow(false)
|
||||
|
||||
var userWallet: UserWallet by Delegates.notNull()
|
||||
var appCurrency: AppCurrency = AppCurrency.Default
|
||||
|
|
@ -317,13 +329,34 @@ internal class SendModel @Inject constructor(
|
|||
ifRight = { wallet ->
|
||||
userWallet = wallet
|
||||
|
||||
val isSingleWalletWithToken = wallet is UserWallet.Cold &&
|
||||
wallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()
|
||||
val isMultiCurrency = wallet.isMultiCurrency
|
||||
getCurrenciesStatusUpdates(
|
||||
isSingleWalletWithToken = isSingleWalletWithToken,
|
||||
isMultiCurrency = isMultiCurrency,
|
||||
)
|
||||
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
getAccountCurrencyStatusUseCase(
|
||||
userWalletId = params.userWalletId,
|
||||
currency = cryptoCurrency,
|
||||
).onEach { (account, cryptoCurrencyStatus) ->
|
||||
cryptoCurrencyStatusFlow.value = cryptoCurrencyStatus
|
||||
feeCryptoCurrencyStatusFlow.value = getFeePaidCryptoCurrencyStatusSyncUseCase(
|
||||
userWalletId = params.userWalletId,
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
).getOrNull() ?: cryptoCurrencyStatus
|
||||
|
||||
isAccountModeFlow.value = isAccountsModeEnabledUseCase.invokeSync()
|
||||
accountFlow.value = account
|
||||
|
||||
if (params.amount != null) {
|
||||
router.replaceAll(Confirm)
|
||||
}
|
||||
}.flowOn(dispatchers.default)
|
||||
.launchIn(modelScope)
|
||||
} else {
|
||||
val isSingleWalletWithToken = wallet is UserWallet.Cold &&
|
||||
wallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()
|
||||
val isMultiCurrency = wallet.isMultiCurrency
|
||||
getCurrenciesStatusUpdates(
|
||||
isSingleWalletWithToken = isSingleWalletWithToken,
|
||||
isMultiCurrency = isMultiCurrency,
|
||||
)
|
||||
}
|
||||
},
|
||||
ifLeft = {
|
||||
Timber.w(it.toString())
|
||||
|
|
@ -352,10 +385,12 @@ internal class SendModel @Inject constructor(
|
|||
).onEach { maybeCryptoCurrency ->
|
||||
maybeCryptoCurrency.fold(
|
||||
ifRight = { cryptoCurrencyStatus ->
|
||||
onDataLoaded(
|
||||
currencyStatus = cryptoCurrencyStatus,
|
||||
feeCurrencyStatus = getFeeCurrencyStatus(cryptoCurrencyStatus, isMultiCurrency),
|
||||
)
|
||||
cryptoCurrencyStatusFlow.value = cryptoCurrencyStatus
|
||||
feeCryptoCurrencyStatusFlow.value = getFeeCurrencyStatus(cryptoCurrencyStatus, isMultiCurrency)
|
||||
|
||||
if (params.amount != null) {
|
||||
router.replaceAll(CommonSendRoute.Confirm)
|
||||
}
|
||||
},
|
||||
ifLeft = {
|
||||
sendConfirmAlertFactory.getGenericErrorState(
|
||||
|
|
@ -366,7 +401,8 @@ internal class SendModel @Inject constructor(
|
|||
)
|
||||
},
|
||||
)
|
||||
}.launchIn(modelScope)
|
||||
}.flowOn(dispatchers.default)
|
||||
.launchIn(modelScope)
|
||||
}
|
||||
|
||||
private fun getCurrencyStatus(
|
||||
|
|
@ -402,15 +438,6 @@ internal class SendModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun onDataLoaded(currencyStatus: CryptoCurrencyStatus, feeCurrencyStatus: CryptoCurrencyStatus) {
|
||||
_cryptoCurrencyStatusFlow.value = currencyStatus
|
||||
_feeCryptoCurrencyStatusFlow.value = feeCurrencyStatus
|
||||
|
||||
if (params.amount != null) {
|
||||
router.replaceAll(CommonSendRoute.Confirm)
|
||||
}
|
||||
}
|
||||
|
||||
private fun subscribeOnQRScannerResult() {
|
||||
listenToQrScanningUseCase(SourceType.SEND)
|
||||
.getOrElse { emptyFlow() }
|
||||
|
|
@ -454,7 +481,7 @@ internal class SendModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun initialState(): SendUM = SendUM(
|
||||
amountUM = AmountState.Empty(isRedesignEnabled = true),
|
||||
amountUM = AmountState.Empty,
|
||||
destinationUM = SendDestinationInitialStateTransformer(
|
||||
cryptoCurrency = cryptoCurrency,
|
||||
).transform(DestinationUM.Empty()),
|
||||
|
|
|
|||
|
|
@ -156,6 +156,8 @@ internal class DefaultNFTSendComponent @AssistedInject constructor(
|
|||
isBalanceHidingFlow = model.isBalanceHiddenFlow,
|
||||
onLoadFee = model::loadFee,
|
||||
analyticsSendSource = analyticsSendSource,
|
||||
account = model.account,
|
||||
isAccountsMode = model.isAccountsMode,
|
||||
onSendTransaction = { innerRouter.replaceAll(CommonSendRoute.ConfirmSuccess) },
|
||||
),
|
||||
)
|
||||
|
|
@ -181,6 +183,8 @@ internal class DefaultNFTSendComponent @AssistedInject constructor(
|
|||
callback = model,
|
||||
currentRoute = model.currentRouteFlow.filterIsInstance<CommonSendRoute.ConfirmSuccess>(),
|
||||
txUrl = txUrl,
|
||||
account = model.account,
|
||||
isAccountsMode = model.isAccountsMode,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import com.tangem.core.ui.decompose.ComposableContentComponent
|
|||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.nft.models.NFTAsset
|
||||
|
|
@ -88,7 +89,9 @@ internal class NFTSendConfirmComponent @AssistedInject constructor(
|
|||
nftAsset = params.nftAsset,
|
||||
nftCollectionName = params.nftCollectionName,
|
||||
isSuccessScreen = false,
|
||||
title = resourceReference(R.string.send_from_wallet_name, wrappedList(params.userWallet.name)),
|
||||
account = params.account,
|
||||
isAccountsMode = params.isAccountsMode,
|
||||
walletTitle = resourceReference(R.string.send_from_wallet_name, wrappedList(params.userWallet.name)),
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -150,6 +153,8 @@ internal class NFTSendConfirmComponent @AssistedInject constructor(
|
|||
val nftCollectionName: String,
|
||||
val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
val feeCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
val account: Account.CryptoPortfolio?,
|
||||
val isAccountsMode: Boolean,
|
||||
val callback: ModelCallback,
|
||||
val currentRoute: Flow<CommonSendRoute.Confirm>,
|
||||
val isBalanceHidingFlow: StateFlow<Boolean>,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ import com.tangem.core.decompose.model.Model
|
|||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.datasource.local.nft.converter.NFTSdkAssetConverter
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.account.status.usecase.GetAccountCurrencyStatusUseCase
|
||||
import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||
|
|
@ -19,6 +22,7 @@ import com.tangem.domain.feedback.SaveBlockchainErrorUseCase
|
|||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||
import com.tangem.domain.feedback.models.BlockchainErrorInfo
|
||||
import com.tangem.domain.feedback.models.FeedbackEmailType
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
|
|
@ -71,6 +75,9 @@ internal class NFTSendModel @Inject constructor(
|
|||
private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase,
|
||||
private val alertFactory: SendConfirmAlertFactory,
|
||||
private val nftSendSuccessTrigger: NFTSendSuccessTrigger,
|
||||
private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase,
|
||||
private val getAccountCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
) : Model(), SendNFTComponentCallback, NFTSendSuccessComponent.ModelCallback {
|
||||
|
||||
val params: NFTSendComponent.Params = paramsContainer.require()
|
||||
|
|
@ -94,6 +101,9 @@ internal class NFTSendModel @Inject constructor(
|
|||
var feeCryptoCurrencyStatus: CryptoCurrencyStatus by Delegates.notNull()
|
||||
var appCurrency: AppCurrency = AppCurrency.Default
|
||||
|
||||
var account: Account.CryptoPortfolio? = null
|
||||
var isAccountsMode: Boolean = false
|
||||
|
||||
init {
|
||||
subscribeOnCurrencyStatusUpdates()
|
||||
initAppCurrency()
|
||||
|
|
@ -176,10 +186,31 @@ internal class NFTSendModel @Inject constructor(
|
|||
?.firstOrNull { it is CryptoCurrency.Coin && it.network == nftAsset.network }
|
||||
?: return@launch
|
||||
|
||||
getCurrenciesStatusUpdates(
|
||||
isSingleWalletWithToken = wallet is UserWallet.Cold &&
|
||||
wallet.scanResponse.cardTypesResolver.isSingleWalletWithToken(),
|
||||
)
|
||||
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
getAccountCurrencyStatusUseCase(
|
||||
userWalletId,
|
||||
cryptoCurrency,
|
||||
).onEach { (maybeAccount, cryptoStatus) ->
|
||||
account = maybeAccount
|
||||
isAccountsMode = isAccountsModeEnabledUseCase.invokeSync()
|
||||
|
||||
cryptoCurrencyStatus = cryptoStatus
|
||||
feeCryptoCurrencyStatus = getFeePaidCryptoCurrencyStatusSyncUseCase(
|
||||
userWalletId = userWalletId,
|
||||
cryptoCurrencyStatus = cryptoStatus,
|
||||
).getOrNull() ?: cryptoStatus
|
||||
|
||||
if (uiState.value.destinationUM is DestinationUM.Empty) {
|
||||
router.replaceAll(Destination(isEditMode = false))
|
||||
}
|
||||
}.flowOn(dispatchers.default)
|
||||
.launchIn(modelScope)
|
||||
} else {
|
||||
getCurrenciesStatusUpdates(
|
||||
isSingleWalletWithToken = wallet is UserWallet.Cold &&
|
||||
wallet.scanResponse.cardTypesResolver.isSingleWalletWithToken(),
|
||||
)
|
||||
}
|
||||
},
|
||||
ifLeft = {
|
||||
alertFactory.getGenericErrorState(::onFailedTxEmailClick)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import com.tangem.core.decompose.context.child
|
|||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.nft.models.NFTAsset
|
||||
|
|
@ -46,7 +47,9 @@ internal class NFTSendSuccessComponent @AssistedInject constructor(
|
|||
nftAsset = params.nftAsset,
|
||||
nftCollectionName = params.nftCollectionName,
|
||||
isSuccessScreen = true,
|
||||
title = resourceReference(R.string.nft_asset),
|
||||
account = params.account,
|
||||
isAccountsMode = params.isAccountsMode,
|
||||
walletTitle = resourceReference(R.string.nft_asset),
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -86,6 +89,8 @@ internal class NFTSendSuccessComponent @AssistedInject constructor(
|
|||
val nftAsset: NFTAsset,
|
||||
val nftCollectionName: String,
|
||||
val txUrl: String,
|
||||
val account: Account.CryptoPortfolio?,
|
||||
val isAccountsMode: Boolean,
|
||||
val callback: ModelCallback,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -26,12 +26,10 @@ internal class SendAmountComponent(
|
|||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
val state by model.uiState.collectAsStateWithLifecycle()
|
||||
val isBalanceHidden by params.isBalanceHidingFlow.collectAsStateWithLifecycle()
|
||||
val isSendWithSwapAvailable by model.isSendWithSwapAvailable.collectAsStateWithLifecycle()
|
||||
|
||||
SendAmountContent(
|
||||
amountState = state,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
clickIntents = model,
|
||||
isSendWithSwapAvailable = isSendWithSwapAvailable,
|
||||
modifier = modifier,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.features.send.v2.subcomponents.amount
|
|||
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
|
|
@ -23,6 +24,8 @@ internal sealed class SendAmountComponentParams {
|
|||
abstract val cryptoCurrency: CryptoCurrency
|
||||
abstract val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>
|
||||
abstract val isBalanceHidingFlow: StateFlow<Boolean>
|
||||
abstract val accountFlow: StateFlow<Account.CryptoPortfolio?>
|
||||
abstract val isAccountModeFlow: StateFlow<Boolean>
|
||||
|
||||
data class AmountParams(
|
||||
override val state: AmountState,
|
||||
|
|
@ -34,6 +37,8 @@ internal sealed class SendAmountComponentParams {
|
|||
override val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
|
||||
override val isBalanceHidingFlow: StateFlow<Boolean>,
|
||||
override val analyticsSendSource: CommonSendAnalyticEvents.CommonSendSource,
|
||||
override val accountFlow: StateFlow<Account.CryptoPortfolio?>,
|
||||
override val isAccountModeFlow: StateFlow<Boolean>,
|
||||
val callback: ModelCallback,
|
||||
val currentRoute: StateFlow<CommonSendRoute>,
|
||||
) : SendAmountComponentParams()
|
||||
|
|
@ -48,6 +53,8 @@ internal sealed class SendAmountComponentParams {
|
|||
override val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
|
||||
override val isBalanceHidingFlow: StateFlow<Boolean>,
|
||||
override val analyticsSendSource: CommonSendAnalyticEvents.CommonSendSource,
|
||||
override val accountFlow: StateFlow<Account.CryptoPortfolio?>,
|
||||
override val isAccountModeFlow: StateFlow<Boolean>,
|
||||
val userWallet: UserWallet,
|
||||
val blockClickEnableFlow: StateFlow<Boolean>,
|
||||
) : SendAmountComponentParams()
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import com.tangem.core.ui.extensions.resourceReference
|
|||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.exchange.RampStateManager
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.isMultiCurrency
|
||||
|
|
@ -118,42 +119,7 @@ internal class SendAmountModel @Inject constructor(
|
|||
|
||||
private fun subscribeOnBalanceHiddenUpdates() {
|
||||
params.isBalanceHidingFlow.onEach { isBalanceHidden ->
|
||||
_uiState.update(
|
||||
AmountBoundaryUpdateTransformer(
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
maxEnterAmount = maxAmountBoundary,
|
||||
appCurrency = appCurrency,
|
||||
isBalanceHidden = params.isBalanceHidingFlow.value,
|
||||
),
|
||||
)
|
||||
}.launchIn(modelScope)
|
||||
}
|
||||
|
||||
private fun subscribeOnCryptoCurrencyStatusFlow() {
|
||||
params.cryptoCurrencyStatusFlow
|
||||
.onEach { newCryptoCurrencyStatus ->
|
||||
cryptoCurrencyStatus = newCryptoCurrencyStatus
|
||||
maxAmountBoundary = MaxEnterAmountConverter().convert(cryptoCurrencyStatus)
|
||||
initMinBoundary()
|
||||
}
|
||||
.launchIn(modelScope)
|
||||
}
|
||||
|
||||
private fun initMinBoundary() {
|
||||
modelScope.launch {
|
||||
minAmountBoundary = getMinimumTransactionAmountSyncUseCase(
|
||||
userWalletId = params.userWalletId,
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
).getOrNull()?.let {
|
||||
EnterAmountBoundary(
|
||||
amount = it,
|
||||
fiatRate = cryptoCurrencyStatus.value.fiatRate.orZero(),
|
||||
)
|
||||
}
|
||||
|
||||
appCurrency = getSelectedAppCurrencyUseCase.invokeSync().getOrElse { AppCurrency.Default }
|
||||
|
||||
if (uiState.value is AmountState.Data) {
|
||||
if (cryptoCurrencyStatus.value != CryptoCurrencyStatus.Loading) {
|
||||
_uiState.update(
|
||||
AmountBoundaryUpdateTransformer(
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
|
|
@ -162,33 +128,87 @@ internal class SendAmountModel @Inject constructor(
|
|||
isBalanceHidden = params.isBalanceHidingFlow.value,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
initialState()
|
||||
}
|
||||
}.launchIn(modelScope)
|
||||
}
|
||||
|
||||
private fun subscribeOnCryptoCurrencyStatusFlow() {
|
||||
combine(
|
||||
flow = params.cryptoCurrencyStatusFlow.distinctUntilChanged { old, new ->
|
||||
old.value.amount == new.value.amount
|
||||
}, // Check only balance changes,
|
||||
flow2 = params.accountFlow,
|
||||
flow3 = params.isAccountModeFlow,
|
||||
) { newCryptoCurrencyStatus, account, isAccountsMode ->
|
||||
maxAmountBoundary = MaxEnterAmountConverter().convert(newCryptoCurrencyStatus)
|
||||
cryptoCurrencyStatus = newCryptoCurrencyStatus
|
||||
initMinBoundary(cryptoCurrencyStatus, account, isAccountsMode)
|
||||
}.flowOn(dispatchers.default)
|
||||
.launchIn(modelScope)
|
||||
}
|
||||
|
||||
private suspend fun initMinBoundary(
|
||||
cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
account: Account.CryptoPortfolio?,
|
||||
isAccountsMode: Boolean,
|
||||
) {
|
||||
minAmountBoundary = getMinimumTransactionAmountSyncUseCase(
|
||||
userWalletId = params.userWalletId,
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
).getOrNull()?.let {
|
||||
EnterAmountBoundary(
|
||||
amount = it,
|
||||
fiatRate = cryptoCurrencyStatus.value.fiatRate.orZero(),
|
||||
)
|
||||
}
|
||||
|
||||
appCurrency = getSelectedAppCurrencyUseCase.invokeSync().getOrElse { AppCurrency.Default }
|
||||
|
||||
if (uiState.value is AmountState.Data) {
|
||||
_uiState.update(
|
||||
AmountBoundaryUpdateTransformer(
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
maxEnterAmount = maxAmountBoundary,
|
||||
appCurrency = appCurrency,
|
||||
isBalanceHidden = params.isBalanceHidingFlow.value,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
initialState(cryptoCurrencyStatus, account, isAccountsMode)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initialState() {
|
||||
private fun initialState(
|
||||
cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
@Suppress("UnusedParameter") account: Account.CryptoPortfolio?,
|
||||
@Suppress("UnusedParameter") isAccountsMode: Boolean,
|
||||
) {
|
||||
if (uiState.value is AmountState.Empty && userWallet != null) {
|
||||
val isOnlyOneWallet = getWalletsUseCase.invokeSync().size == 1
|
||||
val walletTitle = if (isOnlyOneWallet) {
|
||||
resourceReference(R.string.send_from_title)
|
||||
} else {
|
||||
resourceReference(
|
||||
R.string.send_from_wallet_name,
|
||||
WrappedList(listOf(userWallet?.name.orEmpty())), // TODO [REDACTED_TASK_KEY]
|
||||
)
|
||||
}
|
||||
_uiState.update {
|
||||
AmountStateConverterV2(
|
||||
AmountStateConverter(
|
||||
clickIntents = this,
|
||||
appCurrency = appCurrency,
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
maxEnterAmount = maxAmountBoundary,
|
||||
iconStateConverter = CryptoCurrencyToIconStateConverter(),
|
||||
isBalanceHidden = params.isBalanceHidingFlow.value,
|
||||
accountTitleUM = AmountAccountConverter(
|
||||
isAccountsMode = isAccountsMode,
|
||||
walletTitle = walletTitle,
|
||||
prefixText = resourceReference(R.string.common_from),
|
||||
).convert(account),
|
||||
).convert(
|
||||
AmountParameters(
|
||||
title = if (isOnlyOneWallet) {
|
||||
resourceReference(R.string.send_from_title)
|
||||
} else {
|
||||
resourceReference(
|
||||
R.string.send_from_wallet_name,
|
||||
WrappedList(listOf(userWallet?.name.orEmpty())), // TODO [REDACTED_TASK_KEY]
|
||||
)
|
||||
},
|
||||
title = walletTitle,
|
||||
value = "",
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ import com.tangem.features.send.v2.subcomponents.amount.ui.preview.SendAmountCli
|
|||
@Composable
|
||||
fun SendAmountContent(
|
||||
amountState: AmountState,
|
||||
isBalanceHidden: Boolean,
|
||||
clickIntents: SendAmountClickIntents,
|
||||
isSendWithSwapAvailable: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
@ -38,7 +37,6 @@ fun SendAmountContent(
|
|||
Column(modifier = modifier.background(TangemTheme.colors.background.tertiary)) {
|
||||
AmountScreenContent(
|
||||
amountState = amountState,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
clickIntents = clickIntents,
|
||||
extraContent = {
|
||||
SendConvertTokenButton(
|
||||
|
|
@ -95,7 +93,6 @@ private fun SendAmountContent_Preview(@PreviewParameter(SendAmountContentPreview
|
|||
TangemThemePreview {
|
||||
SendAmountContent(
|
||||
amountState = params,
|
||||
isBalanceHidden = true,
|
||||
clickIntents = SendAmountClickIntentsStub,
|
||||
isSendWithSwapAvailable = true,
|
||||
)
|
||||
|
|
@ -106,6 +103,7 @@ private class SendAmountContentPreviewProvider : PreviewParameterProvider<Amount
|
|||
override val values: Sequence<AmountState>
|
||||
get() = sequenceOf(
|
||||
AmountStatePreviewData.amountStateV2,
|
||||
AmountStatePreviewData.amountStateV2Accounts,
|
||||
)
|
||||
}
|
||||
// endregion
|
||||
|
|
@ -11,6 +11,9 @@ import com.tangem.core.decompose.model.Model
|
|||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.account.status.usecase.GetAccountCurrencyStatusUseCase
|
||||
import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase
|
||||
import com.tangem.domain.models.network.CryptoCurrencyAddress
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.isLocked
|
||||
|
|
@ -64,7 +67,10 @@ internal class SendDestinationModel @Inject constructor(
|
|||
private val isSelfSendAvailableUseCase: IsSelfSendAvailableUseCase,
|
||||
private val listenToQrScanningUseCase: ListenToQrScanningUseCase,
|
||||
private val parseQrCodeUseCase: ParseQrCodeUseCase,
|
||||
private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase,
|
||||
private val getAccountCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
) : Model(), SendDestinationClickIntents {
|
||||
private val params: SendDestinationComponentParams = paramsContainer.require()
|
||||
|
||||
|
|
@ -142,7 +148,7 @@ internal class SendDestinationModel @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
fun saveResult() {
|
||||
private fun saveResult() {
|
||||
val params = params as? SendDestinationComponentParams.DestinationParams ?: return
|
||||
params.callback.onDestinationResult(uiState.value)
|
||||
}
|
||||
|
|
@ -193,12 +199,17 @@ internal class SendDestinationModel @Inject constructor(
|
|||
).getOrElse { flowOf(emptyList()) }.map {
|
||||
waitForDelay(RECENT_LOAD_DELAY) { it }
|
||||
}.conflate(),
|
||||
) { destinationWalletList, txHistoryList ->
|
||||
flow3 = isAccountsModeEnabledUseCase().distinctUntilChanged(),
|
||||
flow4 = if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
getAccountCurrencyStatusUseCase(userWalletId, cryptoCurrency).distinctUntilChanged()
|
||||
} else {
|
||||
flowOf(null)
|
||||
},
|
||||
) { destinationWalletList, txHistoryList, isAccountsMode, accountCurrencyStatus ->
|
||||
val isSelfSendAvailable = isSelfSendAvailableUseCase.invokeSync(
|
||||
userWalletId = userWalletId,
|
||||
network = cryptoCurrency.network,
|
||||
)
|
||||
|
||||
_uiState.update(
|
||||
SendDestinationRecentListTransformer(
|
||||
cryptoCurrency = cryptoCurrency,
|
||||
|
|
@ -206,9 +217,11 @@ internal class SendDestinationModel @Inject constructor(
|
|||
isSelfSendAvailable = isSelfSendAvailable,
|
||||
destinationWalletList = destinationWalletList,
|
||||
txHistoryList = txHistoryList,
|
||||
account = accountCurrencyStatus?.account,
|
||||
isAccountsMode = isAccountsMode,
|
||||
),
|
||||
)
|
||||
}.launchIn(modelScope)
|
||||
}.flowOn(dispatchers.default).launchIn(modelScope)
|
||||
}
|
||||
|
||||
private suspend fun List<UserWallet>.toAvailableWallets(): List<DestinationWalletUM> {
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ internal class SendDestinationInitialStateTransformer(
|
|||
isValuePasted = false,
|
||||
)
|
||||
},
|
||||
accountTitleUM = null,
|
||||
wallets = loadingListState(WALLET_KEY_TAG, WALLET_DEFAULT_COUNT),
|
||||
recent = loadingListState(RECENT_KEY_TAG, RECENT_DEFAULT_COUNT),
|
||||
networkName = cryptoCurrency.network.name,
|
||||
|
|
|
|||
|
|
@ -1,24 +1,42 @@
|
|||
package com.tangem.features.send.v2.subcomponents.destination.model.transformers
|
||||
|
||||
import com.tangem.common.ui.account.AccountTitleUM
|
||||
import com.tangem.common.ui.account.toUM
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.TxInfo
|
||||
import com.tangem.features.send.v2.api.subcomponents.destination.entity.DestinationUM
|
||||
import com.tangem.features.send.v2.subcomponents.destination.model.converters.SendRecipientHistoryListConverter
|
||||
import com.tangem.features.send.v2.subcomponents.destination.model.converters.SendRecipientWalletListConverter
|
||||
import com.tangem.features.send.v2.subcomponents.destination.ui.state.DestinationWalletUM
|
||||
import com.tangem.utils.StringsSigns
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class SendDestinationRecentListTransformer(
|
||||
private val senderAddress: String?,
|
||||
private val cryptoCurrency: CryptoCurrency,
|
||||
private val isSelfSendAvailable: Boolean,
|
||||
private val destinationWalletList: List<DestinationWalletUM>,
|
||||
private val txHistoryList: List<TxInfo>,
|
||||
private val account: Account.CryptoPortfolio?,
|
||||
private val isAccountsMode: Boolean,
|
||||
) : Transformer<DestinationUM> {
|
||||
override fun transform(prevState: DestinationUM): DestinationUM {
|
||||
val state = prevState as? DestinationUM.Content ?: return prevState
|
||||
|
||||
return state.copy(
|
||||
accountTitleUM = if (account != null && isAccountsMode) {
|
||||
AccountTitleUM.Account(
|
||||
name = account.accountName.toUM().value,
|
||||
icon = account.icon.toUM(),
|
||||
prefixText = stringReference(StringsSigns.DOT),
|
||||
)
|
||||
} else {
|
||||
AccountTitleUM.Text(TextReference.EMPTY)
|
||||
},
|
||||
wallets = SendRecipientWalletListConverter(
|
||||
senderAddress = senderAddress,
|
||||
isSelfSendAvailable = isSelfSendAvailable,
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ private class DestinationBlockPreviewProvider : PreviewParameterProvider<Destina
|
|||
isValidating = false,
|
||||
isInitialized = true,
|
||||
isRecentHidden = false,
|
||||
accountTitleUM = null,
|
||||
)
|
||||
|
||||
override val values: Sequence<DestinationUM.Content>
|
||||
|
|
|
|||
|
|
@ -23,15 +23,22 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.common.ui.account.AccountNameUM
|
||||
import com.tangem.common.ui.account.AccountTitle
|
||||
import com.tangem.common.ui.account.AccountTitleUM
|
||||
import com.tangem.common.ui.account.toUM
|
||||
import com.tangem.core.ui.components.CircleShimmer
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.components.atoms.text.EllipsisText
|
||||
import com.tangem.core.ui.components.atoms.text.TextEllipsis
|
||||
import com.tangem.core.ui.components.icons.identicon.IdentIcon
|
||||
import com.tangem.core.ui.extensions.rememberHapticFeedback
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.domain.models.account.CryptoPortfolioIcon
|
||||
import com.tangem.features.send.v2.impl.R
|
||||
import com.tangem.utils.StringsSigns
|
||||
|
||||
/**
|
||||
* Row item with title and subtitle
|
||||
|
|
@ -50,6 +57,7 @@ fun ListItemWithIcon(
|
|||
subtitle: String,
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
accountTitleUM: AccountTitleUM? = null,
|
||||
info: String? = null,
|
||||
subtitleEndOffset: Int = 0,
|
||||
@DrawableRes subtitleIconRes: Int? = null,
|
||||
|
|
@ -68,6 +76,7 @@ fun ListItemWithIcon(
|
|||
subtitle = subtitle,
|
||||
onClick = onClick,
|
||||
info = info,
|
||||
accountTitleUM = accountTitleUM,
|
||||
subtitleEndOffset = subtitleEndOffset,
|
||||
subtitleIconRes = subtitleIconRes,
|
||||
modifier = modifier,
|
||||
|
|
@ -80,6 +89,7 @@ fun ListItemWithIcon(
|
|||
private fun ListItemWithIcon(
|
||||
title: String,
|
||||
subtitle: String,
|
||||
accountTitleUM: AccountTitleUM?,
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
info: String? = null,
|
||||
|
|
@ -115,7 +125,7 @@ private fun ListItemWithIcon(
|
|||
ellipsis = TextEllipsis.Middle,
|
||||
modifier = Modifier,
|
||||
)
|
||||
Row {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
if (subtitleIconRes != null) {
|
||||
Icon(
|
||||
painter = painterResource(id = subtitleIconRes),
|
||||
|
|
@ -142,6 +152,13 @@ private fun ListItemWithIcon(
|
|||
color = TangemTheme.colors.text.tertiary,
|
||||
ellipsis = TextEllipsis.OffsetEnd(offsetEnd = offset),
|
||||
)
|
||||
if (accountTitleUM != null) {
|
||||
AccountTitle(
|
||||
accountTitleUM = accountTitleUM,
|
||||
textStyle = TangemTheme.typography.caption2,
|
||||
modifier = Modifier.padding(start = 4.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -195,6 +212,7 @@ private fun ListItemWithIconPreview(
|
|||
ListItemWithIcon(
|
||||
title = config.title,
|
||||
subtitle = config.subtitle,
|
||||
accountTitleUM = config.accountTitleUM,
|
||||
subtitleEndOffset = config.subtitleEndOffset,
|
||||
subtitleIconRes = config.iconRes,
|
||||
onClick = {},
|
||||
|
|
@ -206,6 +224,7 @@ private fun ListItemWithIconPreview(
|
|||
private data class ListItemWithIconPreviewConfig(
|
||||
val title: String,
|
||||
val subtitle: String,
|
||||
val accountTitleUM: AccountTitleUM.Account? = null,
|
||||
val info: String? = null,
|
||||
val subtitleEndOffset: Int = 0,
|
||||
val iconRes: Int? = null,
|
||||
|
|
@ -240,6 +259,15 @@ private class ListItemWithIconPreviewProvider : CollectionPreviewParameterProvid
|
|||
iconRes = R.drawable.ic_arrow_down_24,
|
||||
isLoading = true,
|
||||
),
|
||||
ListItemWithIconPreviewConfig(
|
||||
title = "0x34B4492A412D84A6E606288f3Bd714b89135D4dE",
|
||||
subtitle = "Wallet",
|
||||
accountTitleUM = AccountTitleUM.Account(
|
||||
name = AccountNameUM.DefaultMain.value,
|
||||
icon = CryptoPortfolioIcon.ofDefaultCustomAccount().toUM(),
|
||||
prefixText = stringReference(StringsSigns.DOT),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
//endregion
|
||||
|
|
@ -21,7 +21,9 @@ import androidx.compose.ui.text.buildAnnotatedString
|
|||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.common.ui.account.AccountTitleUM
|
||||
import com.tangem.core.ui.components.SpacerH
|
||||
import com.tangem.core.ui.components.TextShimmer
|
||||
import com.tangem.core.ui.components.containers.FooterContainer
|
||||
import com.tangem.core.ui.components.inputrow.InputRowRecipient
|
||||
import com.tangem.core.ui.extensions.*
|
||||
|
|
@ -46,7 +48,6 @@ internal fun SendDestinationContent(
|
|||
if (state !is DestinationUM.Content) return
|
||||
val recipients = state.recent
|
||||
val wallets = state.wallets
|
||||
val memoField = state.memoTextField
|
||||
val address = state.addressTextField
|
||||
val isValidating by remember(state.isValidating) { derivedStateOf { state.isValidating } }
|
||||
val isError by remember(address.isError) { derivedStateOf { address.isError } }
|
||||
|
|
@ -64,18 +65,23 @@ internal fun SendDestinationContent(
|
|||
onQrCodeClick = clickIntents::onQrCodeScanClick,
|
||||
)
|
||||
memoField(
|
||||
memoField = memoField,
|
||||
memoField = state.memoTextField,
|
||||
onMemoChange = clickIntents::onRecipientMemoValueChange,
|
||||
)
|
||||
listHeaderItem(
|
||||
titleRes = R.string.send_recipient_wallets_title,
|
||||
titleRes = when (state.accountTitleUM) {
|
||||
is AccountTitleUM.Account -> R.string.common_accounts
|
||||
else -> R.string.send_recipient_wallets_title
|
||||
},
|
||||
isLoading = state.accountTitleUM == null,
|
||||
isVisible = wallets.isNotEmpty() && wallets.first().isVisible && !state.isRecentHidden,
|
||||
isFirst = true,
|
||||
)
|
||||
listItem(
|
||||
list = wallets,
|
||||
isLast = recipients.any { !it.isVisible },
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
accountTitleUM = state.accountTitleUM,
|
||||
isBalanceHidden = false,
|
||||
isRecentHidden = state.isRecentHidden,
|
||||
onClick = { title ->
|
||||
clickIntents.onRecipientAddressValueChange(
|
||||
|
|
@ -86,6 +92,7 @@ internal fun SendDestinationContent(
|
|||
)
|
||||
listHeaderItem(
|
||||
titleRes = R.string.send_recent_transactions,
|
||||
isLoading = state.accountTitleUM == null,
|
||||
isVisible = recipients.isNotEmpty() && recipients.first().isVisible && !state.isRecentHidden,
|
||||
isFirst = wallets.any { !it.isVisible },
|
||||
)
|
||||
|
|
@ -180,7 +187,12 @@ private fun LazyListScope.memoField(
|
|||
}
|
||||
}
|
||||
|
||||
private fun LazyListScope.listHeaderItem(@StringRes titleRes: Int, isVisible: Boolean, isFirst: Boolean) {
|
||||
private fun LazyListScope.listHeaderItem(
|
||||
@StringRes titleRes: Int,
|
||||
isVisible: Boolean,
|
||||
isLoading: Boolean,
|
||||
isFirst: Boolean,
|
||||
) {
|
||||
item(key = titleRes) {
|
||||
AnimateRecentAppearance(isVisible) {
|
||||
val (topPadding, paddingFromTop) = if (isFirst) {
|
||||
|
|
@ -189,10 +201,8 @@ private fun LazyListScope.listHeaderItem(@StringRes titleRes: Int, isVisible: Bo
|
|||
0.dp to 8.dp
|
||||
}
|
||||
val topRadius = if (isFirst) 16.dp else 0.dp
|
||||
Text(
|
||||
text = stringResourceSafe(titleRes),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
AnimatedContent(
|
||||
targetState = isLoading,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = topPadding)
|
||||
|
|
@ -209,7 +219,22 @@ private fun LazyListScope.listHeaderItem(@StringRes titleRes: Int, isVisible: Bo
|
|||
start = 12.dp,
|
||||
end = 12.dp,
|
||||
),
|
||||
)
|
||||
) { currentIsLoading ->
|
||||
if (currentIsLoading) {
|
||||
Box {
|
||||
TextShimmer(
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
text = stringResourceSafe(titleRes),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Text(
|
||||
text = stringResourceSafe(titleRes),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -220,6 +245,7 @@ private fun LazyListScope.listItem(
|
|||
isBalanceHidden: Boolean,
|
||||
isRecentHidden: Boolean,
|
||||
onClick: (String) -> Unit,
|
||||
accountTitleUM: AccountTitleUM? = null,
|
||||
) {
|
||||
items(
|
||||
count = list.size,
|
||||
|
|
@ -233,6 +259,7 @@ private fun LazyListScope.listItem(
|
|||
ListItemWithIcon(
|
||||
title = title,
|
||||
subtitle = item.subtitle.orMaskWithStars(isBalanceHidden).resolveReference(),
|
||||
accountTitleUM = accountTitleUM,
|
||||
info = item.timestamp?.resolveReference(),
|
||||
subtitleEndOffset = item.subtitleEndOffset,
|
||||
subtitleIconRes = item.subtitleIconRes,
|
||||
|
|
|
|||
|
|
@ -201,16 +201,11 @@ class SendConfirmationNotificationsTransformerV2Test {
|
|||
|
||||
return AmountState.Data(
|
||||
isPrimaryButtonEnabled = true,
|
||||
isRedesignEnabled = false,
|
||||
title = mockk(relaxed = true),
|
||||
availableBalance = mockk(relaxed = true),
|
||||
accountTitleUM = mockk(relaxed = true),
|
||||
availableBalanceCrypto = mockk(relaxed = true),
|
||||
availableBalanceFiat = mockk(relaxed = true),
|
||||
tokenName = mockk(relaxed = true),
|
||||
tokenIconState = mockk(relaxed = true),
|
||||
segmentedButtonConfig = persistentListOf(),
|
||||
selectedButton = 0,
|
||||
isSegmentedButtonsEnabled = false,
|
||||
amountTextField = AmountFieldModel(
|
||||
value = "1.5",
|
||||
onValueChange = {},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue