Updated on 2026-08-14
This commit is contained in:
parent
698f1e6047
commit
d84f383cf8
29 changed files with 567 additions and 547 deletions
|
|
@ -15,11 +15,11 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.BlurredEdgeTreatment
|
import androidx.compose.ui.draw.BlurredEdgeTreatment
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.draw.innerShadow
|
import androidx.compose.ui.draw.innerShadow
|
||||||
import androidx.compose.ui.platform.testTag
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.StrokeCap
|
import androidx.compose.ui.graphics.StrokeCap
|
||||||
import androidx.compose.ui.graphics.shadow.Shadow
|
import androidx.compose.ui.graphics.shadow.Shadow
|
||||||
import androidx.compose.ui.layout.layoutId
|
import androidx.compose.ui.layout.layoutId
|
||||||
|
import androidx.compose.ui.platform.testTag
|
||||||
import androidx.compose.ui.text.SpanStyle
|
import androidx.compose.ui.text.SpanStyle
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.buildAnnotatedString
|
import androidx.compose.ui.text.buildAnnotatedString
|
||||||
|
|
@ -43,6 +43,8 @@ import com.tangem.core.ui.ds.row.TangemRowLayoutId
|
||||||
import com.tangem.core.ui.extensions.*
|
import com.tangem.core.ui.extensions.*
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||||
|
import com.tangem.core.ui.res.generated.icons.Icons
|
||||||
|
import com.tangem.core.ui.res.generated.icons.ic_chevron_right_24
|
||||||
import com.tangem.core.ui.test.TokenDetailsScreenTestTags
|
import com.tangem.core.ui.test.TokenDetailsScreenTestTags
|
||||||
import dev.chrisbanes.haze.HazeStyle
|
import dev.chrisbanes.haze.HazeStyle
|
||||||
import dev.chrisbanes.haze.HazeTint
|
import dev.chrisbanes.haze.HazeTint
|
||||||
|
|
@ -55,8 +57,8 @@ private const val GLOW_ALPHA = 0.7f
|
||||||
private val BorderWidth = 1.dp
|
private val BorderWidth = 1.dp
|
||||||
private val InnerShadowBlur = 20.dp
|
private val InnerShadowBlur = 20.dp
|
||||||
private val ShimmerSubtitleWidth = 78.dp
|
private val ShimmerSubtitleWidth = 78.dp
|
||||||
private val LoaderSize = 12.dp
|
private val LoaderSize = 20.dp
|
||||||
private val LoaderStrokeWidth = 1.5.dp
|
private val LoaderStrokeWidth = 2.dp
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun EarnBlock(state: EarnBlockUM, modifier: Modifier = Modifier) {
|
fun EarnBlock(state: EarnBlockUM, modifier: Modifier = Modifier) {
|
||||||
|
|
@ -69,31 +71,31 @@ fun EarnBlock(state: EarnBlockUM, modifier: Modifier = Modifier) {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun EarnBlockLoading(modifier: Modifier = Modifier) {
|
private fun EarnBlockLoading(modifier: Modifier = Modifier) {
|
||||||
val shape = RoundedCornerShape(TangemTheme.dimens2.x5)
|
val shape = RoundedCornerShape(24.dp)
|
||||||
TangemRowContainer(
|
TangemRowContainer(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.clip(shape)
|
.clip(shape)
|
||||||
.background(TangemTheme.colors2.surface.level3)
|
.background(TangemTheme.colors3.bg.secondary)
|
||||||
.border(width = BorderWidth, color = TangemTheme.colors2.border.neutral.primary, shape = shape),
|
.border(width = BorderWidth, color = TangemTheme.colors3.border.primary, shape = shape),
|
||||||
contentPadding = PaddingValues(all = TangemTheme.dimens2.x3),
|
contentPadding = PaddingValues(all = 16.dp),
|
||||||
content = {
|
content = {
|
||||||
CircleShimmer(
|
CircleShimmer(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.layoutId(TangemRowLayoutId.HEAD)
|
.layoutId(TangemRowLayoutId.HEAD)
|
||||||
.padding(end = TangemTheme.dimens2.x3)
|
.padding(end = 12.dp)
|
||||||
.size(TangemTheme.dimens2.x10),
|
.size(40.dp),
|
||||||
)
|
)
|
||||||
RectangleShimmer(
|
RectangleShimmer(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.layoutId(TangemRowLayoutId.START_TOP)
|
.layoutId(TangemRowLayoutId.START_TOP)
|
||||||
.size(width = ShimmerSubtitleWidth, height = TangemTheme.dimens2.x4),
|
.size(width = ShimmerSubtitleWidth, height = 16.dp),
|
||||||
radius = TangemTheme.dimens2.x2,
|
radius = 8.dp,
|
||||||
)
|
)
|
||||||
RectangleShimmer(
|
RectangleShimmer(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.layoutId(TangemRowLayoutId.START_BOTTOM)
|
.layoutId(TangemRowLayoutId.START_BOTTOM)
|
||||||
.size(width = TangemTheme.dimens2.x16, height = TangemTheme.dimens2.x5),
|
.size(width = 64.dp, height = 20.dp),
|
||||||
radius = TangemTheme.dimens2.x2,
|
radius = 8.dp,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
@ -101,7 +103,7 @@ private fun EarnBlockLoading(modifier: Modifier = Modifier) {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun EarnBlockContent(state: EarnBlockUM.Content, modifier: Modifier = Modifier) {
|
private fun EarnBlockContent(state: EarnBlockUM.Content, modifier: Modifier = Modifier) {
|
||||||
val shape = RoundedCornerShape(TangemTheme.dimens2.x5)
|
val shape = RoundedCornerShape(24.dp)
|
||||||
|
|
||||||
val clickModifier = state.onClick?.let { Modifier.clickable(onClick = it) } ?: Modifier
|
val clickModifier = state.onClick?.let { Modifier.clickable(onClick = it) } ?: Modifier
|
||||||
|
|
||||||
|
|
@ -109,14 +111,14 @@ private fun EarnBlockContent(state: EarnBlockUM.Content, modifier: Modifier = Mo
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.clip(shape)
|
.clip(shape)
|
||||||
.then(clickModifier.backgroundModifier(state.type, state.backgroundUM, shape)),
|
.then(clickModifier.backgroundModifier(state.type, state.backgroundUM, shape)),
|
||||||
contentPadding = PaddingValues(all = TangemTheme.dimens2.x4),
|
contentPadding = PaddingValues(all = 16.dp),
|
||||||
content = {
|
content = {
|
||||||
EarnBlockIcon(
|
EarnBlockIcon(
|
||||||
type = state.type,
|
type = state.type,
|
||||||
iconUM = state.iconUM,
|
iconUM = state.iconUM,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.layoutId(TangemRowLayoutId.HEAD)
|
.layoutId(TangemRowLayoutId.HEAD)
|
||||||
.padding(end = TangemTheme.dimens2.x3),
|
.padding(end = 12.dp),
|
||||||
)
|
)
|
||||||
|
|
||||||
EarnBlockTitle(
|
EarnBlockTitle(
|
||||||
|
|
@ -124,12 +126,12 @@ private fun EarnBlockContent(state: EarnBlockUM.Content, modifier: Modifier = Mo
|
||||||
type = state.type,
|
type = state.type,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.layoutId(TangemRowLayoutId.START_TOP)
|
.layoutId(TangemRowLayoutId.START_TOP)
|
||||||
.padding(end = TangemTheme.dimens2.x2),
|
.padding(end = 8.dp),
|
||||||
)
|
)
|
||||||
|
|
||||||
val subtitleModifier = Modifier
|
val subtitleModifier = Modifier
|
||||||
.layoutId(TangemRowLayoutId.START_BOTTOM)
|
.layoutId(TangemRowLayoutId.START_BOTTOM)
|
||||||
.padding(end = TangemTheme.dimens2.x2)
|
.padding(end = 8.dp)
|
||||||
when (val subtitle = state.subtitleUM) {
|
when (val subtitle = state.subtitleUM) {
|
||||||
is EarnBlockUM.SubtitleUM.Text -> EarnBlockSubtitle(
|
is EarnBlockUM.SubtitleUM.Text -> EarnBlockSubtitle(
|
||||||
subtitle = subtitle,
|
subtitle = subtitle,
|
||||||
|
|
@ -151,37 +153,37 @@ private fun EarnBlockContent(state: EarnBlockUM.Content, modifier: Modifier = Mo
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun EarnBlockPromo(state: EarnBlockUM.Promo, modifier: Modifier = Modifier) {
|
private fun EarnBlockPromo(state: EarnBlockUM.Promo, modifier: Modifier = Modifier) {
|
||||||
val shape = RoundedCornerShape(TangemTheme.dimens2.x5)
|
val shape = RoundedCornerShape(24.dp)
|
||||||
Column(
|
Column(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.clip(shape)
|
.clip(shape)
|
||||||
.backgroundModifier(state.type, state.backgroundUM, shape)
|
.backgroundModifier(state.type, state.backgroundUM, shape)
|
||||||
.padding(all = TangemTheme.dimens2.x4),
|
.padding(all = 16.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x3),
|
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||||
) {
|
) {
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
EarnBlockIcon(
|
EarnBlockIcon(
|
||||||
type = state.type,
|
type = state.type,
|
||||||
iconUM = state.iconUM,
|
iconUM = state.iconUM,
|
||||||
modifier = Modifier.padding(end = TangemTheme.dimens2.x3),
|
modifier = Modifier.padding(end = 12.dp),
|
||||||
)
|
)
|
||||||
Column(
|
Column(
|
||||||
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x1),
|
verticalArrangement = Arrangement.spacedBy(4.dp),
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = state.title.resolveAnnotatedReference(),
|
text = state.title.resolveAnnotatedReference(),
|
||||||
style = TangemTheme.typography2.bodyMedium16,
|
style = TangemTheme.typography3.body.medium,
|
||||||
color = TangemTheme.colors2.text.neutral.primary,
|
color = TangemTheme.colors3.text.primary,
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = state.subtitle.resolveReference(),
|
text = state.subtitle.resolveReference(),
|
||||||
style = TangemTheme.typography2.captionMedium12,
|
style = TangemTheme.typography3.caption.medium,
|
||||||
color = state.type.accentText(),
|
color = state.type.accentText(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Row(horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x2)) {
|
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
EarnBlockPromoButton(
|
EarnBlockPromoButton(
|
||||||
text = resourceReference(CoreResR.string.common_learn_more),
|
text = resourceReference(CoreResR.string.common_learn_more),
|
||||||
type = TangemButtonType.Secondary,
|
type = TangemButtonType.Secondary,
|
||||||
|
|
@ -225,8 +227,8 @@ private fun Modifier.backgroundModifier(
|
||||||
): Modifier {
|
): Modifier {
|
||||||
return when (backgroundUM) {
|
return when (backgroundUM) {
|
||||||
is EarnBlockUM.BackgroundUM.Surface -> this
|
is EarnBlockUM.BackgroundUM.Surface -> this
|
||||||
.background(TangemTheme.colors2.surface.level3)
|
.background(TangemTheme.colors3.bg.secondary)
|
||||||
.border(width = BorderWidth, color = TangemTheme.colors2.border.neutral.primary, shape = shape)
|
.border(width = BorderWidth, color = TangemTheme.colors3.border.primary, shape = shape)
|
||||||
is EarnBlockUM.BackgroundUM.AccentSoft -> tintedBackground(type.accentSoftTint(), shape)
|
is EarnBlockUM.BackgroundUM.AccentSoft -> tintedBackground(type.accentSoftTint(), shape)
|
||||||
is EarnBlockUM.BackgroundUM.AccentStrong -> tintedBackground(type.accentStrongTint(), shape)
|
is EarnBlockUM.BackgroundUM.AccentStrong -> tintedBackground(type.accentStrongTint(), shape)
|
||||||
}
|
}
|
||||||
|
|
@ -260,77 +262,84 @@ private fun EarnBlockTrailing(type: Type, trailingUM: EarnBlockUM.TrailingUM?, o
|
||||||
modifier = Modifier.layoutId(TangemRowLayoutId.TAIL),
|
modifier = Modifier.layoutId(TangemRowLayoutId.TAIL),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is EarnBlockUM.TrailingUM.Balance -> {
|
is EarnBlockUM.TrailingUM.Balance -> EarnBlockBalance(type = type, trailingUM = trailingUM)
|
||||||
val fiatModifier = Modifier.layoutId(TangemRowLayoutId.END_TOP).let {
|
is EarnBlockUM.TrailingUM.Chevron -> {
|
||||||
if (type == Type.Staking) it.testTag(TokenDetailsScreenTestTags.STAKING_FIAT_AMOUNT) else it
|
TangemIcon(
|
||||||
}
|
tangemIconUM = TangemIconUM.Icon(
|
||||||
val cryptoModifier = Modifier.layoutId(TangemRowLayoutId.END_BOTTOM).let {
|
imageVector = Icons.ic_chevron_right_24,
|
||||||
if (type == Type.Staking) it.testTag(TokenDetailsScreenTestTags.STAKING_TOKEN_AMOUNT) else it
|
tintReference = { TangemTheme.colors3.icon.secondary },
|
||||||
}
|
),
|
||||||
Text(
|
modifier = Modifier
|
||||||
text = trailingUM.fiatValue.orMaskWithStars(trailingUM.isBalanceHidden).resolveAnnotatedReference(),
|
.layoutId(TangemRowLayoutId.TAIL)
|
||||||
style = TangemTheme.typography2.bodySemibold16,
|
.size(24.dp),
|
||||||
color = TangemTheme.colors2.text.neutral.primary,
|
|
||||||
modifier = fiatModifier,
|
|
||||||
)
|
)
|
||||||
Text(
|
}
|
||||||
text = trailingUM.cryptoValue.orMaskWithStars(trailingUM.isBalanceHidden).resolveReference(),
|
is EarnBlockUM.TrailingUM.StatusIcon -> {
|
||||||
style = TangemTheme.typography2.captionMedium12,
|
TangemIcon(
|
||||||
color = TangemTheme.colors2.text.neutral.secondary,
|
tangemIconUM = TangemIconUM.Icon(
|
||||||
modifier = cryptoModifier,
|
iconRes = trailingUM.tone.iconRes(),
|
||||||
|
tintReference = { trailingUM.tone.tint() },
|
||||||
|
),
|
||||||
|
modifier = Modifier
|
||||||
|
.layoutId(TangemRowLayoutId.TAIL)
|
||||||
|
.size(24.dp)
|
||||||
|
.testTag(TokenDetailsScreenTestTags.EARN_BLOCK_TITLE_ICON),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is EarnBlockUM.TrailingUM.Loader -> {
|
||||||
|
CircularProgressIndicator(
|
||||||
|
color = trailingUM.tone.color(),
|
||||||
|
strokeWidth = LoaderStrokeWidth,
|
||||||
|
strokeCap = StrokeCap.Round,
|
||||||
|
modifier = Modifier
|
||||||
|
.layoutId(TangemRowLayoutId.TAIL)
|
||||||
|
.size(LoaderSize),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
null -> Unit
|
null -> Unit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun EarnBlockBalance(type: Type, trailingUM: EarnBlockUM.TrailingUM.Balance) {
|
||||||
|
val fiatModifier = Modifier.layoutId(TangemRowLayoutId.END_TOP).let {
|
||||||
|
if (type == Type.Staking) it.testTag(TokenDetailsScreenTestTags.STAKING_FIAT_AMOUNT) else it
|
||||||
|
}
|
||||||
|
val cryptoModifier = Modifier.layoutId(TangemRowLayoutId.END_BOTTOM).let {
|
||||||
|
if (type == Type.Staking) it.testTag(TokenDetailsScreenTestTags.STAKING_TOKEN_AMOUNT) else it
|
||||||
|
}
|
||||||
|
Text(
|
||||||
|
text = trailingUM.fiatValue.orMaskWithStars(trailingUM.isBalanceHidden).resolveAnnotatedReference(),
|
||||||
|
style = TangemTheme.typography3.body.medium,
|
||||||
|
color = TangemTheme.colors3.text.primary,
|
||||||
|
modifier = fiatModifier,
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = trailingUM.cryptoValue.orMaskWithStars(trailingUM.isBalanceHidden).resolveReference(),
|
||||||
|
style = TangemTheme.typography3.caption.medium,
|
||||||
|
color = TangemTheme.colors3.text.secondary,
|
||||||
|
modifier = cryptoModifier,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun EarnBlockTitle(titleUM: EarnBlockUM.TitleUM, type: Type, modifier: Modifier = Modifier) {
|
private fun EarnBlockTitle(titleUM: EarnBlockUM.TitleUM, type: Type, modifier: Modifier = Modifier) {
|
||||||
val titleText: @Composable () -> Unit = {
|
Text(
|
||||||
Text(
|
text = titleUM.text.resolveReference(),
|
||||||
text = titleUM.text.resolveReference(),
|
style = titleUM.style.textStyle,
|
||||||
style = titleUM.style.textStyle,
|
color = titleUM.tone.color(type),
|
||||||
color = titleUM.tone.color(type),
|
modifier = modifier,
|
||||||
)
|
)
|
||||||
}
|
|
||||||
val icon = titleUM.iconUM
|
|
||||||
if (icon == null) {
|
|
||||||
Box(modifier = modifier) { titleText() }
|
|
||||||
return
|
|
||||||
}
|
|
||||||
Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) {
|
|
||||||
titleText()
|
|
||||||
Spacer(modifier = Modifier.width(TangemTheme.dimens2.x1))
|
|
||||||
TangemIcon(
|
|
||||||
tangemIconUM = TangemIconUM.Icon(
|
|
||||||
iconRes = icon.tone.iconRes(),
|
|
||||||
tintReference = { icon.tone.tint() },
|
|
||||||
),
|
|
||||||
modifier = Modifier
|
|
||||||
.size(TangemTheme.dimens2.x4)
|
|
||||||
.testTag(TokenDetailsScreenTestTags.EARN_BLOCK_TITLE_ICON),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun EarnBlockSubtitle(subtitle: EarnBlockUM.SubtitleUM.Text, type: Type, modifier: Modifier = Modifier) {
|
private fun EarnBlockSubtitle(subtitle: EarnBlockUM.SubtitleUM.Text, type: Type, modifier: Modifier = Modifier) {
|
||||||
val textStyle = subtitle.style.textStyle
|
Text(
|
||||||
val textColor = subtitle.tone.color(type)
|
text = subtitle.text.resolveReference(),
|
||||||
if (subtitle.loader == null) {
|
style = subtitle.style.textStyle,
|
||||||
Text(text = subtitle.text.resolveReference(), style = textStyle, color = textColor, modifier = modifier)
|
color = subtitle.tone.color(type),
|
||||||
return
|
modifier = modifier,
|
||||||
}
|
)
|
||||||
Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) {
|
|
||||||
Text(text = subtitle.text.resolveReference(), style = textStyle, color = textColor)
|
|
||||||
Spacer(modifier = Modifier.width(3.dp))
|
|
||||||
CircularProgressIndicator(
|
|
||||||
color = subtitle.loader.tone.color(),
|
|
||||||
strokeWidth = LoaderStrokeWidth,
|
|
||||||
strokeCap = StrokeCap.Round,
|
|
||||||
modifier = Modifier.size(LoaderSize),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -351,7 +360,7 @@ private fun EarnBlockAccentedSubtitle(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
style = subtitle.style.textStyle,
|
style = subtitle.style.textStyle,
|
||||||
color = TangemTheme.colors2.text.neutral.tertiary,
|
color = TangemTheme.colors3.text.secondary,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -360,32 +369,40 @@ private fun EarnBlockAccentedSubtitle(
|
||||||
private fun EarnBlockIcon(type: Type, iconUM: EarnBlockUM.IconUM, modifier: Modifier = Modifier) {
|
private fun EarnBlockIcon(type: Type, iconUM: EarnBlockUM.IconUM, modifier: Modifier = Modifier) {
|
||||||
Box(
|
Box(
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
modifier = modifier.size(TangemTheme.dimens2.x10),
|
modifier = modifier.size(40.dp),
|
||||||
) {
|
) {
|
||||||
if (iconUM is EarnBlockUM.IconUM.Glowing) {
|
val glowColor = when (iconUM) {
|
||||||
val glowShape = RoundedCornerShape(percent = 50)
|
is EarnBlockUM.IconUM.Glowing -> iconUM.tone.glowColor(type)
|
||||||
|
is EarnBlockUM.IconUM.Plain -> null
|
||||||
|
}
|
||||||
|
if (glowColor != null) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(TangemTheme.dimens2.x6)
|
.size(24.dp)
|
||||||
.hazeForegroundEffectTangem(
|
.hazeForegroundEffectTangem(
|
||||||
style = HazeStyle(
|
style = HazeStyle(
|
||||||
backgroundColor = Color.Transparent,
|
backgroundColor = Color.Transparent,
|
||||||
tint = HazeTint(Color.Transparent),
|
tint = HazeTint(Color.Transparent),
|
||||||
blurRadius = TangemTheme.dimens2.x4,
|
blurRadius = 16.dp,
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
blurredEdgeTreatment = BlurredEdgeTreatment.Unbounded
|
blurredEdgeTreatment = BlurredEdgeTreatment.Unbounded
|
||||||
}
|
}
|
||||||
.background(color = type.accentGlow().copy(alpha = GLOW_ALPHA), shape = glowShape),
|
.background(color = glowColor.copy(alpha = GLOW_ALPHA), shape = RoundedCornerShape(percent = 50)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
val isWarningTone = (iconUM as? EarnBlockUM.IconUM.Glowing)?.tone == EarnBlockUM.IconUM.Tone.Warning
|
||||||
val iconRes = when (iconUM) {
|
val iconRes = when (iconUM) {
|
||||||
is EarnBlockUM.IconUM.Glowing -> iconUM.iconRes
|
is EarnBlockUM.IconUM.Glowing -> iconUM.iconRes
|
||||||
is EarnBlockUM.IconUM.Plain -> iconUM.iconRes
|
is EarnBlockUM.IconUM.Plain -> iconUM.iconRes
|
||||||
}
|
}
|
||||||
TangemIcon(
|
TangemIcon(
|
||||||
tangemIconUM = TangemIconUM.Image(imageRes = iconRes),
|
tangemIconUM = if (isWarningTone) {
|
||||||
modifier = Modifier.size(TangemTheme.dimens2.x10),
|
TangemIconUM.Icon(iconRes = iconRes, tintReference = { TangemTheme.colors3.icon.status.warning })
|
||||||
|
} else {
|
||||||
|
TangemIconUM.Image(imageRes = iconRes)
|
||||||
|
},
|
||||||
|
modifier = Modifier.size(40.dp),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -394,29 +411,36 @@ private fun EarnBlockIcon(type: Type, iconUM: EarnBlockUM.IconUM, modifier: Modi
|
||||||
@Composable
|
@Composable
|
||||||
@ReadOnlyComposable
|
@ReadOnlyComposable
|
||||||
private fun Type.accentText(): Color = when (this) {
|
private fun Type.accentText(): Color = when (this) {
|
||||||
Type.Staking -> TangemTheme.colors2.text.status.accent
|
Type.Staking -> TangemTheme.colors3.text.brand
|
||||||
Type.YieldSupply -> TangemTheme.colors2.text.status.positive
|
Type.YieldSupply -> TangemTheme.colors3.text.accent.green
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@ReadOnlyComposable
|
||||||
|
private fun EarnBlockUM.IconUM.Tone.glowColor(type: Type): Color = when (this) {
|
||||||
|
EarnBlockUM.IconUM.Tone.Accent -> type.accentGlow()
|
||||||
|
EarnBlockUM.IconUM.Tone.Warning -> TangemTheme.colors3.icon.status.warning
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ReadOnlyComposable
|
@ReadOnlyComposable
|
||||||
private fun Type.accentGlow(): Color = when (this) {
|
private fun Type.accentGlow(): Color = when (this) {
|
||||||
Type.Staking -> TangemTheme.colors2.border.status.accent
|
Type.Staking -> TangemTheme.colors3.text.brand
|
||||||
Type.YieldSupply -> TangemTheme.colors2.text.status.positive
|
Type.YieldSupply -> TangemTheme.colors3.text.accent.green
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ReadOnlyComposable
|
@ReadOnlyComposable
|
||||||
private fun Type.accentSoftTint(): Color = when (this) {
|
private fun Type.accentSoftTint(): Color = when (this) {
|
||||||
Type.Staking -> TangemTheme.colors2.markers.backgroundTintedBlue
|
Type.Staking -> TangemTheme.colors3.text.brand
|
||||||
Type.YieldSupply -> TangemTheme.colors2.markers.backgroundTintedGreen
|
Type.YieldSupply -> TangemTheme.colors3.text.accent.green
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ReadOnlyComposable
|
@ReadOnlyComposable
|
||||||
private fun Type.accentStrongTint(): Color = when (this) {
|
private fun Type.accentStrongTint(): Color = when (this) {
|
||||||
Type.Staking -> TangemTheme.colors2.text.status.accent
|
Type.Staking -> TangemTheme.colors3.text.brand
|
||||||
Type.YieldSupply -> TangemTheme.colors2.text.status.positive
|
Type.YieldSupply -> TangemTheme.colors3.text.accent.green
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun EarnBlockUM.TrailingUM.Button.Style.buttonType(type: Type): TangemButtonType = when (this) {
|
private fun EarnBlockUM.TrailingUM.Button.Style.buttonType(type: Type): TangemButtonType = when (this) {
|
||||||
|
|
@ -430,53 +454,53 @@ private fun EarnBlockUM.TrailingUM.Button.Style.buttonType(type: Type): TangemBu
|
||||||
@Composable
|
@Composable
|
||||||
@ReadOnlyComposable
|
@ReadOnlyComposable
|
||||||
private fun EarnBlockUM.TitleUM.Tone.color(type: Type): Color = when (this) {
|
private fun EarnBlockUM.TitleUM.Tone.color(type: Type): Color = when (this) {
|
||||||
EarnBlockUM.TitleUM.Tone.Primary -> TangemTheme.colors2.text.neutral.primary
|
EarnBlockUM.TitleUM.Tone.Primary -> TangemTheme.colors3.text.primary
|
||||||
EarnBlockUM.TitleUM.Tone.Secondary -> TangemTheme.colors2.text.neutral.secondary
|
EarnBlockUM.TitleUM.Tone.Secondary -> TangemTheme.colors3.text.secondary
|
||||||
EarnBlockUM.TitleUM.Tone.Disabled -> TangemTheme.colors2.text.neutral.tertiary
|
EarnBlockUM.TitleUM.Tone.Disabled -> TangemTheme.colors3.text.tertiary
|
||||||
EarnBlockUM.TitleUM.Tone.Accent -> type.accentText()
|
EarnBlockUM.TitleUM.Tone.Accent -> type.accentText()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ReadOnlyComposable
|
@ReadOnlyComposable
|
||||||
private fun EarnBlockUM.SubtitleUM.Tone.color(type: Type): Color = when (this) {
|
private fun EarnBlockUM.SubtitleUM.Tone.color(type: Type): Color = when (this) {
|
||||||
EarnBlockUM.SubtitleUM.Tone.Primary -> TangemTheme.colors2.text.neutral.primary
|
EarnBlockUM.SubtitleUM.Tone.Primary -> TangemTheme.colors3.text.primary
|
||||||
EarnBlockUM.SubtitleUM.Tone.Disabled -> TangemTheme.colors2.text.neutral.tertiary
|
EarnBlockUM.SubtitleUM.Tone.Disabled -> TangemTheme.colors3.text.tertiary
|
||||||
EarnBlockUM.SubtitleUM.Tone.Accent -> type.accentText()
|
EarnBlockUM.SubtitleUM.Tone.Accent -> type.accentText()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun EarnBlockUM.TitleUM.IconTone.iconRes(): Int = when (this) {
|
private fun EarnBlockUM.TrailingUM.StatusIcon.Tone.iconRes(): Int = when (this) {
|
||||||
EarnBlockUM.TitleUM.IconTone.Warning -> R.drawable.ic_attention_default_24
|
EarnBlockUM.TrailingUM.StatusIcon.Tone.Warning -> R.drawable.ic_attention_default_24
|
||||||
EarnBlockUM.TitleUM.IconTone.Info -> R.drawable.ic_alert_circle_24
|
EarnBlockUM.TrailingUM.StatusIcon.Tone.Info -> R.drawable.ic_alert_circle_24
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ReadOnlyComposable
|
@ReadOnlyComposable
|
||||||
private fun EarnBlockUM.TitleUM.IconTone.tint(): Color = when (this) {
|
private fun EarnBlockUM.TrailingUM.StatusIcon.Tone.tint(): Color = when (this) {
|
||||||
EarnBlockUM.TitleUM.IconTone.Warning -> TangemTheme.colors2.graphic.status.attention
|
EarnBlockUM.TrailingUM.StatusIcon.Tone.Warning -> TangemTheme.colors3.icon.status.warning
|
||||||
EarnBlockUM.TitleUM.IconTone.Info -> TangemTheme.colors2.graphic.neutral.secondary
|
EarnBlockUM.TrailingUM.StatusIcon.Tone.Info -> TangemTheme.colors3.icon.secondary
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ReadOnlyComposable
|
@ReadOnlyComposable
|
||||||
private fun EarnBlockUM.SubtitleUM.LoaderTone.color(): Color = when (this) {
|
private fun EarnBlockUM.TrailingUM.Loader.LoaderTone.color(): Color = when (this) {
|
||||||
EarnBlockUM.SubtitleUM.LoaderTone.Positive -> TangemTheme.colors2.text.status.positive
|
EarnBlockUM.TrailingUM.Loader.LoaderTone.Positive -> TangemTheme.colors3.icon.accent.green
|
||||||
EarnBlockUM.SubtitleUM.LoaderTone.Muted -> TangemTheme.colors2.graphic.neutral.tertiaryConstant
|
EarnBlockUM.TrailingUM.Loader.LoaderTone.Muted -> TangemTheme.colors3.icon.tertiary
|
||||||
}
|
}
|
||||||
|
|
||||||
private val EarnBlockUM.TitleUM.Style.textStyle: TextStyle
|
private val EarnBlockUM.TitleUM.Style.textStyle: TextStyle
|
||||||
@Composable
|
@Composable
|
||||||
@ReadOnlyComposable
|
@ReadOnlyComposable
|
||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
EarnBlockUM.TitleUM.Style.Large -> TangemTheme.typography2.bodyMedium16
|
EarnBlockUM.TitleUM.Style.Large -> TangemTheme.typography3.body.medium
|
||||||
EarnBlockUM.TitleUM.Style.Small -> TangemTheme.typography2.captionMedium12
|
EarnBlockUM.TitleUM.Style.Small -> TangemTheme.typography3.caption.medium
|
||||||
}
|
}
|
||||||
|
|
||||||
private val EarnBlockUM.SubtitleUM.Style.textStyle: TextStyle
|
private val EarnBlockUM.SubtitleUM.Style.textStyle: TextStyle
|
||||||
@Composable
|
@Composable
|
||||||
@ReadOnlyComposable
|
@ReadOnlyComposable
|
||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
EarnBlockUM.SubtitleUM.Style.Large -> TangemTheme.typography2.bodyMedium16
|
EarnBlockUM.SubtitleUM.Style.Large -> TangemTheme.typography3.body.medium
|
||||||
EarnBlockUM.SubtitleUM.Style.Small -> TangemTheme.typography2.captionMedium12
|
EarnBlockUM.SubtitleUM.Style.Small -> TangemTheme.typography3.caption.medium
|
||||||
}
|
}
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
|
|
@ -488,7 +512,7 @@ private fun EarnBlock_Staking_Preview(@PreviewParameter(EarnBlockStakingPreviewP
|
||||||
TangemThemePreviewRedesign {
|
TangemThemePreviewRedesign {
|
||||||
EarnBlock(
|
EarnBlock(
|
||||||
state = state,
|
state = state,
|
||||||
modifier = Modifier.padding(TangemTheme.dimens2.x4),
|
modifier = Modifier.padding(16.dp),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -502,7 +526,7 @@ private fun EarnBlock_YieldSupply_Preview(
|
||||||
TangemThemePreviewRedesign {
|
TangemThemePreviewRedesign {
|
||||||
EarnBlock(
|
EarnBlock(
|
||||||
state = state,
|
state = state,
|
||||||
modifier = Modifier.padding(TangemTheme.dimens2.x4),
|
modifier = Modifier.padding(16.dp),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -612,7 +636,7 @@ private class EarnBlockYieldSupplyPreviewProvider : CollectionPreviewParameterPr
|
||||||
),
|
),
|
||||||
onClick = {},
|
onClick = {},
|
||||||
),
|
),
|
||||||
// Content — yield enabled, "Details" button
|
// Content — yield enabled, chevron
|
||||||
EarnBlockUM.Content(
|
EarnBlockUM.Content(
|
||||||
type = Type.YieldSupply,
|
type = Type.YieldSupply,
|
||||||
backgroundUM = EarnBlockUM.BackgroundUM.Surface,
|
backgroundUM = EarnBlockUM.BackgroundUM.Surface,
|
||||||
|
|
@ -630,13 +654,10 @@ private class EarnBlockYieldSupplyPreviewProvider : CollectionPreviewParameterPr
|
||||||
style = EarnBlockUM.SubtitleUM.Style.Large,
|
style = EarnBlockUM.SubtitleUM.Style.Large,
|
||||||
tone = EarnBlockUM.SubtitleUM.Tone.Accent,
|
tone = EarnBlockUM.SubtitleUM.Tone.Accent,
|
||||||
),
|
),
|
||||||
trailingUM = EarnBlockUM.TrailingUM.Button(
|
trailingUM = EarnBlockUM.TrailingUM.Chevron,
|
||||||
text = resourceReference(CoreResR.string.details_title),
|
|
||||||
style = EarnBlockUM.TrailingUM.Button.Style.Secondary,
|
|
||||||
),
|
|
||||||
onClick = {},
|
onClick = {},
|
||||||
),
|
),
|
||||||
// Content with Warning title icon
|
// Content with Warning status icon in trailing
|
||||||
EarnBlockUM.Content(
|
EarnBlockUM.Content(
|
||||||
type = Type.YieldSupply,
|
type = Type.YieldSupply,
|
||||||
backgroundUM = EarnBlockUM.BackgroundUM.Surface,
|
backgroundUM = EarnBlockUM.BackgroundUM.Surface,
|
||||||
|
|
@ -645,7 +666,6 @@ private class EarnBlockYieldSupplyPreviewProvider : CollectionPreviewParameterPr
|
||||||
text = resourceReference(CoreResR.string.common_yield_mode),
|
text = resourceReference(CoreResR.string.common_yield_mode),
|
||||||
style = EarnBlockUM.TitleUM.Style.Small,
|
style = EarnBlockUM.TitleUM.Style.Small,
|
||||||
tone = EarnBlockUM.TitleUM.Tone.Primary,
|
tone = EarnBlockUM.TitleUM.Tone.Primary,
|
||||||
iconUM = EarnBlockUM.TitleUM.IconUM(tone = EarnBlockUM.TitleUM.IconTone.Warning),
|
|
||||||
),
|
),
|
||||||
subtitleUM = EarnBlockUM.SubtitleUM.Text(
|
subtitleUM = EarnBlockUM.SubtitleUM.Text(
|
||||||
text = resourceReference(
|
text = resourceReference(
|
||||||
|
|
@ -655,13 +675,12 @@ private class EarnBlockYieldSupplyPreviewProvider : CollectionPreviewParameterPr
|
||||||
style = EarnBlockUM.SubtitleUM.Style.Large,
|
style = EarnBlockUM.SubtitleUM.Style.Large,
|
||||||
tone = EarnBlockUM.SubtitleUM.Tone.Accent,
|
tone = EarnBlockUM.SubtitleUM.Tone.Accent,
|
||||||
),
|
),
|
||||||
trailingUM = EarnBlockUM.TrailingUM.Button(
|
trailingUM = EarnBlockUM.TrailingUM.StatusIcon(
|
||||||
text = resourceReference(CoreResR.string.details_title),
|
tone = EarnBlockUM.TrailingUM.StatusIcon.Tone.Warning,
|
||||||
style = EarnBlockUM.TrailingUM.Button.Style.Secondary,
|
|
||||||
),
|
),
|
||||||
onClick = {},
|
onClick = {},
|
||||||
),
|
),
|
||||||
// Content with Info title icon
|
// Content with Info status icon in trailing
|
||||||
EarnBlockUM.Content(
|
EarnBlockUM.Content(
|
||||||
type = Type.YieldSupply,
|
type = Type.YieldSupply,
|
||||||
backgroundUM = EarnBlockUM.BackgroundUM.Surface,
|
backgroundUM = EarnBlockUM.BackgroundUM.Surface,
|
||||||
|
|
@ -670,7 +689,6 @@ private class EarnBlockYieldSupplyPreviewProvider : CollectionPreviewParameterPr
|
||||||
text = resourceReference(CoreResR.string.common_yield_mode),
|
text = resourceReference(CoreResR.string.common_yield_mode),
|
||||||
style = EarnBlockUM.TitleUM.Style.Small,
|
style = EarnBlockUM.TitleUM.Style.Small,
|
||||||
tone = EarnBlockUM.TitleUM.Tone.Primary,
|
tone = EarnBlockUM.TitleUM.Tone.Primary,
|
||||||
iconUM = EarnBlockUM.TitleUM.IconUM(tone = EarnBlockUM.TitleUM.IconTone.Info),
|
|
||||||
),
|
),
|
||||||
subtitleUM = EarnBlockUM.SubtitleUM.Text(
|
subtitleUM = EarnBlockUM.SubtitleUM.Text(
|
||||||
text = resourceReference(
|
text = resourceReference(
|
||||||
|
|
@ -680,47 +698,51 @@ private class EarnBlockYieldSupplyPreviewProvider : CollectionPreviewParameterPr
|
||||||
style = EarnBlockUM.SubtitleUM.Style.Large,
|
style = EarnBlockUM.SubtitleUM.Style.Large,
|
||||||
tone = EarnBlockUM.SubtitleUM.Tone.Accent,
|
tone = EarnBlockUM.SubtitleUM.Tone.Accent,
|
||||||
),
|
),
|
||||||
trailingUM = EarnBlockUM.TrailingUM.Button(
|
trailingUM = EarnBlockUM.TrailingUM.StatusIcon(
|
||||||
text = resourceReference(CoreResR.string.details_title),
|
tone = EarnBlockUM.TrailingUM.StatusIcon.Tone.Info,
|
||||||
style = EarnBlockUM.TrailingUM.Button.Style.Secondary,
|
|
||||||
),
|
),
|
||||||
onClick = {},
|
onClick = {},
|
||||||
),
|
),
|
||||||
// Processing.Enter — enabling, no trailing
|
// Processing.Enter — enabling, single-line title, loader in trailing
|
||||||
EarnBlockUM.Content(
|
EarnBlockUM.Content(
|
||||||
type = Type.YieldSupply,
|
type = Type.YieldSupply,
|
||||||
backgroundUM = EarnBlockUM.BackgroundUM.Surface,
|
backgroundUM = EarnBlockUM.BackgroundUM.Surface,
|
||||||
iconUM = EarnBlockUM.IconUM.Glowing(iconRes = R.drawable.ic_yield_40),
|
iconUM = EarnBlockUM.IconUM.Glowing(iconRes = R.drawable.ic_yield_40),
|
||||||
titleUM = EarnBlockUM.TitleUM(
|
titleUM = EarnBlockUM.TitleUM(
|
||||||
text = resourceReference(CoreResR.string.common_yield_mode),
|
text = combinedReference(
|
||||||
|
resourceReference(CoreResR.string.common_yield_mode),
|
||||||
|
stringReference(" "),
|
||||||
|
resourceReference(CoreResR.string.common_enabling),
|
||||||
|
),
|
||||||
style = EarnBlockUM.TitleUM.Style.Small,
|
style = EarnBlockUM.TitleUM.Style.Small,
|
||||||
tone = EarnBlockUM.TitleUM.Tone.Primary,
|
tone = EarnBlockUM.TitleUM.Tone.Primary,
|
||||||
),
|
),
|
||||||
subtitleUM = EarnBlockUM.SubtitleUM.Text(
|
subtitleUM = null,
|
||||||
text = resourceReference(CoreResR.string.common_enabling),
|
trailingUM = EarnBlockUM.TrailingUM.Loader(
|
||||||
style = EarnBlockUM.SubtitleUM.Style.Large,
|
tone = EarnBlockUM.TrailingUM.Loader.LoaderTone.Positive,
|
||||||
tone = EarnBlockUM.SubtitleUM.Tone.Accent,
|
|
||||||
loader = EarnBlockUM.SubtitleUM.Loader(tone = EarnBlockUM.SubtitleUM.LoaderTone.Positive),
|
|
||||||
),
|
),
|
||||||
trailingUM = null,
|
|
||||||
),
|
),
|
||||||
// Processing.Exit — disabling, no trailing, plain icon
|
// Processing.Exit — disabling, single-line title, warning icon, loader in trailing
|
||||||
EarnBlockUM.Content(
|
EarnBlockUM.Content(
|
||||||
type = Type.YieldSupply,
|
type = Type.YieldSupply,
|
||||||
backgroundUM = EarnBlockUM.BackgroundUM.Surface,
|
backgroundUM = EarnBlockUM.BackgroundUM.Surface,
|
||||||
iconUM = EarnBlockUM.IconUM.Plain(iconRes = R.drawable.ic_yield_disabling_40),
|
iconUM = EarnBlockUM.IconUM.Glowing(
|
||||||
|
iconRes = R.drawable.ic_yield_40,
|
||||||
|
tone = EarnBlockUM.IconUM.Tone.Warning,
|
||||||
|
),
|
||||||
titleUM = EarnBlockUM.TitleUM(
|
titleUM = EarnBlockUM.TitleUM(
|
||||||
text = resourceReference(CoreResR.string.common_yield_mode),
|
text = combinedReference(
|
||||||
|
resourceReference(CoreResR.string.common_yield_mode),
|
||||||
|
stringReference(" "),
|
||||||
|
resourceReference(CoreResR.string.common_disabling),
|
||||||
|
),
|
||||||
style = EarnBlockUM.TitleUM.Style.Small,
|
style = EarnBlockUM.TitleUM.Style.Small,
|
||||||
tone = EarnBlockUM.TitleUM.Tone.Primary,
|
tone = EarnBlockUM.TitleUM.Tone.Primary,
|
||||||
),
|
),
|
||||||
subtitleUM = EarnBlockUM.SubtitleUM.Text(
|
subtitleUM = null,
|
||||||
text = resourceReference(CoreResR.string.common_disabling),
|
trailingUM = EarnBlockUM.TrailingUM.Loader(
|
||||||
style = EarnBlockUM.SubtitleUM.Style.Large,
|
tone = EarnBlockUM.TrailingUM.Loader.LoaderTone.Muted,
|
||||||
tone = EarnBlockUM.SubtitleUM.Tone.Disabled,
|
|
||||||
loader = EarnBlockUM.SubtitleUM.Loader(tone = EarnBlockUM.SubtitleUM.LoaderTone.Muted),
|
|
||||||
),
|
),
|
||||||
trailingUM = null,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,11 @@ sealed interface EarnBlockUM {
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
sealed interface IconUM {
|
sealed interface IconUM {
|
||||||
data class Glowing(@DrawableRes val iconRes: Int) : IconUM
|
data class Glowing(@DrawableRes val iconRes: Int, val tone: Tone = Tone.Accent) : IconUM
|
||||||
data class Plain(@DrawableRes val iconRes: Int) : IconUM
|
data class Plain(@DrawableRes val iconRes: Int) : IconUM
|
||||||
|
|
||||||
|
/** Accent — glow/tint follow the block [Type]; Warning — yellow icon tint and glow. */
|
||||||
|
enum class Tone { Accent, Warning }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
|
|
@ -54,13 +57,9 @@ sealed interface EarnBlockUM {
|
||||||
val text: TextReference,
|
val text: TextReference,
|
||||||
val style: Style,
|
val style: Style,
|
||||||
val tone: Tone,
|
val tone: Tone,
|
||||||
val iconUM: IconUM? = null,
|
|
||||||
) {
|
) {
|
||||||
enum class Style { Large, Small }
|
enum class Style { Large, Small }
|
||||||
enum class Tone { Primary, Secondary, Disabled, Accent }
|
enum class Tone { Primary, Secondary, Disabled, Accent }
|
||||||
|
|
||||||
data class IconUM(val tone: IconTone)
|
|
||||||
enum class IconTone { Warning, Info }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
|
|
@ -69,7 +68,6 @@ sealed interface EarnBlockUM {
|
||||||
val text: TextReference,
|
val text: TextReference,
|
||||||
val style: Style,
|
val style: Style,
|
||||||
val tone: Tone,
|
val tone: Tone,
|
||||||
val loader: Loader? = null,
|
|
||||||
) : SubtitleUM
|
) : SubtitleUM
|
||||||
|
|
||||||
data class AccentedText(
|
data class AccentedText(
|
||||||
|
|
@ -78,11 +76,8 @@ sealed interface EarnBlockUM {
|
||||||
val style: Style,
|
val style: Style,
|
||||||
) : SubtitleUM
|
) : SubtitleUM
|
||||||
|
|
||||||
data class Loader(val tone: LoaderTone)
|
|
||||||
|
|
||||||
enum class Style { Large, Small }
|
enum class Style { Large, Small }
|
||||||
enum class Tone { Primary, Disabled, Accent }
|
enum class Tone { Primary, Disabled, Accent }
|
||||||
enum class LoaderTone { Positive, Muted }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
|
|
@ -100,5 +95,18 @@ sealed interface EarnBlockUM {
|
||||||
val cryptoValue: TextReference,
|
val cryptoValue: TextReference,
|
||||||
val isBalanceHidden: Boolean,
|
val isBalanceHidden: Boolean,
|
||||||
) : TrailingUM
|
) : TrailingUM
|
||||||
|
|
||||||
|
/** Chevron indicating the whole row is clickable. */
|
||||||
|
data object Chevron : TrailingUM
|
||||||
|
|
||||||
|
/** Status icon (warning / info) placed in the trailing slot. */
|
||||||
|
data class StatusIcon(val tone: Tone) : TrailingUM {
|
||||||
|
enum class Tone { Warning, Info }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Circular progress indicator placed in the trailing slot (enabling / disabling states). */
|
||||||
|
data class Loader(val tone: LoaderTone) : TrailingUM {
|
||||||
|
enum class LoaderTone { Positive, Muted }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -97,9 +97,11 @@ fun TangemPagerIndicator(
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.offset {
|
modifier = Modifier
|
||||||
IntOffset(animState.slideOffset.value.roundToInt(), 0)
|
.wrapContentWidth(unbounded = true)
|
||||||
},
|
.offset {
|
||||||
|
IntOffset(animState.slideOffset.value.roundToInt(), 0)
|
||||||
|
},
|
||||||
horizontalArrangement = Arrangement.spacedBy(SPACING),
|
horizontalArrangement = Arrangement.spacedBy(SPACING),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
|
|
@ -367,8 +369,8 @@ val TangemPagerIndicatorColors: PagerIndicatorColors
|
||||||
@Composable
|
@Composable
|
||||||
@ReadOnlyComposable
|
@ReadOnlyComposable
|
||||||
get() = PagerIndicatorColors(
|
get() = PagerIndicatorColors(
|
||||||
active = TangemTheme.colors2.graphic.neutral.primary,
|
active = TangemTheme.colors3.bg.inverse,
|
||||||
inactive = TangemTheme.colors2.graphic.neutral.tertiary,
|
inactive = TangemTheme.colors3.bg.opaque.secondary,
|
||||||
overlay = null,
|
overlay = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -413,6 +415,7 @@ private class TangemPagerIndicatorPreviewProvider : PreviewParameterProvider<Int
|
||||||
1,
|
1,
|
||||||
2,
|
2,
|
||||||
3,
|
3,
|
||||||
|
4,
|
||||||
5,
|
5,
|
||||||
6,
|
6,
|
||||||
7,
|
7,
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,10 @@ import androidx.compose.ui.unit.Constraints
|
||||||
import androidx.compose.ui.unit.constrainHeight
|
import androidx.compose.ui.unit.constrainHeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.tangem.core.ui.R
|
import com.tangem.core.ui.R
|
||||||
import com.tangem.core.ui.ds.button.SecondaryTangemButton
|
|
||||||
import com.tangem.core.ui.ds.button.TangemButtonShape
|
|
||||||
import com.tangem.core.ui.ds.button.TangemButtonType
|
import com.tangem.core.ui.ds.button.TangemButtonType
|
||||||
import com.tangem.core.ui.ds.button.TangemButtonUM
|
import com.tangem.core.ui.ds.button.TangemButtonUM
|
||||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||||
|
import com.tangem.core.ui.ds2.button.TangemButton
|
||||||
import com.tangem.core.ui.extensions.orEmpty
|
import com.tangem.core.ui.extensions.orEmpty
|
||||||
import com.tangem.core.ui.extensions.resolveReference
|
import com.tangem.core.ui.extensions.resolveReference
|
||||||
import com.tangem.core.ui.extensions.stringReference
|
import com.tangem.core.ui.extensions.stringReference
|
||||||
|
|
@ -109,12 +108,12 @@ private fun ActionButton(button: TangemButtonUM, modifier: Modifier = Modifier)
|
||||||
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x2),
|
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x2),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
) {
|
) {
|
||||||
SecondaryTangemButton(
|
TangemButton(
|
||||||
tangemIconUM = button.tangemIconUM,
|
|
||||||
onClick = button.onClick,
|
onClick = button.onClick,
|
||||||
|
variant = TangemButton.Variant.Material,
|
||||||
isEnabled = button.isEnabled,
|
isEnabled = button.isEnabled,
|
||||||
shape = TangemButtonShape.Rounded,
|
iconStart = button.tangemIconUM,
|
||||||
onLongClick = button.onLongClick,
|
size = TangemButton.Size.X14,
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = button.text.orEmpty().resolveReference(),
|
text = button.text.orEmpty().resolveReference(),
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,7 @@ package com.tangem.features.markets.token.block.impl.ui
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.layout.requiredSize
|
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
|
@ -38,12 +34,12 @@ import com.tangem.core.ui.extensions.stringResourceSafe
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||||
import com.tangem.core.ui.test.TokenMarketBlockTestTags
|
import com.tangem.core.ui.test.TokenMarketBlockTestTags
|
||||||
import com.tangem.core.ui.R as CoreR
|
|
||||||
import com.tangem.features.markets.impl.R
|
import com.tangem.features.markets.impl.R
|
||||||
import com.tangem.features.markets.token.block.impl.model.formatter.toChartType
|
import com.tangem.features.markets.token.block.impl.model.formatter.toChartType
|
||||||
import com.tangem.features.markets.token.block.impl.ui.state.TokenMarketBlockUM
|
import com.tangem.features.markets.token.block.impl.ui.state.TokenMarketBlockUM
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
import com.tangem.core.ui.R as CoreR
|
||||||
|
|
||||||
private val ChartWidth: Dp = 52.dp
|
private val ChartWidth: Dp = 52.dp
|
||||||
private val ChartHeight: Dp = 32.dp
|
private val ChartHeight: Dp = 32.dp
|
||||||
|
|
@ -115,7 +111,7 @@ internal fun TokenMarketBlock(tokenMarketBlockUM: TokenMarketBlockUM, modifier:
|
||||||
withHazeEffect = false,
|
withHazeEffect = false,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.layoutId(TangemRowLayoutId.TAIL)
|
.layoutId(TangemRowLayoutId.TAIL)
|
||||||
.padding(start = TangemTheme.dimens2.x10),
|
.padding(start = 12.dp),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.util.lerp
|
import androidx.compose.ui.util.lerp
|
||||||
import com.tangem.core.ui.components.SpacerH8
|
import com.tangem.core.ui.components.SpacerH8
|
||||||
import com.tangem.core.ui.components.notifications.NotificationConfig
|
import com.tangem.core.ui.components.notifications.NotificationConfig
|
||||||
import com.tangem.core.ui.components.pager.PagerIndicator
|
import com.tangem.core.ui.ds.TangemPagerIndicator
|
||||||
import com.tangem.core.ui.ds.message.TangemMessage
|
import com.tangem.core.ui.ds.message.TangemMessage
|
||||||
import com.tangem.core.ui.extensions.stringReference
|
import com.tangem.core.ui.extensions.stringReference
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
|
|
@ -134,10 +134,7 @@ private fun BannersCarousel(
|
||||||
|
|
||||||
SpacerH8()
|
SpacerH8()
|
||||||
|
|
||||||
PagerIndicator(
|
TangemPagerIndicator(pagerState = pagerState)
|
||||||
pagerState = pagerState,
|
|
||||||
hasBackground = false,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import com.tangem.core.ui.ds.button.TangemButtonUM
|
||||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||||
import com.tangem.core.ui.extensions.TextReference
|
import com.tangem.core.ui.extensions.TextReference
|
||||||
import com.tangem.core.ui.extensions.resourceReference
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
|
||||||
import com.tangem.features.tokendetails.impl.R
|
import com.tangem.features.tokendetails.impl.R
|
||||||
import com.tangem.utils.transformer.Transformer
|
import com.tangem.utils.transformer.Transformer
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
@ -54,10 +53,7 @@ internal class TokenDetailsStateController @Inject constructor() {
|
||||||
),
|
),
|
||||||
swapButton = TangemButtonUM(
|
swapButton = TangemButtonUM(
|
||||||
text = resourceReference(R.string.actionbutton_swap_title),
|
text = resourceReference(R.string.actionbutton_swap_title),
|
||||||
tangemIconUM = TangemIconUM.Icon(
|
tangemIconUM = TangemIconUM.Icon(iconRes = R.drawable.ic_exchange_default_24),
|
||||||
iconRes = R.drawable.ic_exchange_default_24,
|
|
||||||
tintReference = { TangemTheme.colors2.graphic.neutral.quaternary },
|
|
||||||
),
|
|
||||||
onClick = { },
|
onClick = { },
|
||||||
isEnabled = false,
|
isEnabled = false,
|
||||||
type = TangemButtonType.Secondary,
|
type = TangemButtonType.Secondary,
|
||||||
|
|
|
||||||
|
|
@ -144,13 +144,13 @@ private fun AddAndManageRow(
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResourceSafe(id = title),
|
text = stringResourceSafe(id = title),
|
||||||
style = TangemTheme.typography2.bodyMedium16,
|
style = TangemTheme.typography3.body.medium,
|
||||||
color = TangemTheme.colors2.text.neutral.primary,
|
color = TangemTheme.colors3.text.primary,
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = stringResourceSafe(id = subtitle),
|
text = stringResourceSafe(id = subtitle),
|
||||||
style = TangemTheme.typography2.captionMedium12,
|
style = TangemTheme.typography3.caption.medium,
|
||||||
color = TangemTheme.colors2.text.neutral.secondary,
|
color = TangemTheme.colors3.text.secondary,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
SpacerW(8.dp)
|
SpacerW(8.dp)
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,17 @@
|
||||||
package com.tangem.feature.wallet.child.organizetokens.model.converter.items
|
package com.tangem.feature.wallet.child.organizetokens.model.converter.items
|
||||||
|
|
||||||
import androidx.compose.ui.text.SpanStyle
|
import androidx.compose.ui.text.SpanStyle
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
import com.tangem.common.getTotalCryptoAmount
|
import com.tangem.common.getTotalCryptoAmount
|
||||||
import com.tangem.common.getTotalFiatAmount
|
import com.tangem.common.getTotalFiatAmount
|
||||||
import com.tangem.common.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
import com.tangem.common.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
||||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||||
import com.tangem.core.ui.ds.row.internal.TangemRowTailUM
|
import com.tangem.core.ui.ds.row.internal.TangemRowTailUM
|
||||||
import com.tangem.core.ui.ds.row.token.TangemTokenRowUM
|
import com.tangem.core.ui.ds.row.token.TangemTokenRowUM
|
||||||
|
import com.tangem.core.ui.extensions.combinedReference
|
||||||
import com.tangem.core.ui.extensions.stringReference
|
import com.tangem.core.ui.extensions.stringReference
|
||||||
|
import com.tangem.core.ui.extensions.styledStringReference
|
||||||
import com.tangem.core.ui.format.bigdecimal.cryptoStyled
|
import com.tangem.core.ui.format.bigdecimal.cryptoStyled
|
||||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||||
import com.tangem.core.ui.format.bigdecimal.formatStyled
|
import com.tangem.core.ui.format.bigdecimal.formatStyled
|
||||||
|
|
@ -36,7 +40,21 @@ internal class OrganizeTokenItemConverter(
|
||||||
id = getTokenItemId(currency.id),
|
id = getTokenItemId(currency.id),
|
||||||
headIconUM = TangemIconUM.Currency(iconStateConverter.convert(currencyStatus)),
|
headIconUM = TangemIconUM.Currency(iconStateConverter.convert(currencyStatus)),
|
||||||
titleUM = TangemTokenRowUM.TitleUM.Content(
|
titleUM = TangemTokenRowUM.TitleUM.Content(
|
||||||
text = stringReference(currency.name),
|
text = combinedReference(
|
||||||
|
stringReference(currency.name),
|
||||||
|
stringReference(" "),
|
||||||
|
styledStringReference(
|
||||||
|
value = currency.symbol,
|
||||||
|
spanStyleReference = {
|
||||||
|
SpanStyle(
|
||||||
|
color = TangemTheme.colors3.text.secondary,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
fontSize = 12.sp,
|
||||||
|
letterSpacing = 0.18.sp,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
subtitleUM = TangemTokenRowUM.SubtitleUM.Empty,
|
subtitleUM = TangemTokenRowUM.SubtitleUM.Empty,
|
||||||
topEndContentUM = TangemTokenRowUM.EndContentUM.Content(
|
topEndContentUM = TangemTokenRowUM.EndContentUM.Content(
|
||||||
|
|
|
||||||
|
|
@ -62,11 +62,11 @@ private fun Menu(
|
||||||
private fun SortByBalanceMenuSection(organizeMenuUM: OrganizeTokensUM.OrganizeMenuUM, onDropdownDismiss: () -> Unit) {
|
private fun SortByBalanceMenuSection(organizeMenuUM: OrganizeTokensUM.OrganizeMenuUM, onDropdownDismiss: () -> Unit) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResourceSafe(R.string.organize_tokens_sort_by_balance),
|
text = stringResourceSafe(R.string.organize_tokens_sort_by_balance),
|
||||||
style = TangemTheme.typography2.headingSemibold17,
|
style = TangemTheme.typography3.body.medium,
|
||||||
color = if (organizeMenuUM.isSortedByBalance) {
|
color = if (organizeMenuUM.isSortedByBalance) {
|
||||||
TangemTheme.colors2.text.status.disabled
|
TangemTheme.colors3.text.tertiary
|
||||||
} else {
|
} else {
|
||||||
TangemTheme.colors2.text.neutral.primary
|
TangemTheme.colors3.text.primary
|
||||||
},
|
},
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|
@ -79,12 +79,12 @@ private fun SortByBalanceMenuSection(organizeMenuUM: OrganizeTokensUM.OrganizeMe
|
||||||
},
|
},
|
||||||
enabled = !organizeMenuUM.isSortedByBalance,
|
enabled = !organizeMenuUM.isSortedByBalance,
|
||||||
)
|
)
|
||||||
.padding(vertical = TangemTheme.dimens2.x2_5, horizontal = TangemTheme.dimens2.x4),
|
.padding(vertical = 10.dp, horizontal = 16.dp),
|
||||||
)
|
)
|
||||||
|
|
||||||
HorizontalDivider(
|
HorizontalDivider(
|
||||||
thickness = 0.5.dp,
|
thickness = 0.5.dp,
|
||||||
color = TangemTheme.colors2.border.neutral.quaternary,
|
color = TangemTheme.colors3.border.tertiary,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -102,36 +102,36 @@ private fun GroupTokensMenuSection(organizeMenuUM: OrganizeTokensUM.OrganizeMenu
|
||||||
onDropdownDismiss()
|
onDropdownDismiss()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.padding(vertical = TangemTheme.dimens2.x2_5, horizontal = TangemTheme.dimens2.x4),
|
.padding(vertical = 10.dp, horizontal = 16.dp),
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResourceSafe(R.string.organize_tokens_group),
|
text = stringResourceSafe(R.string.organize_tokens_group),
|
||||||
style = TangemTheme.typography2.headingSemibold17,
|
style = TangemTheme.typography3.body.medium,
|
||||||
color = TangemTheme.colors2.text.neutral.primary,
|
color = TangemTheme.colors3.text.primary,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.size(TangemTheme.dimens2.x6),
|
modifier = Modifier.size(24.dp),
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
) {
|
) {
|
||||||
if (organizeMenuUM.isGrouped) {
|
if (organizeMenuUM.isGrouped) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(TangemTheme.dimens2.x0_5)
|
.padding(2.dp)
|
||||||
.size(TangemTheme.dimens2.x5)
|
.size(20.dp)
|
||||||
.background(
|
.background(
|
||||||
color = TangemTheme.colors2.graphic.neutral.primary,
|
color = TangemTheme.colors3.icon.primary,
|
||||||
shape = CircleShape,
|
shape = CircleShape,
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = ImageVector.vectorResource(R.drawable.ic_check_default_24),
|
imageVector = ImageVector.vectorResource(R.drawable.ic_check_default_24),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = TangemTheme.colors2.graphic.neutral.primaryInverted,
|
tint = TangemTheme.colors3.icon.inverse,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.align(Alignment.Center)
|
.align(Alignment.Center)
|
||||||
.padding(TangemTheme.dimens2.x0_5)
|
.padding(2.dp)
|
||||||
.size(TangemTheme.dimens2.x4),
|
.size(16.dp),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,8 @@ import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||||
import com.tangem.core.ui.components.haze.hazeEffectTangem
|
import com.tangem.core.ui.components.haze.hazeEffectTangem
|
||||||
import com.tangem.core.ui.components.haze.hazeSourceTangem
|
import com.tangem.core.ui.components.haze.hazeSourceTangem
|
||||||
import com.tangem.core.ui.ds.button.TangemButton
|
|
||||||
import com.tangem.core.ui.ds.image.TangemIcon
|
import com.tangem.core.ui.ds.image.TangemIcon
|
||||||
|
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||||
import com.tangem.core.ui.ds.row.TangemRowContainer
|
import com.tangem.core.ui.ds.row.TangemRowContainer
|
||||||
import com.tangem.core.ui.ds.row.TangemRowLayoutId
|
import com.tangem.core.ui.ds.row.TangemRowLayoutId
|
||||||
import com.tangem.core.ui.ds.row.header.TangemHeaderRow
|
import com.tangem.core.ui.ds.row.header.TangemHeaderRow
|
||||||
|
|
@ -43,10 +43,9 @@ import com.tangem.core.ui.ds.row.internal.TangemRowTail
|
||||||
import com.tangem.core.ui.ds.row.token.TangemTokenRowUM
|
import com.tangem.core.ui.ds.row.token.TangemTokenRowUM
|
||||||
import com.tangem.core.ui.ds.row.token.internal.TokenRowEndContent
|
import com.tangem.core.ui.ds.row.token.internal.TokenRowEndContent
|
||||||
import com.tangem.core.ui.ds.row.token.internal.TokenRowTitle
|
import com.tangem.core.ui.ds.row.token.internal.TokenRowTitle
|
||||||
import com.tangem.core.ui.ds.topbar.TangemTopBar
|
import com.tangem.core.ui.ds2.button.TangemButton
|
||||||
import com.tangem.core.ui.ds.topbar.TangemTopBarActionContent
|
import com.tangem.core.ui.ds2.topnavigation.TangemTopNavigation
|
||||||
import com.tangem.core.ui.ds.topbar.TangemTopBarActionUM
|
import com.tangem.core.ui.extensions.copy
|
||||||
import com.tangem.core.ui.ds.topbar.TangemTopBarType
|
|
||||||
import com.tangem.core.ui.extensions.resourceReference
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||||
|
|
@ -82,21 +81,21 @@ internal fun OrganizeTokensContent(
|
||||||
onDismissRequest = onDismiss,
|
onDismissRequest = onDismiss,
|
||||||
content = TangemBottomSheetConfigContent.Empty,
|
content = TangemBottomSheetConfigContent.Empty,
|
||||||
),
|
),
|
||||||
containerColor = TangemTheme.colors2.surface.level2,
|
containerColor = TangemTheme.colors3.bg.primary,
|
||||||
title = {
|
title = {
|
||||||
TangemTopBar(
|
TangemTopNavigation(
|
||||||
|
contentPadding = TangemTopNavigation.DefaultContentPadding.copy(top = 16.dp),
|
||||||
|
windowInsets = WindowInsets(0.dp),
|
||||||
|
blurBackground = false,
|
||||||
|
contentAlign = TangemTopNavigation.ContentAlign.Center,
|
||||||
title = resourceReference(R.string.organize_tokens_title),
|
title = resourceReference(R.string.organize_tokens_title),
|
||||||
type = TangemTopBarType.BottomSheet,
|
endButton = {
|
||||||
endContent = {
|
TangemButton(
|
||||||
TangemTopBarActionContent(
|
|
||||||
actionUM = TangemTopBarActionUM(
|
|
||||||
iconRes = R.drawable.ic_exchange_mini_24,
|
|
||||||
isActionable = true,
|
|
||||||
onClick = { isShowDropdownMenu = true },
|
|
||||||
ghostModeProgress = 0f,
|
|
||||||
),
|
|
||||||
modifier = Modifier.testTag(OrganizeTokensScreenTestTags.MENU_BUTTON),
|
modifier = Modifier.testTag(OrganizeTokensScreenTestTags.MENU_BUTTON),
|
||||||
type = TangemTopBarType.BottomSheet,
|
variant = TangemButton.Variant.Material,
|
||||||
|
size = TangemButton.Size.X11,
|
||||||
|
iconStart = TangemIconUM.Icon(iconRes = R.drawable.ic_exchange_mini_24),
|
||||||
|
onClick = { isShowDropdownMenu = true },
|
||||||
)
|
)
|
||||||
OrganizeDropDownMenu(
|
OrganizeDropDownMenu(
|
||||||
organizeMenuUM = organizeTokensUM.organizeMenuUM,
|
organizeMenuUM = organizeTokensUM.organizeMenuUM,
|
||||||
|
|
@ -137,7 +136,7 @@ private fun TokenList(
|
||||||
var draggingItem by remember { mutableStateOf<OrganizeRowItemUM?>(null) }
|
var draggingItem by remember { mutableStateOf<OrganizeRowItemUM?>(null) }
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier.background(TangemTheme.colors2.surface.level2),
|
modifier = modifier.background(TangemTheme.colors3.bg.primary),
|
||||||
) {
|
) {
|
||||||
val footerInset = LocalTangemBottomSheetContentBottomInset.current
|
val footerInset = LocalTangemBottomSheetContentBottomInset.current
|
||||||
|
|
||||||
|
|
@ -238,7 +237,7 @@ private fun LazyItemScope.DraggableItem(
|
||||||
enabled = isValidDropTarget,
|
enabled = isValidDropTarget,
|
||||||
) { _ ->
|
) { _ ->
|
||||||
val modifierWithBackground = itemModifier
|
val modifierWithBackground = itemModifier
|
||||||
.background(color = TangemTheme.colors.background.primary)
|
.background(color = TangemTheme.colors3.bg.secondary)
|
||||||
.semantics { lazyListItemPosition = index }
|
.semantics { lazyListItemPosition = index }
|
||||||
|
|
||||||
when (item) {
|
when (item) {
|
||||||
|
|
@ -281,16 +280,23 @@ private fun BoxScope.BottomButtons(organizeTokensUM: OrganizeTokensUM) {
|
||||||
.padding(bottom = bottomBarHeight + TangemTheme.dimens2.x4),
|
.padding(bottom = bottomBarHeight + TangemTheme.dimens2.x4),
|
||||||
) {
|
) {
|
||||||
TangemButton(
|
TangemButton(
|
||||||
buttonUM = organizeTokensUM.cancelButton,
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.testTag(OrganizeTokensScreenTestTags.CANCEL_BUTTON),
|
.testTag(OrganizeTokensScreenTestTags.CANCEL_BUTTON),
|
||||||
|
onClick = organizeTokensUM.cancelButton.onClick,
|
||||||
|
text = organizeTokensUM.cancelButton.text,
|
||||||
|
variant = TangemButton.Variant.Secondary,
|
||||||
|
size = TangemButton.Size.X12,
|
||||||
|
isEnabled = organizeTokensUM.cancelButton.isEnabled,
|
||||||
)
|
)
|
||||||
TangemButton(
|
TangemButton(
|
||||||
buttonUM = organizeTokensUM.applyButton,
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.testTag(OrganizeTokensScreenTestTags.APPLY_BUTTON),
|
.testTag(OrganizeTokensScreenTestTags.APPLY_BUTTON),
|
||||||
|
onClick = organizeTokensUM.applyButton.onClick,
|
||||||
|
text = organizeTokensUM.applyButton.text,
|
||||||
|
size = TangemButton.Size.X12,
|
||||||
|
isEnabled = organizeTokensUM.applyButton.isEnabled,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -355,8 +361,8 @@ private fun OrganizeTokenRow(
|
||||||
TokenRowEndContent(
|
TokenRowEndContent(
|
||||||
endContentUM = tokenRowUM.topEndContentUM,
|
endContentUM = tokenRowUM.topEndContentUM,
|
||||||
isBalanceHidden = isBalanceHidden,
|
isBalanceHidden = isBalanceHidden,
|
||||||
textStyle = TangemTheme.typography2.captionSemibold12,
|
textStyle = TangemTheme.typography3.caption.medium,
|
||||||
textColor = TangemTheme.colors2.text.neutral.secondary,
|
textColor = TangemTheme.colors3.text.secondary,
|
||||||
placeholderWidth = TangemTheme.dimens2.x11,
|
placeholderWidth = TangemTheme.dimens2.x11,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.layoutId(layoutId = TangemRowLayoutId.START_BOTTOM)
|
.layoutId(layoutId = TangemRowLayoutId.START_BOTTOM)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.tangem.feature.wallet.child.organizetokens.ui.preview
|
package com.tangem.feature.wallet.child.organizetokens.ui.preview
|
||||||
|
|
||||||
|
import androidx.compose.ui.text.SpanStyle
|
||||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||||
import com.tangem.core.ui.ds.button.TangemButtonType
|
import com.tangem.core.ui.ds.button.TangemButtonType
|
||||||
import com.tangem.core.ui.ds.button.TangemButtonUM
|
import com.tangem.core.ui.ds.button.TangemButtonUM
|
||||||
|
|
@ -8,9 +9,12 @@ import com.tangem.core.ui.ds.row.header.TangemHeaderRowUM
|
||||||
import com.tangem.core.ui.ds.row.internal.TangemRowTailUM
|
import com.tangem.core.ui.ds.row.internal.TangemRowTailUM
|
||||||
import com.tangem.core.ui.ds.row.token.TangemTokenRowUM
|
import com.tangem.core.ui.ds.row.token.TangemTokenRowUM
|
||||||
import com.tangem.core.ui.event.consumedEvent
|
import com.tangem.core.ui.event.consumedEvent
|
||||||
|
import com.tangem.core.ui.extensions.combinedReference
|
||||||
import com.tangem.core.ui.extensions.resourceReference
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
import com.tangem.core.ui.extensions.stringReference
|
import com.tangem.core.ui.extensions.stringReference
|
||||||
|
import com.tangem.core.ui.extensions.styledStringReference
|
||||||
import com.tangem.core.ui.res.TangemColorPalette
|
import com.tangem.core.ui.res.TangemColorPalette
|
||||||
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.feature.wallet.child.organizetokens.entity.OrganizeRowItemUM
|
import com.tangem.feature.wallet.child.organizetokens.entity.OrganizeRowItemUM
|
||||||
import com.tangem.feature.wallet.child.organizetokens.entity.OrganizeTokensUM
|
import com.tangem.feature.wallet.child.organizetokens.entity.OrganizeTokensUM
|
||||||
import com.tangem.feature.wallet.child.organizetokens.entity.RoundingModeUM
|
import com.tangem.feature.wallet.child.organizetokens.entity.RoundingModeUM
|
||||||
|
|
@ -75,7 +79,16 @@ internal object OrganizeTokensPreview {
|
||||||
tokenRowUM = draggableToken.copy(
|
tokenRowUM = draggableToken.copy(
|
||||||
id = "${group.id}_token_$tokenNumber",
|
id = "${group.id}_token_$tokenNumber",
|
||||||
titleUM = TangemTokenRowUM.TitleUM.Content(
|
titleUM = TangemTokenRowUM.TitleUM.Content(
|
||||||
text = stringReference(value = "Token $tokenNumber from $networkNumber network"),
|
text = combinedReference(
|
||||||
|
stringReference(value = "Token $tokenNumber"),
|
||||||
|
stringReference(value = " "),
|
||||||
|
styledStringReference(
|
||||||
|
value = "TKN$tokenNumber",
|
||||||
|
spanStyleReference = {
|
||||||
|
SpanStyle(color = TangemTheme.colors2.text.neutral.secondary)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
groupId = group.id,
|
groupId = group.id,
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.platform.testTag
|
import androidx.compose.ui.platform.testTag
|
||||||
import com.tangem.core.ui.test.BaseBottomSheetTestTags
|
|
||||||
import androidx.compose.ui.res.vectorResource
|
import androidx.compose.ui.res.vectorResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.DpOffset
|
import androidx.compose.ui.unit.DpOffset
|
||||||
|
|
@ -31,6 +30,7 @@ import com.tangem.core.ui.extensions.resolveReference
|
||||||
import com.tangem.core.ui.extensions.stringReference
|
import com.tangem.core.ui.extensions.stringReference
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||||
|
import com.tangem.core.ui.test.BaseBottomSheetTestTags
|
||||||
import com.tangem.feature.wallet.impl.R
|
import com.tangem.feature.wallet.impl.R
|
||||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TokenActionButtonUM
|
import com.tangem.feature.wallet.presentation.wallet.state.model.TokenActionButtonUM
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
@ -60,9 +60,9 @@ internal fun TokenActionContent(
|
||||||
tokenRowUM = tokenRowUM,
|
tokenRowUM = tokenRowUM,
|
||||||
isBalanceHidden = isBalanceHidden,
|
isBalanceHidden = isBalanceHidden,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(horizontal = TangemTheme.dimens2.x3)
|
.padding(horizontal = 12.dp)
|
||||||
.clip(RoundedCornerShape(18.dp))
|
.clip(RoundedCornerShape(18.dp))
|
||||||
.background(TangemTheme.colors2.surface.level3),
|
.background(TangemTheme.colors3.bg.secondary),
|
||||||
)
|
)
|
||||||
TangemContextMenu(
|
TangemContextMenu(
|
||||||
expanded = true,
|
expanded = true,
|
||||||
|
|
@ -93,17 +93,17 @@ private fun TokenActionContextMenuContent(actions: ImmutableList<TokenActionButt
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.widthIn(min = 206.dp)
|
.widthIn(min = 206.dp)
|
||||||
.padding(TangemTheme.dimens2.x1_5),
|
.padding(6.dp),
|
||||||
) {
|
) {
|
||||||
actions.fastForEach { item ->
|
actions.fastForEach { item ->
|
||||||
Column {
|
Column {
|
||||||
Row(
|
Row(
|
||||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x2_5),
|
horizontalArrangement = Arrangement.spacedBy(10.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.testTag(BaseBottomSheetTestTags.ACTION_BUTTON)
|
.testTag(BaseBottomSheetTestTags.ACTION_BUTTON)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clip(RoundedCornerShape(TangemTheme.dimens2.x2_5))
|
.clip(RoundedCornerShape(10.dp))
|
||||||
.clickable(
|
.clickable(
|
||||||
enabled = item.isEnabled,
|
enabled = item.isEnabled,
|
||||||
onClick = {
|
onClick = {
|
||||||
|
|
@ -112,39 +112,39 @@ private fun TokenActionContextMenuContent(actions: ImmutableList<TokenActionButt
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.padding(
|
.padding(
|
||||||
horizontal = TangemTheme.dimens2.x2_5,
|
horizontal = 10.dp,
|
||||||
vertical = TangemTheme.dimens2.x2_5,
|
vertical = 10.dp,
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = ImageVector.vectorResource(item.iconResId),
|
imageVector = ImageVector.vectorResource(item.iconResId),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = if (item.isWarning) {
|
tint = if (item.isWarning) {
|
||||||
TangemTheme.colors2.graphic.status.warning
|
TangemTheme.colors3.icon.accent.red
|
||||||
} else {
|
} else {
|
||||||
TangemTheme.colors2.graphic.neutral.primary
|
TangemTheme.colors3.icon.primary
|
||||||
},
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(TangemTheme.dimens2.x5)
|
.size(20.dp)
|
||||||
.testTag(BaseBottomSheetTestTags.ACTION_ICON),
|
.testTag(BaseBottomSheetTestTags.ACTION_ICON),
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = item.text.resolveReference(),
|
text = item.text.resolveReference(),
|
||||||
style = TangemTheme.typography2.headingRegular17,
|
style = TangemTheme.typography3.body.medium,
|
||||||
color = if (item.isWarning) {
|
color = if (item.isWarning) {
|
||||||
TangemTheme.colors2.text.status.warning
|
TangemTheme.colors3.text.accent.red
|
||||||
} else {
|
} else {
|
||||||
TangemTheme.colors2.text.neutral.primary
|
TangemTheme.colors3.text.primary
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (item.hasDivider) {
|
if (item.hasDivider) {
|
||||||
Spacer(
|
Spacer(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(vertical = TangemTheme.dimens2.x1)
|
.padding(vertical = 4.dp)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(1.dp)
|
.height(1.dp)
|
||||||
.background(TangemTheme.colors2.border.neutral.primary),
|
.background(TangemTheme.colors3.border.primary),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ internal object WalletBalancePreview {
|
||||||
styledStringReference(
|
styledStringReference(
|
||||||
".56",
|
".56",
|
||||||
{
|
{
|
||||||
TangemTheme.typography2.headingRegular28.toSpanStyle()
|
TangemTheme.typography3.heading.medium.toSpanStyle()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
stringReference(" $"),
|
stringReference(" $"),
|
||||||
|
|
@ -55,7 +55,7 @@ internal object WalletBalancePreview {
|
||||||
styledStringReference(
|
styledStringReference(
|
||||||
".56",
|
".56",
|
||||||
{
|
{
|
||||||
TangemTheme.typography2.headingRegular28.toSpanStyle()
|
TangemTheme.typography3.heading.medium.toSpanStyle()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
stringReference(" $"),
|
stringReference(" $"),
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import com.tangem.core.ui.ds.button.TangemButtonUM
|
||||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||||
import com.tangem.core.ui.extensions.TextReference
|
import com.tangem.core.ui.extensions.TextReference
|
||||||
import com.tangem.core.ui.extensions.resourceReference
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
|
||||||
import com.tangem.feature.wallet.impl.R
|
import com.tangem.feature.wallet.impl.R
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -27,16 +26,7 @@ internal sealed class WalletActionButtons(
|
||||||
val buttonUM: TangemButtonUM
|
val buttonUM: TangemButtonUM
|
||||||
get() = TangemButtonUM(
|
get() = TangemButtonUM(
|
||||||
text = text,
|
text = text,
|
||||||
tangemIconUM = TangemIconUM.Icon(
|
tangemIconUM = TangemIconUM.Icon(iconRes = iconRes),
|
||||||
iconRes = iconRes,
|
|
||||||
tintReference = {
|
|
||||||
if (isEnabled) {
|
|
||||||
TangemTheme.colors2.graphic.neutral.primary
|
|
||||||
} else {
|
|
||||||
TangemTheme.colors2.graphic.neutral.quaternary
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
type = TangemButtonType.Secondary,
|
type = TangemButtonType.Secondary,
|
||||||
shape = TangemButtonShape.Rounded,
|
shape = TangemButtonShape.Rounded,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
|
|
|
||||||
|
|
@ -103,14 +103,14 @@ internal class SetTokenListErrorTransformer(
|
||||||
fiat(
|
fiat(
|
||||||
fiatCurrencyCode = appCurrency.code,
|
fiatCurrencyCode = appCurrency.code,
|
||||||
fiatCurrencySymbol = appCurrency.symbol,
|
fiatCurrencySymbol = appCurrency.symbol,
|
||||||
spanStyleReference = { SpanStyle(color = TangemTheme.colors2.text.neutral.secondary) },
|
spanStyleReference = { SpanStyle(color = TangemTheme.colors3.text.secondary) },
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
balance = BigDecimal.ZERO.formatStyled {
|
balance = BigDecimal.ZERO.formatStyled {
|
||||||
fiat(
|
fiat(
|
||||||
fiatCurrencyCode = appCurrency.code,
|
fiatCurrencyCode = appCurrency.code,
|
||||||
fiatCurrencySymbol = appCurrency.symbol,
|
fiatCurrencySymbol = appCurrency.symbol,
|
||||||
spanStyleReference = { TangemTheme.typography2.headingRegular28.toSpanStyle() },
|
spanStyleReference = { TangemTheme.typography3.heading.medium.toSpanStyle() },
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
isZeroBalance = true,
|
isZeroBalance = true,
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ internal class MultiWalletBalanceUMTransformer(
|
||||||
fiat(
|
fiat(
|
||||||
fiatCurrencyCode = appCurrency.code,
|
fiatCurrencyCode = appCurrency.code,
|
||||||
fiatCurrencySymbol = appCurrency.symbol,
|
fiatCurrencySymbol = appCurrency.symbol,
|
||||||
spanStyleReference = { SpanStyle(color = TangemTheme.colors2.text.neutral.secondary) },
|
spanStyleReference = { SpanStyle(color = TangemTheme.colors3.text.secondary) },
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
balance = fiatBalance.amount.formatStyled {
|
balance = fiatBalance.amount.formatStyled {
|
||||||
|
|
@ -60,7 +60,7 @@ internal class MultiWalletBalanceUMTransformer(
|
||||||
fiatCurrencyCode = appCurrency.code,
|
fiatCurrencyCode = appCurrency.code,
|
||||||
fiatCurrencySymbol = appCurrency.symbol,
|
fiatCurrencySymbol = appCurrency.symbol,
|
||||||
spanStyleReference = {
|
spanStyleReference = {
|
||||||
TangemTheme.typography2.headingRegular28.toSpanStyle()
|
TangemTheme.typography3.heading.medium.toSpanStyle()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.graphicsLayer
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
|
import androidx.compose.ui.layout.onSizeChanged
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||||
import androidx.compose.ui.semantics.clearAndSetSemantics
|
import androidx.compose.ui.semantics.clearAndSetSemantics
|
||||||
|
|
@ -46,7 +47,6 @@ import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.DpOffset
|
import androidx.compose.ui.unit.DpOffset
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.arkivanov.decompose.ExperimentalDecomposeApi
|
import com.arkivanov.decompose.ExperimentalDecomposeApi
|
||||||
import com.tangem.core.ui.components.atoms.handComposableComponentHeight
|
|
||||||
import com.tangem.core.ui.components.background.northernlights.NorthernLightsBackground
|
import com.tangem.core.ui.components.background.northernlights.NorthernLightsBackground
|
||||||
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheetDraggableHeader
|
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheetDraggableHeader
|
||||||
import com.tangem.core.ui.components.bottomsheets.state.BottomSheetState
|
import com.tangem.core.ui.components.bottomsheets.state.BottomSheetState
|
||||||
|
|
@ -181,9 +181,6 @@ private fun WalletContent2(
|
||||||
onBottomSheetStateChange: (BottomSheetState) -> Unit,
|
onBottomSheetStateChange: (BottomSheetState) -> Unit,
|
||||||
bottomSheetContent: @Composable (onExpandSheet: () -> Unit) -> Unit,
|
bottomSheetContent: @Composable (onExpandSheet: () -> Unit) -> Unit,
|
||||||
) {
|
) {
|
||||||
val density = LocalDensity.current
|
|
||||||
val bottomBarHeight = with(density) { WindowInsets.systemBars.getBottom(this).toDp() }
|
|
||||||
|
|
||||||
var walletBalance by remember { mutableStateOf<TextReference?>(TextReference.EMPTY) }
|
var walletBalance by remember { mutableStateOf<TextReference?>(TextReference.EMPTY) }
|
||||||
var pullToRefreshConfig by remember {
|
var pullToRefreshConfig by remember {
|
||||||
mutableStateOf(
|
mutableStateOf(
|
||||||
|
|
@ -207,10 +204,15 @@ private fun WalletContent2(
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
) { paddingValues, bottomSheetState ->
|
) { paddingValues, bottomSheetState ->
|
||||||
val marketHintApproxHeight = 140.dp
|
val density = LocalDensity.current
|
||||||
|
var marketsHintHeight by remember { mutableStateOf(0.dp) }
|
||||||
|
val collapsedBodyOverhang = with(density) { behavior.state.partialHeightLimit.toDp() }
|
||||||
|
|
||||||
val contentPadding = PaddingValues(
|
val contentPadding = PaddingValues(
|
||||||
bottom = paddingValues.calculateBottomPadding() + marketHintApproxHeight,
|
bottom = paddingValues.calculateBottomPadding() +
|
||||||
|
marketsHintHeight +
|
||||||
|
collapsedBodyOverhang +
|
||||||
|
TangemTheme.dimens2.x2,
|
||||||
)
|
)
|
||||||
|
|
||||||
val selectedWalletIndex by rememberUpdatedState(state.selectedWalletIndex)
|
val selectedWalletIndex by rememberUpdatedState(state.selectedWalletIndex)
|
||||||
|
|
@ -235,22 +237,17 @@ private fun WalletContent2(
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.hazeSourceTangem(zIndex = -2f),
|
.hazeSourceTangem(zIndex = -2f),
|
||||||
) {
|
) {
|
||||||
val backgroundColor = if (LocalIsInDarkTheme.current) {
|
|
||||||
TangemTheme.colors2.surface.level1
|
|
||||||
} else {
|
|
||||||
TangemTheme.colors2.surface.level2
|
|
||||||
}
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.matchParentSize()
|
.matchParentSize()
|
||||||
.background(backgroundColor),
|
.background(TangemTheme.colors3.bg.primary),
|
||||||
)
|
)
|
||||||
val isSheetExpanded by remember {
|
val isSheetExpanded by remember {
|
||||||
derivedStateOf { bottomSheetState.targetValue == TangemSheetValue.Expanded }
|
derivedStateOf { bottomSheetState.targetValue == TangemSheetValue.Expanded }
|
||||||
}
|
}
|
||||||
if (!isSheetExpanded) {
|
if (!isSheetExpanded) {
|
||||||
NorthernLightsBackground(
|
NorthernLightsBackground(
|
||||||
containerColor = backgroundColor,
|
containerColor = TangemTheme.colors3.bg.primary,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.graphicsLayer { alpha = 1 - behavior.state.collapsedFraction * 2 }
|
.graphicsLayer { alpha = 1 - behavior.state.collapsedFraction * 2 }
|
||||||
.matchParentSize(),
|
.matchParentSize(),
|
||||||
|
|
@ -262,10 +259,10 @@ private fun WalletContent2(
|
||||||
pullToRefreshState = pullToRefreshState,
|
pullToRefreshState = pullToRefreshState,
|
||||||
pullToRefreshConfig = pullToRefreshConfig,
|
pullToRefreshConfig = pullToRefreshConfig,
|
||||||
behavior = behavior,
|
behavior = behavior,
|
||||||
topOffset = subtitleBottom + TangemTheme.dimens2.x2,
|
topOffset = subtitleBottom + 8.dp,
|
||||||
)
|
)
|
||||||
|
|
||||||
val overlay = TangemTheme.colors2.overlay.overlayPrimary
|
val overlay = TangemTheme.colors3.material.tint.solid
|
||||||
|
|
||||||
// Root-coordinates bounds of the "Add & Manage" button per pager page, reported by the
|
// Root-coordinates bounds of the "Add & Manage" button per pager page, reported by the
|
||||||
// button itself, so the markets hint and tooltip can avoid covering it
|
// button itself, so the markets hint and tooltip can avoid covering it
|
||||||
|
|
@ -376,14 +373,14 @@ private fun WalletContent2(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val peekHeight =
|
|
||||||
bottomSheetHeaderHeightProvider() + handComposableComponentHeight + bottomBarHeight
|
|
||||||
MarketsHint(
|
MarketsHint(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.align(Alignment.BottomCenter)
|
.align(Alignment.BottomCenter)
|
||||||
.fillMaxWidth(fraction = .6f)
|
.fillMaxWidth(fraction = .6f)
|
||||||
.padding(bottom = peekHeight),
|
.padding(bottom = paddingValues.calculateBottomPadding())
|
||||||
|
.onSizeChanged { size ->
|
||||||
|
marketsHintHeight = with(density) { size.height.toDp() }
|
||||||
|
},
|
||||||
isVisible = isShowMarketsHint,
|
isVisible = isShowMarketsHint,
|
||||||
obstacleBounds = remember(currentWalletIndex) {
|
obstacleBounds = remember(currentWalletIndex) {
|
||||||
{ organizeButtonBounds[currentWalletIndex] }
|
{ organizeButtonBounds[currentWalletIndex] }
|
||||||
|
|
@ -400,7 +397,7 @@ private fun WalletContent2(
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
isVisible = state.showMarketsOnboarding,
|
isVisible = state.showMarketsOnboarding,
|
||||||
availableHeight = maxHeight,
|
availableHeight = maxHeight,
|
||||||
sheetTopInset = TangemTheme.dimens2.x3,
|
sheetTopInset = 12.dp,
|
||||||
bottomSheetState = bottomSheetState,
|
bottomSheetState = bottomSheetState,
|
||||||
onCloseClick = state.onDismissMarketsTooltip,
|
onCloseClick = state.onDismissMarketsTooltip,
|
||||||
obstacleBounds = remember(walletsPagerState, organizeButtonBounds) {
|
obstacleBounds = remember(walletsPagerState, organizeButtonBounds) {
|
||||||
|
|
@ -425,15 +422,15 @@ private inline fun BaseScaffoldWithMarkets(
|
||||||
) {
|
) {
|
||||||
val density = LocalDensity.current
|
val density = LocalDensity.current
|
||||||
val bottomBarHeight = with(density) { WindowInsets.systemBars.getBottom(density = this).toDp() }
|
val bottomBarHeight = with(density) { WindowInsets.systemBars.getBottom(density = this).toDp() }
|
||||||
val peekHeight = bottomSheetHeaderHeightProvider() + TangemTheme.dimens2.x3 + bottomBarHeight
|
val peekHeight = bottomSheetHeaderHeightProvider() + 12.dp + bottomBarHeight
|
||||||
|
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
||||||
val bottomSheetState = rememberTangemStandardBottomSheetState()
|
val bottomSheetState = rememberTangemStandardBottomSheetState()
|
||||||
val scaffoldState = rememberTangemBottomSheetScaffoldState(bottomSheetState = bottomSheetState)
|
val scaffoldState = rememberTangemBottomSheetScaffoldState(bottomSheetState = bottomSheetState)
|
||||||
|
|
||||||
val expandedBackground = TangemTheme.colors2.surface.level2
|
val expandedBackground = TangemTheme.colors3.bg.primary
|
||||||
val collapsedBackground = TangemTheme.colors2.surface.level3
|
val collapsedBackground = TangemTheme.colors3.bg.secondary
|
||||||
val background by animateColorAsState(
|
val background by animateColorAsState(
|
||||||
targetValue = if (bottomSheetState.targetValue == TangemSheetValue.Expanded) {
|
targetValue = if (bottomSheetState.targetValue == TangemSheetValue.Expanded) {
|
||||||
expandedBackground
|
expandedBackground
|
||||||
|
|
@ -527,8 +524,8 @@ private fun BottomSheet(
|
||||||
|
|
||||||
val maxHeight = LocalWindowSize.current.height
|
val maxHeight = LocalWindowSize.current.height
|
||||||
val shape = RoundedCornerShape(
|
val shape = RoundedCornerShape(
|
||||||
topStart = TangemTheme.dimens2.x8,
|
topStart = 32.dp,
|
||||||
topEnd = TangemTheme.dimens2.x8,
|
topEnd = 32.dp,
|
||||||
)
|
)
|
||||||
CustomBottomSheet(
|
CustomBottomSheet(
|
||||||
state = bottomSheetState,
|
state = bottomSheetState,
|
||||||
|
|
|
||||||
|
|
@ -61,14 +61,14 @@ internal fun MarketsHint(isVisible: Boolean, modifier: Modifier = Modifier, obst
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResourceSafe(R.string.markets_hint),
|
text = stringResourceSafe(R.string.markets_hint),
|
||||||
style = TangemTheme.typography2.bodyRegular15,
|
style = TangemTheme.typography3.subheading.medium,
|
||||||
color = TangemTheme.colors2.text.neutral.tertiary,
|
color = TangemTheme.colors3.text.secondary,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
)
|
)
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.size(size = 24.dp),
|
modifier = Modifier.size(size = 24.dp),
|
||||||
painter = painterResource(id = R.drawable.ic_chevron_24),
|
painter = painterResource(id = R.drawable.ic_chevron_24),
|
||||||
tint = TangemTheme.colors2.graphic.neutral.tertiary,
|
tint = TangemTheme.colors3.icon.secondary,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,9 +32,13 @@ import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.*
|
import androidx.compose.ui.unit.*
|
||||||
import com.tangem.core.ui.components.sheetscaffold.TangemSheetState
|
import com.tangem.core.ui.components.sheetscaffold.TangemSheetState
|
||||||
|
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||||
|
import com.tangem.core.ui.ds2.button.TangemButton
|
||||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||||
|
import com.tangem.core.ui.res.generated.icons.Icons
|
||||||
|
import com.tangem.core.ui.res.generated.icons.ic_cross_20
|
||||||
import com.tangem.core.ui.test.MarketTooltipTestTags
|
import com.tangem.core.ui.test.MarketTooltipTestTags
|
||||||
import com.tangem.core.ui.utils.toPx
|
import com.tangem.core.ui.utils.toPx
|
||||||
import com.tangem.feature.wallet.impl.R
|
import com.tangem.feature.wallet.impl.R
|
||||||
|
|
@ -118,14 +122,14 @@ internal fun MarketsTooltip(
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun MarketsTooltipContent(onCloseClick: () -> Unit, modifier: Modifier = Modifier) {
|
internal fun MarketsTooltipContent(onCloseClick: () -> Unit, modifier: Modifier = Modifier) {
|
||||||
val backgroundColor = TangemTheme.colors.background.action
|
val backgroundColor = TangemTheme.colors3.bg.tertiary
|
||||||
val tipDpSize = DpSize(width = 20.dp, height = 8.dp)
|
val tipDpSize = DpSize(width = 20.dp, height = 8.dp)
|
||||||
val tooltipShape = remember(tipDpSize) { TooltipShape(cornerRadius = 16.dp, tipSize = tipDpSize) }
|
val tooltipShape = remember(tipDpSize) { TooltipShape(cornerRadius = 16.dp, tipSize = tipDpSize) }
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.shadow(
|
.shadow(
|
||||||
elevation = TangemTheme.dimens.elevation12,
|
elevation = 12.dp,
|
||||||
shape = tooltipShape,
|
shape = tooltipShape,
|
||||||
clip = false,
|
clip = false,
|
||||||
ambientColor = Color.Black.copy(alpha = 0.7f),
|
ambientColor = Color.Black.copy(alpha = 0.7f),
|
||||||
|
|
@ -149,27 +153,21 @@ internal fun MarketsTooltipContent(onCloseClick: () -> Unit, modifier: Modifier
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResourceSafe(id = R.string.markets_tooltip_v2_title),
|
text = stringResourceSafe(id = R.string.markets_tooltip_v2_title),
|
||||||
style = TangemTheme.typography.subtitle2,
|
style = TangemTheme.typography3.subheading.medium,
|
||||||
color = TangemTheme.colors.text.primary1,
|
color = TangemTheme.colors3.text.primary,
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = stringResourceSafe(id = R.string.markets_tooltip_message),
|
text = stringResourceSafe(id = R.string.markets_tooltip_message),
|
||||||
style = TangemTheme.typography.caption2,
|
style = TangemTheme.typography3.caption.medium,
|
||||||
color = TangemTheme.colors.text.secondary,
|
color = TangemTheme.colors3.text.secondary,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Icon(
|
TangemButton(
|
||||||
modifier = Modifier
|
variant = TangemButton.Variant.Ghost,
|
||||||
.size(size = 16.dp)
|
size = TangemButton.Size.X7,
|
||||||
.clickable(
|
iconStart = TangemIconUM.Icon(imageVector = Icons.ic_cross_20),
|
||||||
interactionSource = null,
|
onClick = onCloseClick,
|
||||||
indication = null,
|
modifier = Modifier.testTag(MarketTooltipTestTags.CLOSE_BUTTON),
|
||||||
onClick = onCloseClick,
|
|
||||||
)
|
|
||||||
.testTag(MarketTooltipTestTags.CLOSE_BUTTON),
|
|
||||||
painter = painterResource(id = R.drawable.ic_close_24),
|
|
||||||
tint = TangemTheme.colors.icon.informative,
|
|
||||||
contentDescription = null,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import androidx.compose.ui.geometry.Rect
|
||||||
import androidx.compose.ui.layout.boundsInRoot
|
import androidx.compose.ui.layout.boundsInRoot
|
||||||
import androidx.compose.ui.layout.onGloballyPositioned
|
import androidx.compose.ui.layout.onGloballyPositioned
|
||||||
import androidx.compose.ui.platform.testTag
|
import androidx.compose.ui.platform.testTag
|
||||||
import com.tangem.core.ui.ds.button.TangemButton
|
import com.tangem.core.ui.ds2.button.TangemButton
|
||||||
import com.tangem.core.ui.extensions.resourceReference
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
import com.tangem.core.ui.haptic.TangemHapticEffect
|
import com.tangem.core.ui.haptic.TangemHapticEffect
|
||||||
import com.tangem.core.ui.res.LocalHapticManager
|
import com.tangem.core.ui.res.LocalHapticManager
|
||||||
|
|
@ -26,7 +26,7 @@ internal const val ORGANIZE_TOKENS_BUTTON_ITEM_KEY = "OrganizeTokensButton"
|
||||||
internal fun LazyListScope.nftCollections2(state: WalletUM, itemModifier: Modifier) {
|
internal fun LazyListScope.nftCollections2(state: WalletUM, itemModifier: Modifier) {
|
||||||
(state as? WalletUM.Content)?.let { content ->
|
(state as? WalletUM.Content)?.let { content ->
|
||||||
item(key = "NFTCollections", contentType = "NFTCollections") {
|
item(key = "NFTCollections", contentType = "NFTCollections") {
|
||||||
WalletNFTItem(
|
WalletNFTItem2(
|
||||||
modifier = itemModifier,
|
modifier = itemModifier,
|
||||||
state = content.nftState,
|
state = content.nftState,
|
||||||
)
|
)
|
||||||
|
|
@ -62,15 +62,18 @@ internal fun LazyListScope.organizeTokens2(
|
||||||
}
|
}
|
||||||
|
|
||||||
TangemButton(
|
TangemButton(
|
||||||
buttonUM = organizeButton.copy(
|
|
||||||
onClick = {
|
|
||||||
hapticManager.perform(TangemHapticEffect.View.ContextClick)
|
|
||||||
organizeButton.onClick()
|
|
||||||
},
|
|
||||||
),
|
|
||||||
modifier = itemModifier
|
modifier = itemModifier
|
||||||
.onGloballyPositioned { currentOnButtonBoundsChange(it.boundsInRoot()) }
|
.onGloballyPositioned { currentOnButtonBoundsChange(it.boundsInRoot()) }
|
||||||
.testTag(testTag),
|
.testTag(testTag),
|
||||||
|
size = TangemButton.Size.X9,
|
||||||
|
onClick = {
|
||||||
|
hapticManager.perform(TangemHapticEffect.View.ContextClick)
|
||||||
|
organizeButton.onClick()
|
||||||
|
},
|
||||||
|
variant = TangemButton.Variant.Secondary,
|
||||||
|
iconStart = organizeButton.tangemIconUM,
|
||||||
|
text = organizeButton.text,
|
||||||
|
isEnabled = organizeButton.isEnabled,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ import kotlinx.collections.immutable.persistentListOf
|
||||||
internal fun WalletNFTItem2(state: WalletNFTItemUM, modifier: Modifier = Modifier) {
|
internal fun WalletNFTItem2(state: WalletNFTItemUM, modifier: Modifier = Modifier) {
|
||||||
val nftModifier = modifier
|
val nftModifier = modifier
|
||||||
.clip(RoundedCornerShape(18.dp))
|
.clip(RoundedCornerShape(18.dp))
|
||||||
.background(TangemTheme.colors2.surface.level3)
|
.background(TangemTheme.colors3.bg.secondary)
|
||||||
when (state) {
|
when (state) {
|
||||||
is WalletNFTItemUM.Hidden -> Unit
|
is WalletNFTItemUM.Hidden -> Unit
|
||||||
is WalletNFTItemUM.Empty -> WalletNFTItemEmpty(
|
is WalletNFTItemUM.Empty -> WalletNFTItemEmpty(
|
||||||
|
|
@ -70,13 +70,13 @@ private fun WalletNFTItemEmpty(onClick: () -> Unit, modifier: Modifier = Modifie
|
||||||
painter = painterResource(R.drawable.img_nft_empty_collection),
|
painter = painterResource(R.drawable.img_nft_empty_collection),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(TangemTheme.dimens2.x10)
|
.size(40.dp)
|
||||||
.layoutId(TangemRowLayoutId.HEAD),
|
.layoutId(TangemRowLayoutId.HEAD),
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = stringResourceSafe(R.string.nft_wallet_title),
|
text = stringResourceSafe(R.string.nft_wallet_title),
|
||||||
style = TangemTheme.typography2.bodySemibold16,
|
style = TangemTheme.typography3.body.medium,
|
||||||
color = TangemTheme.colors2.text.neutral.primary,
|
color = TangemTheme.colors3.text.primary,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|
@ -85,8 +85,8 @@ private fun WalletNFTItemEmpty(onClick: () -> Unit, modifier: Modifier = Modifie
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = stringResourceSafe(R.string.nft_wallet_receive_nft),
|
text = stringResourceSafe(R.string.nft_wallet_receive_nft),
|
||||||
style = TangemTheme.typography2.captionSemibold12,
|
style = TangemTheme.typography3.caption.medium,
|
||||||
color = TangemTheme.colors2.text.neutral.secondary,
|
color = TangemTheme.colors3.text.secondary,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|
@ -96,7 +96,7 @@ private fun WalletNFTItemEmpty(onClick: () -> Unit, modifier: Modifier = Modifie
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = ImageVector.vectorResource(R.drawable.ic_chevron_small_right_24),
|
imageVector = ImageVector.vectorResource(R.drawable.ic_chevron_small_right_24),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = TangemTheme.colors2.graphic.neutral.tertiaryConstant,
|
tint = TangemTheme.colors3.icon.secondary,
|
||||||
modifier = Modifier.layoutId(TangemRowLayoutId.TAIL),
|
modifier = Modifier.layoutId(TangemRowLayoutId.TAIL),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -116,9 +116,9 @@ private fun WalletNFTItemContent(state: WalletNFTItemUM.Content, onClick: () ->
|
||||||
}
|
}
|
||||||
Text(
|
Text(
|
||||||
text = stringResourceSafe(R.string.nft_wallet_title),
|
text = stringResourceSafe(R.string.nft_wallet_title),
|
||||||
style = TangemTheme.typography2.bodySemibold16.applyBladeBrush(
|
style = TangemTheme.typography3.body.medium.applyBladeBrush(
|
||||||
isEnabled = state.isFlickering,
|
isEnabled = state.isFlickering,
|
||||||
textColor = TangemTheme.colors2.text.neutral.primary,
|
textColor = TangemTheme.colors3.text.primary,
|
||||||
),
|
),
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
|
@ -132,9 +132,9 @@ private fun WalletNFTItemContent(state: WalletNFTItemUM.Content, onClick: () ->
|
||||||
state.allAssetsCount,
|
state.allAssetsCount,
|
||||||
state.collectionsCount,
|
state.collectionsCount,
|
||||||
),
|
),
|
||||||
style = TangemTheme.typography2.captionSemibold12.applyBladeBrush(
|
style = TangemTheme.typography3.caption.medium.applyBladeBrush(
|
||||||
isEnabled = state.isFlickering,
|
isEnabled = state.isFlickering,
|
||||||
textColor = TangemTheme.colors2.text.neutral.secondary,
|
textColor = TangemTheme.colors3.text.secondary,
|
||||||
),
|
),
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
|
@ -145,7 +145,7 @@ private fun WalletNFTItemContent(state: WalletNFTItemUM.Content, onClick: () ->
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = ImageVector.vectorResource(R.drawable.ic_chevron_small_right_24),
|
imageVector = ImageVector.vectorResource(R.drawable.ic_chevron_small_right_24),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
tint = TangemTheme.colors2.graphic.neutral.tertiaryConstant,
|
tint = TangemTheme.colors3.icon.secondary,
|
||||||
modifier = Modifier.layoutId(TangemRowLayoutId.TAIL),
|
modifier = Modifier.layoutId(TangemRowLayoutId.TAIL),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -173,8 +173,8 @@ private fun WalletNFTItemFailed(modifier: Modifier = Modifier) {
|
||||||
}
|
}
|
||||||
Text(
|
Text(
|
||||||
text = stringResourceSafe(R.string.nft_wallet_title),
|
text = stringResourceSafe(R.string.nft_wallet_title),
|
||||||
style = TangemTheme.typography2.bodySemibold16,
|
style = TangemTheme.typography3.body.medium,
|
||||||
color = TangemTheme.colors2.text.neutral.primary,
|
color = TangemTheme.colors3.text.primary,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|
@ -183,8 +183,8 @@ private fun WalletNFTItemFailed(modifier: Modifier = Modifier) {
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = stringResourceSafe(R.string.nft_wallet_unable_to_load),
|
text = stringResourceSafe(R.string.nft_wallet_unable_to_load),
|
||||||
style = TangemTheme.typography2.captionSemibold12,
|
style = TangemTheme.typography3.caption.medium,
|
||||||
color = TangemTheme.colors2.text.neutral.secondary,
|
color = TangemTheme.colors3.text.secondary,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|
@ -207,7 +207,7 @@ private fun WalletNFTItemLoading(modifier: Modifier = Modifier) {
|
||||||
.layoutId(TangemRowLayoutId.HEAD),
|
.layoutId(TangemRowLayoutId.HEAD),
|
||||||
)
|
)
|
||||||
TextShimmer(
|
TextShimmer(
|
||||||
style = TangemTheme.typography2.bodySemibold16,
|
style = TangemTheme.typography3.body.medium,
|
||||||
radius = TangemTheme.dimens2.x25,
|
radius = TangemTheme.dimens2.x25,
|
||||||
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|
@ -216,7 +216,7 @@ private fun WalletNFTItemLoading(modifier: Modifier = Modifier) {
|
||||||
.width(TangemTheme.dimens.size110),
|
.width(TangemTheme.dimens.size110),
|
||||||
)
|
)
|
||||||
TextShimmer(
|
TextShimmer(
|
||||||
style = TangemTheme.typography2.captionSemibold12,
|
style = TangemTheme.typography3.caption.medium,
|
||||||
radius = TangemTheme.dimens2.x25,
|
radius = TangemTheme.dimens2.x25,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.layoutId(TangemRowLayoutId.START_BOTTOM)
|
.layoutId(TangemRowLayoutId.START_BOTTOM)
|
||||||
|
|
@ -251,7 +251,7 @@ private fun BoxScope.CollectionsPreviews(previews: ImmutableList<CollectionPrevi
|
||||||
},
|
},
|
||||||
error = {
|
error = {
|
||||||
Box(
|
Box(
|
||||||
modifier = previewModifier.background(TangemTheme.colors2.surface.level2),
|
modifier = previewModifier.background(TangemTheme.colors3.bg.primary),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
|
|
@ -259,10 +259,9 @@ private fun BoxScope.CollectionsPreviews(previews: ImmutableList<CollectionPrevi
|
||||||
}
|
}
|
||||||
is CollectionPreview.More -> {
|
is CollectionPreview.More -> {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = previewModifier
|
modifier = previewModifier.background(TangemTheme.colors3.bg.primary),
|
||||||
.background(TangemTheme.colors2.surface.level2),
|
|
||||||
imageVector = ImageVector.vectorResource(R.drawable.ic_nft_preview_more_16),
|
imageVector = ImageVector.vectorResource(R.drawable.ic_nft_preview_more_16),
|
||||||
tint = TangemTheme.colors2.text.neutral.secondary,
|
tint = TangemTheme.colors3.text.secondary,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -289,7 +288,7 @@ private fun BoxScope.previews2Modifiers(): List<Modifier> = listOf(
|
||||||
.zIndex(1f)
|
.zIndex(1f)
|
||||||
.padding(TangemTheme.dimens2.x0_5)
|
.padding(TangemTheme.dimens2.x0_5)
|
||||||
.clip(RoundedCornerShape(topStart = 10.dp))
|
.clip(RoundedCornerShape(topStart = 10.dp))
|
||||||
.background(TangemTheme.colors2.surface.level3)
|
.background(TangemTheme.colors3.bg.secondary)
|
||||||
.padding(start = TangemTheme.dimens2.x0_5, top = TangemTheme.dimens2.x0_5)
|
.padding(start = TangemTheme.dimens2.x0_5, top = TangemTheme.dimens2.x0_5)
|
||||||
.size(TangemTheme.dimens2.x6)
|
.size(TangemTheme.dimens2.x6)
|
||||||
.clip(RoundedCornerShape(TangemTheme.dimens2.x2))
|
.clip(RoundedCornerShape(TangemTheme.dimens2.x2))
|
||||||
|
|
@ -307,7 +306,7 @@ private fun BoxScope.previews3Modifiers(): List<Modifier> = listOf(
|
||||||
.zIndex(1f)
|
.zIndex(1f)
|
||||||
.padding(top = 10.dp, end = 1.dp)
|
.padding(top = 10.dp, end = 1.dp)
|
||||||
.clip(RoundedCornerShape(8.dp))
|
.clip(RoundedCornerShape(8.dp))
|
||||||
.background(TangemTheme.colors2.surface.level3)
|
.background(TangemTheme.colors3.bg.secondary)
|
||||||
.padding(TangemTheme.dimens2.x0_5)
|
.padding(TangemTheme.dimens2.x0_5)
|
||||||
.size(18.dp)
|
.size(18.dp)
|
||||||
.clip(RoundedCornerShape(6.dp))
|
.clip(RoundedCornerShape(6.dp))
|
||||||
|
|
@ -347,7 +346,7 @@ private fun Preview_WalletNFTItem(@PreviewParameter(WalletNFTItemProvider2::clas
|
||||||
WalletNFTItem2(
|
WalletNFTItem2(
|
||||||
state = state,
|
state = state,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.background(TangemTheme.colors2.surface.level1),
|
.background(TangemTheme.colors3.bg.primary),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ internal fun WalletBalance(
|
||||||
walletBalanceUM = walletBalanceUM,
|
walletBalanceUM = walletBalanceUM,
|
||||||
isBalanceHidden = isBalanceHidden,
|
isBalanceHidden = isBalanceHidden,
|
||||||
)
|
)
|
||||||
SpacerH(TangemTheme.dimens2.x3)
|
SpacerH(12.dp)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.onGloballyPositioned { coordinates ->
|
modifier = Modifier.onGloballyPositioned { coordinates ->
|
||||||
val rawBottomPx = coordinates.boundsInRoot().bottom
|
val rawBottomPx = coordinates.boundsInRoot().bottom
|
||||||
|
|
@ -113,9 +113,9 @@ internal fun WalletBalance(
|
||||||
SubtitleRow(walletBalanceUM = walletBalanceUM)
|
SubtitleRow(walletBalanceUM = walletBalanceUM)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SpacerH(TangemTheme.dimens2.x2)
|
SpacerH(8.dp)
|
||||||
ActionButtons(buttons = hapticButtons, modifier = Modifier.fillMaxWidth())
|
ActionButtons(buttons = hapticButtons, modifier = Modifier.fillMaxWidth())
|
||||||
SpacerH(TangemTheme.dimens2.x6)
|
SpacerH(24.dp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -140,20 +140,20 @@ private fun SubtitleRow(walletBalanceUM: WalletBalanceUM, modifier: Modifier = M
|
||||||
is WalletAdditionalInfo.Content.SyncProgress -> {
|
is WalletAdditionalInfo.Content.SyncProgress -> {
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x1_5),
|
horizontalArrangement = Arrangement.spacedBy(6.dp),
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = resourceReference(
|
text = resourceReference(
|
||||||
id = R.string.initial_wallet_sync_restore_progress,
|
id = R.string.initial_wallet_sync_restore_progress,
|
||||||
formatArgs = wrappedList(content.progressPercent),
|
formatArgs = wrappedList(content.progressPercent),
|
||||||
).resolveReference(),
|
).resolveReference(),
|
||||||
style = TangemTheme.typography2.bodyRegular14,
|
style = TangemTheme.typography3.subheading.medium,
|
||||||
color = TangemTheme.colors2.text.neutral.tertiary,
|
color = TangemTheme.colors3.text.secondary,
|
||||||
modifier = Modifier.testTag(MainScreenTestTags.SYNC_PROGRESS_TEXT),
|
modifier = Modifier.testTag(MainScreenTestTags.SYNC_PROGRESS_TEXT),
|
||||||
)
|
)
|
||||||
CircularProgressIndicator(
|
CircularProgressIndicator(
|
||||||
modifier = Modifier.size(19.dp),
|
modifier = Modifier.size(19.dp),
|
||||||
color = TangemTheme.colors2.graphic.neutral.primary,
|
color = TangemTheme.colors3.icon.secondary,
|
||||||
strokeWidth = 2.dp,
|
strokeWidth = 2.dp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -161,12 +161,12 @@ private fun SubtitleRow(walletBalanceUM: WalletBalanceUM, modifier: Modifier = M
|
||||||
else -> {
|
else -> {
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x1),
|
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = walletBalanceUM.name,
|
text = walletBalanceUM.name,
|
||||||
style = TangemTheme.typography2.bodyRegular14,
|
style = TangemTheme.typography3.subheading.medium,
|
||||||
color = TangemTheme.colors2.text.neutral.tertiary,
|
color = TangemTheme.colors3.text.secondary,
|
||||||
modifier = Modifier.testTag(MainScreenTestTags.CARD_TITLE),
|
modifier = Modifier.testTag(MainScreenTestTags.CARD_TITLE),
|
||||||
)
|
)
|
||||||
TangemDeviceIcon(
|
TangemDeviceIcon(
|
||||||
|
|
@ -194,36 +194,36 @@ private fun Balance(walletBalanceUM: WalletBalanceUM, isBalanceHidden: Boolean,
|
||||||
when (balanceUM) {
|
when (balanceUM) {
|
||||||
is WalletBalanceUM.Content -> Text(
|
is WalletBalanceUM.Content -> Text(
|
||||||
text = balanceUM.balance.orMaskWithStars(isBalanceHidden).resolveAnnotatedReference(),
|
text = balanceUM.balance.orMaskWithStars(isBalanceHidden).resolveAnnotatedReference(),
|
||||||
style = TangemTheme.typography2.titleRegular44.applyBladeBrush(
|
style = TangemTheme.typography3.display.medium.applyBladeBrush(
|
||||||
isEnabled = balanceUM.isBalanceFlickering,
|
isEnabled = balanceUM.isBalanceFlickering,
|
||||||
textColor = TangemTheme.colors2.text.neutral.primary,
|
textColor = TangemTheme.colors3.text.primary,
|
||||||
),
|
),
|
||||||
color = TangemTheme.colors2.text.neutral.primary,
|
color = TangemTheme.colors3.text.primary,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
autoSize = TextAutoSize.StepBased(
|
autoSize = TextAutoSize.StepBased(
|
||||||
minFontSize = TangemTheme.typography2.bodySemibold15.fontSize,
|
minFontSize = TangemTheme.typography3.body.medium.fontSize,
|
||||||
maxFontSize = TangemTheme.typography2.titleRegular44.fontSize,
|
maxFontSize = TangemTheme.typography3.display.medium.fontSize,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
is WalletBalanceUM.Error -> Text(
|
is WalletBalanceUM.Error -> Text(
|
||||||
text = StringsSigns.DASH_SIGN,
|
text = StringsSigns.DASH_SIGN,
|
||||||
style = TangemTheme.typography2.titleRegular44,
|
style = TangemTheme.typography3.display.medium,
|
||||||
color = TangemTheme.colors2.text.neutral.primary,
|
color = TangemTheme.colors3.text.primary,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
autoSize = TextAutoSize.StepBased(
|
autoSize = TextAutoSize.StepBased(
|
||||||
minFontSize = TangemTheme.typography2.bodySemibold15.fontSize,
|
minFontSize = TangemTheme.typography3.body.medium.fontSize,
|
||||||
maxFontSize = TangemTheme.typography2.titleRegular44.fontSize,
|
maxFontSize = TangemTheme.typography3.display.medium.fontSize,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
is WalletBalanceUM.Loading -> TextShimmer(
|
is WalletBalanceUM.Loading -> TextShimmer(
|
||||||
text = "123456",
|
text = "123456",
|
||||||
style = TangemTheme.typography2.titleRegular44,
|
style = TangemTheme.typography3.display.medium,
|
||||||
radius = TangemTheme.dimens2.x25,
|
radius = 100.dp,
|
||||||
)
|
)
|
||||||
is WalletBalanceUM.Empty -> TextPlaceholder(
|
is WalletBalanceUM.Empty -> TextPlaceholder(
|
||||||
textStyle = TangemTheme.typography2.titleRegular44,
|
textStyle = TangemTheme.typography3.display.medium,
|
||||||
width = 200.dp,
|
width = 200.dp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -244,7 +244,7 @@ private fun WalletBalance_Preview(
|
||||||
behavior = rememberTangemExitUntilCollapsedScrollBehavior(),
|
behavior = rememberTangemExitUntilCollapsedScrollBehavior(),
|
||||||
buttons = params.actionsList,
|
buttons = params.actionsList,
|
||||||
isBalanceHidden = false,
|
isBalanceHidden = false,
|
||||||
modifier = Modifier.background(TangemTheme.colors2.surface.level1),
|
modifier = Modifier.background(TangemTheme.colors3.bg.secondary),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,10 +46,10 @@ internal fun WalletListContent(
|
||||||
promoBannersBlockComponent: PromoBannersBlockComponent? = null,
|
promoBannersBlockComponent: PromoBannersBlockComponent? = null,
|
||||||
walletId: String? = null,
|
walletId: String? = null,
|
||||||
) {
|
) {
|
||||||
val containerColor = TangemTheme.colors2.surface.level1
|
val containerColor = TangemTheme.colors3.bg.primary
|
||||||
|
|
||||||
val movableItemModifier = Modifier.padding(horizontal = TangemTheme.dimens2.x3)
|
val movableItemModifier = Modifier.padding(horizontal = 12.dp)
|
||||||
val itemModifier = movableItemModifier.padding(top = TangemTheme.dimens2.x3)
|
val itemModifier = movableItemModifier.padding(top = 12.dp)
|
||||||
|
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
modifier = modifier.testTag(MainScreenTestTags.SCREEN_CONTAINER),
|
modifier = modifier.testTag(MainScreenTestTags.SCREEN_CONTAINER),
|
||||||
|
|
@ -73,7 +73,7 @@ internal fun WalletListContent(
|
||||||
item(key = "PromoBannersBlock") {
|
item(key = "PromoBannersBlock") {
|
||||||
component.ContentWithPadding(
|
component.ContentWithPadding(
|
||||||
horizontalItemPadding = 12.dp,
|
horizontalItemPadding = 12.dp,
|
||||||
modifier = Modifier.padding(top = TangemTheme.dimens2.x3),
|
modifier = Modifier.padding(top = 12.dp),
|
||||||
walletId = walletId,
|
walletId = walletId,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,41 +1,41 @@
|
||||||
package com.tangem.feature.wallet.presentation.wallet.ui.components.common
|
package com.tangem.feature.wallet.presentation.wallet.ui.components.common
|
||||||
|
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import androidx.compose.animation.core.animateFloatAsState
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.statusBarsPadding
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
|
||||||
import androidx.compose.material3.*
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.graphics.lerp
|
|
||||||
import androidx.compose.ui.platform.testTag
|
import androidx.compose.ui.platform.testTag
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import com.tangem.core.ui.components.haze.hazeEffectTangem
|
import androidx.compose.ui.unit.dp
|
||||||
import com.tangem.core.ui.ds.topbar.TangemTopBar
|
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||||
import com.tangem.core.ui.ds.topbar.TangemTopBarActionContent
|
|
||||||
import com.tangem.core.ui.ds.topbar.TangemTopBarActionUM
|
import com.tangem.core.ui.ds.topbar.TangemTopBarActionUM
|
||||||
import com.tangem.core.ui.ds.topbar.collapsing.TangemCollapsingAppBarBehavior
|
import com.tangem.core.ui.ds.topbar.collapsing.TangemCollapsingAppBarBehavior
|
||||||
import com.tangem.core.ui.ds.topbar.collapsing.rememberTangemExitUntilCollapsedScrollBehavior
|
import com.tangem.core.ui.ds.topbar.collapsing.rememberTangemExitUntilCollapsedScrollBehavior
|
||||||
|
import com.tangem.core.ui.ds2.button.TangemButton
|
||||||
|
import com.tangem.core.ui.ds2.topnavigation.TangemNavigationText
|
||||||
|
import com.tangem.core.ui.ds2.topnavigation.TangemTopNavigation
|
||||||
import com.tangem.core.ui.extensions.TextReference
|
import com.tangem.core.ui.extensions.TextReference
|
||||||
import com.tangem.core.ui.extensions.orMaskWithStars
|
import com.tangem.core.ui.extensions.orMaskWithStars
|
||||||
import com.tangem.core.ui.extensions.stringReference
|
import com.tangem.core.ui.extensions.stringReference
|
||||||
import com.tangem.core.ui.haptic.TangemHapticEffect
|
import com.tangem.core.ui.haptic.TangemHapticEffect
|
||||||
import com.tangem.core.ui.res.*
|
import com.tangem.core.ui.res.LocalHapticManager
|
||||||
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
|
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||||
import com.tangem.core.ui.test.MainScreenTestTags
|
import com.tangem.core.ui.test.MainScreenTestTags
|
||||||
import com.tangem.feature.wallet.impl.R
|
import com.tangem.feature.wallet.impl.R
|
||||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTopBarConfig
|
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTopBarConfig
|
||||||
import dev.chrisbanes.haze.HazeProgressive
|
|
||||||
import dev.chrisbanes.haze.HazeTint
|
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
||||||
private const val VISIBILITY_THRESHOLD = 0.5f
|
private const val VISIBILITY_THRESHOLD = 0.5f
|
||||||
|
private val BRAND_ICON_SLOT_SIZE = 44.dp
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wallet screen collapsing top bar
|
* Wallet screen collapsing top bar
|
||||||
|
|
@ -53,76 +53,54 @@ internal fun WalletTopBar(
|
||||||
behavior: TangemCollapsingAppBarBehavior,
|
behavior: TangemCollapsingAppBarBehavior,
|
||||||
) {
|
) {
|
||||||
val hapticManager = LocalHapticManager.current
|
val hapticManager = LocalHapticManager.current
|
||||||
Surface(
|
val isWrappedBalanceShown by remember {
|
||||||
color = Color.Unspecified,
|
derivedStateOf { behavior.state.collapsedFraction > VISIBILITY_THRESHOLD }
|
||||||
contentColor = Color.Unspecified,
|
}
|
||||||
modifier = Modifier.hazeEffectTangemTopBar(behavior),
|
|
||||||
) {
|
|
||||||
val isWrappedBalanceShown by remember {
|
|
||||||
derivedStateOf { behavior.state.collapsedFraction > VISIBILITY_THRESHOLD }
|
|
||||||
}
|
|
||||||
|
|
||||||
val wrappedBalance = remember(walletBalance, isWrappedBalanceShown, isBalanceHidden) {
|
val wrappedBalance = remember(walletBalance, isWrappedBalanceShown, isBalanceHidden) {
|
||||||
walletBalance?.orMaskWithStars(isBalanceHidden).takeIf { isWrappedBalanceShown }
|
walletBalance?.orMaskWithStars(isBalanceHidden).takeIf { isWrappedBalanceShown }
|
||||||
}
|
}
|
||||||
|
|
||||||
TangemTopBar(
|
TangemTopNavigation(
|
||||||
title = wrappedBalance,
|
modifier = Modifier.testTag(MainScreenTestTags.TOP_BAR),
|
||||||
startContent = {
|
contentAlign = TangemTopNavigation.ContentAlign.Center,
|
||||||
TangemTopBarActionContent(
|
startButton = {
|
||||||
TangemTopBarActionUM(
|
// Non-clickable brand mark, sized to align with the trailing action buttons.
|
||||||
iconRes = R.drawable.ic_tangem_24,
|
Box(modifier = Modifier.size(BRAND_ICON_SLOT_SIZE), contentAlignment = Alignment.Center) {
|
||||||
isActionable = false,
|
Icon(
|
||||||
),
|
painter = painterResource(id = R.drawable.ic_tangem_24),
|
||||||
|
contentDescription = null,
|
||||||
|
tint = TangemTheme.colors3.icon.primary,
|
||||||
)
|
)
|
||||||
},
|
}
|
||||||
endContent = {
|
},
|
||||||
Row(
|
endButtonsGroup = if (topBarConfig.endActions.isNotEmpty()) {
|
||||||
modifier = Modifier
|
{
|
||||||
.clip(CircleShape)
|
topBarConfig.endActions.forEach { action ->
|
||||||
.background(
|
TangemButton(
|
||||||
lerp(
|
variant = TangemButton.Variant.Ghost,
|
||||||
start = Color.Transparent,
|
size = TangemButton.Size.X11,
|
||||||
stop = TangemTheme.colors2.button.backgroundSecondary,
|
iconStart = TangemIconUM.Icon(iconRes = action.iconRes),
|
||||||
fraction = behavior.state.collapsedFraction,
|
isEnabled = action.isActionable && action.onClick != null,
|
||||||
),
|
onClick = {
|
||||||
),
|
hapticManager.perform(TangemHapticEffect.View.ContextClick)
|
||||||
) {
|
action.onClick?.invoke()
|
||||||
topBarConfig.endActions.forEach { action ->
|
},
|
||||||
TangemTopBarActionContent(
|
modifier = Modifier.testTag(MainScreenTestTags.MORE_BUTTON),
|
||||||
action.copy(
|
)
|
||||||
onClick = action.onClick?.let { onClick ->
|
|
||||||
{
|
|
||||||
hapticManager.perform(TangemHapticEffect.View.ContextClick)
|
|
||||||
onClick()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
modifier = Modifier.testTag(MainScreenTestTags.MORE_BUTTON),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
modifier = Modifier
|
} else {
|
||||||
.statusBarsPadding()
|
null
|
||||||
.testTag(MainScreenTestTags.TOP_BAR),
|
},
|
||||||
)
|
contentColumn = {
|
||||||
}
|
AnimatedVisibility(visible = wrappedBalance != null) {
|
||||||
}
|
wrappedBalance?.let { balance ->
|
||||||
|
TangemNavigationText(text = balance, role = TangemNavigationText.Role.Title)
|
||||||
@Composable
|
}
|
||||||
private fun Modifier.hazeEffectTangemTopBar(behavior: TangemCollapsingAppBarBehavior): Modifier {
|
}
|
||||||
val rootBackground by LocalRootBackgroundColor.current
|
},
|
||||||
val intensity by animateFloatAsState(targetValue = behavior.state.collapsedFraction * 2f)
|
)
|
||||||
|
|
||||||
return hazeEffectTangem {
|
|
||||||
fallbackTint = HazeTint(rootBackground.copy(alpha = intensity / 2))
|
|
||||||
progressive = HazeProgressive.verticalGradient(
|
|
||||||
startIntensity = intensity,
|
|
||||||
endIntensity = 0f,
|
|
||||||
preferPerformance = true,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// region Preview
|
// region Preview
|
||||||
|
|
|
||||||
|
|
@ -40,9 +40,6 @@ import com.tangem.core.ui.components.tokenlist.NON_CONTENT_TOKENS_LIST_KEY
|
||||||
import com.tangem.core.ui.components.tokenlist.TokenListItem
|
import com.tangem.core.ui.components.tokenlist.TokenListItem
|
||||||
import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM
|
import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM
|
||||||
import com.tangem.core.ui.decorations.roundedShapeItemDecoration
|
import com.tangem.core.ui.decorations.roundedShapeItemDecoration
|
||||||
import com.tangem.core.ui.ds.button.SecondaryTangemButton
|
|
||||||
import com.tangem.core.ui.ds.button.TangemButtonShape
|
|
||||||
import com.tangem.core.ui.ds.button.TangemButtonSize
|
|
||||||
import com.tangem.core.ui.ds.image.TangemIcon
|
import com.tangem.core.ui.ds.image.TangemIcon
|
||||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||||
import com.tangem.core.ui.ds.row.header.TangemHeaderRow
|
import com.tangem.core.ui.ds.row.header.TangemHeaderRow
|
||||||
|
|
@ -51,6 +48,7 @@ import com.tangem.core.ui.ds.row.internal.TangemRowTailUM
|
||||||
import com.tangem.core.ui.ds.row.token.TangemTokenRow
|
import com.tangem.core.ui.ds.row.token.TangemTokenRow
|
||||||
import com.tangem.core.ui.ds.row.token.TangemTokenRowUM
|
import com.tangem.core.ui.ds.row.token.TangemTokenRowUM
|
||||||
import com.tangem.core.ui.ds.row.token.internal.TokenRowTitle
|
import com.tangem.core.ui.ds.row.token.internal.TokenRowTitle
|
||||||
|
import com.tangem.core.ui.ds2.button.TangemButton
|
||||||
import com.tangem.core.ui.extensions.*
|
import com.tangem.core.ui.extensions.*
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.core.ui.test.MainScreenTestTags
|
import com.tangem.core.ui.test.MainScreenTestTags
|
||||||
|
|
@ -159,13 +157,13 @@ private fun LazyListScope.tokenItem(
|
||||||
val itemModifier = modifier
|
val itemModifier = modifier
|
||||||
.testTag(MainScreenTestTags.TOKEN_LIST_ITEM)
|
.testTag(MainScreenTestTags.TOKEN_LIST_ITEM)
|
||||||
.semantics { lazyListItemPosition = index }
|
.semantics { lazyListItemPosition = index }
|
||||||
.padding(top = if (index == 0) TangemTheme.dimens2.x3 else 0.dp)
|
.padding(top = if (index == 0) 12.dp else 0.dp)
|
||||||
.roundedShapeItemDecoration(
|
.roundedShapeItemDecoration(
|
||||||
radius = 18.dp,
|
radius = 18.dp,
|
||||||
currentIndex = index,
|
currentIndex = index,
|
||||||
addDefaultPadding = false,
|
addDefaultPadding = false,
|
||||||
lastIndex = lastIndex,
|
lastIndex = lastIndex,
|
||||||
backgroundColor = TangemTheme.colors2.surface.level3,
|
backgroundColor = TangemTheme.colors3.bg.secondary,
|
||||||
)
|
)
|
||||||
|
|
||||||
var position by remember { mutableStateOf(Offset.Zero) }
|
var position by remember { mutableStateOf(Offset.Zero) }
|
||||||
|
|
@ -261,11 +259,11 @@ private fun LazyListScope.portfolioItem(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.animateItem(fadeInSpec = null, placementSpec = null, fadeOutSpec = null)
|
.animateItem(fadeInSpec = null, placementSpec = null, fadeOutSpec = null)
|
||||||
.roundedShapeItemDecoration(
|
.roundedShapeItemDecoration(
|
||||||
radius = if (listItem.isExpanded) TangemTheme.dimens2.x6 else TangemTheme.dimens2.x5,
|
radius = if (listItem.isExpanded) 24.dp else 20.dp,
|
||||||
currentIndex = tokenIndex + 1,
|
currentIndex = tokenIndex + 1,
|
||||||
addDefaultPadding = false,
|
addDefaultPadding = false,
|
||||||
lastIndex = lastIndex,
|
lastIndex = lastIndex,
|
||||||
backgroundColor = TangemTheme.colors2.surface.level3,
|
backgroundColor = TangemTheme.colors3.bg.secondary,
|
||||||
),
|
),
|
||||||
visible = listItem.isExpanded,
|
visible = listItem.isExpanded,
|
||||||
) {
|
) {
|
||||||
|
|
@ -327,15 +325,15 @@ private fun LazyListScope.accountItem(
|
||||||
)
|
)
|
||||||
|
|
||||||
val portfolioModifier = modifier
|
val portfolioModifier = modifier
|
||||||
.padding(top = if (index != 0) TangemTheme.dimens2.x2 else TangemTheme.dimens2.x3)
|
.padding(top = if (index != 0) 8.dp else 12.dp)
|
||||||
.testTag(MainScreenTestTags.ACCOUNT_LIST_ITEM)
|
.testTag(MainScreenTestTags.ACCOUNT_LIST_ITEM)
|
||||||
.semantics { lazyListItemPosition = index }
|
.semantics { lazyListItemPosition = index }
|
||||||
.roundedShapeItemDecoration(
|
.roundedShapeItemDecoration(
|
||||||
currentIndex = 0,
|
currentIndex = 0,
|
||||||
radius = if (listItem.isExpanded) TangemTheme.dimens2.x6 else TangemTheme.dimens2.x5,
|
radius = if (listItem.isExpanded) 24.dp else 20.dp,
|
||||||
addDefaultPadding = false,
|
addDefaultPadding = false,
|
||||||
lastIndex = effectiveLastIndex,
|
lastIndex = effectiveLastIndex,
|
||||||
backgroundColor = TangemTheme.colors2.surface.level3,
|
backgroundColor = TangemTheme.colors3.bg.secondary,
|
||||||
)
|
)
|
||||||
if (listItem.isCollapsable) {
|
if (listItem.isCollapsable) {
|
||||||
PortfolioRowItem(
|
PortfolioRowItem(
|
||||||
|
|
@ -422,7 +420,7 @@ internal fun PortfolioRowItem(
|
||||||
}
|
}
|
||||||
|
|
||||||
val iconBoxSize = when (headIcon) {
|
val iconBoxSize = when (headIcon) {
|
||||||
is TangemIconUM.Empty -> TangemTheme.dimens2.x9
|
is TangemIconUM.Empty -> 36.dp
|
||||||
else -> size.toBoxSize()
|
else -> size.toBoxSize()
|
||||||
}
|
}
|
||||||
TangemIcon(
|
TangemIcon(
|
||||||
|
|
@ -444,8 +442,8 @@ internal fun PortfolioRowItem(
|
||||||
animationSpec = tween(durationMillis = 350),
|
animationSpec = tween(durationMillis = 350),
|
||||||
)
|
)
|
||||||
|
|
||||||
val startStyle = TangemTheme.typography2.captionSemibold12
|
val startStyle = TangemTheme.typography3.caption.medium
|
||||||
val stopStyle = TangemTheme.typography2.bodySemibold16
|
val stopStyle = TangemTheme.typography3.body.medium
|
||||||
|
|
||||||
val textStyle by remember(animationFraction.value) {
|
val textStyle by remember(animationFraction.value) {
|
||||||
derivedStateOf { lerp(startStyle, stopStyle, animationFraction.value) }
|
derivedStateOf { lerp(startStyle, stopStyle, animationFraction.value) }
|
||||||
|
|
@ -509,7 +507,7 @@ private fun LazyListScope.nonContentItem(modifier: Modifier = Modifier) {
|
||||||
NonContentItemContent(
|
NonContentItemContent(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.animateItem(fadeInSpec = null, fadeOutSpec = null)
|
.animateItem(fadeInSpec = null, fadeOutSpec = null)
|
||||||
.padding(top = TangemTheme.dimens.spacing96),
|
.padding(top = 96.dp),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -521,7 +519,7 @@ private fun LazyListScope.nonContentItem2(onEmptyClick: () -> Unit, modifier: Mo
|
||||||
) {
|
) {
|
||||||
NonContentItemContentV2(
|
NonContentItemContentV2(
|
||||||
onClick = onEmptyClick,
|
onClick = onEmptyClick,
|
||||||
textColor = TangemTheme.colors2.text.neutral.tertiary,
|
textColor = TangemTheme.colors3.text.secondary,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.animateItem(fadeInSpec = null, fadeOutSpec = null)
|
.animateItem(fadeInSpec = null, fadeOutSpec = null)
|
||||||
.padding(top = 46.dp),
|
.padding(top = 46.dp),
|
||||||
|
|
@ -540,17 +538,17 @@ private fun LazyListScope.nonContentAccountItem(listItem: TokensListItemUM2.Port
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.animateItem(fadeInSpec = null, placementSpec = null, fadeOutSpec = null)
|
.animateItem(fadeInSpec = null, placementSpec = null, fadeOutSpec = null)
|
||||||
.roundedShapeItemDecoration(
|
.roundedShapeItemDecoration(
|
||||||
radius = if (listItem.isExpanded) TangemTheme.dimens2.x6 else TangemTheme.dimens2.x5,
|
radius = if (listItem.isExpanded) 24.dp else 20.dp,
|
||||||
addDefaultPadding = false,
|
addDefaultPadding = false,
|
||||||
currentIndex = 1,
|
currentIndex = 1,
|
||||||
lastIndex = 1,
|
lastIndex = 1,
|
||||||
backgroundColor = TangemTheme.colors2.surface.level3,
|
backgroundColor = TangemTheme.colors3.bg.secondary,
|
||||||
),
|
),
|
||||||
visible = listItem.isExpanded,
|
visible = listItem.isExpanded,
|
||||||
) {
|
) {
|
||||||
NonContentItemContentV2(
|
NonContentItemContentV2(
|
||||||
modifier = Modifier.padding(vertical = 36.dp),
|
modifier = Modifier.padding(vertical = 36.dp),
|
||||||
textColor = TangemTheme.colors2.text.neutral.secondary,
|
textColor = TangemTheme.colors3.text.secondary,
|
||||||
onClick = listItem.onEmptyClick,
|
onClick = listItem.onEmptyClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -566,23 +564,23 @@ internal fun NonContentItemContentV2(textColor: Color, modifier: Modifier = Modi
|
||||||
Icon(
|
Icon(
|
||||||
painter = painterResource(id = R.drawable.ic_empty_64),
|
painter = painterResource(id = R.drawable.ic_empty_64),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
modifier = Modifier.size(size = TangemTheme.dimens2.x16),
|
modifier = Modifier.size(64.dp),
|
||||||
tint = TangemTheme.colors2.graphic.neutral.quaternary,
|
tint = TangemTheme.colors3.icon.tertiary,
|
||||||
)
|
)
|
||||||
SpacerH(TangemTheme.dimens2.x5)
|
SpacerH(20.dp)
|
||||||
Text(
|
Text(
|
||||||
text = stringResourceSafe(id = R.string.main_empty_tokens_list_message),
|
text = stringResourceSafe(id = R.string.main_empty_tokens_list_message),
|
||||||
modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing48),
|
modifier = Modifier.padding(horizontal = 48.dp),
|
||||||
color = textColor,
|
color = textColor,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
style = TangemTheme.typography2.bodyRegular14,
|
style = TangemTheme.typography3.subheading.medium,
|
||||||
)
|
)
|
||||||
SpacerH(TangemTheme.dimens2.x4)
|
SpacerH(16.dp)
|
||||||
SecondaryTangemButton(
|
TangemButton(
|
||||||
text = resourceReference(id = R.string.common_add_tokens),
|
text = resourceReference(id = R.string.common_add_tokens),
|
||||||
|
variant = TangemButton.Variant.Secondary,
|
||||||
|
size = TangemButton.Size.X9,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
size = TangemButtonSize.X8,
|
|
||||||
shape = TangemButtonShape.Rounded,
|
|
||||||
modifier = Modifier.testTag(MainScreenTestTags.EMPTY_TOKENS_ADD_BUTTON),
|
modifier = Modifier.testTag(MainScreenTestTags.EMPTY_TOKENS_ADD_BUTTON),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,6 @@ internal class YieldSupplyToEarnBlockConverter : Converter<YieldSupplyUM, EarnBl
|
||||||
text = resourceReference(CoreResR.string.yield_module_transaction_enter),
|
text = resourceReference(CoreResR.string.yield_module_transaction_enter),
|
||||||
style = EarnBlockUM.TitleUM.Style.Large,
|
style = EarnBlockUM.TitleUM.Style.Large,
|
||||||
tone = EarnBlockUM.TitleUM.Tone.Primary,
|
tone = EarnBlockUM.TitleUM.Tone.Primary,
|
||||||
iconUM = buildTitleIcon(value),
|
|
||||||
),
|
),
|
||||||
subtitleUM = EarnBlockUM.SubtitleUM.Text(
|
subtitleUM = EarnBlockUM.SubtitleUM.Text(
|
||||||
text = combinedReference(
|
text = combinedReference(
|
||||||
|
|
@ -89,18 +88,19 @@ internal class YieldSupplyToEarnBlockConverter : Converter<YieldSupplyUM, EarnBl
|
||||||
style = EarnBlockUM.SubtitleUM.Style.Small,
|
style = EarnBlockUM.SubtitleUM.Style.Small,
|
||||||
tone = EarnBlockUM.SubtitleUM.Tone.Accent,
|
tone = EarnBlockUM.SubtitleUM.Tone.Accent,
|
||||||
),
|
),
|
||||||
trailingUM = EarnBlockUM.TrailingUM.Button(
|
trailingUM = buildTrailing(value),
|
||||||
text = resourceReference(CoreResR.string.details_title),
|
|
||||||
style = EarnBlockUM.TrailingUM.Button.Style.Secondary,
|
|
||||||
),
|
|
||||||
onClick = value.onClick,
|
onClick = value.onClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildTitleIcon(value: YieldSupplyUM.Content): EarnBlockUM.TitleUM.IconUM? = when {
|
private fun buildTrailing(value: YieldSupplyUM.Content): EarnBlockUM.TrailingUM = when {
|
||||||
value.shouldShowWarningIcon -> EarnBlockUM.TitleUM.IconUM(tone = EarnBlockUM.TitleUM.IconTone.Warning)
|
value.shouldShowWarningIcon -> EarnBlockUM.TrailingUM.StatusIcon(
|
||||||
value.shouldShowInfoIcon -> EarnBlockUM.TitleUM.IconUM(tone = EarnBlockUM.TitleUM.IconTone.Info)
|
tone = EarnBlockUM.TrailingUM.StatusIcon.Tone.Warning,
|
||||||
else -> null
|
)
|
||||||
|
value.shouldShowInfoIcon -> EarnBlockUM.TrailingUM.StatusIcon(
|
||||||
|
tone = EarnBlockUM.TrailingUM.StatusIcon.Tone.Info,
|
||||||
|
)
|
||||||
|
else -> EarnBlockUM.TrailingUM.Chevron
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildProcessingEnter(): EarnBlockUM.Content {
|
private fun buildProcessingEnter(): EarnBlockUM.Content {
|
||||||
|
|
@ -109,17 +109,18 @@ internal class YieldSupplyToEarnBlockConverter : Converter<YieldSupplyUM, EarnBl
|
||||||
backgroundUM = EarnBlockUM.BackgroundUM.Surface,
|
backgroundUM = EarnBlockUM.BackgroundUM.Surface,
|
||||||
iconUM = EarnBlockUM.IconUM.Glowing(iconRes = CoreUiR.drawable.ic_yield_40),
|
iconUM = EarnBlockUM.IconUM.Glowing(iconRes = CoreUiR.drawable.ic_yield_40),
|
||||||
titleUM = EarnBlockUM.TitleUM(
|
titleUM = EarnBlockUM.TitleUM(
|
||||||
text = resourceReference(CoreResR.string.common_yield_mode),
|
text = combinedReference(
|
||||||
|
resourceReference(CoreResR.string.common_yield_mode),
|
||||||
|
stringReference(StringsSigns.WHITE_SPACE),
|
||||||
|
resourceReference(CoreResR.string.common_enabling),
|
||||||
|
),
|
||||||
style = EarnBlockUM.TitleUM.Style.Large,
|
style = EarnBlockUM.TitleUM.Style.Large,
|
||||||
tone = EarnBlockUM.TitleUM.Tone.Primary,
|
tone = EarnBlockUM.TitleUM.Tone.Primary,
|
||||||
),
|
),
|
||||||
subtitleUM = EarnBlockUM.SubtitleUM.Text(
|
subtitleUM = null,
|
||||||
text = resourceReference(CoreResR.string.common_enabling),
|
trailingUM = EarnBlockUM.TrailingUM.Loader(
|
||||||
style = EarnBlockUM.SubtitleUM.Style.Small,
|
tone = EarnBlockUM.TrailingUM.Loader.LoaderTone.Positive,
|
||||||
tone = EarnBlockUM.SubtitleUM.Tone.Accent,
|
|
||||||
loader = EarnBlockUM.SubtitleUM.Loader(tone = EarnBlockUM.SubtitleUM.LoaderTone.Positive),
|
|
||||||
),
|
),
|
||||||
trailingUM = null,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,19 +128,23 @@ internal class YieldSupplyToEarnBlockConverter : Converter<YieldSupplyUM, EarnBl
|
||||||
return EarnBlockUM.Content(
|
return EarnBlockUM.Content(
|
||||||
type = EarnBlockUM.Type.YieldSupply,
|
type = EarnBlockUM.Type.YieldSupply,
|
||||||
backgroundUM = EarnBlockUM.BackgroundUM.Surface,
|
backgroundUM = EarnBlockUM.BackgroundUM.Surface,
|
||||||
iconUM = EarnBlockUM.IconUM.Plain(iconRes = CoreUiR.drawable.ic_yield_disabling_40),
|
iconUM = EarnBlockUM.IconUM.Glowing(
|
||||||
|
iconRes = CoreUiR.drawable.ic_yield_40,
|
||||||
|
tone = EarnBlockUM.IconUM.Tone.Warning,
|
||||||
|
),
|
||||||
titleUM = EarnBlockUM.TitleUM(
|
titleUM = EarnBlockUM.TitleUM(
|
||||||
text = resourceReference(CoreResR.string.common_yield_mode),
|
text = combinedReference(
|
||||||
|
resourceReference(CoreResR.string.common_yield_mode),
|
||||||
|
stringReference(StringsSigns.WHITE_SPACE),
|
||||||
|
resourceReference(CoreResR.string.common_disabling),
|
||||||
|
),
|
||||||
style = EarnBlockUM.TitleUM.Style.Large,
|
style = EarnBlockUM.TitleUM.Style.Large,
|
||||||
tone = EarnBlockUM.TitleUM.Tone.Primary,
|
tone = EarnBlockUM.TitleUM.Tone.Primary,
|
||||||
),
|
),
|
||||||
subtitleUM = EarnBlockUM.SubtitleUM.Text(
|
subtitleUM = null,
|
||||||
text = resourceReference(CoreResR.string.common_disabling),
|
trailingUM = EarnBlockUM.TrailingUM.Loader(
|
||||||
style = EarnBlockUM.SubtitleUM.Style.Small,
|
tone = EarnBlockUM.TrailingUM.Loader.LoaderTone.Muted,
|
||||||
tone = EarnBlockUM.SubtitleUM.Tone.Disabled,
|
|
||||||
loader = EarnBlockUM.SubtitleUM.Loader(tone = EarnBlockUM.SubtitleUM.LoaderTone.Muted),
|
|
||||||
),
|
),
|
||||||
trailingUM = null,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,10 +1,6 @@
|
||||||
package com.tangem.features.yield.supply.impl.main.model
|
package com.tangem.features.yield.supply.impl.main.model
|
||||||
|
|
||||||
import arrow.core.Option
|
import arrow.core.*
|
||||||
import arrow.core.left
|
|
||||||
import arrow.core.none
|
|
||||||
import arrow.core.right
|
|
||||||
import arrow.core.some
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import com.tangem.common.routing.AppRoute
|
import com.tangem.common.routing.AppRoute
|
||||||
import com.tangem.common.routing.AppRouter
|
import com.tangem.common.routing.AppRouter
|
||||||
|
|
@ -34,27 +30,13 @@ import com.tangem.domain.yield.supply.models.YieldMarketToken
|
||||||
import com.tangem.domain.yield.supply.models.YieldSupplyPendingStatus
|
import com.tangem.domain.yield.supply.models.YieldSupplyPendingStatus
|
||||||
import com.tangem.domain.yield.supply.promo.usecase.GetBoostedApyUseCase
|
import com.tangem.domain.yield.supply.promo.usecase.GetBoostedApyUseCase
|
||||||
import com.tangem.domain.yield.supply.promo.usecase.IsYieldBoostPromoEnabledForTokenUseCase
|
import com.tangem.domain.yield.supply.promo.usecase.IsYieldBoostPromoEnabledForTokenUseCase
|
||||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyActivateUseCase
|
import com.tangem.domain.yield.supply.usecase.*
|
||||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyDeactivateUseCase
|
|
||||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyEnterStatusFlowUseCase
|
|
||||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyEnterStatusUseCase
|
|
||||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetDustMinAmountUseCase
|
|
||||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetTokenStatusUseCase
|
|
||||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyIsAvailableUseCase
|
|
||||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyMinAmountUseCase
|
|
||||||
import com.tangem.features.yield.supply.api.YieldSupplyComponent
|
import com.tangem.features.yield.supply.api.YieldSupplyComponent
|
||||||
import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics
|
import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics
|
||||||
import com.tangem.features.yield.supply.impl.YieldBoostStoryPreloader
|
import com.tangem.features.yield.supply.impl.YieldBoostStoryPreloader
|
||||||
import com.tangem.features.yield.supply.impl.main.entity.YieldSupplyUM
|
import com.tangem.features.yield.supply.impl.main.entity.YieldSupplyUM
|
||||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||||
import io.mockk.coEvery
|
import io.mockk.*
|
||||||
import io.mockk.coVerify
|
|
||||||
import io.mockk.every
|
|
||||||
import io.mockk.mockk
|
|
||||||
import io.mockk.mockkObject
|
|
||||||
import io.mockk.slot
|
|
||||||
import io.mockk.unmockkObject
|
|
||||||
import io.mockk.verify
|
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.flowOf
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
|
@ -258,7 +240,9 @@ internal class YieldSupplyModelTest {
|
||||||
assertThat(approveEvent.blockchain).isEqualTo("Ethereum")
|
assertThat(approveEvent.blockchain).isEqualTo("Ethereum")
|
||||||
|
|
||||||
val block = model.uiState.value as EarnBlockUM.Content
|
val block = model.uiState.value as EarnBlockUM.Content
|
||||||
assertThat(block.titleUM.iconUM?.tone).isEqualTo(EarnBlockUM.TitleUM.IconTone.Warning)
|
assertThat(block.trailingUM).isEqualTo(
|
||||||
|
EarnBlockUM.TrailingUM.StatusIcon(tone = EarnBlockUM.TrailingUM.StatusIcon.Tone.Warning),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -290,7 +274,9 @@ internal class YieldSupplyModelTest {
|
||||||
assertThat(legacy.shouldShowInfoIcon).isTrue()
|
assertThat(legacy.shouldShowInfoIcon).isTrue()
|
||||||
assertThat(legacy.shouldShowWarningIcon).isFalse()
|
assertThat(legacy.shouldShowWarningIcon).isFalse()
|
||||||
val block = model.uiState.value as EarnBlockUM.Content
|
val block = model.uiState.value as EarnBlockUM.Content
|
||||||
assertThat(block.titleUM.iconUM?.tone).isEqualTo(EarnBlockUM.TitleUM.IconTone.Info)
|
assertThat(block.trailingUM).isEqualTo(
|
||||||
|
EarnBlockUM.TrailingUM.StatusIcon(tone = EarnBlockUM.TrailingUM.StatusIcon.Tone.Info),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -54,9 +54,7 @@ internal class YieldSupplyToEarnBlockConverterTest {
|
||||||
assertThat(earnBlock.titleUM.tone).isEqualTo(EarnBlockUM.TitleUM.Tone.Primary)
|
assertThat(earnBlock.titleUM.tone).isEqualTo(EarnBlockUM.TitleUM.Tone.Primary)
|
||||||
assertThat((earnBlock.subtitleUM as EarnBlockUM.SubtitleUM.Text).tone)
|
assertThat((earnBlock.subtitleUM as EarnBlockUM.SubtitleUM.Text).tone)
|
||||||
.isEqualTo(EarnBlockUM.SubtitleUM.Tone.Accent)
|
.isEqualTo(EarnBlockUM.SubtitleUM.Tone.Accent)
|
||||||
assertThat(earnBlock.trailingUM).isInstanceOf(EarnBlockUM.TrailingUM.Button::class.java)
|
assertThat(earnBlock.trailingUM).isEqualTo(EarnBlockUM.TrailingUM.Chevron)
|
||||||
val button = earnBlock.trailingUM as EarnBlockUM.TrailingUM.Button
|
|
||||||
assertThat(button.isEnabled).isTrue()
|
|
||||||
assertThat(earnBlock.onClick).isNotNull()
|
assertThat(earnBlock.onClick).isNotNull()
|
||||||
earnBlock.onClick?.invoke()
|
earnBlock.onClick?.invoke()
|
||||||
assertThat(clicked).isTrue()
|
assertThat(clicked).isTrue()
|
||||||
|
|
@ -71,7 +69,9 @@ internal class YieldSupplyToEarnBlockConverterTest {
|
||||||
assertThat(earnBlock.type).isEqualTo(EarnBlockUM.Type.YieldSupply)
|
assertThat(earnBlock.type).isEqualTo(EarnBlockUM.Type.YieldSupply)
|
||||||
assertThat(earnBlock.backgroundUM).isEqualTo(EarnBlockUM.BackgroundUM.Surface)
|
assertThat(earnBlock.backgroundUM).isEqualTo(EarnBlockUM.BackgroundUM.Surface)
|
||||||
assertThat(earnBlock.iconUM).isInstanceOf(EarnBlockUM.IconUM.Glowing::class.java)
|
assertThat(earnBlock.iconUM).isInstanceOf(EarnBlockUM.IconUM.Glowing::class.java)
|
||||||
assertThat(earnBlock.trailingUM).isNull()
|
assertThat(earnBlock.trailingUM).isEqualTo(
|
||||||
|
EarnBlockUM.TrailingUM.Loader(tone = EarnBlockUM.TrailingUM.Loader.LoaderTone.Positive),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -82,12 +82,19 @@ internal class YieldSupplyToEarnBlockConverterTest {
|
||||||
val earnBlock = result as EarnBlockUM.Content
|
val earnBlock = result as EarnBlockUM.Content
|
||||||
assertThat(earnBlock.type).isEqualTo(EarnBlockUM.Type.YieldSupply)
|
assertThat(earnBlock.type).isEqualTo(EarnBlockUM.Type.YieldSupply)
|
||||||
assertThat(earnBlock.backgroundUM).isEqualTo(EarnBlockUM.BackgroundUM.Surface)
|
assertThat(earnBlock.backgroundUM).isEqualTo(EarnBlockUM.BackgroundUM.Surface)
|
||||||
assertThat(earnBlock.iconUM).isInstanceOf(EarnBlockUM.IconUM.Plain::class.java)
|
assertThat(earnBlock.iconUM).isEqualTo(
|
||||||
assertThat(earnBlock.trailingUM).isNull()
|
EarnBlockUM.IconUM.Glowing(
|
||||||
|
iconRes = com.tangem.core.ui.R.drawable.ic_yield_40,
|
||||||
|
tone = EarnBlockUM.IconUM.Tone.Warning,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
assertThat(earnBlock.trailingUM).isEqualTo(
|
||||||
|
EarnBlockUM.TrailingUM.Loader(tone = EarnBlockUM.TrailingUM.Loader.LoaderTone.Muted),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `GIVEN Content with showWarningIcon WHEN convert THEN title Warning Icon`() {
|
fun `GIVEN Content with showWarningIcon WHEN convert THEN trailing Warning StatusIcon`() {
|
||||||
val content = YieldSupplyUM.Content(
|
val content = YieldSupplyUM.Content(
|
||||||
apy = "5.1",
|
apy = "5.1",
|
||||||
title = stringReference("Yield Mode"),
|
title = stringReference("Yield Mode"),
|
||||||
|
|
@ -102,13 +109,13 @@ internal class YieldSupplyToEarnBlockConverterTest {
|
||||||
|
|
||||||
assertThat(result).isInstanceOf(EarnBlockUM.Content::class.java)
|
assertThat(result).isInstanceOf(EarnBlockUM.Content::class.java)
|
||||||
val earnBlock = result as EarnBlockUM.Content
|
val earnBlock = result as EarnBlockUM.Content
|
||||||
assertThat(earnBlock.titleUM.iconUM).isNotNull()
|
assertThat(earnBlock.trailingUM).isEqualTo(
|
||||||
assertThat(earnBlock.titleUM.iconUM?.tone).isEqualTo(EarnBlockUM.TitleUM.IconTone.Warning)
|
EarnBlockUM.TrailingUM.StatusIcon(tone = EarnBlockUM.TrailingUM.StatusIcon.Tone.Warning),
|
||||||
assertThat(earnBlock.trailingUM).isInstanceOf(EarnBlockUM.TrailingUM.Button::class.java)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `GIVEN Content with showInfoIcon WHEN convert THEN title Info Icon`() {
|
fun `GIVEN Content with showInfoIcon WHEN convert THEN trailing Info StatusIcon`() {
|
||||||
val content = YieldSupplyUM.Content(
|
val content = YieldSupplyUM.Content(
|
||||||
apy = "5.1",
|
apy = "5.1",
|
||||||
title = stringReference("Yield Mode"),
|
title = stringReference("Yield Mode"),
|
||||||
|
|
@ -123,9 +130,9 @@ internal class YieldSupplyToEarnBlockConverterTest {
|
||||||
|
|
||||||
assertThat(result).isInstanceOf(EarnBlockUM.Content::class.java)
|
assertThat(result).isInstanceOf(EarnBlockUM.Content::class.java)
|
||||||
val earnBlock = result as EarnBlockUM.Content
|
val earnBlock = result as EarnBlockUM.Content
|
||||||
assertThat(earnBlock.titleUM.iconUM).isNotNull()
|
assertThat(earnBlock.trailingUM).isEqualTo(
|
||||||
assertThat(earnBlock.titleUM.iconUM?.tone).isEqualTo(EarnBlockUM.TitleUM.IconTone.Info)
|
EarnBlockUM.TrailingUM.StatusIcon(tone = EarnBlockUM.TrailingUM.StatusIcon.Tone.Info),
|
||||||
assertThat(earnBlock.trailingUM).isInstanceOf(EarnBlockUM.TrailingUM.Button::class.java)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -143,8 +150,9 @@ internal class YieldSupplyToEarnBlockConverterTest {
|
||||||
val result = converter.convert(content)
|
val result = converter.convert(content)
|
||||||
|
|
||||||
val earnBlock = result as EarnBlockUM.Content
|
val earnBlock = result as EarnBlockUM.Content
|
||||||
assertThat(earnBlock.titleUM.iconUM).isNotNull()
|
assertThat(earnBlock.trailingUM).isEqualTo(
|
||||||
assertThat(earnBlock.titleUM.iconUM?.tone).isEqualTo(EarnBlockUM.TitleUM.IconTone.Warning)
|
EarnBlockUM.TrailingUM.StatusIcon(tone = EarnBlockUM.TrailingUM.StatusIcon.Tone.Warning),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue