Updated on 2026-08-14

This commit is contained in:
Tangem 2024-08-01 13:11:43 +05:00
parent 45db7c879f
commit c4adfe3d89
17 changed files with 650 additions and 249 deletions

View file

@ -1,8 +1,11 @@
package com.tangem.features.staking.impl.presentation.state
import com.tangem.common.ui.amountScreen.models.AmountState
import com.tangem.common.ui.navigationButtons.NavigationButtonsState
import com.tangem.core.ui.event.consumedEvent
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
import com.tangem.features.staking.impl.presentation.state.stub.StakingClickIntentsStub
import com.tangem.features.staking.impl.presentation.state.transformers.SetButtonsStateTransformer
import com.tangem.utils.transformer.Transformer
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@ -20,16 +23,21 @@ internal class StakingStateController @Inject constructor() {
val uiState: StateFlow<StakingUiState> get() = mutableUiState.asStateFlow()
private val buttonsTransformer = SetButtonsStateTransformer()
fun update(function: (StakingUiState) -> StakingUiState) {
mutableUiState.update(function = function)
mutableUiState.update(function = buttonsTransformer::transform)
}
fun update(transformer: Transformer<StakingUiState>) {
mutableUiState.update(function = transformer::transform)
mutableUiState.update(function = buttonsTransformer::transform)
}
fun clear() {
mutableUiState.update { getInitialState() }
mutableUiState.update(function = buttonsTransformer::transform)
}
private fun getInitialState(): StakingUiState {
@ -44,7 +52,8 @@ internal class StakingStateController @Inject constructor() {
isBalanceHidden = false,
event = consumedEvent(),
bottomSheetConfig = null,
routeType = RouteType.STAKE,
actionType = StakingActionCommonType.ENTER,
buttonsState = NavigationButtonsState.Empty,
)
}
}

View file

