Updated on 2026-08-14
This commit is contained in:
parent
45db7c879f
commit
c4adfe3d89
17 changed files with 650 additions and 249 deletions
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue