diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/atoms/radiobutton/TangemRadioButton.kt b/core/ui/src/main/java/com/tangem/core/ui/components/atoms/radiobutton/TangemRadioButton.kt new file mode 100644 index 0000000000..777062e8bd --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/components/atoms/radiobutton/TangemRadioButton.kt @@ -0,0 +1,85 @@ +package com.tangem.core.ui.components.atoms.radiobutton + +import android.content.res.Configuration +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material.ripple.rememberRipple +import androidx.compose.material3.Icon +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.drawscope.Stroke +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import com.tangem.core.ui.R +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview + +/** + * [Radio button](https://www.figma.com/design/14ISV23YB1yVW1uNVwqrKv/Android?node-id=101-119&t=FH84ljLBk1vmGAei-4) + * + * @param isSelected Whether the radio button is selected + * @param onClick Called when the user clicks the button + * @param modifier Modifier to be applied to the button + * @param isEnabled Whether the button click is enabled + */ +@Composable +fun TangemRadioButton( + isSelected: Boolean, + onClick: () -> Unit, + modifier: Modifier = Modifier, + isEnabled: Boolean = true, +) { + Box( + modifier = modifier.clickable( + enabled = isEnabled, + interactionSource = remember { MutableInteractionSource() }, + indication = rememberRipple(bounded = false, radius = TangemTheme.dimens.size16), + onClick = onClick, + ), + ) { + val color = TangemTheme.colors.stroke.secondary + val radius = with(LocalDensity.current) { TangemTheme.dimens.size9.toPx() } + val width = with(LocalDensity.current) { TangemTheme.dimens.size2.toPx() } + Canvas( + modifier = Modifier + .size(TangemTheme.dimens.size24) + .padding(TangemTheme.dimens.spacing2), + ) { + drawCircle( + color = color, + radius = radius, + style = Stroke(width), + ) + } + AnimatedVisibility( + visible = isSelected, + label = "Radio button animation", + modifier = modifier + .size(TangemTheme.dimens.size24), + ) { + Icon( + painter = painterResource(id = R.drawable.ic_check_circle_24), + contentDescription = null, + tint = TangemTheme.colors.control.checked, + ) + } + } +} + +// region Preview +@Preview(showBackground = true) +@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun TangemRadioButton_Preview() { + var isSelected by remember { mutableStateOf(false) } + TangemThemePreview { + TangemRadioButton(isSelected, onClick = { isSelected = !isSelected }) + } +} +// endregion \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowBestRate.kt b/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowBestRate.kt index 3f711de362..0a17c85b13 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowBestRate.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowBestRate.kt @@ -5,7 +5,6 @@ import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.* -import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.ripple.rememberRipple import androidx.compose.material3.Icon @@ -14,18 +13,15 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import coil.compose.SubcomposeAsyncImage -import coil.request.ImageRequest import com.tangem.core.ui.R import com.tangem.core.ui.components.SpacerWMax -import com.tangem.core.ui.components.currency.tokenicon.LoadingIcon import com.tangem.core.ui.components.inputrow.inner.DividerContainer +import com.tangem.core.ui.components.inputrow.inner.InputRowAsyncImage import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.res.TangemThemePreview @@ -63,7 +59,7 @@ fun InputRowBestRate( modifier = Modifier .padding(TangemTheme.dimens.spacing12), ) { - InnerIcon(imageUrl = imageUrl) + InputRowAsyncImage(imageUrl = imageUrl, modifier = Modifier.size(TangemTheme.dimens.spacing40)) Column( modifier = Modifier .padding(start = TangemTheme.dimens.spacing12), @@ -131,29 +127,6 @@ private fun InnerTitle(title: TextReference, titleExtra: TextReference, showTag: } } -@Composable -private fun InnerIcon(imageUrl: String) { - SubcomposeAsyncImage( - modifier = Modifier.size(TangemTheme.dimens.size40), - model = ImageRequest.Builder(context = LocalContext.current) - .data(imageUrl) - .crossfade(enable = true) - .allowHardware(enable = false) - .build(), - loading = { LoadingIcon() }, - error = { - Box( - modifier = Modifier - .background( - color = TangemTheme.colors.background.tertiary, - shape = CircleShape, - ), - ) - }, - contentDescription = null, - ) -} - //region preview @Preview @Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowImageBase.kt b/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowImageBase.kt new file mode 100644 index 0000000000..51f7b29ac6 --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowImageBase.kt @@ -0,0 +1,54 @@ +package com.tangem.core.ui.components.inputrow + +import androidx.compose.foundation.layout.* +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import com.tangem.core.ui.components.inputrow.inner.InputRowAsyncImage +import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.resolveAnnotatedReference +import com.tangem.core.ui.extensions.resolveReference +import com.tangem.core.ui.res.TangemTheme + +@Composable +internal fun InputRowImageBase( + subtitle: TextReference, + caption: TextReference, + imageUrl: String, + modifier: Modifier = Modifier, + subtitleColor: Color = TangemTheme.colors.text.primary1, + captionColor: Color = TangemTheme.colors.text.tertiary, + extraContent: @Composable RowScope.() -> Unit = {}, +) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = modifier, + ) { + InputRowAsyncImage( + imageUrl = imageUrl, + modifier = Modifier + .size(TangemTheme.dimens.spacing36) + .padding(vertical = TangemTheme.dimens.size1), + ) + Column( + modifier = Modifier + .weight(1f) + .padding(start = TangemTheme.dimens.spacing12), + ) { + Text( + text = subtitle.resolveReference(), + style = TangemTheme.typography.subtitle2, + color = subtitleColor, + ) + Text( + text = caption.resolveAnnotatedReference(), + style = TangemTheme.typography.caption2, + color = captionColor, + modifier = Modifier.padding(top = TangemTheme.dimens.spacing2), + ) + } + extraContent() + } +} \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowImageChevron.kt b/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowImageChevron.kt new file mode 100644 index 0000000000..9c8fcff521 --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowImageChevron.kt @@ -0,0 +1,46 @@ +package com.tangem.core.ui.components.inputrow + +import androidx.compose.material.Icon +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import com.tangem.core.ui.R +import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.res.TangemTheme + +/** + * Input row component with selector + * [Input Row Image](https://www.figma.com/design/14ISV23YB1yVW1uNVwqrKv/Android?node-id=2100-842&t=hoBXmDX8NeLrp4p6-4) + * + * @param subtitle subtitle text + * @param caption caption text + * @param imageUrl icon to load + * @param modifier modifier + * @param subtitleColor subtitle text color + * @param captionColor caption text color + */ +@Composable +fun InputRowImageChevron( + subtitle: TextReference, + caption: TextReference, + imageUrl: String, + modifier: Modifier = Modifier, + subtitleColor: Color = TangemTheme.colors.text.primary1, + captionColor: Color = TangemTheme.colors.text.tertiary, +) { + InputRowImageBase( + subtitle = subtitle, + caption = caption, + imageUrl = imageUrl, + modifier = modifier, + subtitleColor = subtitleColor, + captionColor = captionColor, + ) { + Icon( + painter = painterResource(id = R.drawable.ic_chevron_right_24), + tint = TangemTheme.colors.icon.informative, + contentDescription = null, + ) + } +} \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowImageSelector.kt b/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowImageSelector.kt new file mode 100644 index 0000000000..9e672eb56b --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowImageSelector.kt @@ -0,0 +1,131 @@ +package com.tangem.core.ui.components.inputrow + +import android.content.res.Configuration +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.padding +import androidx.compose.material.ripple.rememberRipple +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.withStyle +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import com.tangem.core.ui.R +import com.tangem.core.ui.components.atoms.radiobutton.TangemRadioButton +import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.annotatedReference +import com.tangem.core.ui.extensions.combinedReference +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.core.ui.utils.BigDecimalFormatter +import java.math.BigDecimal + +/** + * Input row component with selector + * [Input Row Image](https://www.figma.com/design/14ISV23YB1yVW1uNVwqrKv/Android?node-id=2772-905&t=FH84ljLBk1vmGAei-4) + * + * @param subtitle subtitle text + * @param caption caption text + * @param imageUrl icon to load + * @param onSelect callback when selected + * @param modifier modifier + * @param subtitleColor subtitle text color + * @param captionColor caption text color + * @param isSelected true if selected + */ +@Composable +fun InputRowImageSelector( + subtitle: TextReference, + caption: TextReference, + imageUrl: String, + onSelect: () -> Unit, + modifier: Modifier = Modifier, + subtitleColor: Color = TangemTheme.colors.text.primary1, + captionColor: Color = TangemTheme.colors.text.tertiary, + isSelected: Boolean = false, +) { + InputRowImageBase( + subtitle = subtitle, + caption = caption, + imageUrl = imageUrl, + subtitleColor = subtitleColor, + captionColor = captionColor, + modifier = modifier + .clickable( + onClick = onSelect, + interactionSource = remember { MutableInteractionSource() }, + indication = rememberRipple(), + ) + .padding(TangemTheme.dimens.spacing12), + ) { + TangemRadioButton(isSelected = isSelected, isEnabled = false, onClick = onSelect) + } +} + +//region preview +@Preview +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun InputRowImageSelectorPreview( + @PreviewParameter(InputRowImageSelectorPreviewDataProvider::class) data: InputRowImageSelectorPreviewData, +) { + TangemThemePreview { + InputRowImageSelector( + modifier = Modifier.background(TangemTheme.colors.background.action), + subtitle = data.subtitle, + caption = combinedReference( + resourceReference(R.string.staking_details_apr), + annotatedReference( + buildAnnotatedString { + append(" ") + withStyle(style = SpanStyle(color = TangemTheme.colors.text.accent)) { + append( + BigDecimalFormatter.formatPercent(BigDecimal.ZERO, true), + ) + } + }, + ), + ), + imageUrl = "", + isSelected = false, + onSelect = {}, + ) + } +} + +private data class InputRowImageSelectorPreviewData( + val subtitle: TextReference, + val caption: TextReference, + val showDivider: Boolean, + val actionIconRes: Int?, + val isSelected: Boolean, +) + +private class InputRowImageSelectorPreviewDataProvider : + PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + InputRowImageSelectorPreviewData( + subtitle = TextReference.Str("subtitle"), + caption = TextReference.Str("caption"), + actionIconRes = null, + showDivider = false, + isSelected = false, + ), + InputRowImageSelectorPreviewData( + subtitle = TextReference.Str("subtitle"), + caption = TextReference.Str("caption"), + actionIconRes = R.drawable.ic_chevron_right_24, + showDivider = true, + isSelected = true, + ), + ) +} +//endregion \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/inner/InputRowAsyncImage.kt b/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/inner/InputRowAsyncImage.kt new file mode 100644 index 0000000000..90bf7e86b8 --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/inner/InputRowAsyncImage.kt @@ -0,0 +1,41 @@ +package com.tangem.core.ui.components.inputrow.inner + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import coil.compose.SubcomposeAsyncImage +import coil.request.ImageRequest +import com.tangem.core.ui.components.currency.tokenicon.LoadingIcon +import com.tangem.core.ui.res.TangemTheme + +/** + * Loads image by url for icon in the input row + * + * @param imageUrl url of the image + * @param modifier modifier + */ +@Composable +internal fun InputRowAsyncImage(imageUrl: String, modifier: Modifier = Modifier) { + SubcomposeAsyncImage( + modifier = modifier, + model = ImageRequest.Builder(context = LocalContext.current) + .data(imageUrl) + .crossfade(enable = true) + .allowHardware(enable = false) + .build(), + loading = { LoadingIcon() }, + error = { + Box( + modifier = Modifier + .background( + color = TangemTheme.colors.background.tertiary, + shape = CircleShape, + ), + ) + }, + contentDescription = null, + ) +} \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/extensions/TextReference.kt b/core/ui/src/main/java/com/tangem/core/ui/extensions/TextReference.kt index 13373f947b..386f69b66b 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/extensions/TextReference.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/extensions/TextReference.kt @@ -48,6 +48,13 @@ sealed interface TextReference { */ data class Str(val value: String) : TextReference + /** + * Annotated text + * + * @property value annotated string + */ + data class Annotated(val value: AnnotatedString) : TextReference + /** * Combined reference. It concatenates all [refs]. * @@ -83,6 +90,16 @@ fun stringReference(value: String): TextReference { return TextReference.Str(value) } +/** + * Creates a [TextReference] using an annotated string value. + * + * @param value The annotated string value. + * @return A [TextReference] representing the provided annotated string value. + */ +fun annotatedReference(value: AnnotatedString): TextReference { + return TextReference.Annotated(value) +} + /** * Creates a [TextReference] using a plural string resource ID with count and optional format arguments. * @@ -133,6 +150,7 @@ fun TextReference.resolveReference(): String { } is TextReference.PluralRes -> pluralStringResource(id, count, *formatArgs.toTypedArray()) is TextReference.Str -> value + is TextReference.Annotated -> value.text is TextReference.Combined -> { buildString { refs.forEach { @@ -155,6 +173,7 @@ fun TextReference.resolveReference(resources: Resources): String { } is TextReference.PluralRes -> resources.getQuantityString(id, count, *formatArgs.toTypedArray()) is TextReference.Str -> value + is TextReference.Annotated -> value.text is TextReference.Combined -> { buildString { refs.forEach { @@ -180,9 +199,10 @@ fun TextReference.resolveAnnotatedReference(): AnnotatedString { pluralStringResource(id, count, *formatArgs.toTypedArray()), ) is TextReference.Str -> formatAnnotated(value) + is TextReference.Annotated -> value is TextReference.Combined -> buildAnnotatedString { refs.forEach { - append(formatAnnotated(it.resolveReference())) + append(it.resolveAnnotatedReference()) } } } @@ -195,6 +215,7 @@ operator fun TextReference.plus(ref: TextReference): TextReference { is TextReference.PluralRes, is TextReference.Res, is TextReference.Str, + is TextReference.Annotated, -> TextReference.Combined(refs = wrappedList(this, ref)) } } diff --git a/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt b/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt index a2649901ad..cc51084e66 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt @@ -47,6 +47,7 @@ data class TangemDimens internal constructor( val size5: Dp = 5.dp, val size7: Dp = 7.dp, val size8: Dp = 8.dp, + val size9: Dp = 9.dp, val size10: Dp = 10.dp, val size11: Dp = 11.dp, val size12: Dp = 12.dp, diff --git a/core/ui/src/main/res/drawable/ic_check_circle_24.xml b/core/ui/src/main/res/drawable/ic_check_circle_24.xml new file mode 100644 index 0000000000..21b193accf --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_check_circle_24.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateRouter.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateRouter.kt index 7d70ebd667..79fff44a09 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateRouter.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateRouter.kt @@ -30,7 +30,9 @@ internal class StakingStateRouter( fun onNextClick() { when (stateController.uiState.value.currentStep) { StakingStep.InitialInfo -> showAmount() - StakingStep.Amount -> showConfirm() + StakingStep.Validators, + StakingStep.Amount, + -> showConfirm() StakingStep.Confirm -> showSuccess() StakingStep.Success -> onBackClick() } @@ -51,6 +53,10 @@ internal class StakingStateRouter( stateController.update { it.copy(currentStep = StakingStep.Amount) } } + fun showValidators() { + stateController.update { it.copy(currentStep = StakingStep.Validators) } + } + fun showConfirm() { stateController.update { it.copy(currentStep = StakingStep.Confirm) } } diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingUiState.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingUiState.kt index bd01183407..1f6e81e3b3 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingUiState.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingUiState.kt @@ -6,7 +6,6 @@ import com.tangem.common.ui.amountScreen.models.AmountState import com.tangem.core.ui.event.StateEvent import com.tangem.core.ui.extensions.TextReference import com.tangem.domain.appcurrency.model.AppCurrency -import com.tangem.domain.staking.model.Yield import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents import kotlinx.collections.immutable.ImmutableList import java.math.BigDecimal @@ -85,16 +84,12 @@ internal sealed class StakingStates { val appCurrency: AppCurrency, val isFeeApproximate: Boolean, ) - - data class ValidatorState( - val validatorState: InnerValidatorState, - val availableValidators: List, - ) } enum class StakingStep { InitialInfo, Amount, + Validators, Confirm, Success, } \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/InnerValidatorState.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/ValidatorState.kt similarity index 53% rename from features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/InnerValidatorState.kt rename to features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/ValidatorState.kt index 8a3c91fa45..d99ed81d8e 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/InnerValidatorState.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/ValidatorState.kt @@ -4,13 +4,14 @@ import androidx.compose.runtime.Immutable import com.tangem.domain.staking.model.Yield @Immutable -internal sealed class InnerValidatorState { +internal sealed class ValidatorState { data class Content( val chosenValidator: Yield.Validator, - ) : InnerValidatorState() + val availableValidators: List, + ) : ValidatorState() - data object Loading : InnerValidatorState() + data object Loading : ValidatorState() - data object Error : InnerValidatorState() + data object Error : ValidatorState() } \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/previewdata/ConfirmStakingStatePreviewData.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/previewdata/ConfirmStakingStatePreviewData.kt index 13d3cc4a1c..3e81a056fc 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/previewdata/ConfirmStakingStatePreviewData.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/previewdata/ConfirmStakingStatePreviewData.kt @@ -7,9 +7,9 @@ import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.staking.model.Yield import com.tangem.features.staking.impl.presentation.state.InnerFeeState -import com.tangem.features.staking.impl.presentation.state.InnerValidatorState import com.tangem.features.staking.impl.presentation.state.StakingNotification import com.tangem.features.staking.impl.presentation.state.StakingStates +import com.tangem.features.staking.impl.presentation.state.ValidatorState import kotlinx.collections.immutable.persistentListOf import java.math.BigDecimal @@ -73,10 +73,8 @@ internal object ConfirmStakingStatePreviewData { isFeeApproximate = false, isFeeConvertibleToFiat = true, ), - validatorState = StakingStates.ValidatorState( - validatorState = InnerValidatorState.Content( - chosenValidator = validatorList[0], - ), + validatorState = ValidatorState.Content( + chosenValidator = validatorList[0], availableValidators = validatorList, ), footerText = "You stake \$715.11 and will be receiving ~\$35 monthly", diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/stub/StakingClickIntentsStub.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/stub/StakingClickIntentsStub.kt index 7c01094036..f59a64f975 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/stub/StakingClickIntentsStub.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/stub/StakingClickIntentsStub.kt @@ -1,5 +1,6 @@ package com.tangem.features.staking.impl.presentation.state.stub +import com.tangem.domain.staking.model.Yield import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents object StakingClickIntentsStub : StakingClickIntents { @@ -19,4 +20,8 @@ object StakingClickIntentsStub : StakingClickIntents { override fun onCurrencyChangeClick(isFiat: Boolean) {} override fun onAmountNext() {} + + override fun openValidators() {} + + override fun onValidatorSelect(validator: Yield.Validator) {} } \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt index c06765c6ed..7a0d619a46 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt @@ -14,8 +14,10 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.wallets.models.UserWallet import com.tangem.features.staking.impl.R import com.tangem.features.staking.impl.presentation.state.StakingStates -import com.tangem.features.staking.impl.presentation.state.StakingUiState 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.ValidatorState +import com.tangem.features.staking.impl.presentation.state.previewdata.ConfirmStakingStatePreviewData import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents import com.tangem.utils.Provider import com.tangem.utils.transformer.Transformer @@ -47,6 +49,7 @@ internal class SetInitialDataStateTransformer( currentStep = StakingStep.InitialInfo, initialInfoState = createInitialInfoState(), amountState = createInitialAmountState(), + confirmStakingState = createInitialConfirmationState(), ) } @@ -75,6 +78,15 @@ internal class SetInitialDataStateTransformer( return amountStateConverter.convert("") } + private fun createInitialConfirmationState(): StakingStates.ConfirmStakingState { + return ConfirmStakingStatePreviewData.confirmStakingState.copy( + validatorState = ValidatorState.Content( + chosenValidator = yield.validators.first(), + availableValidators = yield.validators, + ), + ) + } + private fun getAprRange(): TextReference { val aprValues = yield.validators.mapNotNull { it.apr } diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/validator/ValidatorSelectChangeTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/validator/ValidatorSelectChangeTransformer.kt new file mode 100644 index 0000000000..b72f227693 --- /dev/null +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/validator/ValidatorSelectChangeTransformer.kt @@ -0,0 +1,24 @@ +package com.tangem.features.staking.impl.presentation.state.transformers.validator + +import com.tangem.domain.staking.model.Yield +import com.tangem.features.staking.impl.presentation.state.StakingStates +import com.tangem.features.staking.impl.presentation.state.StakingUiState +import com.tangem.features.staking.impl.presentation.state.ValidatorState +import com.tangem.utils.transformer.Transformer + +internal class ValidatorSelectChangeTransformer( + private val selectedValidator: Yield.Validator, +) : Transformer { + override fun transform(prevState: StakingUiState): StakingUiState { + val confirmState = prevState.confirmStakingState as? StakingStates.ConfirmStakingState.Data ?: return prevState + val validatorState = confirmState.validatorState as? ValidatorState.Content ?: return prevState + + return prevState.copy( + confirmStakingState = confirmState.copy( + validatorState = validatorState.copy( + chosenValidator = selectedValidator, + ), + ), + ) + } +} \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingConfirmContent.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingConfirmContent.kt index 9c78086d8f..be8589fa2f 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingConfirmContent.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingConfirmContent.kt @@ -18,11 +18,18 @@ import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview import com.tangem.features.staking.impl.presentation.state.StakingStates import com.tangem.features.staking.impl.presentation.state.previewdata.ConfirmStakingStatePreviewData +import com.tangem.features.staking.impl.presentation.state.stub.StakingClickIntentsStub import com.tangem.features.staking.impl.presentation.ui.block.NotificationsBlock import com.tangem.features.staking.impl.presentation.ui.block.StakingFeeBlock +import com.tangem.features.staking.impl.presentation.ui.block.ValidatorBlock +import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents @Composable -internal fun StakingConfirmContent(amountState: AmountState, state: StakingStates.ConfirmStakingState) { +internal fun StakingConfirmContent( + amountState: AmountState, + state: StakingStates.ConfirmStakingState, + clickIntents: StakingClickIntents, +) { if (state !is StakingStates.ConfirmStakingState.Data) return Column( @@ -39,6 +46,7 @@ internal fun StakingConfirmContent(amountState: AmountState, state: StakingState isEditingDisabled = true, onClick = {}, ) + ValidatorBlock(validatorState = state.validatorState, onClick = clickIntents::openValidators) StakingFeeBlock(feeState = state.feeState) NotificationsBlock(notifications = state.notifications) SpacerHMax() @@ -66,6 +74,7 @@ private fun Preview_StakingConfirmContent() { StakingConfirmContent( amountState = AmountStatePreviewData.amountState, state = ConfirmStakingStatePreviewData.confirmStakingState, + clickIntents = StakingClickIntentsStub, ) } } diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingNavigationButtons.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingNavigationButtons.kt index 21105e3419..9ae31fc482 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingNavigationButtons.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingNavigationButtons.kt @@ -1,6 +1,8 @@ package com.tangem.features.staking.impl.presentation.ui -import androidx.compose.animation.* +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.expandHorizontally +import androidx.compose.animation.shrinkHorizontally import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column @@ -9,7 +11,7 @@ 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.* +import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -24,8 +26,8 @@ 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.StakingStates -import com.tangem.features.staking.impl.presentation.state.StakingUiState import com.tangem.features.staking.impl.presentation.state.StakingStep +import com.tangem.features.staking.impl.presentation.state.StakingUiState @Composable internal fun StakingNavigationButtons(uiState: StakingUiState, modifier: Modifier = Modifier) { @@ -105,7 +107,8 @@ private fun getButtonData(currentState: StakingUiState): Pair Unit> { StakingStep.Amount, StakingStep.Confirm, StakingStep.Success, - -> R.string.common_next to { currentState.clickIntents.onNextClick() } + -> R.string.common_next to currentState.clickIntents::onNextClick + StakingStep.Validators -> R.string.common_continue to currentState.clickIntents::onNextClick } } @@ -113,6 +116,7 @@ private fun isButtonEnabled(uiState: StakingUiState): Boolean { return when (uiState.currentStep) { StakingStep.InitialInfo -> uiState.initialInfoState.isPrimaryButtonEnabled StakingStep.Amount -> uiState.amountState.isPrimaryButtonEnabled + StakingStep.Validators -> uiState.confirmStakingState.isPrimaryButtonEnabled StakingStep.Confirm -> uiState.confirmStakingState.isPrimaryButtonEnabled StakingStep.Success -> true } diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingScreen.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingScreen.kt index a8f36b6e5e..4a41fba77f 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingScreen.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingScreen.kt @@ -16,6 +16,7 @@ import com.tangem.common.ui.amountScreen.AmountScreenContent import com.tangem.core.ui.components.appbar.AppBarWithBackButtonAndIcon 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 kotlinx.coroutines.delay @@ -50,13 +51,16 @@ internal fun StakingScreen(uiState: StakingUiState) { @Composable private fun SendAppBar(uiState: StakingUiState) { val titleRes = when (uiState.currentStep) { - StakingStep.InitialInfo -> stringResource(id = R.string.common_stake) StakingStep.Amount -> stringResource(id = R.string.send_amount_label) - StakingStep.Confirm -> stringResource(id = R.string.common_stake) + StakingStep.InitialInfo, + StakingStep.Validators, + StakingStep.Confirm, + -> stringResource(id = R.string.common_stake) StakingStep.Success -> "" } val backIcon = when (uiState.currentStep) { StakingStep.Amount, + StakingStep.Validators, StakingStep.Confirm, StakingStep.Success, -> { @@ -130,7 +134,16 @@ private fun StakingScreenContent(uiState: StakingUiState, modifier: Modifier = M StakingStep.Confirm -> StakingConfirmContent( amountState = uiState.amountState, state = uiState.confirmStakingState, + clickIntents = uiState.clickIntents, ) + StakingStep.Validators -> { + val confirmState = uiState.confirmStakingState + if (confirmState !is StakingStates.ConfirmStakingState.Data) return@AnimatedContent + StakingValidatorListContent( + state = confirmState.validatorState, + clickIntents = uiState.clickIntents, + ) + } else -> TODO() } } diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingValidatorListContent.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingValidatorListContent.kt new file mode 100644 index 0000000000..1d6e05103d --- /dev/null +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingValidatorListContent.kt @@ -0,0 +1,129 @@ +package com.tangem.features.staking.impl.presentation.ui + +import android.content.res.Configuration +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.withStyle +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import com.tangem.core.ui.components.inputrow.InputRowImageSelector +import com.tangem.core.ui.components.rows.CornersToRound +import com.tangem.core.ui.extensions.annotatedReference +import com.tangem.core.ui.extensions.combinedReference +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.core.ui.utils.BigDecimalFormatter +import com.tangem.features.staking.impl.R +import com.tangem.features.staking.impl.presentation.state.ValidatorState +import com.tangem.features.staking.impl.presentation.state.previewdata.ConfirmStakingStatePreviewData +import com.tangem.features.staking.impl.presentation.state.stub.StakingClickIntentsStub +import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents +import java.math.BigDecimal + +/** + * Staking screen with validators + */ +@Composable +internal fun StakingValidatorListContent( + state: ValidatorState, + clickIntents: StakingClickIntents, + modifier: Modifier = Modifier, +) { + val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() } + + LazyColumn( + contentPadding = PaddingValues(bottom = bottomBarHeight), + modifier = modifier.padding(horizontal = TangemTheme.dimens.spacing16), + ) { + item(key = "HEADER") { + Text( + text = stringResource(R.string.staking_validator), + style = TangemTheme.typography.subtitle2, + color = TangemTheme.colors.text.tertiary, + modifier = Modifier + .fillMaxWidth() + .clip(CornersToRound.TOP_2.getShape()) + .background(TangemTheme.colors.background.action) + .padding( + start = TangemTheme.dimens.spacing12, + end = TangemTheme.dimens.spacing12, + top = TangemTheme.dimens.spacing12, + bottom = TangemTheme.dimens.spacing8, + ), + ) + } + if (state is ValidatorState.Content) { + val validators = state.availableValidators + items( + count = validators.size, + key = { validators[it].address }, + contentType = { validators[it]::class.java }, + ) { index -> + val item = validators[index] + + InputRowImageSelector( + subtitle = stringReference(item.name), + caption = combinedReference( + resourceReference(R.string.staking_details_apr), + annotatedReference( + buildAnnotatedString { + append(" ") + withStyle(style = SpanStyle(color = TangemTheme.colors.text.accent)) { + append( + BigDecimalFormatter.formatPercent(item.apr ?: BigDecimal.ZERO, true), + ) + } + }, + ), + ), + imageUrl = item.image.orEmpty(), + isSelected = item == state.chosenValidator, + onSelect = { clickIntents.onValidatorSelect(item) }, + modifier = Modifier + .clip( + if (index == validators.lastIndex) { + CornersToRound.BOTTOM_2 + } else { + CornersToRound.ZERO + }.getShape(), + ) + .background(TangemTheme.colors.background.action), + ) + } + } + } +} + +// region Preview +@Preview(showBackground = true, widthDp = 360) +@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun StakingValidatorListContent_Preview( + @PreviewParameter(StakingValidatorListContentPreviewProvider::class) + data: ValidatorState, +) { + TangemThemePreview { + StakingValidatorListContent( + state = data, + clickIntents = StakingClickIntentsStub, + ) + } +} + +private class StakingValidatorListContentPreviewProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf(ConfirmStakingStatePreviewData.confirmStakingState.validatorState) +} +// endregion \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/block/ValidatorBlock.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/block/ValidatorBlock.kt new file mode 100644 index 0000000000..4cee3bcba5 --- /dev/null +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/block/ValidatorBlock.kt @@ -0,0 +1,69 @@ +package com.tangem.features.staking.impl.presentation.ui.block + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material.ripple.rememberRipple +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.withStyle +import com.tangem.core.ui.components.inputrow.InputRowImageChevron +import com.tangem.core.ui.extensions.annotatedReference +import com.tangem.core.ui.extensions.combinedReference +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.utils.BigDecimalFormatter +import com.tangem.features.staking.impl.R +import com.tangem.features.staking.impl.presentation.state.ValidatorState +import java.math.BigDecimal + +@Composable +internal fun ValidatorBlock(validatorState: ValidatorState, onClick: () -> Unit) { + Column( + modifier = Modifier + .fillMaxWidth() + .clip(TangemTheme.shapes.roundedCornersXMedium) + .background(TangemTheme.colors.background.action) + .clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = rememberRipple(), + onClick = onClick, + ) + .padding(TangemTheme.dimens.spacing12), + ) { + Text( + text = stringResource(R.string.staking_validator), + style = TangemTheme.typography.subtitle2, + color = TangemTheme.colors.text.tertiary, + modifier = Modifier.padding(bottom = TangemTheme.dimens.spacing6), + ) + if (validatorState is ValidatorState.Content) { + InputRowImageChevron( + subtitle = stringReference(validatorState.chosenValidator.name), + caption = combinedReference( + resourceReference(R.string.staking_details_apr), + annotatedReference( + buildAnnotatedString { + append(" ") + withStyle(SpanStyle(color = TangemTheme.colors.text.accent)) { + val apr = validatorState.chosenValidator.apr ?: BigDecimal.ZERO + append(BigDecimalFormatter.formatPercent(apr, true)) + } + }, + ), + ), + imageUrl = validatorState.chosenValidator.image.orEmpty(), + ) + } + } +} \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingClickIntents.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingClickIntents.kt index 27cd56dced..235659fa3e 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingClickIntents.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingClickIntents.kt @@ -1,6 +1,7 @@ package com.tangem.features.staking.impl.presentation.viewmodel import com.tangem.common.ui.amountScreen.AmountScreenClickIntents +import com.tangem.domain.staking.model.Yield internal interface StakingClickIntents : AmountScreenClickIntents { @@ -11,4 +12,8 @@ internal interface StakingClickIntents : AmountScreenClickIntents { fun onPrevClick() override fun onAmountNext() = onNextClick() + + fun openValidators() + + fun onValidatorSelect(validator: Yield.Validator) } \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt index 15d7803cc7..ee086db4f2 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt @@ -15,22 +15,20 @@ import com.tangem.domain.staking.model.Yield import com.tangem.domain.tokens.GetCryptoCurrencyStatusSyncUseCase import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus -import com.tangem.domain.transaction.usecase.IsFeeApproximateUseCase import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.models.UserWalletId import com.tangem.domain.wallets.usecase.GetUserWalletUseCase 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.StakingStep 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.SetConfirmStateDataStateTransformer import com.tangem.features.staking.impl.presentation.state.transformers.SetInitialDataStateTransformer 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 import com.tangem.features.staking.impl.presentation.state.transformers.amount.AmountPasteDismissStateTransformer +import com.tangem.features.staking.impl.presentation.state.transformers.validator.ValidatorSelectChangeTransformer import com.tangem.utils.Provider import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.hilt.android.lifecycle.HiltViewModel @@ -48,7 +46,6 @@ internal class StakingViewModel @Inject constructor( private val getCryptoCurrencyStatusSyncUseCase: GetCryptoCurrencyStatusSyncUseCase, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val getUserWalletUseCase: GetUserWalletUseCase, - private val isFeeApproximateUseCase: IsFeeApproximateUseCase, savedStateHandle: SavedStateHandle, ) : ViewModel(), DefaultLifecycleObserver, StakingClickIntents { @@ -58,18 +55,17 @@ internal class StakingViewModel @Inject constructor( var stakingStateRouter: StakingStateRouter by Delegates.notNull() private set - private val cryptoCurrencyId: CryptoCurrency.ID = savedStateHandle.get( - AppRoute.Staking.CRYPTO_CURRENCY_ID_KEY, - ) - ?.let { it.unbundle(CryptoCurrency.ID.serializer()) } - ?: error("This screen can't be opened without `CryptoCurrency.ID`") + private val cryptoCurrencyId: CryptoCurrency.ID = + savedStateHandle.get(AppRoute.Staking.CRYPTO_CURRENCY_ID_KEY) + ?.unbundle(CryptoCurrency.ID.serializer()) + ?: error("This screen can't be opened without `CryptoCurrency.ID`") private val userWalletId: UserWalletId = savedStateHandle.get(AppRoute.Staking.USER_WALLET_ID_KEY) - ?.let { it.unbundle(UserWalletId.serializer()) } + ?.unbundle(UserWalletId.serializer()) ?: error("This screen can't be opened without `UserWalletId`") private val yield: Yield = savedStateHandle.get(AppRoute.Staking.YIELD_KEY) - ?.let { it.unbundle(Yield.serializer()) } + ?.unbundle(Yield.serializer()) ?: error("This screen can't be opened without `Yield`") private var cryptoCurrencyStatus: CryptoCurrencyStatus by Delegates.notNull() @@ -90,27 +86,6 @@ internal class StakingViewModel @Inject constructor( override fun onNextClick() { stakingStateRouter.onNextClick() - when (value.currentStep) { - StakingStep.Confirm -> { - stateController.update( - SetConfirmStateDataStateTransformer( - yield = yield, - appCurrencyProvider = Provider { appCurrency }, - cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus }, - isFeeApproximateUseCase = isFeeApproximateUseCase, - ), - ) - } - StakingStep.InitialInfo -> { - // TODO staking - } - StakingStep.Amount -> { - // TODO staking - } - StakingStep.Success -> { - // TODO staking - } - } } override fun onPrevClick() { @@ -133,6 +108,12 @@ internal class StakingViewModel @Inject constructor( stateController.update(AmountCurrencyChangeStateTransformer(cryptoCurrencyStatus, isFiat)) } + override fun openValidators() = stakingStateRouter.showValidators() + + override fun onValidatorSelect(validator: Yield.Validator) { + stateController.update(ValidatorSelectChangeTransformer(validator)) + } + fun setRouter(router: InnerStakingRouter, stateRouter: StakingStateRouter) { innerRouter = router this.stakingStateRouter = stateRouter