Updated on 2026-08-14
This commit is contained in:
parent
fbfcad9325
commit
3acfadfb08
16 changed files with 242 additions and 9 deletions
|
|
@ -42,6 +42,7 @@ internal class StakingStateController @Inject constructor() {
|
|||
confirmStakingState = StakingStates.ConfirmStakingState.Empty(),
|
||||
isBalanceHidden = false,
|
||||
event = consumedEvent(),
|
||||
bottomSheetConfig = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -3,9 +3,11 @@ package com.tangem.features.staking.impl.presentation.state
|
|||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.event.StateEvent
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.features.staking.impl.presentation.state.transformers.InfoType
|
||||
import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -22,6 +24,7 @@ internal data class StakingUiState(
|
|||
val amountState: AmountState,
|
||||
val confirmStakingState: StakingStates.ConfirmStakingState,
|
||||
val isBalanceHidden: Boolean,
|
||||
val bottomSheetConfig: TangemBottomSheetConfig?,
|
||||
val event: StateEvent<StakingEvent>,
|
||||
) {
|
||||
|
||||
|
|
@ -52,6 +55,7 @@ internal sealed class StakingStates {
|
|||
val rewardClaiming: String,
|
||||
val warmupPeriod: String,
|
||||
val rewardSchedule: String,
|
||||
val onInfoClick: (InfoType) -> Unit,
|
||||
) : InitialInfoState()
|
||||
|
||||
data class Empty(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
package com.tangem.features.staking.impl.presentation.state.bottomsheet
|
||||
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
|
||||
data class StakingInfoBottomSheetConfig(
|
||||
val title: TextReference,
|
||||
val text: TextReference,
|
||||
) : TangemBottomSheetConfigContent
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.features.staking.impl.presentation.state.stub
|
||||
|
||||
import com.tangem.domain.staking.model.Yield
|
||||
import com.tangem.features.staking.impl.presentation.state.transformers.InfoType
|
||||
import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents
|
||||
|
||||
object StakingClickIntentsStub : StakingClickIntents {
|
||||
|
|
@ -11,6 +12,8 @@ object StakingClickIntentsStub : StakingClickIntents {
|
|||
|
||||
override fun onPrevClick() {}
|
||||
|
||||
override fun onInfoClick(infoType: InfoType) {}
|
||||
|
||||
override fun onAmountValueChange(value: String) {}
|
||||
|
||||
override fun onAmountPasteTriggerDismiss() {}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
package com.tangem.features.staking.impl.presentation.state.transformers
|
||||
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingUiState
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
|
||||
internal class DismissBottomSheetStateTransformer : Transformer<StakingUiState> {
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
return prevState.copy(bottomSheetConfig = null)
|
||||
}
|
||||
}
|
||||
|
|
@ -70,7 +70,7 @@ internal class SetInitialDataStateTransformer(
|
|||
rewardClaiming = yield.metadata.rewardClaiming,
|
||||
warmupPeriod = yield.metadata.warmupPeriod.days.toString(),
|
||||
rewardSchedule = yield.metadata.rewardSchedule,
|
||||
|
||||
onInfoClick = clickIntents::onInfoClick,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
package com.tangem.features.staking.impl.presentation.state.transformers
|
||||
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.features.staking.impl.R
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingUiState
|
||||
import com.tangem.features.staking.impl.presentation.state.bottomsheet.StakingInfoBottomSheetConfig
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
|
||||
internal class ShowInfoBottomSheetStateTransformer(
|
||||
private val infoType: InfoType,
|
||||
private val onDismiss: () -> Unit,
|
||||
) : Transformer<StakingUiState> {
|
||||
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
return prevState.copy(
|
||||
bottomSheetConfig = TangemBottomSheetConfig(
|
||||
onDismissRequest = onDismiss,
|
||||
isShow = true,
|
||||
content = when (infoType) {
|
||||
InfoType.APY -> StakingInfoBottomSheetConfig(
|
||||
title = resourceReference(R.string.staking_details_apy),
|
||||
text = resourceReference(R.string.staking_details_apy_info),
|
||||
)
|
||||
InfoType.UNBOUNDING_PERIOD -> StakingInfoBottomSheetConfig(
|
||||
title = resourceReference(R.string.staking_details_unbonding_period),
|
||||
text = resourceReference(R.string.staking_details_unbonding_period_info),
|
||||
)
|
||||
InfoType.REWARD_CLAIMING -> StakingInfoBottomSheetConfig(
|
||||
title = resourceReference(R.string.staking_details_reward_claiming),
|
||||
text = resourceReference(R.string.staking_details_reward_claiming_info),
|
||||
)
|
||||
InfoType.WARMUP_PERIOD -> StakingInfoBottomSheetConfig(
|
||||
title = resourceReference(R.string.staking_details_warmup_period),
|
||||
text = resourceReference(R.string.staking_details_warmup_period_info),
|
||||
)
|
||||
InfoType.REWARD_SCHEDULE -> StakingInfoBottomSheetConfig(
|
||||
title = resourceReference(R.string.staking_details_reward_schedule),
|
||||
text = resourceReference(R.string.staking_details_reward_schedule_info),
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
enum class InfoType {
|
||||
APY,
|
||||
UNBOUNDING_PERIOD,
|
||||
REWARD_CLAIMING,
|
||||
WARMUP_PERIOD,
|
||||
REWARD_SCHEDULE,
|
||||
}
|
||||
|
|
@ -25,6 +25,7 @@ import com.tangem.core.ui.res.TangemTheme
|
|||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.staking.impl.R
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
||||
import com.tangem.features.staking.impl.presentation.state.transformers.InfoType
|
||||
|
||||
@Composable
|
||||
internal fun StakingInitialInfoContent(state: StakingStates.InitialInfoState) {
|
||||
|
|
@ -121,11 +122,13 @@ internal fun StakingDetailsRows(state: StakingStates.InitialInfoState.Data) {
|
|||
startText = stringResource(id = R.string.staking_details_apy),
|
||||
endText = state.aprRange.resolveReference(),
|
||||
cornersToRound = CornersToRound.ZERO,
|
||||
iconClick = { state.onInfoClick(InfoType.APY) },
|
||||
)
|
||||
InitialInfoContentRow(
|
||||
startText = stringResource(id = R.string.staking_details_unbonding_period),
|
||||
endText = state.unbondingPeriod,
|
||||
cornersToRound = CornersToRound.ZERO,
|
||||
iconClick = { state.onInfoClick(InfoType.UNBOUNDING_PERIOD) },
|
||||
)
|
||||
InitialInfoContentRow(
|
||||
startText = stringResource(id = R.string.staking_details_minimum_requirement),
|
||||
|
|
@ -136,21 +139,29 @@ internal fun StakingDetailsRows(state: StakingStates.InitialInfoState.Data) {
|
|||
startText = stringResource(id = R.string.staking_details_reward_claiming),
|
||||
endText = state.rewardClaiming,
|
||||
cornersToRound = CornersToRound.ZERO,
|
||||
iconClick = { state.onInfoClick(InfoType.REWARD_CLAIMING) },
|
||||
)
|
||||
InitialInfoContentRow(
|
||||
startText = stringResource(id = R.string.staking_details_warmup_period),
|
||||
endText = state.warmupPeriod,
|
||||
cornersToRound = CornersToRound.ZERO,
|
||||
iconClick = { state.onInfoClick(InfoType.WARMUP_PERIOD) },
|
||||
)
|
||||
InitialInfoContentRow(
|
||||
startText = stringResource(id = R.string.staking_details_reward_schedule),
|
||||
endText = state.rewardSchedule,
|
||||
cornersToRound = CornersToRound.BOTTOM_2,
|
||||
iconClick = { state.onInfoClick(InfoType.REWARD_SCHEDULE) },
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun InitialInfoContentRow(startText: String, endText: String, cornersToRound: CornersToRound) {
|
||||
private fun InitialInfoContentRow(
|
||||
startText: String,
|
||||
endText: String,
|
||||
cornersToRound: CornersToRound,
|
||||
iconClick: (() -> Unit)? = null,
|
||||
) {
|
||||
RoundableCornersRow(
|
||||
startText = startText,
|
||||
startTextColor = TangemTheme.colors.text.primary1,
|
||||
|
|
@ -159,7 +170,8 @@ private fun InitialInfoContentRow(startText: String, endText: String, cornersToR
|
|||
endTextColor = TangemTheme.colors.text.tertiary,
|
||||
endTextStyle = TangemTheme.typography.body2,
|
||||
cornersToRound = cornersToRound,
|
||||
iconResId = null, // TODO staking add bottom sheets when text will be available
|
||||
iconResId = R.drawable.ic_information_24,
|
||||
iconClick = iconClick,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -189,6 +201,7 @@ private class StakingInitialInfoContentPreviewProvider : PreviewParameterProvide
|
|||
rewardClaiming = "Auto",
|
||||
warmupPeriod = "Days",
|
||||
rewardSchedule = "Block",
|
||||
onInfoClick = {},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,11 +14,14 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import com.tangem.common.ui.amountScreen.AmountScreenContent
|
||||
import com.tangem.core.ui.components.appbar.AppBarWithBackButtonAndIcon
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.staking.impl.R
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStep
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingUiState
|
||||
import com.tangem.features.staking.impl.presentation.state.bottomsheet.StakingInfoBottomSheetConfig
|
||||
import com.tangem.features.staking.impl.presentation.ui.bottomsheet.StakingInfoBottomSheet
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
|
@ -45,6 +48,15 @@ internal fun StakingScreen(uiState: StakingUiState) {
|
|||
StakingNavigationButtons(
|
||||
uiState = uiState,
|
||||
)
|
||||
StakingBottomSheet(bottomSheetConfig = uiState.bottomSheetConfig)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun StakingBottomSheet(bottomSheetConfig: TangemBottomSheetConfig?) {
|
||||
if (bottomSheetConfig == null) return
|
||||
when (bottomSheetConfig.content) {
|
||||
is StakingInfoBottomSheetConfig -> StakingInfoBottomSheet(bottomSheetConfig)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
package com.tangem.features.staking.impl.presentation.ui.bottomsheet
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.tangem.core.ui.components.appbar.AppBar
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.staking.impl.presentation.state.bottomsheet.StakingInfoBottomSheetConfig
|
||||
|
||||
@Composable
|
||||
fun StakingInfoBottomSheet(config: TangemBottomSheetConfig) {
|
||||
val scrollState = rememberScrollState()
|
||||
TangemBottomSheet(
|
||||
config = config,
|
||||
) { content: StakingInfoBottomSheetConfig ->
|
||||
Column(
|
||||
modifier = Modifier.verticalScroll(scrollState),
|
||||
) {
|
||||
AppBar(text = content.title)
|
||||
Text(
|
||||
text = content.text.resolveReference(),
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
style = TangemTheme.typography.body2,
|
||||
modifier = Modifier.padding(
|
||||
horizontal = TangemTheme.dimens.spacing28,
|
||||
vertical = TangemTheme.dimens.spacing16,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.tangem.features.staking.impl.presentation.viewmodel
|
|||
|
||||
import com.tangem.common.ui.amountScreen.AmountScreenClickIntents
|
||||
import com.tangem.domain.staking.model.Yield
|
||||
import com.tangem.features.staking.impl.presentation.state.transformers.InfoType
|
||||
|
||||
internal interface StakingClickIntents : AmountScreenClickIntents {
|
||||
|
||||
|
|
@ -11,6 +12,8 @@ internal interface StakingClickIntents : AmountScreenClickIntents {
|
|||
|
||||
fun onPrevClick()
|
||||
|
||||
fun onInfoClick(infoType: InfoType)
|
||||
|
||||
override fun onAmountNext() = onNextClick()
|
||||
|
||||
fun openValidators()
|
||||
|
|
|
|||
|
|
@ -22,8 +22,7 @@ import com.tangem.features.staking.impl.navigation.InnerStakingRouter
|
|||
import com.tangem.features.staking.impl.presentation.state.StakingStateController
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStateRouter
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingUiState
|
||||
import com.tangem.features.staking.impl.presentation.state.transformers.HideBalanceStateTransformer
|
||||
import com.tangem.features.staking.impl.presentation.state.transformers.SetInitialDataStateTransformer
|
||||
import com.tangem.features.staking.impl.presentation.state.transformers.*
|
||||
import com.tangem.features.staking.impl.presentation.state.transformers.amount.AmountChangeStateTransformer
|
||||
import com.tangem.features.staking.impl.presentation.state.transformers.amount.AmountCurrencyChangeStateTransformer
|
||||
import com.tangem.features.staking.impl.presentation.state.transformers.amount.AmountMaxValueStateTransformer
|
||||
|
|
@ -92,6 +91,14 @@ internal class StakingViewModel @Inject constructor(
|
|||
stakingStateRouter.onBackClick()
|
||||
}
|
||||
|
||||
override fun onInfoClick(infoType: InfoType) {
|
||||
stateController.update(
|
||||
ShowInfoBottomSheetStateTransformer(infoType) {
|
||||
stateController.update(DismissBottomSheetStateTransformer())
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
override fun onAmountValueChange(value: String) {
|
||||
stateController.update(AmountChangeStateTransformer(cryptoCurrencyStatus, value))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue