Updated on 2026-08-14

This commit is contained in:
Tangem 2024-10-03 16:13:36 +03:00
commit 1706a25d1a
61 changed files with 717 additions and 347 deletions

View file

@ -24,7 +24,6 @@ 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.TangemColorPalette
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
@ -33,15 +32,17 @@ import com.tangem.core.ui.res.TangemThemePreview
* [Input Row Image](https://www.figma.com/design/14ISV23YB1yVW1uNVwqrKv/Android?node-id=2841-1589&t=u6pOF6lsdpvWLELb-4)
*
* @param subtitle subtitle text
* @param caption caption text
* @param modifier modifier
* @param caption caption text
* @param imageUrl icon to load
* @param iconRes icon resource
* @param subtitleColor subtitle text color
* @param captionColor caption text color
* @param iconTint icon tint
* @param isGrayscaleImage whether to display grayscale image
* @param subtitleEndIconRes icon to show after subtitle
* @param iconEndRes icon to end of row
* @param onImageError composable to show if image loading failed
* @param subtitleExtraContent subtitle extra content
* @param extraContent extra content
*/
@Suppress("LongMethod")
@ -56,10 +57,9 @@ internal fun InputRowImageBase(
captionColor: Color = TangemTheme.colors.text.tertiary,
iconTint: Color = TangemTheme.colors.icon.informative,
isGrayscaleImage: Boolean = false,
@DrawableRes subtitleEndIconRes: Int? = null,
subtitleEndIconTint: Color = TangemColorPalette.Azure,
@DrawableRes iconEndRes: Int? = null,
onImageError: (@Composable () -> Unit)? = null,
subtitleExtraContent: (@Composable RowScope.() -> Unit)? = null,
extraContent: (@Composable RowScope.() -> Unit)? = null,
) {
Row(
@ -100,10 +100,7 @@ internal fun InputRowImageBase(
style = TangemTheme.typography.subtitle2,
color = subtitleColor,
)
SubtitleEndIconRes(
subtitleEndIconRes = subtitleEndIconRes,
subtitleEndIconTint = subtitleEndIconTint,
)
subtitleExtraContent?.invoke(this)
}
if (caption != null) {
Text(
@ -124,23 +121,6 @@ internal fun InputRowImageBase(
}
}
@Composable
private fun RowScope.SubtitleEndIconRes(subtitleEndIconRes: Int?, subtitleEndIconTint: Color) {
AnimatedVisibility(
visible = subtitleEndIconRes != null,
label = "Subtitle end icon visibility animation",
modifier = Modifier.align(Alignment.CenterVertically),
) {
val icon = remember(this) { requireNotNull(subtitleEndIconRes) }
Icon(
painter = rememberVectorPainter(image = ImageVector.vectorResource(id = icon)),
tint = subtitleEndIconTint,
contentDescription = null,
modifier = Modifier.padding(start = TangemTheme.dimens.spacing4),
)
}
}
@Composable
private fun RowScope.InputRowEndIcon(iconRes: Int?) {
AnimatedVisibility(

View file

@ -2,14 +2,21 @@ package com.tangem.core.ui.components.inputrow
import android.content.res.Configuration
import androidx.annotation.DrawableRes
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
@ -17,6 +24,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import com.tangem.core.ui.R
import com.tangem.core.ui.components.atoms.text.EllipsisText
import com.tangem.core.ui.extensions.*
import com.tangem.core.ui.res.TangemColorPalette
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
@ -24,17 +32,19 @@ import com.tangem.core.ui.res.TangemThemePreview
* Input row component with selector
* [Input Row Image](https://www.figma.com/design/14ISV23YB1yVW1uNVwqrKv/Android?node-id=2841-1589&t=u6pOF6lsdpvWLELb-4)
*
* @param title title text
* @param subtitle subtitle text
* @param caption caption text
* @param infoTitle info title text
* @param infoSubtitle info subtitle text
* @param modifier modifier
* @param title title text
* @param caption caption text
* @param infoSubtitle info subtitle text
* @param imageUrl icon to load
* @param iconRes icon resource
* @param subtitleColor subtitle text color
* @param captionColor caption text color
* @param iconTint icon color
* @param isGrayscaleImage whether to display grayscale image
* @param showPendingIcon whether to show pending icon
* @param subtitleEndIconRes subtitle icon to end of row
* @param iconEndRes icon to end of row
* @param onImageError composable to show if image loading failed
*/
@ -78,9 +88,14 @@ fun InputRowImageInfo(
subtitleColor = subtitleColor,
captionColor = captionColor,
isGrayscaleImage = isGrayscaleImage,
subtitleEndIconRes = subtitleEndIconRes,
iconEndRes = iconEndRes,
onImageError = onImageError,
subtitleExtraContent = {
SubtitleEndIconRes(
subtitleEndIconRes = subtitleEndIconRes,
subtitleEndIconTint = TangemColorPalette.Azure,
)
},
) {
Column(
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing2),
@ -120,6 +135,23 @@ fun InputRowImageInfo(
}
}
@Composable
private fun RowScope.SubtitleEndIconRes(subtitleEndIconRes: Int?, subtitleEndIconTint: Color) {
AnimatedVisibility(
visible = subtitleEndIconRes != null,
label = "Subtitle end icon visibility animation",
modifier = Modifier.align(Alignment.CenterVertically),
) {
val icon = remember(this) { requireNotNull(subtitleEndIconRes) }
Icon(
painter = rememberVectorPainter(image = ImageVector.vectorResource(id = icon)),
tint = subtitleEndIconTint,
contentDescription = null,
modifier = Modifier.padding(start = TangemTheme.dimens.spacing4),
)
}
}
// region Preview
@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)

View file

@ -4,6 +4,7 @@ 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.RowScope
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ripple
import androidx.compose.runtime.Composable
@ -40,8 +41,9 @@ import java.math.BigDecimal
* @param subtitleColor subtitle text color
* @param captionColor caption text color
* @param isSelected true if selected
* @param selectorContent selector content
* @param onImageError composable to show if image loading failed
* @param subtitleExtraContent subtitle selector content
* @param selectorContent selector content
*/
@Composable
fun InputRowImageSelector(
@ -54,6 +56,7 @@ fun InputRowImageSelector(
captionColor: Color = TangemTheme.colors.text.tertiary,
isSelected: Boolean = false,
onImageError: (@Composable () -> Unit)? = null,
subtitleExtraContent: (@Composable RowScope.() -> Unit)? = null,
selectorContent: @Composable ((isSelected: Boolean, isEnabled: Boolean, onSelect: () -> Unit) -> Unit),
) {
InputRowImageBase(
@ -63,6 +66,7 @@ fun InputRowImageSelector(
subtitleColor = subtitleColor,
captionColor = captionColor,
onImageError = onImageError,
subtitleExtraContent = subtitleExtraContent,
modifier = modifier
.clickable(
onClick = onSelect,

View file

@ -75,6 +75,7 @@ fun getActiveIconRes(blockchainId: String): Int {
"cyber", "cyber/test" -> R.drawable.img_cyber_22
"sei", "sei/test" -> R.drawable.img_sei_22
"internet-computer" -> R.drawable.img_icp_22
"sui", "sui/test" -> R.drawable.img_sui_22
"energy-web-chain", "energy-web-chain/test" -> R.drawable.img_energy_web_22
"energy-web-x", "energy-web-x/test" -> R.drawable.img_energy_web_22
else -> R.drawable.ic_alert_24
@ -153,6 +154,7 @@ fun getActiveIconResByNetworkId(networkId: String): Int {
"cyber", "cyber/test" -> R.drawable.img_cyber_22
"sei", "sei/test" -> R.drawable.img_sei_22
"internet-computer" -> R.drawable.img_icp_22
"sui", "sui/test" -> R.drawable.img_sui_22
"energy-web-chain", "energy-web-chain/test" -> R.drawable.img_energy_web_22
"energy-web-x", "energy-web-x/test" -> R.drawable.img_energy_web_22
else -> R.drawable.ic_alert_24
@ -228,6 +230,7 @@ fun getActiveIconResByCoinId(coinId: String): Int {
"cyber", "cyber/test" -> R.drawable.img_cyber_22
"sei", "sei/test" -> R.drawable.img_sei_22
"internet-computer" -> R.drawable.img_icp_22
"sui", "sui/test" -> R.drawable.img_sui_22
"energy-web-chain", "energy-web-chain/test" -> R.drawable.img_energy_web_22
"energy-web-x", "energy-web-x/test" -> R.drawable.img_energy_web_22
else -> R.drawable.ic_alert_24
@ -306,6 +309,7 @@ fun getGreyedOutIconRes(blockchainId: String): Int {
"cyber", "cyber/test" -> R.drawable.ic_cyber_22
"sei", "sei/test" -> R.drawable.ic_sei_22
"internet-computer" -> R.drawable.ic_icp_22
"sui", "sui/test" -> R.drawable.ic_sui_22
"energy-web-chain", "energy-web-chain/test" -> R.drawable.ic_energy_web_22
"energy-web-x", "energy-web-x/test" -> R.drawable.ic_energy_web_22
else -> R.drawable.ic_alert_24
@ -384,6 +388,7 @@ fun getGreyedOutIconResByNetworkId(networkId: String): Int {
"cyber", "cyber/test" -> R.drawable.ic_cyber_22
"sei", "sei/test" -> R.drawable.ic_sei_22
"internet-computer" -> R.drawable.ic_icp_22
"sui", "sui/test" -> R.drawable.ic_sui_22
"energy-web-chain", "energy-web-chain/test" -> R.drawable.ic_energy_web_22
"energy-web-x", "energy-web-x/test" -> R.drawable.ic_energy_web_22
else -> R.drawable.ic_alert_24

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="22dp"
android:height="22dp"
android:viewportWidth="22"
android:viewportHeight="22">
<path
android:pathData="M14.8,9.7C15.4,10.5 15.8,11.5 15.8,12.7C15.8,13.8 15.4,14.9 14.7,15.7L14.7,15.8L14.7,15.7C14.6,15.6 14.6,15.5 14.6,15.4C14.3,14 13.2,12.7 11.4,11.7C10.2,11 9.5,10.1 9.3,9.2C9.2,8.6 9.3,8 9.4,7.5C9.6,6.9 9.9,6.5 10.1,6.2L10.8,5.4C10.9,5.2 11.1,5.2 11.2,5.4L14.8,9.7H14.8ZM15.9,8.8L11.2,3.1C11.1,3 10.9,3 10.8,3.1L6.1,8.8L6.1,8.8C5.3,9.9 4.8,11.3 4.8,12.8C4.8,16.2 7.6,19 11,19C14.5,19 17.3,16.2 17.3,12.8C17.3,11.3 16.7,9.9 15.9,8.8L15.9,8.8L15.9,8.8ZM7.3,9.7L7.7,9.1L7.7,9.2C7.7,9.3 7.7,9.4 7.7,9.5C8,10.9 9,12.1 10.6,13C12,13.8 12.8,14.7 13.1,15.7C13.2,16.2 13.2,16.6 13.1,16.9L13.1,17L13.1,17C12.5,17.3 11.8,17.5 11,17.5C8.4,17.5 6.2,15.3 6.2,12.7C6.2,11.5 6.6,10.5 7.3,9.7L7.3,9.7Z"
android:fillColor="#000" />
</vector>

View file

@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="22dp"
android:height="22dp"
android:viewportWidth="22"
android:viewportHeight="22">
<clip-path
android:pathData="M11,0L11,0A11,11 0,0 1,22 11L22,11A11,11 0,0 1,11 22L11,22A11,11 0,0 1,0 11L0,11A11,11 0,0 1,11 0z"/>
<path
android:pathData="M0,0h22v22h-22z"
android:fillColor="#4CA3FF"/>
<path
android:pathData="M14.8,9.7C15.4,10.5 15.8,11.5 15.8,12.7C15.8,13.8 15.4,14.9 14.7,15.7L14.7,15.8L14.7,15.7C14.6,15.6 14.6,15.5 14.6,15.4C14.3,14 13.2,12.7 11.4,11.7C10.2,11 9.5,10.1 9.3,9.2C9.2,8.6 9.3,8 9.4,7.5C9.6,6.9 9.9,6.5 10.1,6.2L10.8,5.4C10.9,5.2 11.1,5.2 11.2,5.4L14.8,9.7H14.8ZM15.9,8.8L11.2,3.1C11.1,3 10.9,3 10.8,3.1L6.1,8.8L6.1,8.8C5.3,9.9 4.8,11.3 4.8,12.8C4.8,16.2 7.6,19 11,19C14.5,19 17.3,16.2 17.3,12.8C17.3,11.3 16.7,9.9 15.9,8.8L15.9,8.8L15.9,8.8ZM7.3,9.7L7.7,9.1L7.7,9.2C7.7,9.3 7.7,9.4 7.7,9.5C8,10.9 9,12.1 10.6,13C12,13.8 12.8,14.7 13.1,15.7C13.2,16.2 13.2,16.6 13.1,16.9L13.1,17L13.1,17C12.5,17.3 11.8,17.5 11,17.5C8.4,17.5 6.2,15.3 6.2,12.7C6.2,11.5 6.6,10.5 7.3,9.7L7.3,9.7Z"
android:fillColor="#ffffff" />
</vector>