Updated on 2026-08-14
This commit is contained in:
commit
c401577838
25 changed files with 810 additions and 108 deletions
|
|
@ -4,8 +4,12 @@ import androidx.compose.foundation.layout.padding
|
|||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.notifications.Notification
|
||||
import com.tangem.core.ui.components.notifications.NotificationConfig
|
||||
import com.tangem.core.ui.ds.message.TangemMessage
|
||||
import com.tangem.core.ui.ds.message.TangemMessageUM
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
|
|
@ -44,4 +48,66 @@ fun LazyListScope.notifications(
|
|||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a list of notifications using TangemMessage composables.
|
||||
*
|
||||
* @param notifications List of NotificationConfig objects to be displayed.
|
||||
* @param contentColor Color to be used for the content of the notifications.
|
||||
* @param modifier Optional Modifier for the notifications.
|
||||
* @param hasPaddingAbove Boolean indicating whether to add padding above the first notification.
|
||||
*/
|
||||
fun LazyListScope.notifications2(
|
||||
notifications: ImmutableList<NotificationConfig>,
|
||||
contentColor: Color,
|
||||
modifier: Modifier = Modifier,
|
||||
hasPaddingAbove: Boolean = false,
|
||||
) {
|
||||
itemsIndexed(
|
||||
items = notifications,
|
||||
key = { index, item -> item.title?.hashCode()?.plus(index) ?: index },
|
||||
contentType = { _, item -> item::class.java },
|
||||
itemContent = { i, item ->
|
||||
val topPadding = if (i == 0 && hasPaddingAbove) 0.dp else 12.dp
|
||||
TangemMessage(
|
||||
config = item,
|
||||
contentColor = contentColor,
|
||||
modifier = modifier
|
||||
.padding(top = topPadding)
|
||||
.animateItem(),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a list of notifications using TangemMessage composables.
|
||||
*
|
||||
* @param notifications List of TangemMessageUM objects to be displayed.
|
||||
* @param contentColor Color to be used for the content of the notifications.
|
||||
* @param modifier Optional Modifier for the notifications.
|
||||
* @param hasPaddingAbove Boolean indicating whether to add padding above the first notification.
|
||||
*/
|
||||
fun LazyListScope.notifications(
|
||||
notifications: ImmutableList<TangemMessageUM>,
|
||||
contentColor: Color,
|
||||
modifier: Modifier = Modifier,
|
||||
hasPaddingAbove: Boolean = false,
|
||||
) {
|
||||
itemsIndexed(
|
||||
items = notifications,
|
||||
key = { _, item -> item.id },
|
||||
contentType = { _, item -> item::class.java },
|
||||
itemContent = { i, item ->
|
||||
val topPadding = if (i == 0 && hasPaddingAbove) TangemTheme.dimens2.x0 else TangemTheme.dimens2.x2
|
||||
TangemMessage(
|
||||
messageUM = item,
|
||||
contentColor = contentColor,
|
||||
modifier = modifier
|
||||
.padding(top = topPadding)
|
||||
.animateItem(),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -24,6 +24,7 @@ import androidx.compose.ui.unit.dp
|
|||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.ds.badge.TangemBadgeSize.*
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.clickableSingle
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
|
@ -48,6 +49,7 @@ fun TangemBadge(badgeUM: TangemBadgeUM, modifier: Modifier = Modifier) {
|
|||
color = badgeUM.color,
|
||||
type = badgeUM.type,
|
||||
iconPosition = badgeUM.iconPosition,
|
||||
onClick = badgeUM.onClick,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
|
@ -64,6 +66,7 @@ fun TangemBadge(badgeUM: TangemBadgeUM, modifier: Modifier = Modifier) {
|
|||
* @param color [TangemBadgeColor] defining the color scheme of the badge.
|
||||
* @param type [TangemBadgeType] defining the style of the badge.
|
||||
* @param iconPosition [TangemBadgeIconPosition] defining icon position of the badge.
|
||||
* @param onClick Lambda to be invoked when the badge is clicked (optional).
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
|
@ -77,6 +80,7 @@ fun TangemBadge(
|
|||
color: TangemBadgeColor = TangemBadgeColor.Gray,
|
||||
type: TangemBadgeType = TangemBadgeType.Solid,
|
||||
iconPosition: TangemBadgeIconPosition = TangemBadgeIconPosition.Start,
|
||||
onClick: (() -> Unit)? = null,
|
||||
) {
|
||||
val iconColor = getIconColor(type = type, color = color)
|
||||
Row(
|
||||
|
|
@ -86,7 +90,8 @@ fun TangemBadge(
|
|||
.heightIn(min = size.toHeightDp())
|
||||
.clip(shape.toShape(size))
|
||||
.getBackgroundColor(type = type, color = color, shape = shape.toShape(size))
|
||||
.padding(size.toPaddingDp(position = iconPosition)),
|
||||
.padding(size.toPaddingDp(position = iconPosition))
|
||||
.clickableSingle(enabled = onClick != null, onClick = { onClick?.invoke() }),
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
visible = iconRes != null && iconPosition == TangemBadgeIconPosition.Start,
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ import com.tangem.core.ui.extensions.TextReference
|
|||
* UI model for [TangemBadge] component
|
||||
*
|
||||
* @param text TextReference for the badge label.
|
||||
* @param modifier Modifier to be applied to the badge.
|
||||
* @param iconRes Drawable resource ID for the icon to be displayed in the badge.
|
||||
* @param size [TangemBadgeSize] defining the size of the badge.
|
||||
* @param shape [TangemBadgeShape] defining the shape of the badge.
|
||||
* @param color [TangemBadgeColor] defining the color scheme of the badge.
|
||||
* @param type [TangemBadgeType] defining the style of the badge.
|
||||
* @param iconPosition [TangemBadgeIconPosition] defining icon position of the badge.
|
||||
* @param onClick Lambda to be invoked when the badge is clicked (optional).
|
||||
*/
|
||||
class TangemBadgeUM(
|
||||
val text: TextReference,
|
||||
|
|
@ -24,4 +24,5 @@ class TangemBadgeUM(
|
|||
val color: TangemBadgeColor = TangemBadgeColor.Gray,
|
||||
val type: TangemBadgeType = TangemBadgeType.Solid,
|
||||
val iconPosition: TangemBadgeIconPosition = TangemBadgeIconPosition.Start,
|
||||
val onClick: (() -> Unit)? = null,
|
||||
)
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
package com.tangem.core.ui.ds.image
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIcon
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.components.icons.identicon.IdentIcon
|
||||
import com.tangem.core.ui.extensions.ColorReference2
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
||||
/**
|
||||
* Model representing different types of icons that can be displayed in the UI.
|
||||
*/
|
||||
@Immutable
|
||||
sealed interface TangemIconUM {
|
||||
|
||||
/** Icon representing a currency. */
|
||||
data class Currency(
|
||||
val currencyIconState: CurrencyIconState,
|
||||
) : TangemIconUM
|
||||
|
||||
/** Icon represented by a drawable resource. */
|
||||
data class Icon(
|
||||
@DrawableRes val iconRes: Int,
|
||||
val tintReference: ColorReference2 = ColorReference2 { TangemTheme.colors2.graphic.neutral.primary },
|
||||
) : TangemIconUM
|
||||
|
||||
/** Image represented by a drawable resource. */
|
||||
data class Image(
|
||||
@DrawableRes val imageRes: Int,
|
||||
) : TangemIconUM
|
||||
|
||||
/** Identicon represented by a text string (e.g., an address). */
|
||||
data class Ident(
|
||||
val text: String,
|
||||
) : TangemIconUM
|
||||
}
|
||||
|
||||
/**
|
||||
* Composable function to display an icon based on the provided [TangemIconUM] type.
|
||||
*
|
||||
* @param tangemIconUM The [TangemIconUM] instance representing the icon to be displayed.
|
||||
* @param modifier The [Modifier] to be applied to the icon.
|
||||
*/
|
||||
@Composable
|
||||
fun TangemIcon(tangemIconUM: TangemIconUM, modifier: Modifier = Modifier) {
|
||||
when (tangemIconUM) {
|
||||
is TangemIconUM.Currency -> {
|
||||
CurrencyIcon(
|
||||
state = tangemIconUM.currencyIconState,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
is TangemIconUM.Icon -> Icon(
|
||||
imageVector = ImageVector.vectorResource(tangemIconUM.iconRes),
|
||||
contentDescription = null,
|
||||
modifier = modifier,
|
||||
tint = tangemIconUM.tintReference(),
|
||||
)
|
||||
is TangemIconUM.Image -> Image(
|
||||
imageVector = ImageVector.vectorResource(tangemIconUM.imageRes),
|
||||
contentDescription = null,
|
||||
modifier = modifier,
|
||||
)
|
||||
is TangemIconUM.Ident -> IdentIcon(
|
||||
address = tangemIconUM.text,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -11,9 +11,11 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
|
|
@ -24,6 +26,7 @@ import com.tangem.core.ui.components.flicker
|
|||
import com.tangem.core.ui.components.notifications.NotificationConfig
|
||||
import com.tangem.core.ui.components.notifications.NotificationConfig.ButtonsState
|
||||
import com.tangem.core.ui.ds.button.*
|
||||
import com.tangem.core.ui.ds.image.TangemIcon
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||
|
|
@ -35,21 +38,31 @@ import kotlinx.collections.immutable.persistentListOf
|
|||
*
|
||||
* @param messageUM Data model containing message properties.
|
||||
* @param modifier Modifier to be applied to the message component.
|
||||
* @param content Optional composable content to be displayed alongside the title and subtitle.
|
||||
*/
|
||||
@Composable
|
||||
fun TangemMessage(
|
||||
messageUM: TangemMessageUM,
|
||||
modifier: Modifier = Modifier,
|
||||
content: @Composable (RowScope.() -> Unit)? = null,
|
||||
contentColor: Color = TangemTheme.colors2.surface.level3,
|
||||
) {
|
||||
TangemMessage(
|
||||
modifier = modifier,
|
||||
modifier = modifier
|
||||
.conditional(messageUM.onClick != null) {
|
||||
clickableSingle(onClick = requireNotNull(messageUM.onClick))
|
||||
},
|
||||
title = messageUM.title,
|
||||
subtitle = messageUM.subtitle,
|
||||
messageEffect = messageUM.messageEffect,
|
||||
isCentered = messageUM.isCentered,
|
||||
content = content,
|
||||
content = {
|
||||
if (messageUM.iconUM != null) {
|
||||
TangemIcon(
|
||||
tangemIconUM = messageUM.iconUM,
|
||||
modifier = Modifier.size(TangemTheme.dimens2.x8),
|
||||
)
|
||||
}
|
||||
},
|
||||
contentColor = contentColor,
|
||||
onCloseClick = messageUM.onCloseClick,
|
||||
buttons = {
|
||||
messageUM.buttonsUM.fastForEach { buttonUM ->
|
||||
|
|
@ -73,7 +86,11 @@ fun TangemMessage(
|
|||
* @see com.tangem.core.ui.components.notifications.Notification for legacy component.
|
||||
*/
|
||||
@Composable
|
||||
fun TangemMessage(config: NotificationConfig, modifier: Modifier = Modifier) {
|
||||
fun TangemMessage(
|
||||
config: NotificationConfig,
|
||||
modifier: Modifier = Modifier,
|
||||
contentColor: Color = TangemTheme.colors2.surface.level3,
|
||||
) {
|
||||
val buttonState = config.buttonsState
|
||||
TangemMessage(
|
||||
title = config.title,
|
||||
|
|
@ -101,6 +118,7 @@ fun TangemMessage(config: NotificationConfig, modifier: Modifier = Modifier) {
|
|||
)
|
||||
}
|
||||
},
|
||||
contentColor = contentColor,
|
||||
buttons = if (buttonState != null) {
|
||||
{
|
||||
TangemMessageLegacyButtons(buttonState = buttonState)
|
||||
|
|
@ -129,10 +147,11 @@ fun TangemMessage(
|
|||
title: TextReference? = null,
|
||||
subtitle: TextReference? = null,
|
||||
messageEffect: TangemMessageEffect = TangemMessageEffect.None,
|
||||
content: (@Composable RowScope.() -> Unit)? = null,
|
||||
buttons: (@Composable RowScope.() -> Unit)? = null,
|
||||
onCloseClick: (() -> Unit)? = null,
|
||||
isCentered: Boolean = false,
|
||||
contentColor: Color = TangemTheme.colors2.surface.level3,
|
||||
content: (@Composable RowScope.() -> Unit)? = null,
|
||||
buttons: (@Composable RowScope.() -> Unit)? = null,
|
||||
) {
|
||||
val alignment = if (isCentered) {
|
||||
Alignment.CenterHorizontally
|
||||
|
|
@ -146,6 +165,7 @@ fun TangemMessage(
|
|||
.messageEffectBackground(
|
||||
messageEffect = messageEffect,
|
||||
radius = TangemTheme.dimens2.x6,
|
||||
contentColor = contentColor,
|
||||
),
|
||||
)
|
||||
Column(
|
||||
|
|
@ -160,8 +180,9 @@ fun TangemMessage(
|
|||
subtitle = subtitle,
|
||||
alignment = alignment,
|
||||
content = content,
|
||||
isCentered = isCentered,
|
||||
)
|
||||
if (buttons != null && !isCentered) {
|
||||
if (buttons != null) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(6.dp),
|
||||
modifier = Modifier
|
||||
|
|
@ -191,8 +212,14 @@ private fun TangemMessageContent(
|
|||
title: TextReference? = null,
|
||||
subtitle: TextReference? = null,
|
||||
alignment: Alignment.Horizontal = Alignment.Start,
|
||||
isCentered: Boolean = false,
|
||||
content: (@Composable RowScope.() -> Unit)? = null,
|
||||
) {
|
||||
val textAlign = if (isCentered) {
|
||||
TextAlign.Center
|
||||
} else {
|
||||
TextAlign.Start
|
||||
}
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x2),
|
||||
modifier = Modifier.padding(TangemTheme.dimens2.x1),
|
||||
|
|
@ -208,10 +235,12 @@ private fun TangemMessageContent(
|
|||
style = TangemTheme.typography2.bodySemibold16,
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
maxLines = 1,
|
||||
textAlign = textAlign,
|
||||
)
|
||||
}
|
||||
if (subtitle != null) {
|
||||
Text(
|
||||
textAlign = textAlign,
|
||||
text = subtitle.resolveAnnotatedReference(),
|
||||
style = TangemTheme.typography2.captionSemibold12,
|
||||
color = TangemTheme.colors2.text.neutral.secondary,
|
||||
|
|
@ -310,12 +339,14 @@ private class TangemMessagePreviewProvider : PreviewParameterProvider<TangemMess
|
|||
override val values: Sequence<TangemMessageUM>
|
||||
get() = sequenceOf(
|
||||
TangemMessageUM(
|
||||
id = "1",
|
||||
title = stringReference("Title text"),
|
||||
subtitle = stringReference("Subtext"),
|
||||
messageEffect = TangemMessageEffect.None,
|
||||
isCentered = true,
|
||||
),
|
||||
TangemMessageUM(
|
||||
id = "2",
|
||||
title = stringReference("Title text"),
|
||||
subtitle = stringReference("Subtext"),
|
||||
messageEffect = TangemMessageEffect.Magic,
|
||||
|
|
@ -335,6 +366,7 @@ private class TangemMessagePreviewProvider : PreviewParameterProvider<TangemMess
|
|||
),
|
||||
),
|
||||
TangemMessageUM(
|
||||
id = "3",
|
||||
title = stringReference("Title text"),
|
||||
subtitle = stringReference("Subtext"),
|
||||
messageEffect = TangemMessageEffect.Card,
|
||||
|
|
@ -348,6 +380,7 @@ private class TangemMessagePreviewProvider : PreviewParameterProvider<TangemMess
|
|||
),
|
||||
),
|
||||
TangemMessageUM(
|
||||
id = "4",
|
||||
title = stringReference("Title text"),
|
||||
subtitle = stringReference("Subtext"),
|
||||
messageEffect = TangemMessageEffect.Warning,
|
||||
|
|
|
|||
|
|
@ -1,18 +1,24 @@
|
|||
package com.tangem.core.ui.ds.message
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.core.*
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableFloatStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.drawWithContent
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.BlendMode
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.drawscope.rotate
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
|
@ -21,6 +27,7 @@ import com.tangem.core.ui.extensions.conditionalCompose
|
|||
import com.tangem.core.ui.res.LocalIsInDarkTheme
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||
import com.tangem.core.ui.utils.toPx
|
||||
import dev.chrisbanes.haze.HazeStyle
|
||||
import dev.chrisbanes.haze.HazeTint
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
|
@ -29,15 +36,15 @@ import kotlinx.collections.immutable.persistentListOf
|
|||
/**
|
||||
* Different visual effects for [Tangem message component].
|
||||
*/
|
||||
enum class TangemMessageEffect {
|
||||
enum class TangemMessageEffect(val isAnimatable: Boolean) {
|
||||
/** Magic effect with vibrant colors */
|
||||
Magic,
|
||||
Magic(true),
|
||||
/** Card effect with bright colors */
|
||||
Card,
|
||||
Card(true),
|
||||
/** Warning effect with alert colors */
|
||||
Warning,
|
||||
Warning(false),
|
||||
/** No special effect */
|
||||
None,
|
||||
None(false),
|
||||
;
|
||||
|
||||
/** Gets the color gradient based on the effect type and [isInDarkTheme] */
|
||||
|
|
@ -223,11 +230,19 @@ enum class TangemMessageEffect {
|
|||
|
||||
/** Applies a message effect background to the [Modifier] based on the provided [messageEffect] and [radius] */
|
||||
@Composable
|
||||
internal fun Modifier.messageEffectBackground(messageEffect: TangemMessageEffect, radius: Dp): Modifier {
|
||||
internal fun Modifier.messageEffectBackground(
|
||||
messageEffect: TangemMessageEffect,
|
||||
radius: Dp,
|
||||
contentColor: Color,
|
||||
): Modifier {
|
||||
val isInDarkTheme = LocalIsInDarkTheme.current
|
||||
val borderGradientColors = remember { messageEffect.getBorderGradient(isInDarkTheme) }
|
||||
val gradientColors = remember { messageEffect.getColorGradient(isInDarkTheme) }
|
||||
|
||||
val angle by rememberAnimationAngle(messageEffect.isAnimatable)
|
||||
val brush = Brush.sweepGradient(messageEffect.getColorGradient(isInDarkTheme))
|
||||
val padding = 1.dp.toPx()
|
||||
|
||||
return this
|
||||
.clip(RoundedCornerShape(radius))
|
||||
.border(
|
||||
|
|
@ -255,14 +270,39 @@ internal fun Modifier.messageEffectBackground(messageEffect: TangemMessageEffect
|
|||
blurRadius = 25.dp
|
||||
}
|
||||
.conditionalCompose(gradientColors.isNotEmpty()) {
|
||||
border(
|
||||
width = 0.dp,
|
||||
brush = Brush.sweepGradient(messageEffect.getColorGradient(isInDarkTheme)),
|
||||
shape = RoundedCornerShape(radius),
|
||||
)
|
||||
drawWithContent {
|
||||
rotate(angle) {
|
||||
drawCircle(
|
||||
brush = brush,
|
||||
radius = size.width,
|
||||
blendMode = BlendMode.SrcIn,
|
||||
)
|
||||
}
|
||||
drawRect(
|
||||
color = contentColor,
|
||||
topLeft = Offset(padding, padding),
|
||||
size = Size(size.width - 2 * padding, size.height - 2 * padding),
|
||||
)
|
||||
drawContent()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun rememberAnimationAngle(isAnimatable: Boolean) = if (isAnimatable) {
|
||||
val infiniteTransition = rememberInfiniteTransition()
|
||||
infiniteTransition.animateFloat(
|
||||
initialValue = 0f,
|
||||
targetValue = 360f,
|
||||
animationSpec = infiniteRepeatable(
|
||||
animation = tween(durationMillis = 3000, easing = LinearEasing),
|
||||
repeatMode = RepeatMode.Restart,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
remember { mutableFloatStateOf(0f) }
|
||||
}
|
||||
|
||||
// region Preview
|
||||
@Composable
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
|
|
@ -281,6 +321,7 @@ private fun TangemMessageEffect_Preview() {
|
|||
.messageEffectBackground(
|
||||
messageEffect = messageEffect,
|
||||
radius = 16.dp,
|
||||
contentColor = TangemTheme.colors2.surface.level1,
|
||||
)
|
||||
.fillMaxWidth()
|
||||
.height(height = 100.dp),
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.core.ui.ds.message
|
|||
|
||||
import androidx.annotation.DrawableRes
|
||||
import com.tangem.core.ui.ds.button.*
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
|
@ -17,11 +18,14 @@ import kotlinx.collections.immutable.persistentListOf
|
|||
* @param onCloseClick Lambda to be invoked when the close button is clicked (optional
|
||||
*/
|
||||
data class TangemMessageUM(
|
||||
val id: String,
|
||||
val title: TextReference,
|
||||
val subtitle: TextReference,
|
||||
val messageEffect: TangemMessageEffect,
|
||||
val isCentered: Boolean,
|
||||
val messageEffect: TangemMessageEffect = TangemMessageEffect.None,
|
||||
val iconUM: TangemIconUM? = null,
|
||||
val isCentered: Boolean = false,
|
||||
val buttonsUM: ImmutableList<TangemMessageButtonUM> = persistentListOf(),
|
||||
val onClick: (() -> Unit)? = null,
|
||||
val onCloseClick: (() -> Unit)? = null,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
package com.tangem.core.ui.ds.row
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
|
||||
/**
|
||||
* Base interface for all row UI models in the Tangem application. Each row UI model must implement this interface
|
||||
*/
|
||||
@Immutable
|
||||
interface TangemRowUM {
|
||||
|
||||
val id: String
|
||||
}
|
||||
|
|
@ -0,0 +1,230 @@
|
|||
package com.tangem.core.ui.ds.row.header
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
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.vector.ImageVector
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
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.SpacerWMax
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.ds.image.TangemIcon
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.clickableSingle
|
||||
import com.tangem.core.ui.extensions.resolveAnnotatedReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||
import com.tangem.core.ui.test.TokenElementsTestTags
|
||||
|
||||
/**
|
||||
* UI model for header row component
|
||||
*
|
||||
* @param headerRowUM UI model for the header row
|
||||
* @param modifier Modifier for the composable
|
||||
*/
|
||||
@Composable
|
||||
fun TangemHeaderRow(headerRowUM: TangemHeaderRowUM, modifier: Modifier = Modifier) {
|
||||
TangemHeaderRow(
|
||||
headTangemIconUM = headerRowUM.startIconUM,
|
||||
footerTangemIconRes = headerRowUM.endIconRes,
|
||||
title = headerRowUM.title,
|
||||
subtitle = headerRowUM.subtitle,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Composable function that represents a header row with customizable title and head content.
|
||||
*
|
||||
* @param modifier Modifier for the composable
|
||||
* @param subtitle Optional subtitle as a TextReference
|
||||
* @param onItemClick Optional click callback for the row
|
||||
* @param footerTangemIconRes Optional drawable resource ID for the footer icon
|
||||
* @param titleContent Composable lambda for the title content
|
||||
* @param headContent Composable lambda for the head content
|
||||
*/
|
||||
@Composable
|
||||
fun TangemHeaderRow(
|
||||
modifier: Modifier = Modifier,
|
||||
subtitle: TextReference? = null,
|
||||
onItemClick: (() -> Unit)? = null,
|
||||
@DrawableRes footerTangemIconRes: Int? = null,
|
||||
titleContent: @Composable (Modifier) -> Unit,
|
||||
headContent: @Composable (Modifier) -> Unit,
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.clickableSingle(enabled = onItemClick != null, onClick = { onItemClick?.invoke() })
|
||||
.padding(
|
||||
top = TangemTheme.dimens2.x4,
|
||||
bottom = TangemTheme.dimens2.x3,
|
||||
start = TangemTheme.dimens2.x4,
|
||||
end = TangemTheme.dimens2.x4,
|
||||
),
|
||||
) {
|
||||
headContent(
|
||||
Modifier
|
||||
.padding(end = TangemTheme.dimens2.x2)
|
||||
.size(TangemTheme.dimens2.x4),
|
||||
)
|
||||
titleContent(Modifier)
|
||||
AnimatedVisibility(
|
||||
visible = subtitle != null,
|
||||
) {
|
||||
val wrappedSubtitle = remember(this) { requireNotNull(subtitle) }
|
||||
Text(
|
||||
text = wrappedSubtitle.resolveAnnotatedReference(),
|
||||
style = TangemTheme.typography2.captionSemibold12,
|
||||
color = TangemTheme.colors2.text.neutral.secondary,
|
||||
maxLines = 1,
|
||||
modifier = Modifier
|
||||
.testTag(tag = TokenElementsTestTags.TOKEN_CRYPTO_AMOUNT)
|
||||
.padding(start = TangemTheme.dimens2.x1),
|
||||
)
|
||||
}
|
||||
SpacerWMax()
|
||||
AnimatedVisibility(
|
||||
visible = footerTangemIconRes != null,
|
||||
) {
|
||||
val wrappedIconUM = remember(this) { requireNotNull(footerTangemIconRes) }
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(id = wrappedIconUM),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors2.graphic.neutral.secondary,
|
||||
modifier = Modifier.size(TangemTheme.dimens2.x4),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Composable function that represents a header row with title, optional subtitle, and optional icons.
|
||||
*
|
||||
* @param title Title as a TextReference
|
||||
* @param modifier Modifier for the composable
|
||||
* @param subtitle Optional subtitle as a TextReference
|
||||
* @param headTangemIconUM Optional TangemIconUM for the head icon
|
||||
* @param footerTangemIconRes Optional drawable resource ID for the footer icon
|
||||
* @param isEnabled Boolean indicating if the row is clickable
|
||||
* @param onItemClick Optional click callback for the row
|
||||
*/
|
||||
@Composable
|
||||
fun TangemHeaderRow(
|
||||
title: TextReference,
|
||||
modifier: Modifier = Modifier,
|
||||
subtitle: TextReference? = null,
|
||||
headTangemIconUM: TangemIconUM? = null,
|
||||
@DrawableRes footerTangemIconRes: Int? = null,
|
||||
isEnabled: Boolean = false,
|
||||
onItemClick: (() -> Unit)? = null,
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.clickableSingle(enabled = isEnabled && onItemClick != null, onClick = { onItemClick?.invoke() })
|
||||
.padding(
|
||||
top = TangemTheme.dimens2.x4,
|
||||
bottom = TangemTheme.dimens2.x3,
|
||||
start = TangemTheme.dimens2.x4,
|
||||
end = TangemTheme.dimens2.x4,
|
||||
),
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
visible = headTangemIconUM != null,
|
||||
) {
|
||||
val wrappedIconUM = remember(this) { requireNotNull(headTangemIconUM) }
|
||||
TangemIcon(
|
||||
tangemIconUM = wrappedIconUM,
|
||||
modifier = Modifier
|
||||
.padding(end = TangemTheme.dimens2.x2)
|
||||
.size(TangemTheme.dimens2.x4),
|
||||
)
|
||||
}
|
||||
Text(
|
||||
text = title.resolveAnnotatedReference(),
|
||||
style = TangemTheme.typography2.captionSemibold12,
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
maxLines = 1,
|
||||
modifier = Modifier.testTag(tag = TokenElementsTestTags.TOKEN_TITLE),
|
||||
)
|
||||
AnimatedVisibility(
|
||||
visible = subtitle != null,
|
||||
) {
|
||||
val wrappedSubtitle = remember(this) { requireNotNull(subtitle) }
|
||||
Text(
|
||||
text = wrappedSubtitle.resolveAnnotatedReference(),
|
||||
style = TangemTheme.typography2.captionSemibold12,
|
||||
color = TangemTheme.colors2.text.neutral.secondary,
|
||||
maxLines = 1,
|
||||
modifier = Modifier
|
||||
.testTag(tag = TokenElementsTestTags.TOKEN_CRYPTO_AMOUNT)
|
||||
.padding(start = TangemTheme.dimens2.x1),
|
||||
)
|
||||
}
|
||||
SpacerWMax()
|
||||
AnimatedVisibility(
|
||||
visible = footerTangemIconRes != null,
|
||||
) {
|
||||
val wrappedIconUM = remember(this) { requireNotNull(footerTangemIconRes) }
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(id = wrappedIconUM),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors2.graphic.neutral.secondary,
|
||||
modifier = Modifier.size(TangemTheme.dimens2.x4),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// region Preview
|
||||
@Composable
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun TangemHeaderRow_Preview(@PreviewParameter(PreviewProvider::class) params: TangemHeaderRowUM) {
|
||||
TangemThemePreviewRedesign {
|
||||
TangemHeaderRow(
|
||||
headerRowUM = params,
|
||||
modifier = Modifier.background(TangemTheme.colors2.surface.level3),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class PreviewProvider : PreviewParameterProvider<TangemHeaderRowUM> {
|
||||
override val values: Sequence<TangemHeaderRowUM>
|
||||
get() = sequenceOf(
|
||||
TangemHeaderRowUM(
|
||||
id = "1",
|
||||
startIconUM = TangemIconUM.Currency(
|
||||
currencyIconState = CurrencyIconState.Locked,
|
||||
),
|
||||
endIconRes = R.drawable.ic_minimize_24,
|
||||
title = stringReference("Account"),
|
||||
subtitle = stringReference("\$ 42,900.17"),
|
||||
),
|
||||
TangemHeaderRowUM(
|
||||
id = "2",
|
||||
title = stringReference("Account"),
|
||||
),
|
||||
)
|
||||
}
|
||||
// endregion
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package com.tangem.core.ui.ds.row.header
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.ds.row.TangemRowUM
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
|
||||
/**
|
||||
* UI model for header row component
|
||||
*
|
||||
* @param id Unique id
|
||||
* @param title Title text reference
|
||||
* @param subtitle Subtitle text reference (optional)
|
||||
* @param startIconUM Icon UI model (optional)
|
||||
* @param endIconRes Icon UI model (optional)
|
||||
* @param isEnabled Flag indicating if click is enabled
|
||||
* @param onItemClick Callback for item click (optional)
|
||||
*/
|
||||
@Immutable
|
||||
data class TangemHeaderRowUM(
|
||||
override val id: String,
|
||||
val title: TextReference,
|
||||
val subtitle: TextReference? = null,
|
||||
val startIconUM: TangemIconUM? = null,
|
||||
@DrawableRes val endIconRes: Int? = null,
|
||||
val isEnabled: Boolean = false,
|
||||
val onItemClick: (() -> Unit)? = null,
|
||||
) : TangemRowUM
|
||||
|
|
@ -16,7 +16,7 @@ import androidx.compose.ui.platform.testTag
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIcon
|
||||
import com.tangem.core.ui.ds.image.TangemIcon
|
||||
import com.tangem.core.ui.ds.row.TangemRowContainer
|
||||
import com.tangem.core.ui.ds.row.TangemRowLayoutId
|
||||
import com.tangem.core.ui.ds.row.token.internal.*
|
||||
|
|
@ -44,19 +44,19 @@ fun TangemTokenRow(
|
|||
) {
|
||||
TangemRowContainer(
|
||||
content = {
|
||||
CurrencyIcon(
|
||||
state = tokenRowUM.iconState,
|
||||
TangemIcon(
|
||||
tangemIconUM = tokenRowUM.headIconUM,
|
||||
modifier = Modifier
|
||||
.layoutId(layoutId = TangemRowLayoutId.HEAD)
|
||||
.padding(end = TangemTheme.dimens2.x2)
|
||||
.testTag(TokenElementsTestTags.TOKEN_ICON),
|
||||
.testTag(tag = TokenElementsTestTags.TOKEN_ICON),
|
||||
)
|
||||
|
||||
TokenRowPromoBanner(
|
||||
promoBannerUM = tokenRowUM.promoBannerUM,
|
||||
modifier = Modifier
|
||||
.layoutId(layoutId = TangemRowLayoutId.EXTRA_TOP)
|
||||
.testTag(TokenElementsTestTags.TOKEN_YIELD_PROMO_BANNER)
|
||||
.testTag(tag = TokenElementsTestTags.TOKEN_YIELD_PROMO_BANNER)
|
||||
.padding(horizontal = TangemTheme.dimens2.x3)
|
||||
.fillMaxWidth(),
|
||||
)
|
||||
|
|
@ -98,7 +98,89 @@ fun TangemTokenRow(
|
|||
reorderableTokenListState = reorderableTokenListState,
|
||||
modifier = Modifier
|
||||
.layoutId(layoutId = TangemRowLayoutId.TAIL)
|
||||
.testTag(TokenElementsTestTags.TOKEN_NON_FIAT_BLOCK),
|
||||
.testTag(tag = TokenElementsTestTags.TOKEN_NON_FIAT_BLOCK),
|
||||
)
|
||||
},
|
||||
modifier = modifier.tokenClickable(tokenRowUM = tokenRowUM),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Composable function that represents a Tangem token row in a list.
|
||||
*
|
||||
* [Token Row](https://www.figma.com/design/RU7AIgwHtGdMfy83T5UOoR/Core-Library?node-id=8207-17583&t=k8dyaykorsNocGVq-4)
|
||||
*
|
||||
* @param tokenRowUM The user model containing the data for the token row.
|
||||
* @param headComponent The composable function representing the head component.
|
||||
* @param titleComponent The composable function representing the title component.
|
||||
* @param isBalanceHidden A boolean indicating whether the balance should be hidden.
|
||||
* @param reorderableTokenListState The state of the reorderable lazy list, if applicable.
|
||||
* @param modifier The modifier to be applied to the row.
|
||||
*/
|
||||
@Composable
|
||||
fun TangemTokenRow(
|
||||
tokenRowUM: TangemTokenRowUM,
|
||||
isBalanceHidden: Boolean,
|
||||
reorderableTokenListState: ReorderableLazyListState?,
|
||||
modifier: Modifier = Modifier,
|
||||
headComponent: @Composable (Modifier) -> Unit,
|
||||
titleComponent: @Composable (Modifier) -> Unit,
|
||||
) {
|
||||
TangemRowContainer(
|
||||
content = {
|
||||
headComponent(
|
||||
Modifier
|
||||
.layoutId(layoutId = TangemRowLayoutId.HEAD)
|
||||
.padding(end = TangemTheme.dimens2.x2)
|
||||
.testTag(tag = TokenElementsTestTags.TOKEN_ICON),
|
||||
)
|
||||
|
||||
TokenRowPromoBanner(
|
||||
promoBannerUM = tokenRowUM.promoBannerUM,
|
||||
modifier = Modifier
|
||||
.layoutId(layoutId = TangemRowLayoutId.EXTRA_TOP)
|
||||
.testTag(tag = TokenElementsTestTags.TOKEN_YIELD_PROMO_BANNER)
|
||||
.padding(horizontal = TangemTheme.dimens2.x3)
|
||||
.fillMaxWidth(),
|
||||
)
|
||||
|
||||
titleComponent(
|
||||
Modifier
|
||||
.layoutId(layoutId = TangemRowLayoutId.START_TOP)
|
||||
.padding(end = TangemTheme.dimens2.x2)
|
||||
.testTag(tag = TokenElementsTestTags.TOKEN_TITLE),
|
||||
)
|
||||
|
||||
TokenRowSubtitle(
|
||||
subtitleUM = tokenRowUM.subtitleUM,
|
||||
modifier = Modifier
|
||||
.layoutId(layoutId = TangemRowLayoutId.START_BOTTOM)
|
||||
.padding(end = TangemTheme.dimens2.x2)
|
||||
.testTag(tag = TokenElementsTestTags.TOKEN_PRICE),
|
||||
)
|
||||
|
||||
TokenRowEndTopContent(
|
||||
endContentUM = tokenRowUM.topEndContentUM,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
modifier = Modifier
|
||||
.layoutId(layoutId = TangemRowLayoutId.END_TOP)
|
||||
.testTag(tag = TokenElementsTestTags.TOKEN_FIAT_AMOUNT),
|
||||
)
|
||||
|
||||
TokenRowEndBottomContent(
|
||||
endContentUM = tokenRowUM.bottomEndContentUM,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
modifier = Modifier
|
||||
.layoutId(layoutId = TangemRowLayoutId.END_BOTTOM)
|
||||
.testTag(tag = TokenElementsTestTags.TOKEN_CRYPTO_AMOUNT),
|
||||
)
|
||||
|
||||
TokenRowTail(
|
||||
tailUM = tokenRowUM.tailUM,
|
||||
reorderableTokenListState = reorderableTokenListState,
|
||||
modifier = Modifier
|
||||
.layoutId(layoutId = TangemRowLayoutId.TAIL)
|
||||
.testTag(tag = TokenElementsTestTags.TOKEN_NON_FIAT_BLOCK),
|
||||
)
|
||||
},
|
||||
modifier = modifier.tokenClickable(tokenRowUM = tokenRowUM),
|
||||
|
|
@ -114,7 +196,7 @@ private fun Modifier.tokenClickable(tokenRowUM: TangemTokenRowUM): Modifier = co
|
|||
val onHapticLongClick = if (onLongClick != null) {
|
||||
{
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
onLongClick(tokenRowUM)
|
||||
onLongClick()
|
||||
}
|
||||
} else {
|
||||
null
|
||||
|
|
@ -123,9 +205,9 @@ private fun Modifier.tokenClickable(tokenRowUM: TangemTokenRowUM): Modifier = co
|
|||
when {
|
||||
onClick == null && onLongClick == null -> this
|
||||
onClick == null && onLongClick != null -> combinedClickable(onClick = {}, onLongClick = onHapticLongClick)
|
||||
onClick != null && onLongClick == null -> combinedClickable(onClick = { onClick(tokenRowUM) })
|
||||
onClick != null && onLongClick == null -> combinedClickable(onClick = onClick)
|
||||
onClick != null && onLongClick != null -> {
|
||||
combinedClickable(onClick = { onClick(tokenRowUM) }, onLongClick = onHapticLongClick)
|
||||
combinedClickable(onClick = onClick, onLongClick = onHapticLongClick)
|
||||
}
|
||||
else -> this
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,20 +4,20 @@ import androidx.compose.runtime.Immutable
|
|||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeState
|
||||
import com.tangem.core.ui.ds.badge.TangemBadgeUM
|
||||
import com.tangem.core.ui.extensions.ColorReference2
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.ds.row.TangemRowUM
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@Immutable
|
||||
sealed class TangemTokenRowUM {
|
||||
sealed class TangemTokenRowUM : TangemRowUM {
|
||||
|
||||
/** Unique id */
|
||||
abstract val id: String
|
||||
abstract override val id: String
|
||||
|
||||
/** Token icon state */
|
||||
abstract val iconState: CurrencyIconState
|
||||
abstract val headIconUM: TangemIconUM.Currency
|
||||
|
||||
/** Token title UM (in one row with [topEndContentUM]) */
|
||||
abstract val titleUM: TitleUM
|
||||
|
|
@ -38,25 +38,25 @@ sealed class TangemTokenRowUM {
|
|||
abstract val promoBannerUM: PromoBannerUM
|
||||
|
||||
/** Callback which will be called when an item is clicked */
|
||||
abstract val onItemClick: ((TangemTokenRowUM) -> Unit)?
|
||||
abstract val onItemClick: (() -> Unit)?
|
||||
|
||||
/** Callback which will be called when an item is long clicked */
|
||||
abstract val onItemLongClick: ((TangemTokenRowUM) -> Unit)?
|
||||
abstract val onItemLongClick: (() -> Unit)?
|
||||
|
||||
/**
|
||||
* Content state of [TangemTokenRowUM]
|
||||
*/
|
||||
data class Content(
|
||||
override val id: String,
|
||||
override val iconState: CurrencyIconState,
|
||||
override val headIconUM: TangemIconUM.Currency,
|
||||
override val titleUM: TitleUM,
|
||||
override val subtitleUM: SubtitleUM,
|
||||
override val topEndContentUM: EndContentUM,
|
||||
override val bottomEndContentUM: EndContentUM,
|
||||
override val promoBannerUM: PromoBannerUM = PromoBannerUM.Empty,
|
||||
override val tailUM: TailUM = TailUM.Empty,
|
||||
override val onItemClick: ((TangemTokenRowUM) -> Unit)?,
|
||||
override val onItemLongClick: ((TangemTokenRowUM) -> Unit)?,
|
||||
override val onItemClick: (() -> Unit)?,
|
||||
override val onItemLongClick: (() -> Unit)?,
|
||||
) : TangemTokenRowUM()
|
||||
|
||||
/**
|
||||
|
|
@ -64,7 +64,7 @@ sealed class TangemTokenRowUM {
|
|||
*/
|
||||
data class Loading(
|
||||
override val id: String,
|
||||
override val iconState: CurrencyIconState,
|
||||
override val headIconUM: TangemIconUM.Currency = TangemIconUM.Currency(CurrencyIconState.Loading),
|
||||
override val titleUM: TitleUM = TitleUM.Loading,
|
||||
override val subtitleUM: SubtitleUM = SubtitleUM.Loading,
|
||||
) : TangemTokenRowUM() {
|
||||
|
|
@ -72,8 +72,8 @@ sealed class TangemTokenRowUM {
|
|||
override val bottomEndContentUM: EndContentUM = EndContentUM.Loading
|
||||
override val promoBannerUM: PromoBannerUM = PromoBannerUM.Empty
|
||||
override val tailUM: TailUM = TailUM.Empty
|
||||
override val onItemClick: ((TangemTokenRowUM) -> Unit)? = null
|
||||
override val onItemLongClick: ((TangemTokenRowUM) -> Unit)? = null
|
||||
override val onItemClick: (() -> Unit)? = null
|
||||
override val onItemLongClick: (() -> Unit)? = null
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -81,12 +81,12 @@ sealed class TangemTokenRowUM {
|
|||
*/
|
||||
data class Actionable(
|
||||
override val id: String,
|
||||
override val iconState: CurrencyIconState,
|
||||
override val headIconUM: TangemIconUM.Currency,
|
||||
override val titleUM: TitleUM,
|
||||
override val subtitleUM: SubtitleUM,
|
||||
override val tailUM: TailUM,
|
||||
override val onItemClick: ((TangemTokenRowUM) -> Unit)?,
|
||||
override val onItemLongClick: ((TangemTokenRowUM) -> Unit)?,
|
||||
override val onItemClick: (() -> Unit)?,
|
||||
override val onItemLongClick: (() -> Unit)?,
|
||||
override val topEndContentUM: EndContentUM = EndContentUM.Empty,
|
||||
override val bottomEndContentUM: EndContentUM = EndContentUM.Empty,
|
||||
) : TangemTokenRowUM() {
|
||||
|
|
@ -116,7 +116,7 @@ sealed class TangemTokenRowUM {
|
|||
val text: TextReference,
|
||||
val isAvailable: Boolean = true,
|
||||
val isFlickering: Boolean = false,
|
||||
val icons: ImmutableList<IconUM> = persistentListOf(),
|
||||
val icons: ImmutableList<TangemIconUM> = persistentListOf(),
|
||||
val priceChangeUM: PriceChangeState = PriceChangeState.Unknown,
|
||||
val badge: TangemBadgeUM? = null,
|
||||
) : SubtitleUM()
|
||||
|
|
@ -133,7 +133,7 @@ sealed class TangemTokenRowUM {
|
|||
val text: TextReference,
|
||||
val isAvailable: Boolean = true,
|
||||
val isFlickering: Boolean = false,
|
||||
val icons: ImmutableList<IconUM> = persistentListOf(),
|
||||
val icons: ImmutableList<TangemIconUM.Icon> = persistentListOf(),
|
||||
val priceChangeUM: PriceChangeState = PriceChangeState.Unknown,
|
||||
) : EndContentUM()
|
||||
|
||||
|
|
@ -164,9 +164,4 @@ sealed class TangemTokenRowUM {
|
|||
|
||||
data object Empty : TailUM()
|
||||
}
|
||||
|
||||
data class IconUM(
|
||||
val iconRes: Int,
|
||||
val tintReference: ColorReference2 = ColorReference2 { TangemTheme.colors2.graphic.neutral.primary },
|
||||
)
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ import com.tangem.core.ui.R
|
|||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeState
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeType
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.ds.row.token.TangemTokenRowUM
|
||||
import com.tangem.core.ui.extensions.combinedReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
|
|
@ -63,49 +64,60 @@ internal object TangemTokenRowPreviewData {
|
|||
text = stringReference("Title"),
|
||||
)
|
||||
|
||||
private val accountResIcon: CurrencyIconState.CryptoPortfolio.Icon
|
||||
get() = CurrencyIconState.CryptoPortfolio.Icon(
|
||||
resId = R.drawable.ic_rounded_star_24,
|
||||
color = Color.Blue,
|
||||
isGrayscale = false,
|
||||
)
|
||||
private val accountLetterIcon: CurrencyIconState.CryptoPortfolio.Letter
|
||||
get() = CurrencyIconState.CryptoPortfolio.Letter(
|
||||
char = stringReference("A"),
|
||||
color = Color.Blue,
|
||||
isGrayscale = false,
|
||||
private val accountResIcon: TangemIconUM.Currency
|
||||
get() = TangemIconUM.Currency(
|
||||
CurrencyIconState.CryptoPortfolio.Icon(
|
||||
resId = R.drawable.ic_rounded_star_24,
|
||||
color = Color.Blue,
|
||||
isGrayscale = false,
|
||||
),
|
||||
)
|
||||
|
||||
private val coinIconState
|
||||
get() = CurrencyIconState.CoinIcon(
|
||||
url = null,
|
||||
fallbackResId = R.drawable.img_polygon_22,
|
||||
isGrayscale = false,
|
||||
shouldShowCustomBadge = false,
|
||||
private val accountLetterIcon: TangemIconUM.Currency
|
||||
get() = TangemIconUM.Currency(
|
||||
CurrencyIconState.CryptoPortfolio.Letter(
|
||||
char = stringReference("A"),
|
||||
color = Color.Blue,
|
||||
isGrayscale = false,
|
||||
),
|
||||
)
|
||||
|
||||
private val tokenIconState
|
||||
get() = CurrencyIconState.TokenIcon(
|
||||
url = null,
|
||||
topBadgeIconResId = R.drawable.img_polygon_22,
|
||||
fallbackTint = TangemColorPalette.Black,
|
||||
fallbackBackground = TangemColorPalette.Meadow,
|
||||
isGrayscale = false,
|
||||
shouldShowCustomBadge = false,
|
||||
private val coinIconState: TangemIconUM.Currency
|
||||
get() = TangemIconUM.Currency(
|
||||
CurrencyIconState.CoinIcon(
|
||||
url = null,
|
||||
fallbackResId = R.drawable.img_polygon_22,
|
||||
isGrayscale = false,
|
||||
shouldShowCustomBadge = false,
|
||||
),
|
||||
)
|
||||
|
||||
private val customTokenIconState
|
||||
get() = CurrencyIconState.CustomTokenIcon(
|
||||
tint = TangemColorPalette.Black,
|
||||
background = TangemColorPalette.Meadow,
|
||||
topBadgeIconResId = R.drawable.img_polygon_22,
|
||||
isGrayscale = false,
|
||||
private val tokenIconState: TangemIconUM.Currency
|
||||
get() = TangemIconUM.Currency(
|
||||
CurrencyIconState.TokenIcon(
|
||||
url = null,
|
||||
topBadgeIconResId = R.drawable.img_polygon_22,
|
||||
fallbackTint = TangemColorPalette.Black,
|
||||
fallbackBackground = TangemColorPalette.Meadow,
|
||||
isGrayscale = false,
|
||||
shouldShowCustomBadge = false,
|
||||
),
|
||||
)
|
||||
|
||||
private val customTokenIconState: TangemIconUM.Currency
|
||||
get() = TangemIconUM.Currency(
|
||||
CurrencyIconState.CustomTokenIcon(
|
||||
tint = TangemColorPalette.Black,
|
||||
background = TangemColorPalette.Meadow,
|
||||
topBadgeIconResId = R.drawable.img_polygon_22,
|
||||
isGrayscale = false,
|
||||
),
|
||||
)
|
||||
|
||||
val defaultState: TangemTokenRowUM.Content
|
||||
get() = TangemTokenRowUM.Content(
|
||||
id = UUID.randomUUID().toString(),
|
||||
iconState = coinIconState,
|
||||
headIconUM = coinIconState,
|
||||
titleUM = titleUM,
|
||||
subtitleUM = subtitleUM,
|
||||
topEndContentUM = topEndContentUM,
|
||||
|
|
@ -131,9 +143,9 @@ internal object TangemTokenRowPreviewData {
|
|||
}),
|
||||
),
|
||||
icons = persistentListOf(
|
||||
TangemTokenRowUM.IconUM(R.drawable.ic_staking_mini_10),
|
||||
TangemTokenRowUM.IconUM(R.drawable.ic_attention_12),
|
||||
TangemTokenRowUM.IconUM(R.drawable.ic_error_sync_24),
|
||||
TangemIconUM.Icon(R.drawable.ic_staking_mini_10),
|
||||
TangemIconUM.Icon(R.drawable.ic_attention_12),
|
||||
TangemIconUM.Icon(R.drawable.ic_error_sync_24),
|
||||
),
|
||||
),
|
||||
bottomEndContentUM = bottomEndContentUM,
|
||||
|
|
@ -146,7 +158,7 @@ internal object TangemTokenRowPreviewData {
|
|||
val tokenState: TangemTokenRowUM.Content
|
||||
get() = TangemTokenRowUM.Content(
|
||||
id = UUID.randomUUID().toString(),
|
||||
iconState = tokenIconState,
|
||||
headIconUM = tokenIconState,
|
||||
titleUM = titleUM,
|
||||
subtitleUM = subtitleUM,
|
||||
topEndContentUM = topEndContentUM,
|
||||
|
|
@ -160,7 +172,7 @@ internal object TangemTokenRowPreviewData {
|
|||
val customTokenState: TangemTokenRowUM.Content
|
||||
get() = TangemTokenRowUM.Content(
|
||||
id = UUID.randomUUID().toString(),
|
||||
iconState = customTokenIconState,
|
||||
headIconUM = customTokenIconState,
|
||||
titleUM = titleUM,
|
||||
subtitleUM = subtitleUM,
|
||||
topEndContentUM = topEndContentUM,
|
||||
|
|
@ -174,7 +186,7 @@ internal object TangemTokenRowPreviewData {
|
|||
val draggableState: TangemTokenRowUM.Actionable
|
||||
get() = TangemTokenRowUM.Actionable(
|
||||
id = UUID.randomUUID().toString(),
|
||||
iconState = coinIconState,
|
||||
headIconUM = coinIconState,
|
||||
titleUM = titleUM,
|
||||
subtitleUM = subtitleUM,
|
||||
tailUM = TangemTokenRowUM.TailUM.Draggable,
|
||||
|
|
@ -185,7 +197,7 @@ internal object TangemTokenRowPreviewData {
|
|||
val draggableStateV2: TangemTokenRowUM.Actionable
|
||||
get() = TangemTokenRowUM.Actionable(
|
||||
id = UUID.randomUUID().toString(),
|
||||
iconState = coinIconState,
|
||||
headIconUM = coinIconState,
|
||||
titleUM = titleUM,
|
||||
subtitleUM = subtitleUM,
|
||||
topEndContentUM = topEndContentUM,
|
||||
|
|
@ -198,12 +210,12 @@ internal object TangemTokenRowPreviewData {
|
|||
val loadingState: TangemTokenRowUM.Loading
|
||||
get() = TangemTokenRowUM.Loading(
|
||||
id = UUID.randomUUID().toString(),
|
||||
iconState = coinIconState,
|
||||
headIconUM = coinIconState,
|
||||
titleUM = TangemTokenRowUM.TitleUM.Loading,
|
||||
subtitleUM = TangemTokenRowUM.SubtitleUM.Loading,
|
||||
)
|
||||
|
||||
val unreachableState: TangemTokenRowUM.Content
|
||||
val unreachableState: TangemTokenRowUM
|
||||
get() = defaultState.copy(
|
||||
topEndContentUM = TangemTokenRowUM.EndContentUM.Content(
|
||||
text = stringReference(StringsSigns.DASH_SIGN),
|
||||
|
|
@ -219,7 +231,7 @@ internal object TangemTokenRowPreviewData {
|
|||
val accountState: TangemTokenRowUM.Content
|
||||
get() = TangemTokenRowUM.Content(
|
||||
id = UUID.randomUUID().toString(),
|
||||
iconState = accountResIcon,
|
||||
headIconUM = accountResIcon,
|
||||
titleUM = TangemTokenRowUM.TitleUM.Content(
|
||||
text = stringReference(value = "Portfolio"),
|
||||
),
|
||||
|
|
@ -239,7 +251,7 @@ internal object TangemTokenRowPreviewData {
|
|||
|
||||
val accountLetterState: TangemTokenRowUM.Content
|
||||
get() = accountState.copy(
|
||||
iconState = accountLetterIcon,
|
||||
headIconUM = accountLetterIcon,
|
||||
)
|
||||
|
||||
val accountEllipsisState: TangemTokenRowUM.Content
|
||||
|
|
|
|||
|
|
@ -65,9 +65,9 @@ private fun Content(
|
|||
),
|
||||
)
|
||||
|
||||
when (endContentUM.priceChangeUM) {
|
||||
when (val priceChangeUM = endContentUM.priceChangeUM) {
|
||||
is PriceChangeState.Content -> TokenRowPriceChangeContent(
|
||||
priceChangeState = endContentUM.priceChangeUM,
|
||||
priceChangeState = priceChangeUM,
|
||||
isFlickering = endContentUM.isFlickering,
|
||||
isAvailable = endContentUM.isAvailable,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -65,9 +65,9 @@ private fun SubtitleContent(subtitleUM: TangemTokenRowUM.SubtitleUM.Content, mod
|
|||
),
|
||||
)
|
||||
|
||||
when (subtitleUM.priceChangeUM) {
|
||||
when (val priceChangeUM = subtitleUM.priceChangeUM) {
|
||||
is PriceChangeState.Content -> TokenRowPriceChangeContent(
|
||||
priceChangeState = subtitleUM.priceChangeUM,
|
||||
priceChangeState = priceChangeUM,
|
||||
isFlickering = subtitleUM.isFlickering,
|
||||
isAvailable = subtitleUM.isAvailable,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -21,12 +21,12 @@ import com.tangem.core.ui.components.TextShimmer
|
|||
import com.tangem.core.ui.ds.badge.TangemBadge
|
||||
import com.tangem.core.ui.ds.row.token.TangemTokenRowUM
|
||||
import com.tangem.core.ui.extensions.conditional
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.resolveAnnotatedReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||
|
||||
@Composable
|
||||
internal fun TokenRowTitle(titleUM: TangemTokenRowUM.TitleUM, modifier: Modifier = Modifier) {
|
||||
fun TokenRowTitle(titleUM: TangemTokenRowUM.TitleUM, modifier: Modifier = Modifier) {
|
||||
when (titleUM) {
|
||||
is TangemTokenRowUM.TitleUM.Content -> ContentTitle(titleUM = titleUM, modifier = modifier)
|
||||
TangemTokenRowUM.TitleUM.Loading -> TextShimmer(
|
||||
|
|
@ -42,7 +42,7 @@ internal fun TokenRowTitle(titleUM: TangemTokenRowUM.TitleUM, modifier: Modifier
|
|||
private fun ContentTitle(titleUM: TangemTokenRowUM.TitleUM.Content, modifier: Modifier = Modifier) {
|
||||
Row(
|
||||
modifier = modifier,
|
||||
horizontalArrangement = Arrangement.spacedBy(space = TangemTheme.dimens2.x4),
|
||||
horizontalArrangement = Arrangement.spacedBy(space = TangemTheme.dimens2.x1),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
/*
|
||||
|
|
@ -50,7 +50,7 @@ private fun ContentTitle(titleUM: TangemTokenRowUM.TitleUM.Content, modifier: Mo
|
|||
* So we need to use [weight] to avoid displacement.
|
||||
*/
|
||||
Text(
|
||||
text = titleUM.text.resolveReference(),
|
||||
text = titleUM.text.resolveAnnotatedReference(),
|
||||
modifier = Modifier.weight(weight = 1f, fill = false),
|
||||
color = if (titleUM.isAvailable) {
|
||||
TangemTheme.colors2.text.neutral.primary
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import com.tangem.core.ui.extensions.clickableSingle
|
||||
import com.tangem.core.ui.extensions.conditional
|
||||
import com.tangem.core.ui.extensions.conditionalCompose
|
||||
|
|
@ -37,16 +38,20 @@ internal fun TangemTopBarInner(
|
|||
onEndContentClick: (() -> Unit)? = null,
|
||||
isGhostButtons: Boolean = false,
|
||||
) {
|
||||
val statusBarHeight = with(LocalDensity.current) { WindowInsets.statusBars.getTop(density = this).toDp() }
|
||||
Box(
|
||||
modifier = modifier
|
||||
.height(TangemTheme.dimens2.x16)
|
||||
.height(TangemTheme.dimens2.x16 + statusBarHeight)
|
||||
.fillMaxWidth()
|
||||
.padding(top = statusBarHeight)
|
||||
.padding(TangemTheme.dimens2.x4, TangemTheme.dimens2.x3),
|
||||
) {
|
||||
val iconModifier = Modifier
|
||||
.size(TangemTheme.dimens2.x10)
|
||||
.clip(RoundedCornerShape(TangemTheme.dimens2.x25))
|
||||
.background(TangemTheme.colors2.button.backgroundSecondary)
|
||||
.conditionalCompose(isGhostButtons) {
|
||||
background(TangemTheme.colors2.button.backgroundSecondary)
|
||||
}
|
||||
|
||||
AnimatedVisibility(
|
||||
visible = startContent != null,
|
||||
|
|
|
|||
|
|
@ -384,6 +384,13 @@ fun TextReference.orMaskWithStars(maskWithStars: Boolean): TextReference {
|
|||
return if (maskWithStars) stringReference(THREE_STARS) else this
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the TextReference itself if it's not null, otherwise returns an empty TextReference.
|
||||
*/
|
||||
fun TextReference?.orEmpty(): TextReference {
|
||||
return this ?: TextReference.EMPTY
|
||||
}
|
||||
|
||||
@ReadOnlyComposable
|
||||
@Composable
|
||||
private fun createStyledText(
|
||||
|
|
|
|||
10
core/ui/src/main/res/drawable/ic_attention_default_24.xml
Normal file
10
core/ui/src/main/res/drawable/ic_attention_default_24.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M19.395,21C21.017,21 22,19.882 22,18.433C22,17.987 21.866,17.523 21.628,17.106L14.223,4.298C13.727,3.436 12.878,3 12,3C11.122,3 10.263,3.436 9.777,4.298L2.372,17.106C2.115,17.533 2,17.987 2,18.433C2,19.882 2.983,21 4.605,21H19.395ZM12.009,14.672C11.513,14.672 11.237,14.387 11.227,13.885L11.103,8.732C11.094,8.229 11.466,7.869 12,7.869C12.515,7.869 12.916,8.239 12.906,8.741L12.763,13.885C12.754,14.397 12.477,14.672 12.009,14.672ZM12.009,17.845C11.437,17.845 10.941,17.39 10.941,16.832C10.941,16.263 11.427,15.808 12.009,15.808C12.582,15.808 13.069,16.254 13.069,16.832C13.069,17.4 12.573,17.845 12.009,17.845Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
12
core/ui/src/main/res/drawable/ic_dollar_default_24.xml
Normal file
12
core/ui/src/main/res/drawable/ic_dollar_default_24.xml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M12.5,18H14.5C16.157,18 17.5,16.657 17.5,15C17.5,13.343 16.157,12 14.5,12H10C8.343,12 7,10.657 7,9C7,7.343 8.343,6 10,6L12.5,6M12.5,18L7,18M12.5,18V21M17.5,6L12.5,6M12.5,6V3"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
||||
12
core/ui/src/main/res/drawable/ic_error_sync_default_24.xml
Normal file
12
core/ui/src/main/res/drawable/ic_error_sync_default_24.xml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M16.769,18.101C18.179,17.943 21,16.677 21,13.83C21,11.484 19.163,9.602 15.943,9.558C15.876,9.557 15.817,9.515 15.797,9.451C15.078,7.202 11.191,2.872 5.957,6.235C0.785,9.558 3.136,17.152 7.367,18.101M12.068,15.728V12.406M12.068,19.905V20"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
||||
12
core/ui/src/main/res/drawable/ic_exchange_default_24.xml
Normal file
12
core/ui/src/main/res/drawable/ic_exchange_default_24.xml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M20.777,10.615L20.777,13.115C20.777,15.876 18.539,18.115 15.777,18.115L6.777,18.115M11.277,14.115L6.789,17.705C6.531,17.911 6.54,18.306 6.807,18.5L11.777,22.115M3.134,13.5L3.134,11C3.134,8.239 5.372,6 8.134,6L17.134,6M12.634,10L17.122,6.409C17.38,6.203 17.371,5.809 17.104,5.615L12.134,2"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
||||
12
core/ui/src/main/res/drawable/ic_filter_default_24.xml
Normal file
12
core/ui/src/main/res/drawable/ic_filter_default_24.xml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M4,7.078L11.278,7.078M11.278,7.078C11.278,8.806 12.671,10.207 14.389,10.207C16.107,10.207 17.5,8.806 17.5,7.078M11.278,7.078C11.278,5.351 12.671,3.95 14.389,3.95C16.107,3.95 17.5,5.351 17.5,7.078M17.5,7.078L20,7.078M20,16.822H12.5M12.5,16.822C12.5,18.549 11.107,19.95 9.389,19.95C7.671,19.95 6.278,18.549 6.278,16.822M12.5,16.822C12.5,15.094 11.107,13.693 9.389,13.693C7.671,13.693 6.278,15.094 6.278,16.822M6.278,16.822H4"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
||||
33
core/ui/src/main/res/drawable/ic_more_default_24.xml
Normal file
33
core/ui/src/main/res/drawable/ic_more_default_24.xml
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M11.264,12.05C11.264,11.636 11.6,11.3 12.014,11.3C12.428,11.3 12.764,11.636 12.764,12.05C12.764,12.464 12.428,12.8 12.014,12.8C11.6,12.8 11.264,12.464 11.264,12.05Z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M18.5,12.05C18.5,11.636 18.836,11.3 19.25,11.3C19.664,11.3 20,11.636 20,12.05C20,12.464 19.664,12.8 19.25,12.8C18.836,12.8 18.5,12.464 18.5,12.05Z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M4,12.05C4,11.636 4.336,11.3 4.75,11.3C5.164,11.3 5.5,11.636 5.5,12.05C5.5,12.464 5.164,12.8 4.75,12.8C4.336,12.8 4,12.464 4,12.05Z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M11.264,12.05C11.264,11.636 11.6,11.3 12.014,11.3C12.428,11.3 12.764,11.636 12.764,12.05C12.764,12.464 12.428,12.8 12.014,12.8C11.6,12.8 11.264,12.464 11.264,12.05Z"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M18.5,12.05C18.5,11.636 18.836,11.3 19.25,11.3C19.664,11.3 20,11.636 20,12.05C20,12.464 19.664,12.8 19.25,12.8C18.836,12.8 18.5,12.464 18.5,12.05Z"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M4,12.05C4,11.636 4.336,11.3 4.75,11.3C5.164,11.3 5.5,11.636 5.5,12.05C5.5,12.464 5.164,12.8 4.75,12.8C4.336,12.8 4,12.464 4,12.05Z"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
||||
13
core/ui/src/main/res/drawable/ic_plus_default_24.xml
Normal file
13
core/ui/src/main/res/drawable/ic_plus_default_24.xml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M12.495,3.5V20.5M21,11.995L4,11.995"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
||||
Loading…
Add table
Add a link
Reference in a new issue