Updated on 2026-08-14

This commit is contained in:
Tangem 2025-08-29 13:18:48 +05:00
commit 69d0f963fd
8 changed files with 69 additions and 5 deletions

View file

@ -13,6 +13,7 @@ import com.tangem.core.ui.extensions.combinedReference
import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.extensions.wrappedList import com.tangem.core.ui.extensions.wrappedList
import com.tangem.core.ui.extensions.orMaskWithStars
import com.tangem.core.ui.format.bigdecimal.crypto import com.tangem.core.ui.format.bigdecimal.crypto
import com.tangem.core.ui.format.bigdecimal.fiat import com.tangem.core.ui.format.bigdecimal.fiat
import com.tangem.core.ui.format.bigdecimal.format import com.tangem.core.ui.format.bigdecimal.format
@ -97,7 +98,9 @@ class AmountStateConverter(
* @property maxEnterAmount max enter amount data * @property maxEnterAmount max enter amount data
* @property cryptoCurrencyStatus current cryptocurrency status * @property cryptoCurrencyStatus current cryptocurrency status
* @property iconStateConverter currency icon converter * @property iconStateConverter currency icon converter
* @property isBalanceHidden is balance hidden status
*/ */
@Suppress("LongParameterList")
class AmountStateConverterV2( class AmountStateConverterV2(
private val clickIntents: AmountScreenClickIntents, private val clickIntents: AmountScreenClickIntents,
private val appCurrency: AppCurrency, private val appCurrency: AppCurrency,
@ -105,6 +108,7 @@ class AmountStateConverterV2(
private val maxEnterAmount: EnterAmountBoundary, private val maxEnterAmount: EnterAmountBoundary,
private val iconStateConverter: CryptoCurrencyToIconStateConverter, private val iconStateConverter: CryptoCurrencyToIconStateConverter,
private val isRedesignEnabled: Boolean, private val isRedesignEnabled: Boolean,
private val isBalanceHidden: Boolean,
) : Converter<AmountParameters, AmountState> { ) : Converter<AmountParameters, AmountState> {
private val amountFieldConverter by lazy(LazyThreadSafetyMode.NONE) { private val amountFieldConverter by lazy(LazyThreadSafetyMode.NONE) {
@ -133,11 +137,12 @@ class AmountStateConverterV2(
stringReference(crypto), stringReference(crypto),
stringReference(" $DOT "), stringReference(" $DOT "),
stringReference(fiat), stringReference(fiat),
) ).orMaskWithStars(isBalanceHidden)
} else { } else {
resourceReference(R.string.common_crypto_fiat_format, wrappedList(crypto, fiat)) resourceReference(R.string.common_crypto_fiat_format, wrappedList(crypto, fiat))
.orMaskWithStars(isBalanceHidden)
}, },
availableBalanceShort = stringReference(crypto), availableBalanceShort = stringReference(crypto).orMaskWithStars(isBalanceHidden),
tokenName = stringReference(cryptoCurrencyStatus.currency.name), tokenName = stringReference(cryptoCurrencyStatus.currency.name),
tokenIconState = iconStateConverter.convert(cryptoCurrencyStatus.currency), tokenIconState = iconStateConverter.convert(cryptoCurrencyStatus.currency),
amountTextField = amountFieldConverter.convert(value.value), amountTextField = amountFieldConverter.convert(value.value),

View file

@ -7,6 +7,7 @@ import com.tangem.core.ui.extensions.combinedReference
import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.extensions.wrappedList import com.tangem.core.ui.extensions.wrappedList
import com.tangem.core.ui.extensions.orMaskWithStars
import com.tangem.core.ui.format.bigdecimal.crypto import com.tangem.core.ui.format.bigdecimal.crypto
import com.tangem.core.ui.format.bigdecimal.fiat import com.tangem.core.ui.format.bigdecimal.fiat
import com.tangem.core.ui.format.bigdecimal.format import com.tangem.core.ui.format.bigdecimal.format
@ -28,6 +29,7 @@ class AmountBoundaryUpdateTransformer(
private val maxEnterAmount: EnterAmountBoundary, private val maxEnterAmount: EnterAmountBoundary,
private val appCurrency: AppCurrency, private val appCurrency: AppCurrency,
private val isRedesignEnabled: Boolean, private val isRedesignEnabled: Boolean,
private val isBalanceHidden: Boolean,
) : Transformer<AmountState> { ) : Transformer<AmountState> {
override fun transform(prevState: AmountState): AmountState { override fun transform(prevState: AmountState): AmountState {
@ -47,8 +49,8 @@ class AmountBoundaryUpdateTransformer(
} }
return prevState.copy( return prevState.copy(
availableBalance = availableBalance, availableBalance = availableBalance.orMaskWithStars(isBalanceHidden),
availableBalanceShort = stringReference(crypto), availableBalanceShort = stringReference(crypto).orMaskWithStars(isBalanceHidden),
) )
} }
} }

View file

@ -72,6 +72,7 @@ internal class SendConfirmComponent(
userWalletId = params.userWallet.walletId, userWalletId = params.userWallet.walletId,
cryptoCurrency = params.cryptoCurrencyStatus.currency, cryptoCurrency = params.cryptoCurrencyStatus.currency,
cryptoCurrencyStatusFlow = params.cryptoCurrencyStatusFlow, cryptoCurrencyStatusFlow = params.cryptoCurrencyStatusFlow,
isBalanceHidingFlow = params.isBalanceHidingFlow,
), ),
onResult = model::onAmountResult, onResult = model::onAmountResult,
onClick = model::showEditAmount, onClick = model::showEditAmount,