@ -1,6 +1,7 @@
package com.tangem.features.staking.impl.presentation.state
import com.tangem.common.routing.AppRouter
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
internal class StakingStateRouter(
private val appRouter: AppRouter,
@ -14,12 +15,12 @@ internal class StakingStateRouter(
fun onNextClick() {
when (stateController.value.currentStep) {
StakingStep.InitialInfo -> when (stateController.value.routeType) {
RouteType.STAKE -> showAmount()
RouteType.OTHER,
RouteType.UNSTAKE,
StakingStep.InitialInfo -> when (stateController.value.actionType) {
StakingActionCommonType.ENTER -> showAmount()
StakingActionCommonType.PENDING_OTHER,
StakingActionCommonType.EXIT,
-> showConfirmation()
RouteType.CLAIM -> showRewardsValidators()
StakingActionCommonType.PENDING_REWARDS -> showRewardsValidators()
}
StakingStep.RewardsValidators,
StakingStep.Validators,
@ -37,7 +38,7 @@ internal class StakingStateRouter(
StakingStep.InitialInfo -> onBackClick()
StakingStep.Amount -> showInitial()
StakingStep.Confirmation -> {
if (uiState.routeType == RouteType.OTHER || uiState.routeType == RouteType.UNSTAKE) {
if (uiState.actionType != StakingActionCommonType.ENTER) {
showInitial()
} else {
showAmount()

View file

@ -2,11 +2,13 @@ package com.tangem.features.staking.impl.presentation.state
import androidx.compose.runtime.Immutable
import com.tangem.common.ui.amountScreen.models.AmountState
import com.tangem.common.ui.navigationButtons.NavigationButtonsState
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.components.list.RoundedListWithDividersItemData
import com.tangem.core.ui.event.StateEvent
import com.tangem.core.ui.extensions.TextReference
import com.tangem.domain.staking.model.stakekit.PendingAction
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
import com.tangem.features.staking.impl.presentation.state.transformers.InfoType
import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents
import kotlinx.collections.immutable.ImmutableList
@ -25,7 +27,8 @@ internal data class StakingUiState(
val confirmationState: StakingStates.ConfirmationState,
val isBalanceHidden: Boolean,
val bottomSheetConfig: TangemBottomSheetConfig?,
val routeType: RouteType,
val actionType: StakingActionCommonType,
val buttonsState: NavigationButtonsState,
val event: StateEvent<StakingEvent>,
) {
@ -98,11 +101,4 @@ enum class StakingStep {
Amount,
Confirmation,
Validators,
}
enum class RouteType {
STAKE,
UNSTAKE,
CLAIM,
OTHER,
}

View file

@ -0,0 +1,226 @@
package com.tangem.features.staking.impl.presentation.state.transformers
import com.tangem.common.ui.navigationButtons.NavigationButton
import com.tangem.common.ui.navigationButtons.NavigationButtonsState
import com.tangem.core.ui.R
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.domain.staking.model.stakekit.PendingAction
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
import com.tangem.domain.staking.model.stakekit.action.StakingActionType
import com.tangem.features.staking.impl.presentation.state.*
import com.tangem.utils.transformer.Transformer
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
internal class SetButtonsStateTransformer : Transformer<StakingUiState> {
override fun transform(prevState: StakingUiState): StakingUiState {
val confirmState = prevState.confirmationState as? StakingStates.ConfirmationState.Data
val buttonsState = if (prevState.isButtonsVisible()) {
NavigationButtonsState.Data(
primaryButton = getPrimaryButton(prevState),
prevButton = getPrevButton(prevState),
secondaryButton = getSecondaryButton(prevState),
extraButtons = getExtraButtons(prevState),
txUrl = (confirmState?.transactionDoneState as? TransactionDoneState.Content)?.txUrl,
)
} else {
NavigationButtonsState.Empty
}
return prevState.copy(buttonsState = buttonsState)
}
private fun getPrimaryButton(prevState: StakingUiState): NavigationButton {
val confirmState = prevState.confirmationState as? StakingStates.ConfirmationState.Data
val innerConfirmState = confirmState?.innerState
val isPrimaryInProgress =
confirmState?.pendingActions?.getPrimaryAction() == confirmState?.pendingActionInProgress
val isConfirmation = prevState.currentStep == StakingStep.Confirmation
val isInProgress = innerConfirmState == InnerConfirmationStakingState.IN_PROGRESS
val isCompleted = innerConfirmState == InnerConfirmationStakingState.COMPLETED
val isIconVisible = isConfirmation && !isCompleted
val isShowProgress = isInProgress && isPrimaryInProgress
return NavigationButton(
textReference = prevState.getButtonText(),
iconRes = R.drawable.ic_tangem_24,
isSecondary = false,
isIconVisible = isIconVisible,
showProgress = isShowProgress,
isEnabled = prevState.isButtonEnabled(),
onClick = { prevState.onPrimaryClick() },
)
}
private fun getSecondaryButton(prevState: StakingUiState): NavigationButton? {
val confirmState = prevState.confirmationState as? StakingStates.ConfirmationState.Data
val innerConfirmState = confirmState?.innerState
val isConfirmation = prevState.currentStep == StakingStep.Confirmation
val isInProgress = innerConfirmState == InnerConfirmationStakingState.IN_PROGRESS
val isCompleted = innerConfirmState == InnerConfirmationStakingState.COMPLETED
return confirmState?.pendingActions?.getSecondaryAction()?.let { pendingAction ->
val isSecondaryInProgress = pendingAction == confirmState.pendingActionInProgress
val isShowProgress = isInProgress && isSecondaryInProgress
NavigationButton(
textReference = getPendingActionTitle(pendingAction.type),
iconRes = R.drawable.ic_tangem_24,
isSecondary = true,
isIconVisible = true,
showProgress = isShowProgress,
isEnabled = prevState.isButtonEnabled(),
onClick = { prevState.clickIntents.onActionClick(pendingAction) },
).takeIf { isConfirmation && !isCompleted }
}
}
private fun getPrevButton(prevState: StakingUiState): NavigationButton? {
return NavigationButton(
textReference = TextReference.EMPTY,
iconRes = R.drawable.ic_back_24,
isSecondary = true,
isIconVisible = true,
showProgress = false,
isEnabled = true,
onClick = prevState.clickIntents::onPrevClick,
).takeIf { prevState.currentStep.isPrevButtonVisible() }
}
private fun getExtraButtons(prevState: StakingUiState): ImmutableList<NavigationButton> {
return persistentListOf(
NavigationButton(
textReference = resourceReference(R.string.common_explore),
iconRes = R.drawable.ic_web_24,
isSecondary = true,
isIconVisible = true,
showProgress = false,
isEnabled = true,
onClick = prevState.clickIntents::onExploreClick,
),
NavigationButton(
textReference = resourceReference(R.string.common_share),
iconRes = R.drawable.ic_share_24,
isSecondary = true,
isIconVisible = true,
showProgress = false,
isEnabled = true,
onClick = prevState.clickIntents::onShareClick,
),
)
}
private fun List<PendingAction>.getPrimaryAction(): PendingAction? = getOrNull(0)
private fun List<PendingAction>.getSecondaryAction(): PendingAction? = getOrNull(1)
private fun StakingUiState.isButtonsVisible(): Boolean = when (currentStep) {
StakingStep.InitialInfo -> {
val initialState = initialInfoState as? StakingStates.InitialInfoState.Data
initialState?.isStakeMoreAvailable == true || initialState?.yieldBalance is InnerYieldBalanceState.Empty
}
StakingStep.RewardsValidators -> false
else -> true
}
private fun StakingUiState.getButtonText(): TextReference {
return when (currentStep) {
StakingStep.InitialInfo -> {
val initialState = initialInfoState as? StakingStates.InitialInfoState.Data
if (initialState?.yieldBalance is InnerYieldBalanceState.Data) {
resourceReference(R.string.staking_stake_more)
} else {
resourceReference(R.string.common_next)
}
}
StakingStep.Confirmation -> {
if (confirmationState is StakingStates.ConfirmationState.Data) {
if (confirmationState.innerState == InnerConfirmationStakingState.COMPLETED) {
resourceReference(R.string.common_close)
} else {
when (actionType) {
StakingActionCommonType.ENTER -> resourceReference(R.string.common_stake)
StakingActionCommonType.EXIT -> resourceReference(R.string.common_unstake)
StakingActionCommonType.PENDING_OTHER,
StakingActionCommonType.PENDING_REWARDS,
-> getPendingActionTitle(confirmationState.pendingActions.firstOrNull()?.type)
}
}
} else {
resourceReference(R.string.common_close)
}
}
StakingStep.Validators -> resourceReference(R.string.common_continue)
StakingStep.Amount,
StakingStep.RewardsValidators,
-> resourceReference(R.string.common_next)
}
}
private fun StakingUiState.onPrimaryClick() {
when (currentStep) {
StakingStep.InitialInfo,
StakingStep.Validators,
StakingStep.Amount,
-> clickIntents.onNextClick()
StakingStep.Confirmation -> {
if (confirmationState is StakingStates.ConfirmationState.Data) {
if (confirmationState.innerState == InnerConfirmationStakingState.COMPLETED) {
clickIntents.onBackClick()
} else {
clickIntents.onActionClick(confirmationState.pendingActions.firstOrNull())
}
} else {
clickIntents.onBackClick()
}
}
StakingStep.RewardsValidators -> Unit
}
}
private fun StakingStep.isPrevButtonVisible(): Boolean = when (this) {
StakingStep.InitialInfo,
StakingStep.RewardsValidators,
StakingStep.Confirmation,
-> false
StakingStep.Amount,
StakingStep.Validators,
-> true
}
private fun StakingUiState.isButtonEnabled(): Boolean {
return when (currentStep) {
StakingStep.InitialInfo -> initialInfoState.isPrimaryButtonEnabled
StakingStep.Amount -> amountState.isPrimaryButtonEnabled
StakingStep.Confirmation -> confirmationState.isPrimaryButtonEnabled
StakingStep.RewardsValidators -> rewardsValidatorsState.isPrimaryButtonEnabled
StakingStep.Validators -> true
}
}
@Suppress("CyclomaticComplexMethod")
private fun getPendingActionTitle(type: StakingActionType?): TextReference = when (type) {
StakingActionType.CLAIM_REWARDS -> resourceReference(R.string.common_claim_rewards)
StakingActionType.RESTAKE_REWARDS -> resourceReference(R.string.staking_restake_rewards)
StakingActionType.WITHDRAW -> resourceReference(R.string.staking_withdraw)
StakingActionType.RESTAKE -> resourceReference(R.string.staking_restake)
StakingActionType.CLAIM_UNSTAKED -> resourceReference(R.string.staking_claim_unstaked)
StakingActionType.UNLOCK_LOCKED -> resourceReference(R.string.staking_unlocked_locked)
StakingActionType.STAKE_LOCKED -> resourceReference(R.string.staking_stake_locked)
StakingActionType.VOTE -> resourceReference(R.string.staking_vote)
StakingActionType.REVOKE -> resourceReference(R.string.staking_revoke)
StakingActionType.VOTE_LOCKED -> resourceReference(R.string.staking_vote_locked)
StakingActionType.REVOTE -> resourceReference(R.string.staking_revote)
StakingActionType.REBOND -> resourceReference(R.string.staking_rebond)
StakingActionType.MIGRATE -> resourceReference(R.string.staking_migrate)
StakingActionType.STAKE -> resourceReference(R.string.common_stake)
StakingActionType.UNSTAKE -> resourceReference(R.string.common_unstake)
StakingActionType.UNKNOWN -> TextReference.EMPTY
null -> TextReference.EMPTY
}
}

View file

@ -19,7 +19,6 @@ internal class SetConfirmationStateAssentTransformer(
private val cryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus>,
private val stakingGasEstimate: StakingGasEstimate,
private val pendingActionList: ImmutableList<PendingAction>,
private val pendingAction: PendingAction?,
) : Transformer<StakingUiState> {
override fun transform(prevState: StakingUiState): StakingUiState {
@ -49,7 +48,6 @@ internal class SetConfirmationStateAssentTransformer(
),
validatorState = validatorState.copySealed(isClickable = true),
pendingActions = pendingActionList,
pendingActionInProgress = pendingAction,
isPrimaryButtonEnabled = true,
)
} else {

View file

@ -1,11 +1,14 @@
package com.tangem.features.staking.impl.presentation.state.transformers
import com.tangem.domain.staking.model.stakekit.PendingAction
import com.tangem.features.staking.impl.presentation.state.InnerConfirmationStakingState
import com.tangem.features.staking.impl.presentation.state.StakingStates
import com.tangem.features.staking.impl.presentation.state.StakingUiState
import com.tangem.utils.transformer.Transformer
internal class SetConfirmationStateInProgressTransformer : Transformer<StakingUiState> {
internal class SetConfirmationStateInProgressTransformer(
private val pendingAction: PendingAction?,
) : Transformer<StakingUiState> {
override fun transform(prevState: StakingUiState): StakingUiState {
return prevState.copy(
@ -19,6 +22,7 @@ internal class SetConfirmationStateInProgressTransformer : Transformer<StakingUi
isPrimaryButtonEnabled = false,
innerState = InnerConfirmationStakingState.IN_PROGRESS,
validatorState = validatorState.copySealed(isClickable = false),
pendingActionInProgress = pendingAction,
)
} else {
this

View file

@ -18,8 +18,8 @@ import com.tangem.core.ui.components.SpacerHMax
import com.tangem.core.ui.components.transactions.TransactionDoneTitle
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
import com.tangem.features.staking.impl.R
import com.tangem.features.staking.impl.presentation.state.RouteType
import com.tangem.features.staking.impl.presentation.state.StakingStates
import com.tangem.features.staking.impl.presentation.state.TransactionDoneState
import com.tangem.features.staking.impl.presentation.state.previewdata.ConfirmationStatePreviewData
@ -34,7 +34,7 @@ internal fun StakingConfirmationContent(
amountState: AmountState,
state: StakingStates.ConfirmationState,
clickIntents: StakingClickIntents,
type: RouteType,
type: StakingActionCommonType,
) {
if (state !is StakingStates.ConfirmationState.Data) return
@ -62,7 +62,7 @@ internal fun StakingConfirmationContent(
isEditingDisabled = true,
onClick = {},
)
if (type == RouteType.STAKE) {
if (type == StakingActionCommonType.ENTER) {
ValidatorBlock(validatorState = state.validatorState, onClick = clickIntents::openValidators)
}
StakingFeeBlock(feeState = state.feeState)
@ -93,7 +93,7 @@ private fun Preview_StakingConfirmationContent() {
amountState = AmountStatePreviewData.amountState,
state = ConfirmationStatePreviewData.assentStakingState,
clickIntents = StakingClickIntentsStub,
type = RouteType.STAKE,
type = StakingActionCommonType.ENTER,
)
}
}

View file

@ -1,199 +0,0 @@
package com.tangem.features.staking.impl.presentation.ui
import androidx.compose.animation.*
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import com.tangem.common.ui.amountScreen.ui.SendDoneButtons
import com.tangem.core.ui.R
import com.tangem.core.ui.components.SpacerW12
import com.tangem.core.ui.components.buttons.common.TangemButton
import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition
import com.tangem.core.ui.components.buttons.common.TangemButtonsDefaults
import com.tangem.core.ui.res.TangemTheme
import com.tangem.features.staking.impl.presentation.state.*
@Composable
internal fun StakingNavigationButtons(uiState: StakingUiState, modifier: Modifier = Modifier) {
val confirmInnerState = (uiState.confirmationState as? StakingStates.ConfirmationState.Data)?.innerState
val isSuccessState = confirmInnerState == InnerConfirmationStakingState.COMPLETED
Column(
modifier = modifier
.padding(
start = TangemTheme.dimens.spacing16,
end = TangemTheme.dimens.spacing16,
bottom = TangemTheme.dimens.spacing16,
),
) {
val confirmationDataState = uiState.confirmationState as? StakingStates.ConfirmationState.Data
val transactionDoneState = confirmationDataState?.transactionDoneState as? TransactionDoneState.Content
SendDoneButtons(
txUrl = transactionDoneState?.txUrl.orEmpty(),
onExploreClick = uiState.clickIntents::onExploreClick,
onShareClick = uiState.clickIntents::onShareClick,
isVisible = isSuccessState,
)
StakingNavigationButton(
uiState = uiState,
modifier = Modifier,
)
}
}
@Composable
private fun StakingNavigationButton(uiState: StakingUiState, modifier: Modifier = Modifier) {
val hapticFeedback = LocalHapticFeedback.current
val isButtonsVisible = isPrevButtonVisible(uiState.currentStep)
val innerConfirmState = (uiState.confirmationState as? StakingStates.ConfirmationState.Data)?.innerState
val isInProgressInnerState = innerConfirmState == InnerConfirmationStakingState.IN_PROGRESS
val isInAssentInnerState = innerConfirmState == InnerConfirmationStakingState.ASSENT
val showTangemIcon = uiState.currentStep == StakingStep.Confirmation &&
(isInProgressInnerState || isInAssentInnerState)
val buttonTextId = getButtonData(currentState = uiState)
val (isButtonEnabled, isButtonDisplayed) = isButtonEnabled(uiState)
val buttonIcon = if (showTangemIcon) {
TangemButtonIconPosition.End(R.drawable.ic_tangem_24)
} else {
TangemButtonIconPosition.None
}
Row(modifier = modifier) {
AnimatedVisibility(
visible = isButtonsVisible,
enter = expandHorizontally(expandFrom = Alignment.End),
exit = shrinkHorizontally(shrinkTowards = Alignment.End),
) {
Row {
Icon(
painter = painterResource(R.drawable.ic_back_24),
tint = TangemTheme.colors.icon.primary1,
contentDescription = null,
modifier = Modifier
.clip(RoundedCornerShape(TangemTheme.dimens.radius16))
.background(TangemTheme.colors.button.secondary)
.clickable { uiState.clickIntents.onPrevClick() }
.padding(TangemTheme.dimens.spacing12),
)
SpacerW12()
}
}
AnimatedVisibility(
visible = isButtonDisplayed,
enter = fadeIn(),
exit = fadeOut(),
) {
TangemButton(
text = stringResource(buttonTextId),
icon = buttonIcon,
enabled = isButtonEnabled && isButtonDisplayed,
onClick = {
if (showTangemIcon) hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
onPrimaryClick(uiState)
},
showProgress = isInProgressInnerState,
modifier = Modifier.fillMaxWidth(),
colors = TangemButtonsDefaults.primaryButtonColors,
)
}
}
}
private fun getButtonData(currentState: StakingUiState): Int {
return when (currentState.currentStep) {
StakingStep.InitialInfo -> {
val initialState = currentState.initialInfoState as? StakingStates.InitialInfoState.Data
if (initialState?.yieldBalance is InnerYieldBalanceState.Data) {
R.string.staking_stake_more
} else {
R.string.common_next
}
}
StakingStep.Confirmation -> {
val confirmationState = currentState.confirmationState
if (confirmationState is StakingStates.ConfirmationState.Data) {
if (confirmationState.innerState == InnerConfirmationStakingState.COMPLETED) {
R.string.common_close
} else {
when (currentState.routeType) {
RouteType.STAKE -> R.string.common_stake
RouteType.CLAIM -> R.string.common_claim_rewards
RouteType.UNSTAKE -> R.string.common_unstake
RouteType.OTHER -> R.string.common_stake
}
}
} else {
R.string.common_close
}
}
StakingStep.Validators -> R.string.common_continue
StakingStep.Amount,
StakingStep.RewardsValidators,
-> R.string.common_next
}
}
private fun onPrimaryClick(currentState: StakingUiState) {
when (currentState.currentStep) {
StakingStep.InitialInfo,
StakingStep.Validators,
StakingStep.Amount,
-> currentState.clickIntents.onNextClick()
StakingStep.Confirmation -> {
val confirmationState = currentState.confirmationState
if (confirmationState is StakingStates.ConfirmationState.Data) {
if (confirmationState.innerState == InnerConfirmationStakingState.COMPLETED) {
currentState.clickIntents.onBackClick()
} else {
currentState.clickIntents.onNextClick()
}
} else {
currentState.clickIntents.onBackClick()
}
}
StakingStep.RewardsValidators -> Unit
}
}
private fun isPrevButtonVisible(step: StakingStep): Boolean = when (step) {
StakingStep.InitialInfo,
StakingStep.RewardsValidators,
StakingStep.Confirmation,
-> false
StakingStep.Amount,
StakingStep.Validators,
-> true
}
private fun isButtonEnabled(uiState: StakingUiState): Pair<Boolean, Boolean> {
return when (uiState.currentStep) {
StakingStep.InitialInfo -> {
val initialState = uiState.initialInfoState as? StakingStates.InitialInfoState.Data
val isDisplayed = initialState?.isStakeMoreAvailable == true ||
initialState?.yieldBalance is InnerYieldBalanceState.Empty
uiState.initialInfoState.isPrimaryButtonEnabled to isDisplayed
}
StakingStep.Amount -> uiState.amountState.isPrimaryButtonEnabled to true
StakingStep.Confirmation -> uiState.confirmationState.isPrimaryButtonEnabled to true
StakingStep.RewardsValidators -> uiState.rewardsValidatorsState.isPrimaryButtonEnabled to false
StakingStep.Validators -> true to true
}
}

View file

@ -13,6 +13,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import com.tangem.common.ui.amountScreen.AmountScreenContent
import com.tangem.common.ui.navigationButtons.NavigationButtonsBlock
import com.tangem.core.ui.components.appbar.AppBarWithBackButtonAndIcon
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.res.TangemTheme
@ -45,8 +46,13 @@ internal fun StakingScreen(uiState: StakingUiState) {
uiState = uiState,
modifier = Modifier.weight(1f),
)
StakingNavigationButtons(
uiState = uiState,
NavigationButtonsBlock(
buttonState = uiState.buttonsState,
modifier = Modifier.padding(
start = TangemTheme.dimens.spacing16,
end = TangemTheme.dimens.spacing16,
bottom = TangemTheme.dimens.spacing16,
),
)
StakingBottomSheet(bottomSheetConfig = uiState.bottomSheetConfig)
}
@ -155,7 +161,7 @@ private fun StakingScreenContent(uiState: StakingUiState, modifier: Modifier = M
amountState = uiState.amountState,
state = uiState.confirmationState,
clickIntents = uiState.clickIntents,
type = uiState.routeType,
type = uiState.actionType,
)
StakingStep.Validators -> {
val confirmState = uiState.confirmationState

View file

@ -117,7 +117,7 @@ internal class StakingViewModel @Inject constructor(
private fun handleOnNextConfirmationClick(pendingAction: PendingAction?) {
if (isAssentState()) {
viewModelScope.launch {
stateController.update(SetConfirmationStateInProgressTransformer())
stateController.update(SetConfirmationStateInProgressTransformer(pendingAction))
val confirmationState =
value.confirmationState as? StakingStates.ConfirmationState.Data ?: error("No confirmation state")
@ -128,7 +128,7 @@ internal class StakingViewModel @Inject constructor(
userWalletId = userWalletId,
network = cryptoCurrencyStatus.currency.network,
params = ActionParams(
actionCommonType = getStakingCommonType(),
actionCommonType = value.actionType,
integrationId = yield.id,
amount = (value.amountState as? AmountState.Data)?.amountTextField?.cryptoAmount?.value
?: error("No amount provided"),
@ -149,7 +149,6 @@ internal class StakingViewModel @Inject constructor(
gasEstimate = stakingTransaction.gasEstimate ?: error("No gas estimate available"),
txData = TransactionData.Compiled(value = it.hexToBytes()),
pendingActionList = confirmationState.pendingActions,
pendingAction = pendingAction,
)
} ?: error("No unsigned transaction available")
}
@ -170,7 +169,7 @@ internal class StakingViewModel @Inject constructor(
userWalletId = userWalletId,
network = cryptoCurrencyStatus.currency.network,
params = ActionParams(
actionCommonType = getStakingCommonType(),
actionCommonType = value.actionType,
integrationId = yield.id,
amount = (value.amountState as? AmountState.Data)?.amountTextField?.cryptoAmount?.value
?: error("No amount provided"),
@ -189,7 +188,6 @@ internal class StakingViewModel @Inject constructor(
cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus },
stakingGasEstimate = stakingGasEstimate,
pendingActionList = pendingActions,
pendingAction = pendingAction,
),
)
}
@ -230,17 +228,17 @@ internal class StakingViewModel @Inject constructor(
}
override fun openRewardsValidators() {
stateController.update { it.copy(routeType = RouteType.CLAIM) }
stateController.update { it.copy(actionType = StakingActionCommonType.PENDING_REWARDS) }
onNextClick()
}
override fun onActiveStake(activeStake: BalanceState) {
val routeType = if (activeStake.pendingActions.isEmpty()) {
RouteType.UNSTAKE
val actionType = if (activeStake.pendingActions.isEmpty()) {
StakingActionCommonType.EXIT
} else {
RouteType.OTHER
StakingActionCommonType.PENDING_OTHER
}
stateController.update { it.copy(routeType = routeType) }
stateController.update { it.copy(actionType = actionType) }
stateController.update(AmountChangeStateTransformer(cryptoCurrencyStatus, yield, activeStake.cryptoValue))
onNextClick(activeStake.pendingActions)
}
@ -256,7 +254,7 @@ internal class StakingViewModel @Inject constructor(
}
override fun onShareClick() {
// TODO staking analytics event
// TODO add hash to clipboard and send analytics event
}
fun setRouter(router: InnerStakingRouter, stateRouter: StakingStateRouter) {
@ -325,7 +323,6 @@ internal class StakingViewModel @Inject constructor(
gasEstimate: StakingGasEstimate,
txData: TransactionData,
pendingActionList: ImmutableList<PendingAction>,
pendingAction: PendingAction?,
) {
sendTransactionUseCase(
txData = txData,
@ -340,7 +337,6 @@ internal class StakingViewModel @Inject constructor(
cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus },
stakingGasEstimate = gasEstimate,
pendingActionList = pendingActionList,
pendingAction = pendingAction,
),
)
// todo add error dialog
@ -398,12 +394,4 @@ internal class StakingViewModel @Inject constructor(
(value.confirmationState as? StakingStates.ConfirmationState.Data)?.innerState ==
InnerConfirmationStakingState.ASSENT
}
private fun getStakingCommonType() = when (value.routeType) {
RouteType.STAKE -> StakingActionCommonType.ENTER
RouteType.UNSTAKE -> StakingActionCommonType.EXIT
RouteType.CLAIM,
RouteType.OTHER,
-> StakingActionCommonType.PENDING
}
}