Updated on 2026-08-14

This commit is contained in:
Tangem 2025-06-30 16:34:00 +05:00
parent 0ab1c7507a
commit d14a5cb87a
13 changed files with 255 additions and 100 deletions

View file

@ -82,7 +82,6 @@ internal class ProxyAppRouter(
override fun defaultCompletionHandler(isSuccess: Boolean, errorMessage: String) {
if (!isSuccess) {
Timber.tag("ASDASD").d(errorMessage)
analyticsExceptionHandler.sendException(ExceptionAnalyticsEvent(RuntimeException(errorMessage)))
Timber.w(errorMessage)

View file

@ -30,8 +30,6 @@ fun AmountScreenContent(
clickIntents: AmountScreenClickIntents,
modifier: Modifier = Modifier,
) {
if (amountState !is AmountState.Data) return
// Do not put fillMaxSize() in here
LazyColumn(
modifier = modifier
@ -49,7 +47,7 @@ fun AmountScreenContent(
onCurrencyChange = clickIntents::onCurrencyChangeClick,
onMaxAmountClick = clickIntents::onMaxValueClick,
)
} else {
} else if (amountState is AmountState.Data) {
amountField(
amountState = amountState,
isBalanceHidden = isBalanceHidden,

View file

@ -0,0 +1,46 @@
package com.tangem.common.ui.amountScreen.converters.field
import com.tangem.common.ui.R
import com.tangem.common.ui.amountScreen.models.AmountState
import com.tangem.common.ui.amountScreen.models.EnterAmountBoundary
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.wrappedList
import com.tangem.core.ui.format.bigdecimal.crypto
import com.tangem.core.ui.format.bigdecimal.fiat
import com.tangem.core.ui.format.bigdecimal.format
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.utils.transformer.Transformer
/**
* Updates amount boundaries and revalidates current amount state
*
* @property cryptoCurrencyStatus current cryptocurrency status
* @property maxEnterAmount new maximum enter amount boundary
* @property appCurrency current app currency
* @property isRedesignEnabled whether redesign mode is enabled
*/
class AmountBoundaryUpdateTransformer(
private val cryptoCurrencyStatus: CryptoCurrencyStatus,
private val maxEnterAmount: EnterAmountBoundary,
private val appCurrency: AppCurrency,
private val isRedesignEnabled: Boolean,
) : Transformer<AmountState> {
override fun transform(prevState: AmountState): AmountState {
if (prevState !is AmountState.Data) return prevState
val fiat = maxEnterAmount.fiatAmount.format { fiat(appCurrency.code, appCurrency.symbol) }
val crypto = maxEnterAmount.amount.format { crypto(cryptoCurrencyStatus.currency) }
val availableBalance = if (isRedesignEnabled) {
resourceReference(R.string.common_balance, wrappedList(crypto))
} else {
resourceReference(R.string.common_crypto_fiat_format, wrappedList(crypto, fiat))
}
return prevState.copy(
availableBalance = availableBalance,
)
}
}

View file

@ -100,8 +100,8 @@ class AmountFieldConverterV2(
val cryptoAmount = cryptoDecimal.convertToAmount(cryptoCurrencyStatus.currency)
val fiatRate = cryptoCurrencyStatus.value.fiatRate
val (fiatValue, fiatDecimal) = when {
fiatRate.isNullOrZero() -> "" to null
value.isEmpty() -> "" to BigDecimal.ZERO
fiatRate.isNullOrZero() -> "" to null
else -> {
val fiatDecimal = fiatRate?.multiply(cryptoDecimal)
val fiatValue = fiatDecimal?.parseBigDecimal(FIAT_DECIMALS).orEmpty()

View file

@ -12,6 +12,7 @@ import java.math.BigDecimal
sealed class AmountState {
abstract val isPrimaryButtonEnabled: Boolean
abstract val isRedesignEnabled: Boolean
/**
* @param isPrimaryButtonEnabled indicates if next state button enabled
@ -29,6 +30,7 @@ sealed class AmountState {
*/
data class Data(
override val isPrimaryButtonEnabled: Boolean,
override val isRedesignEnabled: Boolean,
val title: TextReference,
val availableBalance: TextReference,
val tokenName: TextReference,
@ -41,10 +43,10 @@ sealed class AmountState {
val isEditingDisabled: Boolean = false,
val reduceAmountBy: BigDecimal = BigDecimal.ZERO,
val isIgnoreReduce: Boolean = false,
val isRedesignEnabled: Boolean,
) : AmountState()
data class Empty(
override val isPrimaryButtonEnabled: Boolean = false,
override val isRedesignEnabled: Boolean,
) : AmountState()
}

View file

@ -19,7 +19,7 @@ import java.math.BigDecimal
object AmountStatePreviewData {
val emptyState = AmountState.Empty()
val emptyState = AmountState.Empty(isRedesignEnabled = true)
val amountState = AmountState.Data(
isPrimaryButtonEnabled = false,

View file

@ -19,6 +19,7 @@ import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.decompose.navigation.inner.InnerRouter
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.features.send.v2.api.SendComponent
import com.tangem.features.send.v2.common.CommonSendRoute
import com.tangem.features.send.v2.common.analytics.CommonSendAnalyticEvents
@ -57,14 +58,19 @@ internal class DefaultSendComponent @AssistedInject constructor(
popCallback = { onChildBack() },
)
private val model: SendModel = getOrCreateModel(params = params, router = innerRouter)
private val initialRoute = if (params.amount == null) {
CommonSendRoute.Destination(isEditMode = false)
if (model.uiState.value.isRedesignEnabled) {
CommonSendRoute.Amount(isEditMode = false)
} else {
CommonSendRoute.Destination(isEditMode = false)
}
} else {
CommonSendRoute.Empty
}
private val currentRoute = MutableStateFlow(initialRoute)
private val model: SendModel = getOrCreateModel(params = params, router = innerRouter)
private val currentRoute = MutableStateFlow(initialRoute)
private val childStack = childStack(
key = "sendInnerStack",
@ -155,9 +161,14 @@ internal class DefaultSendComponent @AssistedInject constructor(
callback = model,
onBackClick = ::onChildBack,
onNextClick = {
val nextRoute = if (model.uiState.value.isRedesignEnabled) {
CommonSendRoute.Confirm
} else {
CommonSendRoute.Amount(isEditMode = false)
}
innerRouter.safeNextClick(
currentRoute = route,
nextRoute = CommonSendRoute.Amount(isEditMode = false),
nextRoute = nextRoute,
popBack = ::onChildBack,
childStack = childStack,
)
@ -169,50 +180,54 @@ internal class DefaultSendComponent @AssistedInject constructor(
factoryContext: AppComponentContext,
route: CommonSendRoute,
): ComposableContentComponent {
val cryptoCurrencyStatus = model.cryptoCurrencyStatus
return if (cryptoCurrencyStatus != null) {
SendAmountComponent(
appComponentContext = factoryContext,
params = SendAmountComponentParams.AmountParams(
state = model.uiState.value.amountUM,
currentRoute = currentRoute.filterIsInstance<CommonSendRoute.Amount>(),
isBalanceHidingFlow = model.isBalanceHiddenFlow,
analyticsCategoryName = analyticCategoryName,
userWallet = model.userWallet,
appCurrency = model.appCurrency,
cryptoCurrencyStatus = cryptoCurrencyStatus,
callback = model,
predefinedValues = model.predefinedValues,
onBackClick = {
if (route.isEditMode) {
return SendAmountComponent(
appComponentContext = factoryContext,
params = SendAmountComponentParams.AmountParams(
state = model.uiState.value.amountUM,
currentRoute = currentRoute.filterIsInstance<CommonSendRoute.Amount>(),
isBalanceHidingFlow = model.isBalanceHiddenFlow,
analyticsCategoryName = analyticCategoryName,
appCurrency = model.appCurrency,
userWalletId = params.userWalletId,
cryptoCurrency = params.currency,
cryptoCurrencyStatusFlow = model.cryptoCurrencyStatusFlow,
callback = model,
predefinedValues = model.predefinedValues,
onBackClick = {
if (route.isEditMode) {
onChildBack()
} else {
analyticsEventHandler.send(
CommonSendAnalyticEvents.CloseButtonClicked(
categoryName = analyticCategoryName,
source = SendScreenSource.Amount,
isFromSummary = false,
isValid = model.uiState.value.amountUM.isPrimaryButtonEnabled,
),
)
if (model.uiState.value.isRedesignEnabled) {
onChildBack()
} else {
analyticsEventHandler.send(
CommonSendAnalyticEvents.CloseButtonClicked(
categoryName = analyticCategoryName,
source = SendScreenSource.Amount,
isFromSummary = false,
isValid = model.uiState.value.amountUM.isPrimaryButtonEnabled,
),
)
router.pop()
}
},
onNextClick = {
innerRouter.safeNextClick(
currentRoute = route,
nextRoute = CommonSendRoute.Confirm,
popBack = ::onChildBack,
childStack = childStack,
)
},
isRedesignEnabled = model.uiState.value.isRedesignEnabled,
),
)
} else {
model.showAlertError()
getStubComponent()
}
}
},
onNextClick = {
val nextRoute = if (model.uiState.value.isRedesignEnabled) {
CommonSendRoute.Destination(isEditMode = false)
} else {
CommonSendRoute.Confirm
}
innerRouter.safeNextClick(
currentRoute = route,
nextRoute = nextRoute,
popBack = ::onChildBack,
childStack = childStack,
)
},
isRedesignEnabled = model.uiState.value.isRedesignEnabled,
),
)
}
@Suppress("ComplexCondition")
@ -220,8 +235,8 @@ internal class DefaultSendComponent @AssistedInject constructor(
val state = model.uiState.value
val sendAmount = (state.amountUM as? AmountState.Data)?.amountTextField?.cryptoAmount?.value
val destinationAddress = (state.destinationUM as? DestinationUM.Content)?.addressTextField?.value
val cryptoCurrencyStatus = model.cryptoCurrencyStatus
val feeCryptoCurrencyStatus = model.feeCryptoCurrencyStatus
val cryptoCurrencyStatus = model.cryptoCurrencyStatusFlow.value
val feeCryptoCurrencyStatus = model.feeCryptoCurrencyStatusFlow.value
return if (sendAmount != null && destinationAddress != null &&
feeCryptoCurrencyStatus != null && cryptoCurrencyStatus != null
@ -251,10 +266,12 @@ internal class DefaultSendComponent @AssistedInject constructor(
}
private fun getConfirmComponent(factoryContext: AppComponentContext): ComposableContentComponent {
val cryptoCurrencyStatus = model.cryptoCurrencyStatus
val feeCryptoCurrencyStatus = model.feeCryptoCurrencyStatus
val cryptoCurrencyStatus = model.cryptoCurrencyStatusFlow.value
val feeCryptoCurrencyStatus = model.feeCryptoCurrencyStatusFlow.value
return if (cryptoCurrencyStatus != null && feeCryptoCurrencyStatus != null) {
return if (cryptoCurrencyStatus.value != CryptoCurrencyStatus.Loading &&
feeCryptoCurrencyStatus.value != CryptoCurrencyStatus.Loading
) {
SendConfirmComponent(
appComponentContext = factoryContext,
params = SendConfirmComponent.Params(
@ -265,6 +282,8 @@ internal class DefaultSendComponent @AssistedInject constructor(
analyticsCategoryName = analyticCategoryName,
cryptoCurrencyStatus = cryptoCurrencyStatus,
feeCryptoCurrencyStatus = feeCryptoCurrencyStatus,
cryptoCurrencyStatusFlow = model.cryptoCurrencyStatusFlow,
feeCryptoCurrencyStatusFlow = model.feeCryptoCurrencyStatusFlow,
appCurrency = model.appCurrency,
callback = model,
predefinedValues = model.predefinedValues,

View file

@ -31,6 +31,7 @@ import com.tangem.features.send.v2.subcomponents.fee.SendFeeComponentParams
import com.tangem.features.send.v2.subcomponents.notifications.DefaultSendNotificationsComponent
import com.tangem.utils.extensions.orZero
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.StateFlow
internal class SendConfirmComponent(
appComponentContext: AppComponentContext,
@ -62,11 +63,13 @@ internal class SendConfirmComponent(
state = model.uiState.value.amountUM,
analyticsCategoryName = params.analyticsCategoryName,
userWallet = params.userWallet,
cryptoCurrencyStatus = params.cryptoCurrencyStatus,
appCurrency = params.appCurrency,
blockClickEnableFlow = blockClickEnableFlow.asStateFlow(),
predefinedValues = params.predefinedValues,
isRedesignEnabled = model.uiState.value.isRedesignEnabled,
userWalletId = params.userWallet.walletId,
cryptoCurrency = params.cryptoCurrencyStatus.currency,
cryptoCurrencyStatusFlow = params.cryptoCurrencyStatusFlow,
),
onResult = model::onAmountResult,
onClick = model::showEditAmount,
@ -145,6 +148,8 @@ internal class SendConfirmComponent(
val userWallet: UserWallet,
val cryptoCurrencyStatus: CryptoCurrencyStatus,
val feeCryptoCurrencyStatus: CryptoCurrencyStatus,
val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
val feeCryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
val appCurrency: AppCurrency,
val callback: ModelCallback,
val currentRoute: Flow<CommonSendRoute>,

View file

@ -92,7 +92,6 @@ internal class SendModel @Inject constructor(
) : Model(), SendComponentCallback {
private val params: SendComponent.Params = paramsContainer.require()
private val userWalletId = params.userWalletId
private val cryptoCurrency = params.currency
private val _uiState = MutableStateFlow(initialState())
@ -101,9 +100,23 @@ internal class SendModel @Inject constructor(
private val _isBalanceHiddenFlow = MutableStateFlow(false)
val isBalanceHiddenFlow = _isBalanceHiddenFlow.asStateFlow()
private val _cryptoCurrencyStatusFlow = MutableStateFlow(
CryptoCurrencyStatus(
params.currency,
value = CryptoCurrencyStatus.Loading,
),
)
val cryptoCurrencyStatusFlow = _cryptoCurrencyStatusFlow.asStateFlow()
private val _feeCryptoCurrencyStatusFlow = MutableStateFlow(
CryptoCurrencyStatus(
params.currency,
value = CryptoCurrencyStatus.Loading,
),
)
val feeCryptoCurrencyStatusFlow = _feeCryptoCurrencyStatusFlow.asStateFlow()
var userWallet: UserWallet by Delegates.notNull()
var cryptoCurrencyStatus: CryptoCurrencyStatus? = null
var feeCryptoCurrencyStatus: CryptoCurrencyStatus? = null
var appCurrency: AppCurrency = AppCurrency.Default
var predefinedValues: PredefinedValues = PredefinedValues.Empty
@ -279,16 +292,16 @@ internal class SendModel @Inject constructor(
): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
return when {
isSingleWalletWithToken -> getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet(
userWalletId = userWalletId,
userWalletId = params.userWalletId,
currencyId = cryptoCurrency.id,
isSingleWalletWithTokens = true,
)
isMultiCurrency -> getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet(
userWalletId = userWalletId,
userWalletId = params.userWalletId,
currencyId = cryptoCurrency.id,
isSingleWalletWithTokens = false,
)
else -> getSingleCryptoCurrencyStatusUseCase.invokeSingleWallet(userWalletId = userWalletId)
else -> getSingleCryptoCurrencyStatusUseCase.invokeSingleWallet(userWalletId = params.userWalletId)
}
}
@ -298,7 +311,7 @@ internal class SendModel @Inject constructor(
): CryptoCurrencyStatus {
return if (isMultiCurrency) {
getFeePaidCryptoCurrencyStatusSyncUseCase(
userWalletId = userWalletId,
userWalletId = params.userWalletId,
cryptoCurrencyStatus = cryptoCurrencyStatus,
).getOrNull() ?: cryptoCurrencyStatus
} else {
@ -307,8 +320,8 @@ internal class SendModel @Inject constructor(
}
private fun onDataLoaded(currencyStatus: CryptoCurrencyStatus, feeCurrencyStatus: CryptoCurrencyStatus) {
cryptoCurrencyStatus = currencyStatus
feeCryptoCurrencyStatus = feeCurrencyStatus
_cryptoCurrencyStatusFlow.value = currencyStatus
_feeCryptoCurrencyStatusFlow.value = feeCurrencyStatus
if (params.amount != null) {
router.replaceAll(CommonSendRoute.Confirm)
@ -360,7 +373,7 @@ internal class SendModel @Inject constructor(
}
private fun initialState(): SendUM = SendUM(
amountUM = AmountState.Empty(),
amountUM = AmountState.Empty(isRedesignEnabled = sendFeatureToggles.isSendRedesignEnabled),
destinationUM = SendDestinationInitialStateTransformer(
cryptoCurrency = cryptoCurrency,
isRedesignEnabled = sendFeatureToggles.isSendRedesignEnabled,

View file

@ -2,8 +2,10 @@ 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.currency.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.features.send.v2.common.CommonSendRoute
import com.tangem.features.send.v2.common.PredefinedValues
import com.tangem.features.send.v2.subcomponents.amount.SendAmountComponent.ModelCallback
@ -14,20 +16,22 @@ internal sealed class SendAmountComponentParams {
abstract val state: AmountState
abstract val analyticsCategoryName: String
abstract val userWallet: UserWallet
abstract val userWalletId: UserWalletId
abstract val appCurrency: AppCurrency
abstract val cryptoCurrencyStatus: CryptoCurrencyStatus
abstract val predefinedValues: PredefinedValues
abstract val isRedesignEnabled: Boolean
abstract val cryptoCurrency: CryptoCurrency
abstract val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>
data class AmountParams(
override val state: AmountState,
override val analyticsCategoryName: String,
override val userWallet: UserWallet,
override val userWalletId: UserWalletId,
override val appCurrency: AppCurrency,
override val cryptoCurrencyStatus: CryptoCurrencyStatus,
override val predefinedValues: PredefinedValues,
override val isRedesignEnabled: Boolean,
override val cryptoCurrency: CryptoCurrency,
override val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
val callback: ModelCallback,
val currentRoute: Flow<CommonSendRoute.Amount>,
val isBalanceHidingFlow: StateFlow<Boolean>,
@ -38,11 +42,13 @@ internal sealed class SendAmountComponentParams {
data class AmountBlockParams(
override val state: AmountState,
override val analyticsCategoryName: String,
override val userWallet: UserWallet,
override val appCurrency: AppCurrency,
override val cryptoCurrencyStatus: CryptoCurrencyStatus,
override val userWalletId: UserWalletId,
override val predefinedValues: PredefinedValues,
override val isRedesignEnabled: Boolean,
override val cryptoCurrency: CryptoCurrency,
override val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
val userWallet: UserWallet,
val blockClickEnableFlow: StateFlow<Boolean>,
) : SendAmountComponentParams()
}

View file

@ -1,10 +1,13 @@
package com.tangem.features.send.v2.subcomponents.amount.model
import androidx.compose.runtime.Stable
import arrow.core.getOrElse
import com.tangem.common.ui.amountScreen.AmountScreenClickIntents
import com.tangem.common.ui.amountScreen.converters.*
import com.tangem.common.ui.amountScreen.converters.field.AmountFieldChangeTransformer
import com.tangem.common.ui.amountScreen.converters.field.AmountFieldSetMaxAmountTransformer
import com.tangem.common.ui.amountScreen.converters.field.AmountBoundaryUpdateTransformer
import com.tangem.common.ui.amountScreen.converters.MaxEnterAmountConverter
import com.tangem.common.ui.amountScreen.models.AmountParameters
import com.tangem.common.ui.amountScreen.models.AmountState
import com.tangem.common.ui.amountScreen.models.EnterAmountBoundary
@ -14,9 +17,14 @@ import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.WrappedList
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.tokens.GetMinimumTransactionAmountSyncUseCase
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.features.send.v2.api.SendFeatureToggles
import com.tangem.features.send.v2.common.PredefinedValues
import com.tangem.features.send.v2.common.ui.state.NavigationUM
@ -36,6 +44,7 @@ import com.tangem.utils.transformer.update
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import javax.inject.Inject
import kotlin.properties.Delegates
@Suppress("LongParameterList")
@Stable
@ -49,33 +58,59 @@ internal class SendAmountModel @Inject constructor(
private val sendAmountUpdateQRListener: SendAmountUpdateQRListener,
private val analyticsEventHandler: AnalyticsEventHandler,
private val sendFeatureToggles: SendFeatureToggles,
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
private val getUserWalletUseCase: GetUserWalletUseCase,
) : Model(), AmountScreenClickIntents {
private val params: SendAmountComponentParams = paramsContainer.require()
private var appCurrency: AppCurrency = AppCurrency.Default
private var userWallet: UserWallet? = null
private val _uiState = MutableStateFlow(params.state)
val uiState = _uiState.asStateFlow()
private val analyticsCategoryName = params.analyticsCategoryName
private val userWallet = params.userWallet
private val cryptoCurrencyStatus = params.cryptoCurrencyStatus
private var cryptoCurrencyStatus: CryptoCurrencyStatus = CryptoCurrencyStatus(
currency = params.cryptoCurrency,
value = CryptoCurrencyStatus.Loading,
)
private var minAmountBoundary: EnterAmountBoundary? = null
private var maxAmountBoundary: EnterAmountBoundary = MaxEnterAmountConverter().convert(cryptoCurrencyStatus)
private var maxAmountBoundary: EnterAmountBoundary by Delegates.notNull()
init {
configAmountNavigation()
initMinBoundary()
subscribeOnAmountReduceByTriggerUpdates()
subscribeOnAmountReduceToTriggerUpdates()
subscribeOnAmountIgnoreReduceTriggerUpdates()
subscribeOnAmountUpdateQRTriggerUpdates()
initAppCurrency()
subscribeOnCryptoCurrencyStatusFlow()
}
private fun initAppCurrency() {
modelScope.launch {
userWallet = getUserWalletUseCase(params.userWalletId).getOrNull()
appCurrency = getSelectedAppCurrencyUseCase.invokeSync().getOrElse { AppCurrency.Default }
}
}
private fun subscribeOnCryptoCurrencyStatusFlow() {
params.cryptoCurrencyStatusFlow
.onEach { newCryptoCurrencyStatus ->
cryptoCurrencyStatus = newCryptoCurrencyStatus
maxAmountBoundary = MaxEnterAmountConverter().convert(cryptoCurrencyStatus)
if (uiState.value is AmountState.Empty) {
subscribeOnAmountReduceByTriggerUpdates()
subscribeOnAmountReduceToTriggerUpdates()
subscribeOnAmountIgnoreReduceTriggerUpdates()
subscribeOnAmountUpdateQRTriggerUpdates()
}
initMinBoundary()
}
.launchIn(modelScope)
}
private fun initMinBoundary() {
modelScope.launch {
minAmountBoundary = getMinimumTransactionAmountSyncUseCase(
userWalletId = userWallet.walletId,
userWalletId = params.userWalletId,
cryptoCurrencyStatus = cryptoCurrencyStatus,
).getOrNull()?.let {
EnterAmountBoundary(
@ -84,23 +119,37 @@ internal class SendAmountModel @Inject constructor(
)
}
initialState()
if (uiState.value is AmountState.Data) {
_uiState.update(
AmountBoundaryUpdateTransformer(
cryptoCurrencyStatus = cryptoCurrencyStatus,
maxEnterAmount = maxAmountBoundary,
appCurrency = appCurrency,
isRedesignEnabled = sendFeatureToggles.isSendRedesignEnabled,
),
)
} else {
initialState()
}
}
}
private fun initialState() {
if (uiState.value is AmountState.Empty) {
if (uiState.value is AmountState.Empty && userWallet != null) {
_uiState.update {
AmountStateConverterV2(
clickIntents = this,
appCurrency = params.appCurrency,
appCurrency = appCurrency,
cryptoCurrencyStatus = cryptoCurrencyStatus,
maxEnterAmount = maxAmountBoundary,
iconStateConverter = CryptoCurrencyToIconStateConverter(),
isRedesignEnabled = sendFeatureToggles.isSendRedesignEnabled,
).convert(
AmountParameters(
title = stringReference(userWallet.name),
title = resourceReference(
R.string.send_from_wallet_name,
WrappedList(listOf(userWallet?.name.orEmpty())), // TODO [REDACTED_TASK_KEY]
),
value = "",
),
)
@ -242,7 +291,7 @@ internal class SendAmountModel @Inject constructor(
NavigationUM.Content(
title = resourceReference(R.string.send_amount_label),
subtitle = null,
backIconRes = if (route.isEditMode) {
backIconRes = if (route.isEditMode || params.isRedesignEnabled) {
R.drawable.ic_back_24
} else {
R.drawable.ic_close_24
@ -260,15 +309,19 @@ internal class SendAmountModel @Inject constructor(
params.onNextClick()
},
),
prevButton = ButtonsUM.PrimaryButtonUM(
text = TextReference.EMPTY,
iconResId = R.drawable.ic_back_24,
isEnabled = true,
onClick = {
saveResult()
params.onBackClick()
},
).takeIf { route.isEditMode.not() },
prevButton = if (params.isRedesignEnabled) {
null
} else {
ButtonsUM.PrimaryButtonUM(
text = TextReference.EMPTY,
iconResId = R.drawable.ic_back_24,
isEnabled = true,
onClick = {
saveResult()
params.onBackClick()
},
).takeIf { route.isEditMode.not() }
},
secondaryPairButtonsUM = null,
),
)

View file

@ -8,6 +8,7 @@ import com.tangem.core.decompose.di.ModelScoped
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.TextReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.domain.models.network.CryptoCurrencyAddress
import com.tangem.domain.qrscanning.models.SourceType
@ -293,6 +294,7 @@ internal class SendDestinationModel @Inject constructor(
params.callback.onDestinationResult(uiState.value)
}
@Suppress("LongMethod")
private fun configDestinationNavigation() {
val params = params as? SendDestinationComponentParams.DestinationParams ?: return
combine(
@ -305,7 +307,7 @@ internal class SendDestinationModel @Inject constructor(
NavigationUM.Content(
title = params.title,
subtitle = null,
backIconRes = if (route.isEditMode) {
backIconRes = if (route.isEditMode || isRedesignEnabled) {
R.drawable.ic_back_24
} else {
R.drawable.ic_close_24
@ -345,7 +347,19 @@ internal class SendDestinationModel @Inject constructor(
params.onNextClick()
},
),
prevButton = null,
prevButton = if (isRedesignEnabled) {
ButtonsUM.PrimaryButtonUM(
text = TextReference.EMPTY,
iconResId = R.drawable.ic_back_24,
isEnabled = true,
onClick = {
saveResult()
params.onBackClick()
},
)
} else {
null
},
secondaryPairButtonsUM = null,
),
)

View file

@ -78,7 +78,7 @@ internal class StakingStateController @Inject constructor(
cryptoCurrencyBlockchainId = "",
currentStep = StakingStep.InitialInfo,
initialInfoState = StakingStates.InitialInfoState.Empty(),
amountState = AmountState.Empty(),
amountState = AmountState.Empty(isRedesignEnabled = false),
validatorState = StakingStates.ValidatorState.Empty(),
rewardsValidatorsState = StakingStates.RewardsValidatorsState.Empty(),
confirmationState = StakingStates.ConfirmationState.Empty(),