Updated on 2026-08-14
This commit is contained in:
parent
7cc1bb7379
commit
ea30176490
14 changed files with 156 additions and 43 deletions
|
|
@ -127,7 +127,7 @@ internal class SetInitialDataStateTransformer(
|
|||
startText = TextReference.Res(R.string.staking_details_minimum_requirement),
|
||||
endText = TextReference.Str(
|
||||
value = BigDecimalFormatter.formatCryptoAmount(
|
||||
cryptoAmount = yield.args.enter.args[KEY_AMOUNT]?.minimum?.toBigDecimal(),
|
||||
cryptoAmount = yield.args.enter.args[Yield.Args.ArgType.AMOUNT]?.minimum,
|
||||
cryptoCurrency = cryptoCurrencyStatus.currency.symbol,
|
||||
decimals = cryptoCurrencyStatus.currency.decimals,
|
||||
),
|
||||
|
|
@ -191,6 +191,5 @@ internal class SetInitialDataStateTransformer(
|
|||
|
||||
companion object {
|
||||
private val EQUALITY_THRESHOLD = BigDecimal(1E-10)
|
||||
private const val KEY_AMOUNT = "amount"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +1,33 @@
|
|||
package com.tangem.features.staking.impl.presentation.state.transformers.amount
|
||||
|
||||
import com.tangem.common.ui.amountScreen.converters.field.AmountFieldChangeTransformer
|
||||
import com.tangem.domain.staking.model.stakekit.Yield
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingUiState
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
|
||||
internal class AmountChangeStateTransformer(
|
||||
private val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
private val yield: Yield,
|
||||
private val value: String,
|
||||
) : Transformer<StakingUiState> {
|
||||
|
||||
private val amountRequirementStateTransformer by lazy(LazyThreadSafetyMode.NONE) {
|
||||
AmountRequirementStateTransformer(
|
||||
cryptoCurrencyStatus,
|
||||
yield,
|
||||
value,
|
||||
)
|
||||
}
|
||||
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
val updatedAmountState = AmountFieldChangeTransformer(
|
||||
cryptoCurrencyStatus,
|
||||
value,
|
||||
).transform(prevState.amountState)
|
||||
|
||||
return prevState.copy(
|
||||
amountState = AmountFieldChangeTransformer(cryptoCurrencyStatus, value).transform(prevState.amountState),
|
||||
amountState = amountRequirementStateTransformer.transform(updatedAmountState),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,32 @@
|
|||
package com.tangem.features.staking.impl.presentation.state.transformers.amount
|
||||
|
||||
import com.tangem.common.ui.amountScreen.converters.field.AmountFieldMaxAmountTransformer
|
||||
import com.tangem.core.ui.utils.parseBigDecimal
|
||||
import com.tangem.domain.staking.model.stakekit.Yield
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingUiState
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
|
||||
internal class AmountMaxValueStateTransformer(
|
||||
private val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
private val yield: Yield,
|
||||
) : Transformer<StakingUiState> {
|
||||
|
||||
private val amountRequirementStateTransformer by lazy(LazyThreadSafetyMode.NONE) {
|
||||
val value = cryptoCurrencyStatus.value.amount
|
||||
?.parseBigDecimal(cryptoCurrencyStatus.currency.decimals)
|
||||
.orEmpty()
|
||||
AmountRequirementStateTransformer(
|
||||
cryptoCurrencyStatus,
|
||||
yield,
|
||||
value,
|
||||
)
|
||||
}
|
||||
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
val updatedAmountState = AmountFieldMaxAmountTransformer(cryptoCurrencyStatus).transform(prevState.amountState)
|
||||
return prevState.copy(
|
||||
amountState = AmountFieldMaxAmountTransformer(cryptoCurrencyStatus).transform(prevState.amountState),
|
||||
amountState = amountRequirementStateTransformer.transform(updatedAmountState),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package com.tangem.features.staking.impl.presentation.state.transformers.amount
|
||||
|
||||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.core.ui.utils.parseToBigDecimal
|
||||
import com.tangem.domain.staking.model.stakekit.Yield
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.staking.impl.R
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
|
||||
internal class AmountRequirementStateTransformer(
|
||||
private val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
private val yield: Yield,
|
||||
private val value: String,
|
||||
) : Transformer<AmountState> {
|
||||
override fun transform(prevState: AmountState): AmountState {
|
||||
val amountRequirements = yield.args.enter.args[Yield.Args.ArgType.AMOUNT]
|
||||
val amountDecimal = value.parseToBigDecimal(cryptoCurrencyStatus.currency.decimals)
|
||||
|
||||
return if (prevState !is AmountState.Data || amountRequirements == null) {
|
||||
prevState
|
||||
} else {
|
||||
val isAlreadyErrorState = prevState.amountTextField.isError
|
||||
val isAmountRequired = amountRequirements.required
|
||||
val isAmountZero = amountDecimal.isZero()
|
||||
val isExceedsRequirements =
|
||||
amountRequirements.maximum?.compareTo(amountDecimal) == -1 ||
|
||||
amountRequirements.minimum?.compareTo(amountDecimal) == 1
|
||||
|
||||
val isRequirementError = !isAmountZero && isAmountRequired && isExceedsRequirements && !isAlreadyErrorState
|
||||
if (isRequirementError) {
|
||||
prevState.copy(
|
||||
amountTextField = prevState.amountTextField.copy(
|
||||
isError = true,
|
||||
error = resourceReference(
|
||||
R.string.staking_amount_requirement_error,
|
||||
wrappedList(
|
||||
BigDecimalFormatter.formatCryptoAmount(
|
||||
amountRequirements.minimum,
|
||||
cryptoCurrencyStatus.currency.symbol,
|
||||
cryptoCurrencyStatus.currency.decimals,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
prevState
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -67,7 +67,7 @@ internal fun StakingInitialInfoContent(state: StakingStates.InitialInfoState, cl
|
|||
)
|
||||
}
|
||||
}
|
||||
AnimatedContent(targetState = state.yieldBalance, label = "Rewards block visibility animation") {
|
||||
AnimatedContent(targetState = state.yieldBalance, label = "Staking yield visibility animation") {
|
||||
if (it is InnerYieldBalanceState.Data) {
|
||||
ActiveStakingBlock(it.balance, clickIntents::onActiveStake)
|
||||
}
|
||||
|
|
@ -168,6 +168,7 @@ private fun StakingRewardBlock(
|
|||
.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(),
|
||||
enabled = isRewardsToClaim,
|
||||
onClick = onRewardsClick,
|
||||
),
|
||||
)
|
||||
|
|
@ -192,18 +193,20 @@ private fun ActiveStakingBlock(groups: List<BalanceGroupedState>, onClick: (Bala
|
|||
) {
|
||||
group.items.forEachIndexed { index, balance ->
|
||||
key(balance.validator.address) {
|
||||
val caption = combinedReference(
|
||||
if (group.type == BalanceGroupType.UNSTAKED) {
|
||||
resourceReference(R.string.staking_details_unbonding_period)
|
||||
val caption = if (group.type == BalanceGroupType.UNSTAKED) {
|
||||
combinedReference(
|
||||
resourceReference(R.string.staking_details_unbonding_period),
|
||||
annotatedReference {
|
||||
appendSpace()
|
||||
appendColored(
|
||||
text = balance.unbondingPeriod.resolveReference(),
|
||||
color = TangemTheme.colors.text.accent,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
resourceReference(R.string.app_name)
|
||||
},
|
||||
)
|
||||
} else {
|
||||
combinedReference(
|
||||
resourceReference(R.string.app_name),
|
||||
annotatedReference {
|
||||
appendSpace()
|
||||
appendColored(
|
||||
|
|
@ -213,9 +216,9 @@ private fun ActiveStakingBlock(groups: List<BalanceGroupedState>, onClick: (Bala
|
|||
),
|
||||
color = TangemTheme.colors.text.accent,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
InputRowImageInfo(
|
||||
title = group.title.takeIf { index == 0 },
|
||||
subtitle = stringReference(balance.validator.name),
|
||||
|
|
|
|||
|
|
@ -148,17 +148,10 @@ private fun getButtonData(currentState: StakingUiState): Int {
|
|||
|
||||
private fun onPrimaryClick(currentState: StakingUiState) {
|
||||
when (currentState.currentStep) {
|
||||
StakingStep.InitialInfo -> {
|
||||
val initialState = currentState.initialInfoState as? StakingStates.InitialInfoState.Data
|
||||
if (initialState?.yieldBalance is InnerYieldBalanceState.Data) {
|
||||
if (initialState.isStakeMoreAvailable) {
|
||||
currentState.clickIntents.onNextClick()
|
||||
}
|
||||
} else {
|
||||
currentState.clickIntents.onNextClick()
|
||||
}
|
||||
}
|
||||
StakingStep.Amount -> currentState.clickIntents.onNextClick()
|
||||
StakingStep.InitialInfo,
|
||||
StakingStep.Validators,
|
||||
StakingStep.Amount,
|
||||
-> currentState.clickIntents.onNextClick()
|
||||
StakingStep.Confirmation -> {
|
||||
val confirmationState = currentState.confirmationState
|
||||
if (confirmationState is StakingStates.ConfirmationState.Data) {
|
||||
|
|
@ -171,7 +164,6 @@ private fun onPrimaryClick(currentState: StakingUiState) {
|
|||
currentState.clickIntents.onBackClick()
|
||||
}
|
||||
}
|
||||
StakingStep.Validators -> currentState.clickIntents.onNextClick()
|
||||
StakingStep.RewardsValidators -> Unit
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ internal class StakingViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onAmountValueChange(value: String) {
|
||||
stateController.update(AmountChangeStateTransformer(cryptoCurrencyStatus, value))
|
||||
stateController.update(AmountChangeStateTransformer(cryptoCurrencyStatus, yield, value))
|
||||
}
|
||||
|
||||
override fun onAmountPasteTriggerDismiss() {
|
||||
|
|
@ -204,7 +204,7 @@ internal class StakingViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onMaxValueClick() {
|
||||
stateController.update(AmountMaxValueStateTransformer(cryptoCurrencyStatus))
|
||||
stateController.update(AmountMaxValueStateTransformer(cryptoCurrencyStatus, yield))
|
||||
}
|
||||
|
||||
override fun onCurrencyChangeClick(isFiat: Boolean) {
|
||||
|
|
@ -223,7 +223,7 @@ internal class StakingViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun selectRewardValidator(rewardValue: String) {
|
||||
stateController.update(AmountChangeStateTransformer(cryptoCurrencyStatus, rewardValue))
|
||||
stateController.update(AmountChangeStateTransformer(cryptoCurrencyStatus, yield, rewardValue))
|
||||
onNextClick()
|
||||
}
|
||||
|
||||
|
|
@ -234,7 +234,7 @@ internal class StakingViewModel @Inject constructor(
|
|||
RouteType.OTHER
|
||||
}
|
||||
stateController.update { it.copy(routeType = routeType) }
|
||||
stateController.update(AmountChangeStateTransformer(cryptoCurrencyStatus, activeStake.cryptoValue))
|
||||
stateController.update(AmountChangeStateTransformer(cryptoCurrencyStatus, yield, activeStake.cryptoValue))
|
||||
onNextClick(activeStake.pendingActions)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue