Updated on 2026-08-14

This commit is contained in:
Tangem 2026-05-04 09:40:55 +02:00
parent 3fe7585ba8
commit d0bc6087fe
34 changed files with 569 additions and 461 deletions

View file

@ -72,14 +72,14 @@ fun MarketListItemContentV2(model: MarketsListItemUM, modifier: Modifier = Modif
TangemIcon(
tangemIconUM = TangemIconUM.Url(model.iconUrl, fallbackRes = R.drawable.ic_custom_token_44),
modifier = Modifier
.size(40.dp)
.size(TangemTheme.dimens2.x10)
.layoutId(layoutId = TangemRowLayoutId.HEAD),
)
TokenTitle(
modifier = Modifier
.layoutId(layoutId = TangemRowLayoutId.START_TOP)
.padding(horizontal = TangemTheme.dimens2.x2),
.padding(start = TangemTheme.dimens2.x3),
name = model.name,
currencySymbol = model.currencySymbol,
)
@ -97,7 +97,7 @@ fun MarketListItemContentV2(model: MarketsListItemUM, modifier: Modifier = Modif
TokenSubtitle(
modifier = Modifier
.layoutId(layoutId = TangemRowLayoutId.START_BOTTOM)
.padding(end = TangemTheme.dimens2.x2, start = TangemTheme.dimens2.x3),
.padding(start = TangemTheme.dimens2.x3),
ratingPosition = model.ratingPosition,
marketCap = model.marketCap,
stakingRate = model.stakingRate,
@ -112,7 +112,7 @@ fun MarketListItemContentV2(model: MarketsListItemUM, modifier: Modifier = Modif
if (windowSize.widthAtLeast(WindowSizeType.Small)) {
Chart(
modifier = Modifier
.padding(start = TangemTheme.dimens2.x2)
.padding(start = TangemTheme.dimens2.x3)
.layoutId(layoutId = TangemRowLayoutId.TAIL),
chartType = model.chartType,
chartRawData = model.chartData,
@ -140,7 +140,7 @@ private fun TokenTitle(name: String, currencySymbol: String, modifier: Modifier
modifier = Modifier.alignByBaseline(),
text = currencySymbol,
color = TangemTheme.colors2.text.neutral.secondary,
style = TangemTheme.typography2.captionSemibold12,
style = TangemTheme.typography2.captionMedium12,
maxLines = 1,
overflow = TextOverflow.Visible,
)
@ -197,7 +197,7 @@ private fun RowScope.TokenRatingPlace(ratingPosition: String?, ratingColor: Colo
textAlign = TextAlign.Center,
text = ratingPosition ?: MINUS,
color = ratingColor,
style = TangemTheme.typography2.captionSemibold12.copy(letterSpacing = 0.sp),
style = TangemTheme.typography2.captionMedium12.copy(letterSpacing = 0.sp),
maxLines = 1,
)
@ -216,7 +216,7 @@ private fun RowScope.TokenMarketCapText(text: String, ratingColor: Color, modifi
modifier = modifier.alignByBaseline(),
text = text,
color = ratingColor,
style = TangemTheme.typography2.captionSemibold12,
style = TangemTheme.typography2.captionMedium12,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)

View file

@ -25,13 +25,17 @@ import dev.chrisbanes.haze.HazeTint
* elements and floating button at the bottom of the screen.
*/
@Composable
fun BottomFade(modifier: Modifier = Modifier, backgroundColor: Color = TangemTheme.colors.background.secondary) {
fun BottomFade(
modifier: Modifier = Modifier,
backgroundColor: Color = TangemTheme.colors.background.secondary,
height: Dp = 100.dp,
) {
val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() }
Box(
modifier = modifier
.fillMaxWidth()
.height(TangemTheme.dimens.size100 + bottomBarHeight)
.height(height + bottomBarHeight)
.background(
brush = Brush.verticalGradient(
colors = listOf(

View file

@ -6,12 +6,14 @@ import androidx.compose.material3.CardColors
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Shape
import com.tangem.core.ui.res.TangemTheme
@Composable
fun BlockCard(
modifier: Modifier = Modifier,
enabled: Boolean = true,
shape: Shape = TangemTheme.shapes.roundedCornersXMedium,
colors: CardColors = TangemBlockCardColors,
onClick: () -> Unit = {},
content: @Composable ColumnScope.() -> Unit = {},
@ -19,7 +21,7 @@ fun BlockCard(
Card(
modifier = modifier,
onClick = onClick,
shape = TangemTheme.shapes.roundedCornersXMedium,
shape = shape,
colors = colors,
enabled = enabled,
content = content,

View file

@ -127,13 +127,13 @@ private fun DescriptionItemV2(
onClick = onReadMoreClick,
),
text = text,
style = TangemTheme.typography2.bodyRegular15,
style = TangemTheme.typography2.bodyMedium16,
)
} else {
Text(
modifier = modifier,
text = description.resolveReference(),
style = TangemTheme.typography2.bodyRegular15,
style = TangemTheme.typography2.bodyMedium16,
color = TangemTheme.colors2.text.neutral.tertiary,
)
}
@ -179,17 +179,17 @@ private fun DescriptionPlaceholderV2(modifier: Modifier = Modifier) {
) {
TextShimmer(
modifier = Modifier.fillMaxWidth(),
style = TangemTheme.typography2.bodyRegular15,
style = TangemTheme.typography2.bodyMedium16,
radius = TangemTheme.dimens2.x25,
)
TextShimmer(
modifier = Modifier.fillMaxWidth(),
style = TangemTheme.typography2.bodyRegular15,
style = TangemTheme.typography2.bodyMedium16,
radius = TangemTheme.dimens2.x25,
)
TextShimmer(
modifier = Modifier.fillMaxWidth(fraction = 0.8f),
style = TangemTheme.typography2.bodyRegular15,
style = TangemTheme.typography2.bodyMedium16,
radius = TangemTheme.dimens2.x25,
)
}

View file

@ -14,20 +14,20 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.*
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.graphicsLayer
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.*
import com.tangem.core.ui.components.haze.hazeEffectTangem
import com.tangem.core.ui.extensions.conditionalCompose
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreviewRedesign
import dev.chrisbanes.haze.HazeState
import dev.chrisbanes.haze.rememberHazeState
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
@ -63,6 +63,7 @@ private val SMALL_DOT_SIZE = DpSize(4.dp, 4.dp)
fun TangemPagerIndicator(
pagerState: PagerState,
modifier: Modifier = Modifier,
hazeState: HazeState = rememberHazeState(),
colors: PagerIndicatorColors = TangemPagerIndicatorColors,
) {
val totalPages = pagerState.pageCount
@ -84,10 +85,12 @@ fun TangemPagerIndicator(
.width(getSize(totalPages))
.conditionalCompose(colors.overlay != null) {
colors.overlay?.let { overlay ->
background(
color = overlay,
shape = CircleShape,
)
this
.clip(CircleShape)
.hazeEffectTangem(hazeState) {
this.blurRadius = 16.dp
backgroundColor = overlay
}
} ?: this
}
.padding(TangemTheme.dimens2.x3),

View file

@ -1,8 +1,10 @@
package com.tangem.core.ui.ds.tabs
import android.content.res.Configuration
import androidx.compose.animation.core.AnimationSpec
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.snap
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
@ -86,7 +88,7 @@ fun TangemSegmentedPicker(
val density = LocalDensity.current
val itemsWidths = remember { mutableStateListOf(*Array(items.size) { 0.dp }) }
val selectedIndex = remember { mutableStateOf(items.indexOfFirstOrNull { it == initialSelectedItem } ?: 0) }
val selectedIndex = remember { mutableIntStateOf(items.indexOfFirstOrNull { it == initialSelectedItem } ?: 0) }
val segmentHeight = remember { mutableStateOf(0.dp) }
val shape = RoundedCornerShape(TangemTheme.dimens2.x25)
@ -105,7 +107,7 @@ fun TangemSegmentedPicker(
) {
SegmentSelection(
itemsWidths = itemsWidths,
selectedIndex = selectedIndex.value,
selectedIndex = selectedIndex.intValue,
segmentHeight = segmentHeight.value,
)
Row(verticalAlignment = Alignment.CenterVertically) {
@ -151,18 +153,30 @@ fun TangemSegmentedPicker(
@Composable
private fun SegmentSelection(itemsWidths: SnapshotStateList<Dp>, selectedIndex: Int, segmentHeight: Dp) {
var hasInitiallyMeasured by remember { mutableStateOf(false) }
val animationSpec: AnimationSpec<Dp> = if (hasInitiallyMeasured) {
tween(durationMillis = 300)
} else {
snap()
}
val indicatorOffset by animateDpAsState(
targetValue = itemsWidths.take(selectedIndex).fold(0.dp, Dp::plus),
animationSpec = tween(durationMillis = 300),
animationSpec = animationSpec,
label = "indicatorOffset",
)
val indicatorWidth by animateDpAsState(
targetValue = itemsWidths[selectedIndex],
animationSpec = tween(durationMillis = 300),
animationSpec = animationSpec,
label = "indicatorWidth",
)
LaunchedEffect(itemsWidths[selectedIndex] > 0.dp) {
if (itemsWidths[selectedIndex] > 0.dp) hasInitiallyMeasured = true
}
Box(
modifier = Modifier
.offset {

View file

@ -30,7 +30,7 @@ internal fun MetricsCard(
modifier = modifier
.background(
color = cardColor,
shape = RoundedCornerShape(TangemTheme.dimens2.x5),
shape = RoundedCornerShape(TangemTheme.dimens2.x6),
)
.conditional(
condition = onClick != null,
@ -67,7 +67,7 @@ private fun MetricsCardPreview() {
content = {
Text(
text = "Market cap",
style = TangemTheme.typography2.captionSemibold12,
style = TangemTheme.typography2.captionMedium12,
color = TangemTheme.colors2.text.neutral.tertiary,
)
},

View file

@ -1,14 +1,12 @@
package com.tangem.features.feed.ui.earn.components
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.res.TangemTheme
@Composable
@ -17,12 +15,7 @@ internal fun CardFilterBlock(modifier: Modifier = Modifier, content: @Composable
modifier = modifier
.fillMaxWidth()
.background(
color = TangemTheme.colors2.surface.level2,
shape = RoundedCornerShape(TangemTheme.dimens2.x5),
)
.border(
width = 1.dp,
color = TangemTheme.colors2.border.neutral.primary,
color = TangemTheme.colors2.surface.level3,
shape = RoundedCornerShape(TangemTheme.dimens2.x5),
),
content = content,

View file

@ -28,7 +28,7 @@ internal inline fun <reified T : TangemBottomSheetConfigContent> EarnFilterBotto
TangemBottomSheet<T>(
config = config,
type = TangemBottomSheetType.Modal,
containerColor = TangemTheme.colors2.surface.level3,
containerColor = TangemTheme.colors2.surface.level2,
title = {
TangemTopBar(
title = resourceReference(R.string.earn_filter_by),

View file

@ -151,7 +151,16 @@ private fun NetworksTypesBlock(
addDefaultPadding = false,
)
.clickable { onOptionClick(item) },
contentPadding = PaddingValues(horizontal = 12.dp, vertical = 12.dp),
contentPadding = PaddingValues(
start = TangemTheme.dimens2.x3,
end = TangemTheme.dimens2.x3,
top = if (index == 0) 18.dp else TangemTheme.dimens2.x3,
bottom = if (index == allMyNetworks.lastIndex) {
18.dp
} else {
TangemTheme.dimens2.x3
},
),
) {
Text(
modifier = Modifier.layoutId(layoutId = TangemRowLayoutId.START_TOP),
@ -190,7 +199,7 @@ private fun SpecificNetworksBlock(
.padding(horizontal = 16.dp)
.padding(top = 16.dp, bottom = 8.dp),
text = stringResourceSafe(id = R.string.earn_filter_networks),
style = TangemTheme.typography2.bodyRegular14,
style = TangemTheme.typography2.subheadlineMedium14,
color = TangemTheme.colors2.text.neutral.tertiary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,

View file

@ -117,13 +117,15 @@ private fun ContentV2(content: EarnFilterByTypeBottomSheetContentUM) {
overflow = TextOverflow.Ellipsis,
)
TangemCheckbox(
modifier = Modifier
.padding(start = 8.dp)
.layoutId(layoutId = TangemRowLayoutId.TAIL),
isChecked = type == content.selectedOption,
onCheckedChange = { content.onOptionClick(type) },
)
if (type == content.selectedOption) {
TangemCheckbox(
modifier = Modifier
.padding(start = 8.dp)
.layoutId(layoutId = TangemRowLayoutId.TAIL),
isChecked = true,
onCheckedChange = { content.onOptionClick(type) },
)
}
}
}
}

View file

@ -3,6 +3,7 @@ package com.tangem.features.feed.ui.earn.components
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
@ -46,7 +47,7 @@ private fun MostlyUsedCardV2(item: EarnListItemUM, onClick: () -> Unit, modifier
OpportunitiesBG(
modifier = modifier
.width(178.dp)
.clip(TangemTheme.shapes.roundedCornersXMedium)
.clip(RoundedCornerShape(TangemTheme.dimens2.x6))
.clickable(onClick = onClick),
icon = TangemIconUM.Currency(item.currencyIconState),
) {
@ -76,7 +77,7 @@ private fun MostlyUsedCardV2(item: EarnListItemUM, onClick: () -> Unit, modifier
Text(
text = item.symbol.resolveReference(),
color = TangemTheme.colors.text.tertiary,
style = TangemTheme.typography2.captionSemibold12,
style = TangemTheme.typography2.captionMedium12,
maxLines = 1,
)
}
@ -86,7 +87,7 @@ private fun MostlyUsedCardV2(item: EarnListItemUM, onClick: () -> Unit, modifier
Text(
text = item.earnValue.resolveReference(),
color = TangemTheme.colors2.text.status.positive,
style = TangemTheme.typography2.captionSemibold12,
style = TangemTheme.typography2.captionMedium12,
maxLines = 1,
)
}

View file

@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.platform.testTag
@ -21,6 +22,7 @@ import com.tangem.core.ui.extensions.conditionalCompose
import com.tangem.core.ui.res.LocalMainBottomSheetColor
import com.tangem.core.ui.res.LocalRedesignEnabled
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.res.TangemThemePreviewRedesign
import com.tangem.core.ui.test.BaseSearchBarTestTags.SEARCH_BAR
import com.tangem.features.feed.model.market.list.state.SortByTypeUM
import com.tangem.features.feed.ui.components.FeedSearchBar
@ -159,4 +161,14 @@ private fun FeedListPreview() {
TangemThemePreview {
FeedList(state = createFeedPreviewState(), contentPadding = PaddingValues())
}
}
@Preview(showBackground = true, heightDp = 1500)
@Composable
private fun FeedListPreviewV2() {
TangemThemePreviewRedesign {
CompositionLocalProvider(LocalRedesignEnabled provides true) {
FeedList(state = createFeedPreviewState(), contentPadding = PaddingValues())
}
}
}

View file

@ -32,7 +32,7 @@ internal fun ColumnScope.Header(
) {
val isRedesignEnabled = LocalRedesignEnabled.current
if (isRedesignEnabled) {
SpacerH(20.dp)
SpacerH(16.dp)
}
AnimatedContent(isLoading) { animatedState ->
Row(

View file

@ -48,18 +48,17 @@ private fun DateBlockV2(currentDate: String) {
Text(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 24.dp),
.padding(horizontal = TangemTheme.dimens2.x6),
text = stringResourceSafe(R.string.feed_market_and_news),
style = TangemTheme.typography2.headingRegular28,
style = TangemTheme.typography2.headingSemibold28,
color = TangemTheme.colors2.text.neutral.primary,
)
Text(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 24.dp),
.padding(horizontal = TangemTheme.dimens2.x6),
text = currentDate,
style = TangemTheme.typography2.headingRegular28,
color = TangemTheme.colors2.text.neutral.tertiary,
)
SpacerH(TangemTheme.dimens2.x6)
}

View file

@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
@ -117,7 +118,7 @@ internal fun ColumnScope.MarketPulseBlock(marketChartConfig: MarketChartConfig,
)
LazyRow(
modifier = Modifier.padding(vertical = if (isRedesignEnabled) 12.dp else 4.dp),
modifier = Modifier.padding(vertical = 4.dp),
verticalAlignment = Alignment.CenterVertically,
contentPadding = if (isRedesignEnabled) {
PaddingValues(horizontal = 16.dp, vertical = 6.dp)
@ -180,6 +181,11 @@ private fun Charts(
TangemTheme.colors.background.action
},
),
shape = if (isRedesignEnabled) {
RoundedCornerShape(TangemTheme.dimens2.x6)
} else {
TangemTheme.shapes.roundedCornersXMedium
},
) {
Column(modifier = Modifier.fillMaxWidth()) {
when (marketChart) {

View file

@ -6,6 +6,8 @@ import androidx.compose.foundation.layout.Column
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
@ -37,12 +39,14 @@ import com.tangem.features.feed.ui.feed.state.*
internal const val FOURTH_ITEM_INDEX = 3
private const val GRADIENT_START = 0f
private const val GRADIENT_END = 0.5f
private const val LINEAR_GRADIENT_FIRST_PART_V2 = 0xFFA3A0FF
private const val LINEAR_GRADIENT_SECOND_PART_V2 = 0xFFF79DFF
private const val LINEAR_GRADIENT_FIRST_PART_V2 = 0xFF7B78FF
private const val LINEAR_GRADIENT_SECOND_PART_V2 = 0xFFC56BCD
private const val LINEAR_GRADIENT_FIRST_PART_V1 = 0xFF635EEC
private const val LINEAR_GRADIENT_SECOND_PART_V1 = 0xFFE05AED
private const val MAGIC_ICON_COLOR = 0xFF7D78FF
@Composable
internal fun NewsBlock(feedListCallbacks: FeedListCallbacks, news: NewsUM, trendingArticle: ArticleConfigUM?) {
AnimatedContent(news.newsUMState) { newsUMState ->
@ -102,10 +106,19 @@ private fun NewsContentBlock(feedListCallbacks: FeedListCallbacks, news: NewsUM,
SpacerW(4.dp)
Image(
imageVector = ImageVector.vectorResource(R.drawable.ic_stars_20),
contentDescription = null,
)
if (isRedesignEnabled) {
Icon(
modifier = Modifier.size(TangemTheme.dimens2.x6),
tint = Color(MAGIC_ICON_COLOR),
imageVector = ImageVector.vectorResource(R.drawable.ic_magic_28),
contentDescription = null,
)
} else {
Image(
imageVector = ImageVector.vectorResource(R.drawable.ic_stars_20),
contentDescription = null,
)
}
SpacerW(2.dp)

View file

@ -45,7 +45,7 @@ internal fun NewsSlider(newsSliderConfig: NewsSliderConfig) {
articleConfigUM = article,
onArticleClick = { newsSliderConfig.callbacks.onArticleClick(article.id) },
modifier = articleModifier
.width(228.dp)
.width(280.dp)
.heightIn(min = 172.dp)
.fillMaxHeight(),
colors = TangemBlockCardColors.copy(containerColor = TangemTheme.colors.background.action),
@ -56,7 +56,7 @@ internal fun NewsSlider(newsSliderConfig: NewsSliderConfig) {
item(contentType = "show_more") {
ShowMoreArticlesCard(
modifier = Modifier
.width(228.dp)
.width(280.dp)
.heightIn(min = 172.dp)
.onFirstVisible(
minFractionVisible = 0.5f,

View file

@ -34,6 +34,7 @@ import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.LocalIsInDarkTheme
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreviewRedesign
import com.tangem.utils.StringsSigns
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toImmutableSet
@ -70,12 +71,15 @@ private fun TrendingArticle(
onClick = onArticleClick,
) {
Column(
modifier = Modifier.padding(16.dp),
modifier = Modifier.padding(TangemTheme.dimens2.x4),
horizontalAlignment = Alignment.Start,
) {
DayAndRatingInfo(rating = stringReference("${articleConfigUM.score}"))
DayAndRatingInfo(
rating = stringReference("${articleConfigUM.score}"),
createdAt = articleConfigUM.createdAt,
)
SpacerH(8.dp)
SpacerH(TangemTheme.dimens2.x2)
Text(
text = articleConfigUM.title,
@ -88,17 +92,7 @@ private fun TrendingArticle(
textAlign = TextAlign.Start,
)
SpacerH(18.dp)
Text(
text = articleConfigUM.createdAt.resolveReference(),
style = TangemTheme.typography2.captionSemibold12,
color = TangemTheme.colors2.text.neutral.secondary,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
)
SpacerH(18.dp)
SpacerH(TangemTheme.dimens2.x8)
Tags(tags = articleConfigUM.tags.toImmutableList())
}
@ -111,14 +105,9 @@ internal fun ShowMoreArticlesCardV2(modifier: Modifier = Modifier, onClick: () -
horizontalAlignment = Alignment.CenterHorizontally,
modifier = modifier
.fillMaxSize()
.clip(RoundedCornerShape(20.dp))
.clip(RoundedCornerShape(TangemTheme.dimens2.x6))
.background(color = TangemTheme.colors2.surface.level3)
.clickable(onClick = onClick)
.border(
width = 1.dp,
color = TangemTheme.colors2.border.neutral.primary,
shape = RoundedCornerShape(20.dp),
)
.padding(vertical = 41.dp, horizontal = 16.dp),
) {
Image(
@ -139,7 +128,7 @@ internal fun ShowMoreArticlesCardV2(modifier: Modifier = Modifier, onClick: () -
Text(
text = stringResourceSafe(R.string.news_stay_in_the_loop),
style = TangemTheme.typography2.captionSemibold12,
style = TangemTheme.typography2.captionMedium12,
color = TangemTheme.colors2.text.neutral.secondary,
)
}
@ -153,24 +142,20 @@ private fun DefaultArticle(
) {
Column(
modifier = modifier
.clip(RoundedCornerShape(20.dp))
.clip(RoundedCornerShape(TangemTheme.dimens2.x6))
.background(color = TangemTheme.colors2.surface.level3)
.clickable(onClick = onArticleClick)
.border(
width = 1.dp,
color = TangemTheme.colors2.border.neutral.primary,
shape = RoundedCornerShape(20.dp),
)
.padding(16.dp),
.padding(TangemTheme.dimens2.x4),
) {
Row(verticalAlignment = Alignment.CenterVertically) {
RatingInfo(
rating = stringReference("${articleConfigUM.score}"),
isTrending = false,
createdAt = articleConfigUM.createdAt,
)
}
SpacerH(8.dp)
SpacerH(TangemTheme.dimens2.x2)
Text(
modifier = Modifier.weight(1f),
@ -185,17 +170,7 @@ private fun DefaultArticle(
overflow = TextOverflow.Ellipsis,
)
SpacerH(8.dp)
Text(
text = articleConfigUM.createdAt.resolveReference(),
style = TangemTheme.typography2.captionSemibold12,
color = TangemTheme.colors2.text.neutral.secondary,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
)
SpacerH(8.dp)
SpacerH(TangemTheme.dimens2.x8)
Tags(tags = articleConfigUM.tags.toImmutableList())
}
@ -220,7 +195,7 @@ private fun TrendingArticleBackground(
Box(
modifier = modifier
.clip(RoundedCornerShape(20.dp))
.clip(RoundedCornerShape(TangemTheme.dimens2.x6))
.drawBehind {
drawRect(bgColor)
@ -279,45 +254,61 @@ private fun TrendingArticleBackground(
}
@Composable
private fun DayAndRatingInfo(rating: TextReference, modifier: Modifier = Modifier) {
private fun DayAndRatingInfo(createdAt: TextReference, rating: TextReference, modifier: Modifier = Modifier) {
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
) {
RatingInfo(rating = rating, isTrending = true)
RatingInfo(rating = rating, isTrending = true, createdAt = createdAt)
SpacerW(8.dp)
Text(
text = stringResourceSafe(R.string.feed_trending_now),
style = TangemTheme.typography2.captionSemibold12,
style = TangemTheme.typography2.captionMedium12,
color = TangemTheme.colors2.text.neutral.primary,
)
}
}
@Composable
private fun RatingInfo(rating: TextReference, isTrending: Boolean) {
private fun RatingInfo(rating: TextReference, isTrending: Boolean, createdAt: TextReference) {
val iconTint = if (isTrending) {
TangemTheme.colors2.fill.status.attention
} else {
TangemTheme.colors2.markers.iconGray
}
val captionColor = if (isTrending) {
TangemTheme.colors2.text.status.attention
} else {
TangemTheme.colors2.text.neutral.secondary
}
Icon(
imageVector = ImageVector.vectorResource(R.drawable.ic_wrapped_circle_star_16),
tint = if (isTrending) {
TangemTheme.colors2.fill.status.attention
} else {
TangemTheme.colors2.markers.iconGray
},
tint = iconTint,
contentDescription = null,
)
SpacerW(2.dp)
SpacerW(TangemTheme.dimens2.x1)
Text(
text = rating.resolveReference(),
color = if (isTrending) {
TangemTheme.colors2.text.status.attention
} else {
TangemTheme.colors2.text.neutral.secondary
},
style = TangemTheme.typography2.captionSemibold12,
color = captionColor,
style = TangemTheme.typography2.captionMedium12,
)
Text(
modifier = Modifier.padding(horizontal = TangemTheme.dimens2.x0_5),
text = StringsSigns.DOT,
color = captionColor,
style = TangemTheme.typography2.captionMedium12,
)
Text(
text = createdAt.resolveReference(),
color = captionColor,
style = TangemTheme.typography2.captionMedium12,
)
}

View file

@ -3,7 +3,6 @@ package com.tangem.features.feed.ui.feed.components.articles
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.material3.VerticalDivider
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -12,22 +11,16 @@ import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.R
import com.tangem.core.ui.components.SpacerW
import com.tangem.core.ui.components.label.Label
import com.tangem.core.ui.components.label.entity.LabelLeadingContentUM
import com.tangem.core.ui.components.label.entity.LabelUM
import com.tangem.core.ui.ds.badge.TangemBadge
import com.tangem.core.ui.ds.badge.TangemBadgeColor
import com.tangem.core.ui.ds.badge.TangemBadgeIconPosition
import com.tangem.core.ui.ds.badge.TangemBadgeShape
import com.tangem.core.ui.ds.badge.TangemBadgeSize
import com.tangem.core.ui.ds.badge.TangemBadgeType
import com.tangem.core.ui.ds.badge.*
import com.tangem.core.ui.ds.image.TangemIconUM
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.LocalRedesignEnabled
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.res.TangemThemePreviewRedesign
import com.tangem.utils.StringsSigns
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
@ -100,7 +93,6 @@ private fun ArticleHeaderV1(
}
}
@OptIn(ExperimentalLayoutApi::class)
@Composable
private fun ArticleHeaderV2(
isTrending: Boolean,
@ -111,127 +103,121 @@ private fun ArticleHeaderV2(
modifier: Modifier = Modifier,
) {
Column(modifier = modifier) {
Row(
modifier = Modifier
.heightIn(min = 66.dp)
.padding(top = 16.dp),
verticalAlignment = Alignment.Bottom,
) {
DateBlock(
modifier = Modifier.weight(1f),
createdAt = createdAt,
)
SpacerW(30.dp)
VerticalDivider(
modifier = Modifier
.height(46.dp)
.padding(bottom = 4.dp),
color = TangemTheme.colors2.border.neutral.primary,
)
SpacerW(30.dp)
ScoreBlock(
modifier = Modifier.weight(1f),
score = score,
isTrending = isTrending,
)
}
Text(
modifier = Modifier.padding(vertical = 36.dp),
text = title,
style = TangemTheme.typography2.headingBold34,
color = TangemTheme.colors2.text.neutral.primary,
ArticleHeaderV2MetaRow(
isTrending = isTrending,
score = score,
createdAt = createdAt,
)
if (tags.isNotEmpty()) {
Spacer(modifier = Modifier.height(20.dp))
FlowRow(
horizontalArrangement = Arrangement.spacedBy(4.dp),
verticalArrangement = Arrangement.spacedBy(4.dp),
) {
tags.forEach { tag ->
TangemBadge(
text = tag.text,
tangemIconUM = when (val content = tag.leadingContent) {
LabelLeadingContentUM.None -> null
is LabelLeadingContentUM.Token -> TangemIconUM.Url(
url = content.iconUrl,
fallbackRes = R.drawable.ic_alert_24,
)
},
shape = TangemBadgeShape.Rounded,
size = TangemBadgeSize.X9,
type = TangemBadgeType.Tinted,
color = TangemBadgeColor.Gray,
iconPosition = when (tag.leadingContent) {
LabelLeadingContentUM.None -> TangemBadgeIconPosition.None
is LabelLeadingContentUM.Token -> TangemBadgeIconPosition.Start
},
)
}
}
}
ArticleHeaderV2Title(title = title)
ArticleHeaderV2Tags(tags = tags)
}
}
@Composable
private fun ScoreBlock(score: Float, isTrending: Boolean, modifier: Modifier = Modifier) {
Column(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(10.dp),
private fun ArticleHeaderV2MetaRow(isTrending: Boolean, score: Float, createdAt: String) {
val starTint = if (isTrending) {
TangemTheme.colors2.fill.status.attention
} else {
TangemTheme.colors2.graphic.neutral.primary
}
val scoreColor = if (isTrending) {
TangemTheme.colors2.text.status.attention
} else {
TangemTheme.colors2.text.neutral.tertiary
}
Row(
modifier = Modifier.padding(horizontal = TangemTheme.dimens2.x1),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x2),
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(10.dp),
) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = ImageVector.vectorResource(R.drawable.ic_wrapped_circle_star_16),
tint = if (isTrending) {
TangemTheme.colors2.fill.status.attention
} else {
TangemTheme.colors2.graphic.neutral.primary
},
contentDescription = null,
)
Text(
text = score.toString(),
style = TangemTheme.typography2.bodyRegular16,
color = if (isTrending) {
TangemTheme.colors2.text.status.attention
} else {
TangemTheme.colors2.text.neutral.primary
},
)
}
Icon(
modifier = Modifier.size(TangemTheme.dimens2.x5),
imageVector = ImageVector.vectorResource(R.drawable.ic_wrapped_circle_star_16),
tint = starTint,
contentDescription = null,
)
Text(
text = stringResourceSafe(R.string.news_trending_score),
style = TangemTheme.typography2.captionSemibold13,
text = score.toString(),
style = TangemTheme.typography2.bodyMedium16,
color = scoreColor,
)
Text(
text = StringsSigns.DOT,
color = TangemTheme.colors2.text.neutral.tertiary,
style = TangemTheme.typography2.bodyMedium16,
)
}
}
@Composable
private fun DateBlock(createdAt: String, modifier: Modifier = Modifier) {
Column(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(10.dp),
) {
Icon(
modifier = Modifier.size(20.dp),
imageVector = ImageVector.vectorResource(R.drawable.ic_calendar_20),
tint = TangemTheme.colors2.fill.neutral.primary,
tint = TangemTheme.colors2.graphic.neutral.secondary,
contentDescription = null,
)
Text(
text = createdAt,
style = TangemTheme.typography2.captionSemibold13,
color = TangemTheme.colors2.text.neutral.tertiary,
style = TangemTheme.typography2.bodyMedium16,
)
}
}
@Composable
private fun ArticleHeaderV2Title(title: String) {
Text(
modifier = Modifier
.padding(
top = TangemTheme.dimens2.x4,
bottom = TangemTheme.dimens2.x1_5,
start = TangemTheme.dimens2.x1,
),
text = title,
style = TangemTheme.typography2.headingSemibold28,
color = TangemTheme.colors2.text.neutral.primary,
)
}
@OptIn(ExperimentalLayoutApi::class)
@Composable
private fun ArticleHeaderV2Tags(tags: ImmutableList<LabelUM>) {
if (tags.isEmpty()) return
Spacer(modifier = Modifier.height(TangemTheme.dimens2.x6))
FlowRow(
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x1),
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x1),
) {
tags.forEach { tag ->
ArticleHeaderTagBadge(tag = tag)
}
}
}
@Composable
private fun ArticleHeaderTagBadge(tag: LabelUM) {
TangemBadge(
text = tag.text,
tangemIconUM = labelLeadingIcon(tag.leadingContent),
shape = TangemBadgeShape.Rounded,
size = TangemBadgeSize.X9,
type = TangemBadgeType.Tinted,
color = TangemBadgeColor.Gray,
iconPosition = labelLeadingBadgeIconPosition(tag.leadingContent),
)
}
private fun labelLeadingIcon(content: LabelLeadingContentUM): TangemIconUM? = when (content) {
LabelLeadingContentUM.None -> null
is LabelLeadingContentUM.Token -> TangemIconUM.Url(
url = content.iconUrl,
fallbackRes = R.drawable.ic_alert_24,
)
}
private fun labelLeadingBadgeIconPosition(content: LabelLeadingContentUM): TangemBadgeIconPosition = when (content) {
LabelLeadingContentUM.None -> TangemBadgeIconPosition.None
is LabelLeadingContentUM.Token -> TangemBadgeIconPosition.Start
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun ArticleHeaderPreviewV1() {

View file

@ -265,7 +265,7 @@ internal object FeedListPreviewDataProvider {
}
private fun createEarnListItemsUM(): ImmutableList<EarnListItemUM> {
return List(5) {
return List(1) {
EarnListItemUM(
network = stringReference("Ethereum"),
symbol = stringReference("USDT"),

View file

@ -125,7 +125,9 @@ private fun Content(
.fillMaxWidth(),
)
}
item { SpacerH16() }
item {
if (isRedesignEnabled) SpacerH(TangemTheme.dimens2.x3) else SpacerH16()
}
item("intervalSelector") {
IntervalSelector(
trendInterval = state.selectedInterval,
@ -136,7 +138,9 @@ private fun Content(
.fillMaxWidth(),
)
}
item { SpacerH32() }
item {
if (isRedesignEnabled) SpacerH(TangemTheme.dimens2.x3) else SpacerH32()
}
item("chart") {
MarketTokenDetailsChart(
modifier = Modifier.fillMaxWidth(),

View file

@ -11,7 +11,6 @@ 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.res.vectorResource
import androidx.compose.ui.text.style.TextOverflow
@ -26,8 +25,6 @@ internal fun InformationTextBlock(
text: TextReference,
modifier: Modifier = Modifier,
onInfoClick: (() -> Unit)? = null,
textColor: Color = TangemTheme.colors2.text.neutral.tertiary,
infoIconColor: Color = TangemTheme.colors2.markers.iconGray,
informationTextBlockIconPosition: InformationTextBlockIconPosition = InformationTextBlockIconPosition.START,
) {
val interactionSource = remember { MutableInteractionSource() }
@ -36,7 +33,7 @@ internal fun InformationTextBlock(
Icon(
modifier = Modifier.size(TangemTheme.dimens2.x4),
imageVector = ImageVector.vectorResource(id = R.drawable.ic_information_24),
tint = infoIconColor,
tint = TangemTheme.colors2.fill.neutral.secondary,
contentDescription = null,
)
}
@ -44,8 +41,8 @@ internal fun InformationTextBlock(
val contentText: @Composable () -> Unit = {
Text(
text = text.resolveReference(),
style = TangemTheme.typography2.captionSemibold12,
color = textColor,
style = TangemTheme.typography2.captionMedium12,
color = TangemTheme.colors2.text.neutral.secondary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)

View file

@ -14,10 +14,10 @@ import com.tangem.core.ui.components.TextShimmer
import com.tangem.core.ui.components.block.information.InformationBlock
import com.tangem.core.ui.components.buttons.chip.Chip
import com.tangem.core.ui.components.inputrow.inner.DividerContainer
import com.tangem.core.ui.ds.badge.TangemBadge
import com.tangem.core.ui.ds.badge.TangemBadgeIconPosition
import com.tangem.core.ui.ds.badge.TangemBadgeShape
import com.tangem.core.ui.ds.badge.TangemBadgeSize
import com.tangem.core.ui.ds.button.SecondaryTangemButton
import com.tangem.core.ui.ds.button.TangemButtonIconPosition
import com.tangem.core.ui.ds.button.TangemButtonShape
import com.tangem.core.ui.ds.button.TangemButtonSize
import com.tangem.core.ui.ds.image.TangemIconUM
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.extensions.stringResourceSafe
@ -174,7 +174,7 @@ private fun SubBlockV2(
Text(
modifier = Modifier.padding(start = 10.dp, top = TangemTheme.dimens2.x4),
text = title,
style = TangemTheme.typography2.bodySemibold16,
style = TangemTheme.typography2.headingSemibold20,
color = TangemTheme.colors2.text.neutral.primary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
@ -185,16 +185,16 @@ private fun SubBlockV2(
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x2),
) {
links.fastForEach { link ->
TangemBadge(
text = stringReference(link.title),
SecondaryTangemButton(
onClick = { onLinkClick(link) },
iconPosition = TangemBadgeIconPosition.Start,
text = stringReference(link.title),
iconPosition = TangemButtonIconPosition.Start,
tangemIconUM = TangemIconUM.Icon(
iconRes = link.iconRes,
tintReference = { TangemTheme.colors2.markers.iconGray },
tintReference = { TangemTheme.colors2.graphic.neutral.primary },
),
size = TangemBadgeSize.X9,
shape = TangemBadgeShape.Rounded,
size = TangemButtonSize.X9,
shape = TangemButtonShape.Rounded,
)
}
}

View file

@ -94,18 +94,18 @@ private fun ListedOnBlockV2(state: ListedOnUM, modifier: Modifier = Modifier) {
},
title = {
Row(verticalAlignment = Alignment.CenterVertically) {
Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
Column(verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x1)) {
Text(
text = state.title.resolveReference(),
style = TangemTheme.typography2.headingSemibold20,
color = TangemTheme.colors2.text.neutral.primary,
style = TangemTheme.typography2.captionMedium12,
color = TangemTheme.colors2.text.neutral.secondary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
Text(
text = state.description.resolveReference(),
style = TangemTheme.typography2.captionSemibold13,
color = TangemTheme.colors2.text.neutral.secondary,
style = TangemTheme.typography2.headingSemibold20,
color = TangemTheme.colors2.text.neutral.primary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
@ -114,7 +114,7 @@ private fun ListedOnBlockV2(state: ListedOnUM, modifier: Modifier = Modifier) {
SpacerWMax()
Icon(
modifier = Modifier.size(20.dp),
modifier = Modifier.size(TangemTheme.dimens2.x5),
imageVector = ImageVector.vectorResource(R.drawable.ic_chevron_small_right_24),
tint = TangemTheme.colors2.markers.iconGray,
contentDescription = null,
@ -165,7 +165,7 @@ internal fun ListedOnBlockPlaceholderV2(modifier: Modifier = Modifier) {
radius = TangemTheme.dimens2.x25,
)
TextShimmer(
style = TangemTheme.typography2.captionSemibold13,
style = TangemTheme.typography2.captionMedium13,
modifier = Modifier.width(66.dp),
radius = TangemTheme.dimens2.x25,
)

View file

@ -42,7 +42,7 @@ import com.tangem.features.feed.ui.market.detailed.state.TrendingVolumeLiquidity
internal fun MarketCapCard(item: InfoPointUMV2.MarketCap) {
MetricsCard(
modifier = Modifier
.heightIn(120.dp)
.heightIn(104.dp)
.fillMaxWidth(),
title = { MetricValueText(value = item.capitalizationValue) },
content = {
@ -66,7 +66,7 @@ internal fun TradingVolumeCard(item: InfoPointUMV2.TradingVolume) {
MetricsCard(
modifier = Modifier
.heightIn(120.dp)
.heightIn(104.dp)
.fillMaxWidth(),
title = {
Row {
@ -74,7 +74,7 @@ internal fun TradingVolumeCard(item: InfoPointUMV2.TradingVolume) {
Text(
modifier = Modifier.padding(TangemTheme.dimens2.x1),
text = stringResourceSafe(R.string.markets_token_details_trading_interval),
style = TangemTheme.typography2.captionSemibold11,
style = TangemTheme.typography2.captionMedium11,
color = valueColor,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
@ -97,24 +97,21 @@ internal fun TradingVolumeCard(item: InfoPointUMV2.TradingVolume) {
SpacerH(12.dp)
InformationTextBlock(
text = resourceReference(R.string.markets_token_details_trading_volume),
textColor = tradingColor,
infoIconColor = tradingColor,
onInfoClick = item.onInfoClick,
)
}
},
cardColor = tradingColor.copy(alpha = .2f),
cardColor = TangemTheme.colors2.surface.level3,
)
}
@Composable
internal fun MarketPositionCard(item: InfoPointUMV2.MarketPosition) {
val ratingCardColor = mapRatingToCardColor(marketRatingType = item.marketRatingType)
val ratingColor = mapRatingToColor(marketRatingType = item.marketRatingType)
MetricsCard(
modifier = Modifier
.heightIn(120.dp)
.heightIn(104.dp)
.fillMaxWidth(),
title = {
Row(verticalAlignment = Alignment.CenterVertically) {
@ -140,13 +137,11 @@ internal fun MarketPositionCard(item: InfoPointUMV2.MarketPosition) {
SpacerH(12.dp)
InformationTextBlock(
text = resourceReference(R.string.markets_token_details_market_rating),
textColor = ratingColor,
infoIconColor = ratingColor,
onInfoClick = item.onInfoClick,
)
}
},
cardColor = ratingCardColor,
cardColor = TangemTheme.colors2.surface.level3,
)
}
@ -154,7 +149,7 @@ internal fun MarketPositionCard(item: InfoPointUMV2.MarketPosition) {
internal fun FDVCard(item: InfoPointUMV2.FullyDilutedValuation) {
MetricsCard(
modifier = Modifier
.heightIn(120.dp)
.heightIn(104.dp)
.fillMaxWidth(),
title = {
if (item.fullyDilutedValuationChange24 != null) {
@ -163,7 +158,7 @@ internal fun FDVCard(item: InfoPointUMV2.FullyDilutedValuation) {
Text(
modifier = Modifier.padding(TangemTheme.dimens2.x1),
text = stringResourceSafe(R.string.markets_token_details_trading_interval),
style = TangemTheme.typography2.captionSemibold11,
style = TangemTheme.typography2.captionMedium11,
color = TangemTheme.colors2.text.neutral.primary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
@ -179,7 +174,7 @@ internal fun FDVCard(item: InfoPointUMV2.FullyDilutedValuation) {
Text(
text = item.value?.resolveReference()
?: stringResourceSafe(R.string.token_market_metrics_no_data),
style = TangemTheme.typography2.captionSemibold12,
style = TangemTheme.typography2.captionMedium12,
color = TangemTheme.colors2.text.neutral.primary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
@ -200,14 +195,14 @@ internal fun FDVCard(item: InfoPointUMV2.FullyDilutedValuation) {
internal fun CirculatingSupplyCard(item: InfoPointUMV2.CirculatingSupply) {
MetricsCard(
modifier = Modifier
.heightIn(min = if (item.fillValue == null) 88.dp else 114.dp)
.heightIn(min = if (item.fillValue == null) 88.dp else 106.dp)
.fillMaxWidth(),
title = {
TangemRowContainer(contentPadding = PaddingValues(0.dp)) {
Text(
modifier = Modifier.layoutId(TangemRowLayoutId.START_TOP),
text = stringResourceSafe(R.string.markets_token_details_circulating_supply),
style = TangemTheme.typography2.captionSemibold13,
style = TangemTheme.typography2.captionMedium12,
color = TangemTheme.colors2.text.neutral.tertiary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
@ -223,7 +218,7 @@ internal fun CirculatingSupplyCard(item: InfoPointUMV2.CirculatingSupply) {
Text(
modifier = Modifier.layoutId(TangemRowLayoutId.END_TOP),
text = stringResourceSafe(R.string.markets_token_details_max_supply),
style = TangemTheme.typography2.captionSemibold13,
style = TangemTheme.typography2.captionMedium12,
color = TangemTheme.colors2.text.neutral.tertiary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
@ -235,7 +230,7 @@ internal fun CirculatingSupplyCard(item: InfoPointUMV2.CirculatingSupply) {
.padding(top = 12.dp)
.layoutId(TangemRowLayoutId.END_BOTTOM),
text = item.maxValue.resolveReference(),
style = TangemTheme.typography2.headingSemibold22,
style = TangemTheme.typography2.headingSemibold20,
color = TangemTheme.colors2.text.neutral.primary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
@ -270,7 +265,7 @@ private fun MetricValueText(value: TextReference?, modifier: Modifier = Modifier
Text(
modifier = modifier,
text = value?.resolveReference() ?: stringResourceSafe(R.string.token_market_metrics_no_data),
style = TangemTheme.typography2.headingSemibold22,
style = TangemTheme.typography2.headingSemibold20,
color = metricValueColor(hasData = value != null),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
@ -338,7 +333,7 @@ private fun RatingChangeContent(iconRes: Int, iconTint: Color, changeValue: Stri
SpacerW(2.dp)
Text(
text = changeValue,
style = TangemTheme.typography2.captionSemibold12,
style = TangemTheme.typography2.captionMedium12,
color = textColor,
)
}
@ -366,14 +361,6 @@ private fun MarketRatingType.baseColor(): Color {
@Composable
private fun mapRatingToColor(marketRatingType: MarketRatingType): Color = marketRatingType.baseColor()
@Composable
private fun mapRatingToCardColor(marketRatingType: MarketRatingType): Color {
return when (marketRatingType) {
MarketRatingType.OTHER -> TangemTheme.colors2.surface.level3
else -> marketRatingType.baseColor().copy(alpha = 0.3f)
}
}
// endregion
private const val GOLD_PLACE_COLOR_NIGHT = 0xFFFBEE76

View file

@ -27,7 +27,7 @@ import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.res.TangemThemePreviewRedesign
import com.tangem.core.ui.utils.PreviewShimmerContainer
import com.tangem.features.feed.impl.R
import com.tangem.features.feed.ui.components.ContainerWithDivider
import com.tangem.features.feed.ui.components.TokenMarketInformationBlock
import com.tangem.features.feed.ui.market.detailed.state.SecurityScoreUM
@Composable
@ -80,45 +80,42 @@ private fun SecurityScoreBlockV1(state: SecurityScoreUM, modifier: Modifier = Mo
@Composable
private fun SecurityScoreBlockV2(state: SecurityScoreUM, modifier: Modifier = Modifier) {
ContainerWithDivider(
TokenMarketInformationBlock(
modifier = modifier,
showDivider = true,
) {
TangemRowContainer(modifier = Modifier.padding(top = 20.dp, bottom = 24.dp)) {
Text(
modifier = Modifier.layoutId(layoutId = TangemRowLayoutId.START_TOP),
text = "${state.score}",
color = TangemTheme.colors2.text.neutral.primary,
style = TangemTheme.typography2.headingBold28,
)
title = {
TangemRowContainer(contentPadding = PaddingValues()) {
Text(
modifier = Modifier.layoutId(layoutId = TangemRowLayoutId.START_TOP),
text = "${state.score}",
color = TangemTheme.colors2.text.neutral.primary,
style = TangemTheme.typography2.headingSemibold20,
)
InformationTextBlock(
modifier = Modifier.layoutId(layoutId = TangemRowLayoutId.START_BOTTOM),
text = resourceReference(R.string.markets_token_details_security_score),
onInfoClick = state.onInfoClick,
textColor = TangemTheme.colors2.text.neutral.primary,
informationTextBlockIconPosition = InformationTextBlockIconPosition.END,
)
InformationTextBlock(
modifier = Modifier.layoutId(layoutId = TangemRowLayoutId.START_BOTTOM),
text = resourceReference(R.string.markets_token_details_security_score),
onInfoClick = state.onInfoClick,
informationTextBlockIconPosition = InformationTextBlockIconPosition.START,
)
Text(
modifier = Modifier.layoutId(layoutId = TangemRowLayoutId.END_BOTTOM),
text = state.description.resolveReference(),
style = TangemTheme.typography2.captionSemibold12,
color = TangemTheme.colors2.text.neutral.tertiary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
Text(
modifier = Modifier.layoutId(layoutId = TangemRowLayoutId.END_BOTTOM),
text = state.description.resolveReference(),
style = TangemTheme.typography2.captionMedium12,
color = TangemTheme.colors2.text.neutral.secondary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
ScoreStarsBlock(
modifier = Modifier
.padding(bottom = 16.dp)
.layoutId(layoutId = TangemRowLayoutId.END_TOP),
score = state.score,
scoreTextStyle = TangemTheme.typography.body1,
horizontalSpacing = TangemTheme.dimens.spacing8,
)
}
}
ScoreStarsBlock(
modifier = Modifier.layoutId(layoutId = TangemRowLayoutId.END_TOP),
score = state.score,
scoreTextStyle = TangemTheme.typography.body1,
horizontalSpacing = TangemTheme.dimens.spacing8,
)
}
},
)
}
@Composable
@ -146,7 +143,7 @@ private fun SecurityScoreBlockPlaceholderV2(modifier: Modifier = Modifier) {
.width(74.dp)
.padding(top = 8.dp)
.layoutId(layoutId = TangemRowLayoutId.START_BOTTOM),
style = TangemTheme.typography2.captionSemibold12,
style = TangemTheme.typography2.captionMedium12,
radius = TangemTheme.dimens2.x25,
)
@ -163,7 +160,7 @@ private fun SecurityScoreBlockPlaceholderV2(modifier: Modifier = Modifier) {
.width(96.dp)
.padding(top = 8.dp)
.layoutId(layoutId = TangemRowLayoutId.END_BOTTOM),
style = TangemTheme.typography2.captionSemibold12,
style = TangemTheme.typography2.captionMedium12,
radius = TangemTheme.dimens2.x25,
)
}

View file

@ -11,7 +11,9 @@ import androidx.compose.ui.unit.dp
import com.tangem.core.ui.components.UnableToLoadData
import com.tangem.core.ui.components.items.DescriptionItem
import com.tangem.core.ui.components.items.DescriptionPlaceholder
import com.tangem.core.ui.extensions.conditionalCompose
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.LocalRedesignEnabled
import com.tangem.core.ui.res.TangemTheme
import com.tangem.features.feed.impl.R
import com.tangem.features.feed.ui.feed.components.NewsSlider
@ -161,7 +163,18 @@ private fun LazyListScope.aboutCoinHeader() {
private fun LazyListScope.description(description: MarketsTokenDetailsUM.Description) {
item("description") {
DescriptionItem(
modifier = Modifier.blockPaddings(),
modifier = Modifier
.conditionalCompose(
condition = LocalRedesignEnabled.current,
modifier = {
this
.padding(horizontal = TangemTheme.dimens2.x4)
.padding(bottom = TangemTheme.dimens2.x8)
},
otherModifier = {
blockPaddings()
},
),
description = description.shortDescription,
hasFullDescription = description.fullDescription != null,
onReadMoreClick = description.onReadMoreClick,
@ -249,12 +262,6 @@ internal fun LazyListScope.infoBlocksListV2(state: MarketsTokenDetailsUM.Informa
)
}
if (relatedNews.articles.isNotEmpty()) {
relatedNews(relatedNews)
} else {
sectionStub(RelatedNews.SECTION_KEY)
}
if (state.securityScore != null) {
item("securityScore") {
SecurityScoreBlock(
@ -264,6 +271,12 @@ internal fun LazyListScope.infoBlocksListV2(state: MarketsTokenDetailsUM.Informa
}
}
if (relatedNews.articles.isNotEmpty()) {
relatedNewsV2(relatedNews)
} else {
sectionStub(RelatedNews.SECTION_KEY)
}
if (state.links != null) {
item("links") {
LinksBlock(
@ -367,11 +380,52 @@ private fun LazyListScope.relatedNews(relatedNews: RelatedNews) {
}
}
private fun LazyListScope.relatedNewsV2(relatedNews: RelatedNews) {
item(RelatedNews.SECTION_KEY) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = TangemTheme.dimens2.x8)
.onFirstVisible(
minFractionVisible = 0.5f,
callback = relatedNews.onFirstVisible,
),
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x3),
) {
Text(
modifier = Modifier.padding(start = TangemTheme.dimens2.x6),
text = stringResourceSafe(R.string.news_related_news),
style = TangemTheme.typography2.headingSemibold20,
color = TangemTheme.colors2.text.neutral.primary,
)
NewsSlider(
NewsSliderConfig(
callbacks = NewsSliderCallbacks(
onOpenAllNews = {}, // not applicable here
onSliderScroll = relatedNews.onScroll,
onSliderEndReached = {}, // not applicable here
onArticleClick = relatedNews.onArticledClicked,
),
content = relatedNews.articles,
shouldShowSeeAllNewsItem = false,
),
)
}
}
}
@Composable
private fun Modifier.blockPaddings(): Modifier {
return this.padding(
start = TangemTheme.dimens.spacing16,
end = TangemTheme.dimens.spacing16,
bottom = TangemTheme.dimens.spacing12,
)
return if (LocalRedesignEnabled.current) {
this
.padding(horizontal = TangemTheme.dimens2.x4)
.padding(bottom = TangemTheme.dimens2.x2)
} else {
this.padding(
start = TangemTheme.dimens.spacing16,
end = TangemTheme.dimens.spacing16,
bottom = TangemTheme.dimens.spacing12,
)
}
}

View file

@ -22,6 +22,9 @@ import com.tangem.features.feed.ui.news.details.components.NewsDetailsPlaceholde
import com.tangem.features.feed.ui.news.details.state.ArticlesStateUM
import com.tangem.features.feed.ui.news.details.state.MockArticlesFactory
import com.tangem.features.feed.ui.news.details.state.NewsDetailsUM
import dev.chrisbanes.haze.rememberHazeState
private const val PAGER_BG_ALPHA = .1f
@Composable
internal fun NewsDetailsContent(state: NewsDetailsUM, contentPadding: PaddingValues, modifier: Modifier = Modifier) {
@ -64,6 +67,7 @@ private fun Content(contentPadding: PaddingValues, state: NewsDetailsUM, backgro
initialPage = state.selectedArticleIndex,
pageCount = { state.articles.size },
)
val localHaze = rememberHazeState()
if (state.articles.isNotEmpty()) {
LaunchedEffect(pagerState) {
@ -98,6 +102,7 @@ private fun Content(contentPadding: PaddingValues, state: NewsDetailsUM, backgro
onLikeClick = { state.onLikeClick(article.id) },
relatedTokensUM = state.relatedTokensUM,
contentPadding = contentPadding,
hazeState = localHaze,
)
}
if (state.articles.size > 1) {
@ -108,8 +113,9 @@ private fun Content(contentPadding: PaddingValues, state: NewsDetailsUM, backgro
.align(Alignment.BottomCenter)
.windowInsetsPadding(WindowInsets.navigationBars),
colors = TangemPagerIndicatorColors.copy(
overlay = TangemTheme.colors2.tabs.backgroundSecondary.copy(alpha = .1f),
overlay = TangemTheme.colors2.tabs.backgroundSecondary.copy(PAGER_BG_ALPHA),
),
hazeState = localHaze,
)
} else {
PagerIndicator(

View file

@ -6,7 +6,6 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
@ -19,7 +18,6 @@ import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.R
import com.tangem.core.ui.components.BottomFade
import com.tangem.core.ui.components.BottomFadeWithBlur
import com.tangem.core.ui.components.SecondaryButtonIconStart
import com.tangem.core.ui.components.SpacerH
import com.tangem.core.ui.components.buttons.common.TangemButtonSize
@ -38,10 +36,11 @@ import com.tangem.features.feed.ui.feed.components.articles.ArticleHeader
import com.tangem.features.feed.ui.news.details.state.ArticleUM
import com.tangem.features.feed.ui.news.details.state.RelatedArticleUM
import com.tangem.features.feed.ui.news.details.state.RelatedTokensUM
import dev.chrisbanes.haze.rememberHazeState
import dev.chrisbanes.haze.HazeState
@Composable
internal fun ArticleDetail(
hazeState: HazeState,
contentPadding: PaddingValues,
article: ArticleUM,
onLikeClick: () -> Unit,
@ -55,6 +54,7 @@ internal fun ArticleDetail(
onLikeClick = onLikeClick,
relatedTokensUM = relatedTokensUM,
modifier = modifier,
hazeState = hazeState,
)
} else {
ArticleDetailV1(
@ -195,7 +195,8 @@ private fun ArticleDetailV1(
@Suppress("LongMethod")
@Composable
internal fun ArticleDetailV2(
private fun ArticleDetailV2(
hazeState: HazeState,
contentPadding: PaddingValues,
article: ArticleUM,
onLikeClick: () -> Unit,
@ -206,16 +207,16 @@ internal fun ArticleDetailV2(
val density = LocalDensity.current
val background = LocalMainBottomSheetColor.current.value
val pagerHeight = 32.dp
val bottomPadding = pagerHeight + 56.dp + with(density) {
val bottomPadding = pagerHeight + TangemTheme.dimens2.x4 + with(density) {
WindowInsets.navigationBars.getBottom(this).div(this.density)
}.dp
CompositionLocalProvider(LocalHazeState provides rememberHazeState()) {
CompositionLocalProvider(LocalHazeState provides hazeState) {
Box(modifier = modifier) {
LazyColumn(
modifier = Modifier
.fillMaxSize()
.hazeSourceTangem(zIndex = -1f)
.hazeSourceTangem(hazeState)
.background(background),
contentPadding = PaddingValues(bottom = bottomPadding, top = contentPadding.calculateTopPadding()),
) {
@ -227,39 +228,27 @@ internal fun ArticleDetailV2(
tags = article.tags,
isTrending = article.isTrending,
modifier = Modifier
.padding(top = 16.dp)
.padding(horizontal = 16.dp),
.padding(top = TangemTheme.dimens2.x1_5, bottom = TangemTheme.dimens2.x6)
.padding(horizontal = TangemTheme.dimens2.x4),
)
if (article.shortContent.isNotEmpty()) {
QuickRecap(
content = article.shortContent,
modifier = Modifier
.padding(top = 32.dp)
.padding(horizontal = 16.dp),
modifier = Modifier.padding(horizontal = TangemTheme.dimens2.x4),
)
}
Text(
text = article.content,
style = TangemTheme.typography2.bodyRegular16,
style = TangemTheme.typography2.bodyMedium16,
color = TangemTheme.colors2.text.neutral.primary,
modifier = Modifier
.padding(top = 12.dp)
.padding(horizontal = 16.dp),
.padding(vertical = TangemTheme.dimens2.x5, horizontal = TangemTheme.dimens2.x6),
)
SpacerH(24.dp)
HorizontalDivider(
modifier = Modifier.padding(horizontal = 24.dp),
color = TangemTheme.colors2.border.neutral.primary,
)
SpacerH(20.dp)
SecondaryTangemButton(
modifier = Modifier.padding(horizontal = 24.dp),
modifier = Modifier.padding(horizontal = TangemTheme.dimens2.x6),
text = resourceReference(R.string.news_like),
size = com.tangem.core.ui.ds.button.TangemButtonSize.X9,
tangemIconUM = if (article.isLiked) {
@ -286,31 +275,27 @@ internal fun ArticleDetailV2(
is RelatedTokensUM.Content -> relatedTokensUM.onTokenClick
else -> null
},
modifier = Modifier.padding(horizontal = 16.dp),
modifier = Modifier.padding(horizontal = TangemTheme.dimens2.x4),
)
if (article.relatedArticles.isNotEmpty()) {
SpacerH(24.dp)
Row(
modifier = Modifier.padding(horizontal = 16.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
Text(
text = stringResourceSafe(R.string.news_sources),
style = TangemTheme.typography2.headingSemibold20,
color = TangemTheme.colors2.text.neutral.primary,
)
}
SpacerH(TangemTheme.dimens2.x4)
Text(
modifier = Modifier.padding(horizontal = TangemTheme.dimens2.x6),
text = stringResourceSafe(R.string.news_sources),
style = TangemTheme.typography2.headingSemibold20,
color = TangemTheme.colors2.text.neutral.primary,
)
}
}
if (article.relatedArticles.isNotEmpty()) {
item("relatedArticles") {
LazyRow(
modifier = Modifier.padding(vertical = 12.dp),
modifier = Modifier.padding(vertical = TangemTheme.dimens2.x3),
state = rememberLazyListState(),
contentPadding = PaddingValues(horizontal = 16.dp),
horizontalArrangement = Arrangement.spacedBy(12.dp),
contentPadding = PaddingValues(horizontal = TangemTheme.dimens2.x4),
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x3),
) {
items(
items = article.relatedArticles,
@ -326,12 +311,12 @@ internal fun ArticleDetailV2(
}
}
BottomFadeWithBlur(
BottomFade(
modifier = Modifier
.align(Alignment.BottomCenter)
.height(80.dp)
.fillMaxWidth(),
backgroundColor = background,
height = TangemTheme.dimens2.x15,
)
}
}

View file

@ -3,7 +3,6 @@ package com.tangem.features.feed.ui.news.details.components
import android.content.res.Configuration
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material3.VerticalDivider
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
@ -111,38 +110,12 @@ private fun NewsDetailsPlaceholderV2(contentPadding: PaddingValues, background:
.padding(16.dp),
) {
SpacerH(contentPadding.calculateTopPadding())
Row(
modifier = Modifier.height(50.dp),
horizontalArrangement = Arrangement.spacedBy(30.dp),
) {
Column {
RectangleShimmer(
modifier = Modifier.size(width = 50.dp, height = 20.dp),
radius = TangemTheme.dimens2.x25,
)
SpacerH(10.dp)
RectangleShimmer(
modifier = Modifier.size(width = 90.dp, height = 18.dp),
radius = TangemTheme.dimens2.x25,
)
}
RectangleShimmer(
modifier = Modifier.size(width = 90.dp, height = 20.dp),
radius = TangemTheme.dimens2.x25,
)
VerticalDivider(color = TangemTheme.colors2.border.neutral.primary)
Column {
RectangleShimmer(
modifier = Modifier.size(width = 50.dp, height = 20.dp),
radius = TangemTheme.dimens2.x25,
)
SpacerH(10.dp)
RectangleShimmer(
modifier = Modifier.size(width = 90.dp, height = 18.dp),
radius = TangemTheme.dimens2.x25,
)
}
}
SpacerH(36.dp)
SpacerH(16.dp)
RectangleShimmer(
modifier = Modifier
@ -161,7 +134,7 @@ private fun NewsDetailsPlaceholderV2(contentPadding: PaddingValues, background:
radius = TangemTheme.dimens2.x25,
)
SpacerH(36.dp)
SpacerH(30.dp)
Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
RectangleShimmer(

View file

@ -82,7 +82,7 @@ private fun QuickRecapV2(content: String, modifier: Modifier = Modifier) {
contentDescription = null,
)
SpacerW(2.dp)
SpacerW(TangemTheme.dimens2.x1)
Text(
text = buildAnnotatedString {
@ -97,26 +97,26 @@ private fun QuickRecapV2(content: String, modifier: Modifier = Modifier) {
append(stringResourceSafe(R.string.news_quick_recap))
}
},
style = TangemTheme.typography2.bodyRegular14,
style = TangemTheme.typography2.subheadlineMedium14,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
)
}
SpacerH(10.dp)
SpacerH(TangemTheme.dimens2.x2_5)
Box {
VerticalDivider(
modifier = Modifier
.fillMaxHeight()
.padding(start = 10.dp),
thickness = 2.dp,
.padding(start = TangemTheme.dimens2.x2_5),
thickness = TangemTheme.dimens2.x0_5,
color = Color(QUICK_RECAP_DIVIDER_COLOR),
)
Text(
modifier = Modifier.padding(start = 20.dp),
modifier = Modifier.padding(start = TangemTheme.dimens2.x5),
text = content,
style = TangemTheme.typography2.bodyRegular16,
style = TangemTheme.typography2.bodyMedium16,
color = TangemTheme.colors2.text.neutral.primary,
)
}
@ -138,7 +138,7 @@ private fun QuickRecapPreview() {
}
private const val QUICK_RECAP_DIVIDER_COLOR = 0xFFA99FFF
private const val LINEAR_GRADIENT_FIRST_PART = 0xFFA3A0FF
private const val LINEAR_GRADIENT_SECOND_PART = 0xFFF79DFF
private const val LINEAR_GRADIENT_FIRST_PART = 0xFF7B78FF
private const val LINEAR_GRADIENT_SECOND_PART = 0xFFC56BCD
private const val GRADIENT_START = 0f
private const val GRADIENT_END = 0.5f

View file

@ -1,7 +1,6 @@
package com.tangem.features.feed.ui.news.details.components
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
@ -113,42 +112,37 @@ private fun RelatedNewsItemV1(relatedArticle: RelatedArticleUM, modifier: Modifi
private fun RelatedNewsItemV2(relatedArticle: RelatedArticleUM, modifier: Modifier = Modifier) {
Column(
modifier = modifier
.sizeIn(maxWidth = 228.dp, minHeight = 160.dp)
.sizeIn(maxWidth = 280.dp, minHeight = 164.dp)
.background(
color = TangemTheme.colors2.surface.level3,
shape = RoundedCornerShape(TangemTheme.dimens2.x5),
shape = RoundedCornerShape(TangemTheme.dimens2.x6),
)
.clickable(onClick = relatedArticle.onClick)
.border(
width = 1.dp,
color = TangemTheme.colors2.border.neutral.primary,
shape = RoundedCornerShape(TangemTheme.dimens2.x5),
)
.padding(16.dp),
.padding(TangemTheme.dimens2.x4),
) {
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Row(horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x4)) {
Column(modifier = Modifier.weight(1f)) {
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(bottom = 4.dp)) {
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(
painter = painterResource(id = R.drawable.ic_explore_16),
contentDescription = null,
tint = TangemTheme.colors2.markers.iconGray,
modifier = Modifier.size(16.dp),
modifier = Modifier.size(TangemTheme.dimens2.x4),
)
SpacerW(2.dp)
SpacerW(TangemTheme.dimens2.x0_5)
Text(
text = relatedArticle.media.name,
style = TangemTheme.typography2.captionSemibold12,
style = TangemTheme.typography2.captionMedium12,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
color = TangemTheme.colors2.text.neutral.secondary,
)
}
if (relatedArticle.title.isNotEmpty()) {
SpacerH(8.dp)
SpacerH(TangemTheme.dimens2.x2)
Text(
text = relatedArticle.title,
style = TangemTheme.typography2.bodyRegular16,
style = TangemTheme.typography2.bodyMedium16,
color = TangemTheme.colors2.text.neutral.primary,
maxLines = 3,
overflow = TextOverflow.Ellipsis,
@ -181,7 +175,7 @@ private fun RelatedNewsItemV2(relatedArticle: RelatedArticleUM, modifier: Modifi
SpacerHMax()
Text(
text = relatedArticle.publishedAt.resolveReference(),
style = TangemTheme.typography2.captionSemibold12,
style = TangemTheme.typography2.captionMedium12,
color = TangemTheme.colors2.text.neutral.secondary,
)
}

View file

@ -1,8 +1,11 @@
package com.tangem.features.feed.ui.news.details.components
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
@ -28,7 +31,27 @@ internal fun RelatedTokensBlock(
onItemClick: ((MarketsListItemUM) -> Unit)?,
modifier: Modifier = Modifier,
) {
val isRedesignEnabled = LocalRedesignEnabled.current
if (LocalRedesignEnabled.current) {
RelatedTokensBlockV2(
relatedTokensUM = relatedTokensUM,
onItemClick = onItemClick,
modifier = modifier,
)
} else {
RelatedTokensBlockV1(
relatedTokensUM = relatedTokensUM,
onItemClick = onItemClick,
modifier = modifier,
)
}
}
@Composable
internal fun RelatedTokensBlockV1(
relatedTokensUM: RelatedTokensUM,
onItemClick: ((MarketsListItemUM) -> Unit)?,
modifier: Modifier = Modifier,
) {
val isVisible = remember(relatedTokensUM) {
when (relatedTokensUM) {
is RelatedTokensUM.Content -> relatedTokensUM.items.isNotEmpty()
@ -41,30 +64,15 @@ internal fun RelatedTokensBlock(
Column(modifier = modifier) {
SpacerH(40.dp)
if (isRedesignEnabled) {
Text(
modifier = Modifier.padding(horizontal = 8.dp),
text = stringResourceSafe(R.string.news_related_tokens),
style = TangemTheme.typography2.headingSemibold20,
color = TangemTheme.colors2.text.neutral.primary,
)
} else {
Text(
text = stringResourceSafe(R.string.news_related_tokens),
style = TangemTheme.typography.h3,
color = TangemTheme.colors.text.primary1,
)
}
Text(
text = stringResourceSafe(R.string.news_related_tokens),
style = TangemTheme.typography.h3,
color = TangemTheme.colors.text.primary1,
)
SpacerH(12.dp)
BlockCard(
colors = TangemBlockCardColors.copy(
containerColor = if (isRedesignEnabled) {
TangemTheme.colors2.surface.level3
} else {
TangemTheme.colors.background.action
},
),
colors = TangemBlockCardColors.copy(containerColor = TangemTheme.colors.background.action),
) {
Column(modifier = Modifier.fillMaxWidth()) {
when (relatedTokensUM) {
@ -86,4 +94,72 @@ internal fun RelatedTokensBlock(
}
}
}
}
@Composable
internal fun RelatedTokensBlockV2(
relatedTokensUM: RelatedTokensUM,
onItemClick: ((MarketsListItemUM) -> Unit)?,
modifier: Modifier = Modifier,
) {
val isVisible = remember(relatedTokensUM) {
when (relatedTokensUM) {
is RelatedTokensUM.Content -> relatedTokensUM.items.isNotEmpty()
RelatedTokensUM.Loading -> true
RelatedTokensUM.LoadingError -> false
}
}
if (!isVisible) return
Column(modifier = modifier) {
SpacerH(TangemTheme.dimens2.x6)
Text(
modifier = Modifier
.padding(horizontal = TangemTheme.dimens2.x2)
.padding(top = TangemTheme.dimens2.x4, bottom = TangemTheme.dimens2.x2),
text = stringResourceSafe(R.string.news_related_tokens),
style = TangemTheme.typography2.headingSemibold20,
color = TangemTheme.colors2.text.neutral.primary,
)
SpacerH(TangemTheme.dimens2.x3)
Column(modifier = Modifier.fillMaxWidth()) {
when (relatedTokensUM) {
is RelatedTokensUM.Content -> {
relatedTokensUM.items.fastForEach { marketsListItemUM ->
WithDecorated {
MarketsListItem(
model = marketsListItemUM,
onClick = { onItemClick?.invoke(marketsListItemUM) },
)
}
SpacerH(TangemTheme.dimens2.x2)
}
}
RelatedTokensUM.Loading -> {
repeat(RELATED_TOKEN_MAX_COUNT) {
WithDecorated {
MarketsListItemPlaceholder()
}
SpacerH(TangemTheme.dimens2.x2)
}
}
RelatedTokensUM.LoadingError -> Unit
}
}
}
}
@Composable
private fun WithDecorated(modifier: Modifier = Modifier, content: @Composable ColumnScope.() -> Unit) {
Column(
modifier = modifier
.fillMaxWidth()
.background(
color = TangemTheme.colors2.surface.level3,
shape = RoundedCornerShape(TangemTheme.dimens2.x5),
),
content = content,
)
}