Updated on 2026-08-14

This commit is contained in:
Tangem 2024-08-08 12:28:07 +03:00
parent 39f26e5eb1
commit 5f95aadd6c
8 changed files with 417 additions and 85 deletions

View file

@ -18,6 +18,8 @@ object StakingClickIntentsStub : StakingClickIntents {
override fun onPrevClick() {}
override fun onInitialInfoBannerClick() {}
override fun onInfoClick(infoType: InfoType) {}
override fun onAmountValueChange(value: String) {}

View file

@ -87,8 +87,8 @@ internal class SetInitialDataStateTransformer(
val yieldBalance = cryptoCurrencyStatus.value.yieldBalance
return listOfNotNull(
createAnnualPercentageRateItem(),
createAvailableItem(cryptoCurrencyStatus),
createApyItem(),
createUnbondingPeriodItem(),
createMinimumRequirementItem(cryptoCurrencyStatus),
createRewardClaimingItem(),
@ -97,6 +97,15 @@ internal class SetInitialDataStateTransformer(
).toPersistentList()
}
private fun createAnnualPercentageRateItem(): RoundedListWithDividersItemData {
return RoundedListWithDividersItemData(
id = R.string.staking_details_annual_percentage_rate,
startText = TextReference.Res(R.string.staking_details_annual_percentage_rate),
endText = getAprRange(),
iconClick = { clickIntents.onInfoClick(InfoType.ANNUAL_PERCENTAGE_RATE) },
)
}
private fun createAvailableItem(cryptoCurrencyStatus: CryptoCurrencyStatus): RoundedListWithDividersItemData {
return RoundedListWithDividersItemData(
id = R.string.staking_details_available,
@ -111,15 +120,6 @@ internal class SetInitialDataStateTransformer(
)
}
private fun createApyItem(): RoundedListWithDividersItemData {
return RoundedListWithDividersItemData(
id = R.string.staking_details_annual_percentage_rate,
startText = TextReference.Res(R.string.staking_details_annual_percentage_rate),
endText = getAprRange(),
iconClick = { clickIntents.onInfoClick(InfoType.APY) },
)
}
private fun createUnbondingPeriodItem(): RoundedListWithDividersItemData {
return RoundedListWithDividersItemData(
id = R.string.staking_details_unbonding_period,
@ -161,7 +161,10 @@ internal class SetInitialDataStateTransformer(
)
}
private fun createWarmupPeriodItem(): RoundedListWithDividersItemData {
private fun createWarmupPeriodItem(): RoundedListWithDividersItemData? {
val warmupPeriod = yield.metadata.warmupPeriod.days
if (warmupPeriod == 0) return null
return RoundedListWithDividersItemData(
id = R.string.staking_details_warmup_period,
startText = TextReference.Res(R.string.staking_details_warmup_period),

View file

@ -18,7 +18,7 @@ internal class ShowInfoBottomSheetStateTransformer(
onDismissRequest = onDismiss,
isShow = true,
content = when (infoType) {
InfoType.APY -> StakingInfoBottomSheetConfig(
InfoType.ANNUAL_PERCENTAGE_RATE -> StakingInfoBottomSheetConfig(
title = resourceReference(R.string.staking_details_annual_percentage_rate),
text = resourceReference(R.string.staking_details_annual_percentage_rate_info),
)
@ -45,7 +45,7 @@ internal class ShowInfoBottomSheetStateTransformer(
}
enum class InfoType {
APY,
ANNUAL_PERCENTAGE_RATE,
UNBONDING_PERIOD,
REWARD_CLAIMING,
WARMUP_PERIOD,

View file

@ -2,14 +2,13 @@ package com.tangem.features.staking.impl.presentation.ui
import android.content.res.Configuration
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
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.lazy.LazyColumn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.key
@ -17,8 +16,12 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.*
import androidx.compose.ui.res.painterResource
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
@ -28,6 +31,7 @@ import com.tangem.core.ui.components.inputrow.InputRowDefault
import com.tangem.core.ui.components.inputrow.InputRowImageInfo
import com.tangem.core.ui.components.list.roundedListWithDividersItems
import com.tangem.core.ui.extensions.*
import com.tangem.core.ui.res.TangemColorPalette
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.utils.BigDecimalFormatter
@ -45,9 +49,7 @@ import com.tangem.utils.StringsSigns.PLUS
import com.tangem.utils.extensions.orZero
import kotlinx.collections.immutable.ImmutableList
// TODO staking metrics block is temporary disabled
// private const val METRICS_BLOCK_KEY = "MetricsBlock"
private const val BANNER_BLOCK_KEY = "BannerBlock"
private const val STAKING_REWARD_BLOCK_KEY = "StakingRewardBlock"
private const val ACTIVE_STAKING_BLOCK_KEY = "ActiveStakingBlock"
@ -61,16 +63,16 @@ internal fun StakingInitialInfoContent(state: StakingStates.InitialInfoState, cl
.background(TangemTheme.colors.background.secondary)
.padding(horizontal = TangemTheme.dimens.spacing16),
) {
// TODO staking metrics block is temporary disabled
// https://www.figma.com/design/Vs6SkVsFnUPsSCNwlnVf5U?node-id=12484-35755#876661319
// if (state.yieldBalance == InnerYieldBalanceState.Empty) {
// item(key = METRICS_BLOCK_KEY) {
// Column(modifier = Modifier.animateItemPlacement()) {
// MetricsBlock(state)
// SpacerH12()
// }
// }
// }
if (state.yieldBalance == InnerYieldBalanceState.Empty) {
item(key = BANNER_BLOCK_KEY) {
Column(
modifier = Modifier.animateItemPlacement(),
) {
BannerBlock(onClick = clickIntents::onInitialInfoBannerClick)
SpacerH12()
}
}
}
this.roundedListWithDividersItems(
rows = state.infoItems,
@ -102,66 +104,31 @@ internal fun StakingInitialInfoContent(state: StakingStates.InitialInfoState, cl
}
}
@Suppress("UnusedPrivateMember")
@Composable
private fun MetricsBlock(state: StakingStates.InitialInfoState.Data) {
Column(
modifier = Modifier
.background(
color = TangemTheme.colors.background.primary,
shape = RoundedCornerShape(TangemTheme.dimens.radius12),
)
.padding(TangemTheme.dimens.spacing12)
.fillMaxWidth(),
private fun BannerBlock(onClick: () -> Unit) {
Box(
modifier = Modifier.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(),
onClick = onClick,
),
) {
Text(
text = stringResource(id = R.string.staking_details_metrics_block_header),
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.tertiary,
Image(
modifier = Modifier.fillMaxSize(),
painter = painterResource(R.drawable.img_staking_banner),
contentDescription = null,
)
Spacer(modifier = Modifier.height(TangemTheme.dimens.size8))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
) {
Column(modifier = Modifier.weight(1F)) {
Text(
text = stringResource(id = R.string.staking_details_apr),
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.tertiary,
)
Text(
modifier = Modifier.padding(top = TangemTheme.dimens.spacing8),
text = state.aprRange.resolveReference(),
style = TangemTheme.typography.body1,
color = TangemTheme.colors.text.accent,
)
}
Column(modifier = Modifier.weight(1F)) {
Row {
Text(
modifier = Modifier.padding(end = TangemTheme.dimens.spacing4),
text = stringResource(id = R.string.staking_details_market_rating),
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.tertiary,
)
Icon(
modifier = Modifier
.size(TangemTheme.dimens.size16)
.align(Alignment.CenterVertically),
painter = painterResource(id = R.drawable.ic_alert_24),
contentDescription = null,
tint = TangemTheme.colors.text.tertiary,
)
Text(
modifier = Modifier
.align(Alignment.CenterStart)
.padding(TangemTheme.dimens.spacing16),
text = buildAnnotatedString {
withStyle(SpanStyle(Brush.linearGradient(textGradientColors))) {
append(stringResource(R.string.staking_details_banner_text))
}
Text(
modifier = Modifier.padding(top = TangemTheme.dimens.spacing8),
text = "1", // TODO staking
style = TangemTheme.typography.body1,
color = TangemTheme.colors.text.accent,
)
}
}
},
style = TangemTheme.typography.h2,
)
}
}
@ -271,6 +238,11 @@ private fun ActiveStakingBlock(groups: ImmutableList<BalanceGroupedState>, onCli
}
}
private val textGradientColors = listOf(
TangemColorPalette.White,
Color(0xff8fb4df),
)
// region preview
@Preview(showBackground = true, widthDp = 360)

View file

@ -22,6 +22,8 @@ internal interface StakingClickIntents : AmountScreenClickIntents {
fun onPrevClick()
fun onInitialInfoBannerClick()
fun onInfoClick(infoType: InfoType)
override fun onAmountNext() = onNextClick(actionType = null)

View file

@ -207,6 +207,10 @@ internal class StakingViewModel @Inject constructor(
stakingStateRouter.onPrevClick()
}
override fun onInitialInfoBannerClick() {
innerRouter.openUrl(WHAT_IS_STAKING_ARTICLE_URL)
}
override fun onInfoClick(infoType: InfoType) {
stateController.update(
ShowInfoBottomSheetStateTransformer(infoType) {
@ -401,4 +405,8 @@ internal class StakingViewModel @Inject constructor(
(value.confirmationState as? StakingStates.ConfirmationState.Data)?.innerState ==
InnerConfirmationStakingState.ASSENT
}
companion object {
const val WHAT_IS_STAKING_ARTICLE_URL = "TODO staking"
}
}