From d0bc6087fe26cd428460f5a89a2c3f7dbea06d7d Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 4 May 2026 09:40:55 +0200 Subject: [PATCH] Updated on 2026-08-14 --- .../common/ui/markets/MarketListItemV2.kt | 14 +- .../com/tangem/core/ui/components/Fade.kt | 8 +- .../core/ui/components/block/BlockCard.kt | 4 +- .../ui/components/items/DecriptionItem.kt | 10 +- .../tangem/core/ui/ds/TangemPagerIndicator.kt | 21 +- .../core/ui/ds/tabs/TangemSegmentedPicker.kt | 22 +- .../feed/ui/components/MetricsCard.kt | 4 +- .../ui/earn/components/CardFilterBlock.kt | 9 +- .../earn/components/EarnFilterBottomSheet.kt | 2 +- .../EarnFilterByNetworkBottomSheet.kt | 13 +- .../components/EarnFilterByTypeBottomSheet.kt | 16 +- .../feed/ui/earn/components/MostlyUsedCard.kt | 7 +- .../tangem/features/feed/ui/feed/FeedList.kt | 12 + .../feed/ui/feed/components/BlockHeader.kt | 2 +- .../feed/ui/feed/components/DateBlock.kt | 7 +- .../feed/ui/feed/components/MarketsBlock.kt | 8 +- .../feed/ui/feed/components/NewsBlock.kt | 25 ++- .../feed/ui/feed/components/NewsSlider.kt | 4 +- .../feed/components/articles/ArticleCardV2.kt | 105 ++++----- .../feed/components/articles/ArticleHeader.kt | 206 ++++++++---------- .../preview/FeedListPreviewDataProvider.kt | 2 +- .../detailed/MarketsTokenDetailsContent.kt | 8 +- .../components/InformationTextBlock.kt | 9 +- .../market/detailed/components/LinksBlock.kt | 22 +- .../detailed/components/ListedOnBlock.kt | 14 +- .../detailed/components/MetricsCards.kt | 43 ++-- .../detailed/components/SecurityScoreBlock.kt | 73 +++---- .../components/TokenMarketDetailsBody.kt | 78 ++++++- .../ui/news/details/NewsDetailsContent.kt | 8 +- .../news/details/components/ArticleDetail.kt | 69 +++--- .../components/NewsDetailsPlaceholder.kt | 39 +--- .../ui/news/details/components/QuickRecap.kt | 18 +- .../details/components/RelatedNewsItem.kt | 28 +-- .../details/components/RelatedTokensBlock.kt | 120 ++++++++-- 34 files changed, 569 insertions(+), 461 deletions(-) diff --git a/common/ui-markets/src/main/kotlin/com/tangem/common/ui/markets/MarketListItemV2.kt b/common/ui-markets/src/main/kotlin/com/tangem/common/ui/markets/MarketListItemV2.kt index 9f5a2c1e63..66511d08d6 100644 --- a/common/ui-markets/src/main/kotlin/com/tangem/common/ui/markets/MarketListItemV2.kt +++ b/common/ui-markets/src/main/kotlin/com/tangem/common/ui/markets/MarketListItemV2.kt @@ -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, ) diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/Fade.kt b/core/ui/src/main/java/com/tangem/core/ui/components/Fade.kt index fcc03b10e6..709b5a6625 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/Fade.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/Fade.kt @@ -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( diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/block/BlockCard.kt b/core/ui/src/main/java/com/tangem/core/ui/components/block/BlockCard.kt index 49752f2700..6d19073670 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/block/BlockCard.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/block/BlockCard.kt @@ -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, diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/items/DecriptionItem.kt b/core/ui/src/main/java/com/tangem/core/ui/components/items/DecriptionItem.kt index 2841c1c57e..a3dd844b63 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/items/DecriptionItem.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/items/DecriptionItem.kt @@ -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, ) } diff --git a/core/ui/src/main/java/com/tangem/core/ui/ds/TangemPagerIndicator.kt b/core/ui/src/main/java/com/tangem/core/ui/ds/TangemPagerIndicator.kt index 05fcdc6c3a..e86793d0d1 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/ds/TangemPagerIndicator.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/ds/TangemPagerIndicator.kt @@ -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), diff --git a/core/ui/src/main/java/com/tangem/core/ui/ds/tabs/TangemSegmentedPicker.kt b/core/ui/src/main/java/com/tangem/core/ui/ds/tabs/TangemSegmentedPicker.kt index b685eab6d8..7483bad306 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/ds/tabs/TangemSegmentedPicker.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/ds/tabs/TangemSegmentedPicker.kt @@ -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, selectedIndex: Int, segmentHeight: Dp) { + var hasInitiallyMeasured by remember { mutableStateOf(false) } + + val animationSpec: AnimationSpec = 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 { diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/components/MetricsCard.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/components/MetricsCard.kt index ed671b018a..abef06881d 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/components/MetricsCard.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/components/MetricsCard.kt @@ -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, ) }, diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/CardFilterBlock.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/CardFilterBlock.kt index 56cb167e10..b4b2087cad 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/CardFilterBlock.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/CardFilterBlock.kt @@ -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, diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/EarnFilterBottomSheet.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/EarnFilterBottomSheet.kt index dff1428685..d89e5a05a2 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/EarnFilterBottomSheet.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/EarnFilterBottomSheet.kt @@ -28,7 +28,7 @@ internal inline fun EarnFilterBotto TangemBottomSheet( config = config, type = TangemBottomSheetType.Modal, - containerColor = TangemTheme.colors2.surface.level3, + containerColor = TangemTheme.colors2.surface.level2, title = { TangemTopBar( title = resourceReference(R.string.earn_filter_by), diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/EarnFilterByNetworkBottomSheet.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/EarnFilterByNetworkBottomSheet.kt index befac566af..50ffe3073a 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/EarnFilterByNetworkBottomSheet.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/EarnFilterByNetworkBottomSheet.kt @@ -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, diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/EarnFilterByTypeBottomSheet.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/EarnFilterByTypeBottomSheet.kt index 9c8a7d4381..6b6da63857 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/EarnFilterByTypeBottomSheet.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/EarnFilterByTypeBottomSheet.kt @@ -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) }, + ) + } } } } diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/MostlyUsedCard.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/MostlyUsedCard.kt index 1acfb25681..e1e90b4328 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/MostlyUsedCard.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/MostlyUsedCard.kt @@ -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, ) } diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/FeedList.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/FeedList.kt index e69bccddd0..3f80f6214c 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/FeedList.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/FeedList.kt @@ -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()) + } + } } \ No newline at end of file diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/BlockHeader.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/BlockHeader.kt index 32a6229d2e..5c9fc72db8 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/BlockHeader.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/BlockHeader.kt @@ -32,7 +32,7 @@ internal fun ColumnScope.Header( ) { val isRedesignEnabled = LocalRedesignEnabled.current if (isRedesignEnabled) { - SpacerH(20.dp) + SpacerH(16.dp) } AnimatedContent(isLoading) { animatedState -> Row( diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/DateBlock.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/DateBlock.kt index b38b335ae1..2c3ffe2bd8 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/DateBlock.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/DateBlock.kt @@ -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) } \ No newline at end of file diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/MarketsBlock.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/MarketsBlock.kt index daf0b624ae..9bf3a68523 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/MarketsBlock.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/MarketsBlock.kt @@ -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) { diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/NewsBlock.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/NewsBlock.kt index 443eff2ac5..84414ebab7 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/NewsBlock.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/NewsBlock.kt @@ -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) diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/NewsSlider.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/NewsSlider.kt index 87a5053d61..866a07785d 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/NewsSlider.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/NewsSlider.kt @@ -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, diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/articles/ArticleCardV2.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/articles/ArticleCardV2.kt index 56fa348c48..86b88e8137 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/articles/ArticleCardV2.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/articles/ArticleCardV2.kt @@ -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, ) } diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/articles/ArticleHeader.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/articles/ArticleHeader.kt index 90e3717cd0..530d0a1dc5 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/articles/ArticleHeader.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/articles/ArticleHeader.kt @@ -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) { + 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() { diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/preview/FeedListPreviewDataProvider.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/preview/FeedListPreviewDataProvider.kt index e3a0a86a28..ed2ebcdccb 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/preview/FeedListPreviewDataProvider.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/preview/FeedListPreviewDataProvider.kt @@ -265,7 +265,7 @@ internal object FeedListPreviewDataProvider { } private fun createEarnListItemsUM(): ImmutableList { - return List(5) { + return List(1) { EarnListItemUM( network = stringReference("Ethereum"), symbol = stringReference("USDT"), diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/MarketsTokenDetailsContent.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/MarketsTokenDetailsContent.kt index 3377a8eb08..b84d7cde77 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/MarketsTokenDetailsContent.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/MarketsTokenDetailsContent.kt @@ -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(), diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/InformationTextBlock.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/InformationTextBlock.kt index e6cfb24267..98b635eab6 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/InformationTextBlock.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/InformationTextBlock.kt @@ -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, ) diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/LinksBlock.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/LinksBlock.kt index 778af344f2..ff70bd80a1 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/LinksBlock.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/LinksBlock.kt @@ -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, ) } } diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/ListedOnBlock.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/ListedOnBlock.kt index e7e041f634..a8f1472bd7 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/ListedOnBlock.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/ListedOnBlock.kt @@ -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, ) diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/MetricsCards.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/MetricsCards.kt index 966cf8e307..c61808563d 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/MetricsCards.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/MetricsCards.kt @@ -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 diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/SecurityScoreBlock.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/SecurityScoreBlock.kt index dd7c78854c..ed8956d257 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/SecurityScoreBlock.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/SecurityScoreBlock.kt @@ -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, ) } diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/TokenMarketDetailsBody.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/TokenMarketDetailsBody.kt index b1d372de32..20520a4398 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/TokenMarketDetailsBody.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/TokenMarketDetailsBody.kt @@ -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, + ) + } } \ No newline at end of file diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/NewsDetailsContent.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/NewsDetailsContent.kt index 9b7905ade3..6e71c83a26 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/NewsDetailsContent.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/NewsDetailsContent.kt @@ -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( diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/components/ArticleDetail.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/components/ArticleDetail.kt index 4b9ac978b3..d7fdd670cf 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/components/ArticleDetail.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/components/ArticleDetail.kt @@ -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, ) } } diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/components/NewsDetailsPlaceholder.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/components/NewsDetailsPlaceholder.kt index dc9107030f..e102f1591a 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/components/NewsDetailsPlaceholder.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/components/NewsDetailsPlaceholder.kt @@ -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( diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/components/QuickRecap.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/components/QuickRecap.kt index 6cc0ec1434..5730440a49 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/components/QuickRecap.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/components/QuickRecap.kt @@ -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 \ No newline at end of file diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/components/RelatedNewsItem.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/components/RelatedNewsItem.kt index a3810b1bda..f99d0eff17 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/components/RelatedNewsItem.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/components/RelatedNewsItem.kt @@ -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, ) } diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/components/RelatedTokensBlock.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/components/RelatedTokensBlock.kt index 7f37764ee5..8013858af1 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/components/RelatedTokensBlock.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/news/details/components/RelatedTokensBlock.kt @@ -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, + ) } \ No newline at end of file