View file

@ -28,6 +28,7 @@ import com.tangem.domain.feedback.models.FeedbackEmailType
import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.requireColdWallet import com.tangem.domain.models.wallet.requireColdWallet
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
import com.tangem.domain.settings.IsSendTapHelpEnabledUseCase import com.tangem.domain.settings.IsSendTapHelpEnabledUseCase
import com.tangem.domain.settings.NeverShowTapHelpUseCase import com.tangem.domain.settings.NeverShowTapHelpUseCase
import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
@ -105,6 +106,7 @@ internal class SendConfirmModel @Inject constructor(
private val feeSelectorReloadTrigger: FeeSelectorReloadTrigger, private val feeSelectorReloadTrigger: FeeSelectorReloadTrigger,
private val feeReloadTrigger: SendFeeReloadTrigger, private val feeReloadTrigger: SendFeeReloadTrigger,
private val sendAmountReduceTrigger: SendAmountReduceTrigger, private val sendAmountReduceTrigger: SendAmountReduceTrigger,
private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
sendBalanceUpdaterFactory: SendBalanceUpdater.Factory, sendBalanceUpdaterFactory: SendBalanceUpdater.Factory,
) : Model(), SendConfirmClickIntents, FeeSelectorModelCallback, SendNotificationsComponent.ModelCallback { ) : Model(), SendConfirmClickIntents, FeeSelectorModelCallback, SendNotificationsComponent.ModelCallback {
@ -121,6 +123,9 @@ internal class SendConfirmModel @Inject constructor(
private val _uiState = MutableStateFlow(params.state) private val _uiState = MutableStateFlow(params.state)
val uiState = _uiState.asStateFlow() val uiState = _uiState.asStateFlow()
val isBalanceHiddenFlow: StateFlow<Boolean>
field = MutableStateFlow(false)
private val amountState private val amountState
get() = uiState.value.amountUM as? AmountState.Data get() = uiState.value.amountUM as? AmountState.Data
private val destinationUM private val destinationUM
@ -164,6 +169,7 @@ internal class SendConfirmModel @Inject constructor(
subscribeOnNotificationsUpdateTrigger() subscribeOnNotificationsUpdateTrigger()
subscribeOnCheckFeeResultUpdates() subscribeOnCheckFeeResultUpdates()
initialState() initialState()
subscribeOnBalanceHidden()
} }
fun updateState(state: SendUM) { fun updateState(state: SendUM) {
@ -519,6 +525,16 @@ internal class SendConfirmModel @Inject constructor(
}.launchIn(modelScope) }.launchIn(modelScope)
} }
private fun subscribeOnBalanceHidden() {
getBalanceHidingSettingsUseCase()
.conflate()
.distinctUntilChanged()
.onEach { balanceHidingSettings ->
isBalanceHiddenFlow.update { balanceHidingSettings.isBalanceHidden }
}
.launchIn(modelScope)
}
private fun updateConfirmNotifications() { private fun updateConfirmNotifications() {
modelScope.launch { modelScope.launch {
notificationsUpdateTrigger.triggerUpdate( notificationsUpdateTrigger.triggerUpdate(

View file

@ -21,6 +21,7 @@ internal sealed class SendAmountComponentParams {
abstract val isRedesignEnabled: Boolean abstract val isRedesignEnabled: Boolean
abstract val cryptoCurrency: CryptoCurrency abstract val cryptoCurrency: CryptoCurrency
abstract val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus> abstract val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>
abstract val isBalanceHidingFlow: StateFlow<Boolean>
data class AmountParams( data class AmountParams(
override val state: AmountState, override val state: AmountState,
@ -31,9 +32,9 @@ internal sealed class SendAmountComponentParams {
override val isRedesignEnabled: Boolean, override val isRedesignEnabled: Boolean,
override val cryptoCurrency: CryptoCurrency, override val cryptoCurrency: CryptoCurrency,
override val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>, override val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
override val isBalanceHidingFlow: StateFlow<Boolean>,
val callback: ModelCallback, val callback: ModelCallback,
val currentRoute: StateFlow<CommonSendRoute>, val currentRoute: StateFlow<CommonSendRoute>,
val isBalanceHidingFlow: StateFlow<Boolean>,
) : SendAmountComponentParams() ) : SendAmountComponentParams()
data class AmountBlockParams( data class AmountBlockParams(
@ -45,6 +46,7 @@ internal sealed class SendAmountComponentParams {
override val isRedesignEnabled: Boolean, override val isRedesignEnabled: Boolean,
override val cryptoCurrency: CryptoCurrency, override val cryptoCurrency: CryptoCurrency,
override val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>, override val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
override val isBalanceHidingFlow: StateFlow<Boolean>,
val userWallet: UserWallet, val userWallet: UserWallet,
val blockClickEnableFlow: StateFlow<Boolean>, val blockClickEnableFlow: StateFlow<Boolean>,
) : SendAmountComponentParams() ) : SendAmountComponentParams()

View file

@ -102,6 +102,7 @@ internal class SendAmountModel @Inject constructor(
subscribeOnAmountReduceToTriggerUpdates() subscribeOnAmountReduceToTriggerUpdates()
subscribeOnAmountIgnoreReduceTriggerUpdates() subscribeOnAmountIgnoreReduceTriggerUpdates()
subscribeOnAmountUpdateTriggerUpdates() subscribeOnAmountUpdateTriggerUpdates()
subscribeOnBalanceHiddenUpdates()
} }
private fun initAppCurrency() { private fun initAppCurrency() {
@ -119,6 +120,20 @@ internal class SendAmountModel @Inject constructor(
}.launchIn(modelScope) }.launchIn(modelScope)
} }
private fun subscribeOnBalanceHiddenUpdates() {
params.isBalanceHidingFlow.onEach { isBalanceHidden ->
_uiState.update(
AmountBoundaryUpdateTransformer(
cryptoCurrencyStatus = cryptoCurrencyStatus,
maxEnterAmount = maxAmountBoundary,
appCurrency = appCurrency,
isRedesignEnabled = sendFeatureToggles.isSendRedesignEnabled,
isBalanceHidden = params.isBalanceHidingFlow.value,
),
)
}.launchIn(modelScope)
}
private fun subscribeOnCryptoCurrencyStatusFlow() { private fun subscribeOnCryptoCurrencyStatusFlow() {
params.cryptoCurrencyStatusFlow params.cryptoCurrencyStatusFlow
.onEach { newCryptoCurrencyStatus -> .onEach { newCryptoCurrencyStatus ->
@ -150,6 +165,7 @@ internal class SendAmountModel @Inject constructor(
maxEnterAmount = maxAmountBoundary, maxEnterAmount = maxAmountBoundary,
appCurrency = appCurrency, appCurrency = appCurrency,
isRedesignEnabled = sendFeatureToggles.isSendRedesignEnabled, isRedesignEnabled = sendFeatureToggles.isSendRedesignEnabled,
isBalanceHidden = params.isBalanceHidingFlow.value,
), ),
) )
} else { } else {
@ -168,6 +184,7 @@ internal class SendAmountModel @Inject constructor(
maxEnterAmount = maxAmountBoundary, maxEnterAmount = maxAmountBoundary,
iconStateConverter = CryptoCurrencyToIconStateConverter(), iconStateConverter = CryptoCurrencyToIconStateConverter(),
isRedesignEnabled = sendFeatureToggles.isSendRedesignEnabled, isRedesignEnabled = sendFeatureToggles.isSendRedesignEnabled,
isBalanceHidden = params.isBalanceHidingFlow.value,
).convert( ).convert(
AmountParameters( AmountParameters(
title = resourceReference( title = resourceReference(

View file

@ -131,6 +131,7 @@ internal class SwapAmountModel @Inject constructor(
subscribeOnAmountReduceByTriggerUpdates() subscribeOnAmountReduceByTriggerUpdates()
subscribeOnAmountIgnoreReduceTriggerUpdates() subscribeOnAmountIgnoreReduceTriggerUpdates()
subscribeOnReloadQuotesTriggerUpdates() subscribeOnReloadQuotesTriggerUpdates()
subscribeOnBalanceHiddenUpdates()
} }
fun onStart() { fun onStart() {
@ -322,6 +323,25 @@ internal class SwapAmountModel @Inject constructor(
) )
} }
private fun subscribeOnBalanceHiddenUpdates() {
params.isBalanceHidingFlow.onEach {
val primaryCryptoCurrencyStatus = (uiState.value as? SwapAmountUM.Content)?.primaryCryptoCurrencyStatus
if (primaryCryptoCurrencyStatus != null) {
uiState.transformerUpdate(
SwapAmountPrimaryReadyStateTransformer(
userWallet = userWallet,
primaryCryptoCurrencyStatus = primaryCryptoCurrencyStatus,
appCurrency = appCurrency,
swapDirection = swapDirection,
clickIntents = this,
isBalanceHidden = params.isBalanceHidingFlow.value,
showBestRateAnimation = showBestRateAnimation,
),
)
}
}.launchIn(modelScope)
}
private fun confirmSendWithSwapClose() { private fun confirmSendWithSwapClose() {
val amountParams = params as? SwapAmountComponentParams.AmountParams ?: return val amountParams = params as? SwapAmountComponentParams.AmountParams ?: return
val amountFieldData = uiState.value.primaryAmount.amountField as? AmountState.Data val amountFieldData = uiState.value.primaryAmount.amountField as? AmountState.Data

View file

@ -48,6 +48,7 @@ internal class SwapAmountFieldConverter(
maxEnterAmount = maxEnterAmountConverter.convert(cryptoCurrencyStatus), maxEnterAmount = maxEnterAmountConverter.convert(cryptoCurrencyStatus),
iconStateConverter = iconStateConverter, iconStateConverter = iconStateConverter,
isRedesignEnabled = true, isRedesignEnabled = true,
isBalanceHidden = isBalanceHidden,
).convert( ).convert(
AmountParameters( AmountParameters(
title = combinedReference( title = combinedReference(