Updated on 2026-08-14
This commit is contained in:
parent
fa948bd91a
commit
6369a3f33a
11 changed files with 544 additions and 30 deletions
|
|
@ -0,0 +1,78 @@
|
|||
package com.tangem.core.ui.components.atoms.radiobutton
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.drawscope.Stroke
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
|
||||
/**
|
||||
* [Radio button](https://www.figma.com/design/14ISV23YB1yVW1uNVwqrKv/Android?node-id=101-119&t=FH84ljLBk1vmGAei-4)
|
||||
*
|
||||
* @param isSelected Whether the radio button is selected
|
||||
* @param onClick Called when the user clicks the button
|
||||
* @param modifier Modifier to be applied to the button
|
||||
*/
|
||||
@Composable
|
||||
fun TangemRadioButton(isSelected: Boolean, onClick: () -> Unit, modifier: Modifier = Modifier) {
|
||||
Box(
|
||||
modifier = modifier.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(bounded = false, radius = TangemTheme.dimens.size16),
|
||||
onClick = onClick,
|
||||
),
|
||||
) {
|
||||
val color = TangemTheme.colors.stroke.secondary
|
||||
val radius = with(LocalDensity.current) { TangemTheme.dimens.size9.toPx() }
|
||||
val width = with(LocalDensity.current) { TangemTheme.dimens.size2.toPx() }
|
||||
Canvas(
|
||||
modifier = Modifier
|
||||
.size(TangemTheme.dimens.size24)
|
||||
.padding(TangemTheme.dimens.spacing2),
|
||||
) {
|
||||
drawCircle(
|
||||
color = color,
|
||||
radius = radius,
|
||||
style = Stroke(width),
|
||||
)
|
||||
}
|
||||
AnimatedVisibility(
|
||||
visible = isSelected,
|
||||
label = "Radio button animation",
|
||||
modifier = modifier
|
||||
.size(TangemTheme.dimens.size24),
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_check_circle_24),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors.control.checked,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// region Preview
|
||||
@Preview(showBackground = true)
|
||||
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun TangemRadioButton_Preview() {
|
||||
var isSelected by remember { mutableStateOf(false) }
|
||||
TangemThemePreview {
|
||||
TangemRadioButton(isSelected, onClick = { isSelected = !isSelected })
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
|
|
@ -5,7 +5,6 @@ import androidx.compose.foundation.background
|
|||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.material3.Icon
|
||||
|
|
@ -14,18 +13,15 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import coil.compose.SubcomposeAsyncImage
|
||||
import coil.request.ImageRequest
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.SpacerWMax
|
||||
import com.tangem.core.ui.components.currency.tokenicon.LoadingIcon
|
||||
import com.tangem.core.ui.components.inputrow.inner.DividerContainer
|
||||
import com.tangem.core.ui.components.inputrow.inner.InputRowAsyncImage
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
|
|
@ -63,7 +59,7 @@ fun InputRowBestRate(
|
|||
modifier = Modifier
|
||||
.padding(TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
InnerIcon(imageUrl = imageUrl)
|
||||
InputRowAsyncImage(imageUrl = imageUrl, modifier = Modifier.size(TangemTheme.dimens.spacing40))
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(start = TangemTheme.dimens.spacing12),
|
||||
|
|
@ -131,29 +127,6 @@ private fun InnerTitle(title: TextReference, titleExtra: TextReference, showTag:
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun InnerIcon(imageUrl: String) {
|
||||
SubcomposeAsyncImage(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size40),
|
||||
model = ImageRequest.Builder(context = LocalContext.current)
|
||||
.data(imageUrl)
|
||||
.crossfade(enable = true)
|
||||
.allowHardware(enable = false)
|
||||
.build(),
|
||||
loading = { LoadingIcon() },
|
||||
error = {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.background(
|
||||
color = TangemTheme.colors.background.tertiary,
|
||||
shape = CircleShape,
|
||||
),
|
||||
)
|
||||
},
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
|
||||
//region preview
|
||||
@Preview
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
package com.tangem.core.ui.components.inputrow
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import com.tangem.core.ui.components.inputrow.inner.InputRowAsyncImage
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveAnnotatedReference
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
||||
@Composable
|
||||
internal fun InputRowImageBase(
|
||||
subtitle: TextReference,
|
||||
caption: TextReference,
|
||||
imageUrl: String,
|
||||
modifier: Modifier = Modifier,
|
||||
subtitleColor: Color = TangemTheme.colors.text.primary1,
|
||||
captionColor: Color = TangemTheme.colors.text.tertiary,
|
||||
extraContent: @Composable RowScope.() -> Unit = {},
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = modifier,
|
||||
) {
|
||||
InputRowAsyncImage(
|
||||
imageUrl = imageUrl,
|
||||
modifier = Modifier
|
||||
.size(TangemTheme.dimens.spacing36)
|
||||
.padding(vertical = TangemTheme.dimens.size1),
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(start = TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
Text(
|
||||
text = subtitle.resolveReference(),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = subtitleColor,
|
||||
)
|
||||
Text(
|
||||
text = caption.resolveAnnotatedReference(),
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = captionColor,
|
||||
modifier = Modifier.padding(top = TangemTheme.dimens.spacing2),
|
||||
)
|
||||
}
|
||||
extraContent()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package com.tangem.core.ui.components.inputrow
|
||||
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
||||
/**
|
||||
* Input row component with selector
|
||||
* [Input Row Image](https://www.figma.com/design/14ISV23YB1yVW1uNVwqrKv/Android?node-id=2100-842&t=hoBXmDX8NeLrp4p6-4)
|
||||
*
|
||||
* @param subtitle subtitle text
|
||||
* @param caption caption text
|
||||
* @param imageUrl icon to load
|
||||
* @param modifier modifier
|
||||
* @param subtitleColor subtitle text color
|
||||
* @param captionColor caption text color
|
||||
*/
|
||||
@Composable
|
||||
fun InputRowImageChevron(
|
||||
subtitle: TextReference,
|
||||
caption: TextReference,
|
||||
imageUrl: String,
|
||||
modifier: Modifier = Modifier,
|
||||
subtitleColor: Color = TangemTheme.colors.text.primary1,
|
||||
captionColor: Color = TangemTheme.colors.text.tertiary,
|
||||
) {
|
||||
InputRowImageBase(
|
||||
subtitle = subtitle,
|
||||
caption = caption,
|
||||
imageUrl = imageUrl,
|
||||
modifier = modifier,
|
||||
subtitleColor = subtitleColor,
|
||||
captionColor = captionColor,
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_chevron_right_24),
|
||||
tint = TangemTheme.colors.icon.informative,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
package com.tangem.core.ui.components.inputrow
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.atoms.radiobutton.TangemRadioButton
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.annotatedReference
|
||||
import com.tangem.core.ui.extensions.combinedReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
* Input row component with selector
|
||||
* [Input Row Image](https://www.figma.com/design/14ISV23YB1yVW1uNVwqrKv/Android?node-id=2772-905&t=FH84ljLBk1vmGAei-4)
|
||||
*
|
||||
* @param subtitle subtitle text
|
||||
* @param caption caption text
|
||||
* @param imageUrl icon to load
|
||||
* @param onSelect callback when selected
|
||||
* @param modifier modifier
|
||||
* @param subtitleColor subtitle text color
|
||||
* @param captionColor caption text color
|
||||
* @param isSelected true if selected
|
||||
*/
|
||||
@Composable
|
||||
fun InputRowImageSelector(
|
||||
subtitle: TextReference,
|
||||
caption: TextReference,
|
||||
imageUrl: String,
|
||||
onSelect: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
subtitleColor: Color = TangemTheme.colors.text.primary1,
|
||||
captionColor: Color = TangemTheme.colors.text.tertiary,
|
||||
isSelected: Boolean = false,
|
||||
) {
|
||||
InputRowImageBase(
|
||||
subtitle = subtitle,
|
||||
caption = caption,
|
||||
imageUrl = imageUrl,
|
||||
subtitleColor = subtitleColor,
|
||||
captionColor = captionColor,
|
||||
modifier = modifier
|
||||
.clickable(
|
||||
onClick = onSelect,
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(),
|
||||
)
|
||||
.padding(TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
TangemRadioButton(isSelected = isSelected, isEnabled = false, onClick = onSelect)
|
||||
}
|
||||
}
|
||||
|
||||
//region preview
|
||||
@Preview
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun InputRowImageSelectorPreview(
|
||||
@PreviewParameter(InputRowImageSelectorPreviewDataProvider::class) data: InputRowImageSelectorPreviewData,
|
||||
) {
|
||||
TangemThemePreview {
|
||||
InputRowImageSelector(
|
||||
modifier = Modifier.background(TangemTheme.colors.background.action),
|
||||
subtitle = data.subtitle,
|
||||
caption = combinedReference(
|
||||
resourceReference(R.string.staking_details_apr),
|
||||
annotatedReference(
|
||||
buildAnnotatedString {
|
||||
append(" ")
|
||||
withStyle(style = SpanStyle(color = TangemTheme.colors.text.accent)) {
|
||||
append(
|
||||
BigDecimalFormatter.formatPercent(BigDecimal.ZERO, true),
|
||||
)
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
imageUrl = "",
|
||||
isSelected = false,
|
||||
onSelect = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private data class InputRowImageSelectorPreviewData(
|
||||
val subtitle: TextReference,
|
||||
val caption: TextReference,
|
||||
val showDivider: Boolean,
|
||||
val actionIconRes: Int?,
|
||||
val isSelected: Boolean,
|
||||
)
|
||||
|
||||
private class InputRowImageSelectorPreviewDataProvider :
|
||||
PreviewParameterProvider<InputRowImageSelectorPreviewData> {
|
||||
override val values: Sequence<InputRowImageSelectorPreviewData>
|
||||
get() = sequenceOf(
|
||||
InputRowImageSelectorPreviewData(
|
||||
subtitle = TextReference.Str("subtitle"),
|
||||
caption = TextReference.Str("caption"),
|
||||
actionIconRes = null,
|
||||
showDivider = false,
|
||||
isSelected = false,
|
||||
),
|
||||
InputRowImageSelectorPreviewData(
|
||||
subtitle = TextReference.Str("subtitle"),
|
||||
caption = TextReference.Str("caption"),
|
||||
actionIconRes = R.drawable.ic_chevron_right_24,
|
||||
showDivider = true,
|
||||
isSelected = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
//endregion
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package com.tangem.core.ui.components.inputrow.inner
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import coil.compose.SubcomposeAsyncImage
|
||||
import coil.request.ImageRequest
|
||||
import com.tangem.core.ui.components.currency.tokenicon.LoadingIcon
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
||||
/**
|
||||
* Loads image by url for icon in the input row
|
||||
*
|
||||
* @param imageUrl url of the image
|
||||
* @param modifier modifier
|
||||
*/
|
||||
@Composable
|
||||
internal fun InputRowAsyncImage(imageUrl: String, modifier: Modifier = Modifier) {
|
||||
SubcomposeAsyncImage(
|
||||
modifier = modifier,
|
||||
model = ImageRequest.Builder(context = LocalContext.current)
|
||||
.data(imageUrl)
|
||||
.crossfade(enable = true)
|
||||
.allowHardware(enable = false)
|
||||
.build(),
|
||||
loading = { LoadingIcon() },
|
||||
error = {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.background(
|
||||
color = TangemTheme.colors.background.tertiary,
|
||||
shape = CircleShape,
|
||||
),
|
||||
)
|
||||
},
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
|
|
@ -48,6 +48,13 @@ sealed interface TextReference {
|
|||
*/
|
||||
data class Str(val value: String) : TextReference
|
||||
|
||||
/**
|
||||
* Annotated text
|
||||
*
|
||||
* @property value annotated string
|
||||
*/
|
||||
data class Annotated(val value: AnnotatedString) : TextReference
|
||||
|
||||
/**
|
||||
* Combined reference. It concatenates all [refs].
|
||||
*
|
||||
|
|
@ -83,6 +90,16 @@ fun stringReference(value: String): TextReference {
|
|||
return TextReference.Str(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a [TextReference] using an annotated string value.
|
||||
*
|
||||
* @param value The annotated string value.
|
||||
* @return A [TextReference] representing the provided annotated string value.
|
||||
*/
|
||||
fun annotatedReference(value: AnnotatedString): TextReference {
|
||||
return TextReference.Annotated(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a [TextReference] using a plural string resource ID with count and optional format arguments.
|
||||
*
|
||||
|
|
@ -133,6 +150,7 @@ fun TextReference.resolveReference(): String {
|
|||
}
|
||||
is TextReference.PluralRes -> pluralStringResource(id, count, *formatArgs.toTypedArray())
|
||||
is TextReference.Str -> value
|
||||
is TextReference.Annotated -> value.text
|
||||
is TextReference.Combined -> {
|
||||
buildString {
|
||||
refs.forEach {
|
||||
|
|
@ -155,6 +173,7 @@ fun TextReference.resolveReference(resources: Resources): String {
|
|||
}
|
||||
is TextReference.PluralRes -> resources.getQuantityString(id, count, *formatArgs.toTypedArray())
|
||||
is TextReference.Str -> value
|
||||
is TextReference.Annotated -> value.text
|
||||
is TextReference.Combined -> {
|
||||
buildString {
|
||||
refs.forEach {
|
||||
|
|
@ -180,9 +199,10 @@ fun TextReference.resolveAnnotatedReference(): AnnotatedString {
|
|||
pluralStringResource(id, count, *formatArgs.toTypedArray()),
|
||||
)
|
||||
is TextReference.Str -> formatAnnotated(value)
|
||||
is TextReference.Annotated -> value
|
||||
is TextReference.Combined -> buildAnnotatedString {
|
||||
refs.forEach {
|
||||
append(formatAnnotated(it.resolveReference()))
|
||||
append(it.resolveAnnotatedReference())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -195,6 +215,7 @@ operator fun TextReference.plus(ref: TextReference): TextReference {
|
|||
is TextReference.PluralRes,
|
||||
is TextReference.Res,
|
||||
is TextReference.Str,
|
||||
is TextReference.Annotated,
|
||||
-> TextReference.Combined(refs = wrappedList(this, ref))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ data class TangemDimens internal constructor(
|
|||
val size5: Dp = 5.dp,
|
||||
val size7: Dp = 7.dp,
|
||||
val size8: Dp = 8.dp,
|
||||
val size9: Dp = 9.dp,
|
||||
val size10: Dp = 10.dp,
|
||||
val size11: Dp = 11.dp,
|
||||
val size12: Dp = 12.dp,
|
||||
|
|
|
|||
5
core/ui/src/main/res/drawable/ic_check_circle_24.xml
Normal file
5
core/ui/src/main/res/drawable/ic_check_circle_24.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<path android:fillColor="#1E1E1E" android:pathData="M12,2C6.5,2 2,6.5 2,12C2,17.5 6.5,22 12,22C17.5,22 22,17.5 22,12C22,6.5 17.5,2 12,2ZM10,17L5,12L6.41,10.59L10,14.17L17.59,6.58L19,8L10,17Z"/>
|
||||
|
||||
</vector>
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package com.tangem.features.staking.impl.presentation.state.stub
|
||||
|
||||
import com.tangem.domain.staking.model.Yield
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
||||
|
||||
internal object StakingValidatorStateStub {
|
||||
private val validator = Yield.Validator(
|
||||
address = "address",
|
||||
status = "status",
|
||||
name = "Binance",
|
||||
image = null,
|
||||
website = null,
|
||||
apr = "0.0354".toBigDecimal(),
|
||||
commission = null,
|
||||
stakedBalance = null,
|
||||
votingPower = null,
|
||||
preferred = false,
|
||||
)
|
||||
|
||||
val state = StakingStates.ValidatorState.Data(
|
||||
isPrimaryButtonEnabled = false,
|
||||
validators = listOf(
|
||||
validator,
|
||||
validator.copy(
|
||||
address = "TRONLink",
|
||||
name = "TRONLink",
|
||||
apr = "0.0506".toBigDecimal(),
|
||||
),
|
||||
validator.copy(
|
||||
address = "1inch",
|
||||
name = "1inch",
|
||||
apr = "0.0306".toBigDecimal(),
|
||||
),
|
||||
),
|
||||
selectedValidator = validator,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
package com.tangem.features.staking.impl.presentation.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import com.tangem.core.ui.components.inputrow.InputRowImageSelector
|
||||
import com.tangem.core.ui.components.rows.CornersToRound
|
||||
import com.tangem.core.ui.extensions.annotatedReference
|
||||
import com.tangem.core.ui.extensions.combinedReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.features.staking.impl.R
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
||||
import com.tangem.features.staking.impl.presentation.state.stub.StakingClickIntentsStub
|
||||
import com.tangem.features.staking.impl.presentation.state.stub.StakingValidatorStateStub
|
||||
import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
* Staking screen with validators
|
||||
*/
|
||||
@Composable
|
||||
internal fun StakingValidatorListContent(
|
||||
state: StakingStates.ValidatorState,
|
||||
clickIntents: StakingClickIntents,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
if (state !is StakingStates.ValidatorState.Data) return
|
||||
val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() }
|
||||
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(bottom = bottomBarHeight),
|
||||
modifier = modifier.padding(horizontal = TangemTheme.dimens.spacing16),
|
||||
) {
|
||||
item(key = "HEADER") {
|
||||
Text(
|
||||
text = stringResource(R.string.staking_validator),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clip(CornersToRound.TOP_2.getShape())
|
||||
.background(TangemTheme.colors.background.action)
|
||||
.padding(
|
||||
start = TangemTheme.dimens.spacing12,
|
||||
end = TangemTheme.dimens.spacing12,
|
||||
top = TangemTheme.dimens.spacing12,
|
||||
bottom = TangemTheme.dimens.spacing8,
|
||||
),
|
||||
)
|
||||
}
|
||||
items(
|
||||
count = state.validators.size,
|
||||
key = { state.validators[it] },
|
||||
contentType = { state.validators[it]::class.java },
|
||||
) { index ->
|
||||
val item = state.validators[index]
|
||||
|
||||
InputRowImageSelector(
|
||||
subtitle = stringReference(item.name),
|
||||
caption = combinedReference(
|
||||
resourceReference(R.string.staking_details_apr),
|
||||
annotatedReference(
|
||||
buildAnnotatedString {
|
||||
append(" ")
|
||||
withStyle(style = SpanStyle(color = TangemTheme.colors.text.accent)) {
|
||||
append(
|
||||
BigDecimalFormatter.formatPercent(item.apr ?: BigDecimal.ZERO, true),
|
||||
)
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
imageUrl = item.image.orEmpty(),
|
||||
isSelected = item == state.selectedValidator,
|
||||
onSelect = { clickIntents.onValidatorSelect(item) },
|
||||
modifier = Modifier
|
||||
.clip(
|
||||
if (index == state.validators.lastIndex) {
|
||||
CornersToRound.BOTTOM_2
|
||||
} else {
|
||||
CornersToRound.ZERO
|
||||
}.getShape(),
|
||||
)
|
||||
.background(TangemTheme.colors.background.action),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// region Preview
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun StakingValidatorListContent_Preview(
|
||||
@PreviewParameter(StakingValidatorListContentPreviewProvider::class)
|
||||
data: StakingStates.ValidatorState.Data,
|
||||
) {
|
||||
TangemThemePreview {
|
||||
StakingValidatorListContent(
|
||||
state = data,
|
||||
clickIntents = StakingClickIntentsStub,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class StakingValidatorListContentPreviewProvider : PreviewParameterProvider<StakingStates.ValidatorState.Data> {
|
||||
override val values: Sequence<StakingStates.ValidatorState.Data>
|
||||
get() = sequenceOf(StakingValidatorStateStub.state)
|
||||
}
|
||||
// endregion
|
||||
Loading…
Add table
Add a link
Reference in a new issue