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 179ed39563..df7eea3655 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 @@ -3,7 +3,6 @@ package com.tangem.common.ui.markets import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* -import androidx.compose.foundation.layout.Arrangement import androidx.compose.material3.Button import androidx.compose.material3.Icon import androidx.compose.material3.Text @@ -34,10 +33,12 @@ import com.tangem.core.ui.components.RectangleShimmer import com.tangem.core.ui.components.SpacerW4 import com.tangem.core.ui.components.marketprice.PriceChangeInPercent import com.tangem.core.ui.components.marketprice.PriceChangeType +import com.tangem.core.ui.ds.badge.* import com.tangem.core.ui.ds.image.TangemIcon import com.tangem.core.ui.ds.image.TangemIconUM import com.tangem.core.ui.ds.row.TangemRowContainer import com.tangem.core.ui.ds.row.TangemRowLayoutId +import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.res.LocalIsInDarkTheme import com.tangem.core.ui.res.LocalWindowSize import com.tangem.core.ui.res.TangemTheme @@ -95,7 +96,7 @@ fun MarketListItemContentV2(model: MarketsListItemUM, modifier: Modifier = Modif .padding(end = TangemTheme.dimens2.x2, start = TangemTheme.dimens2.x3), ratingPosition = model.ratingPosition, marketCap = model.marketCap, - // stakingRate = model.stakingRate, TODO in [REDACTED_TASK_KEY] + stakingRate = model.stakingRate, ) PriceChangeInPercent( @@ -146,7 +147,7 @@ private fun TokenTitle(name: String, currencySymbol: String, modifier: Modifier private fun TokenSubtitle( ratingPosition: String?, marketCap: String?, - // stakingRate: TextReference?, TODO in [REDACTED_TASK_KEY] + stakingRate: TextReference?, modifier: Modifier = Modifier, ) { val ratingColor = mapRatingToColor(ratingPosition) @@ -154,7 +155,7 @@ private fun TokenSubtitle( Row( modifier = modifier, verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x2), + horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x1), ) { TokenRatingPlace( ratingPosition = ratingPosition, @@ -167,6 +168,9 @@ private fun TokenSubtitle( text = marketCap, ) } + if (stakingRate != null) { + StakingRate(stakingRate = stakingRate) + } } } @@ -214,6 +218,18 @@ private fun RowScope.TokenMarketCapText(text: String, ratingColor: Color, modifi ) } +@Composable +private fun RowScope.StakingRate(stakingRate: TextReference, modifier: Modifier = Modifier) { + TangemBadge( + modifier = modifier.alignByBaseline(), + text = stakingRate, + shape = TangemBadgeShape.Rounded, + size = TangemBadgeSize.X4, + type = TangemBadgeType.Tinted, + color = TangemBadgeColor.Gray, + ) +} + @Composable private fun Chart(chartType: MarketChartLook.Type, chartRawData: MarketChartRawData?, modifier: Modifier = Modifier) { Box( diff --git a/common/ui-markets/src/main/kotlin/com/tangem/common/ui/markets/MarketsListItemPlaceholder.kt b/common/ui-markets/src/main/kotlin/com/tangem/common/ui/markets/MarketsListItemPlaceholder.kt index 3e11c3c039..1da509b1d8 100644 --- a/common/ui-markets/src/main/kotlin/com/tangem/common/ui/markets/MarketsListItemPlaceholder.kt +++ b/common/ui-markets/src/main/kotlin/com/tangem/common/ui/markets/MarketsListItemPlaceholder.kt @@ -4,23 +4,29 @@ import android.content.res.Configuration import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.tangem.core.ui.components.CircleShimmer -import com.tangem.core.ui.components.RectangleShimmer -import com.tangem.core.ui.components.SpacerH -import com.tangem.core.ui.components.SpacerW12 -import com.tangem.core.ui.res.LocalWindowSize -import com.tangem.core.ui.res.TangemTheme -import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.core.ui.components.* +import com.tangem.core.ui.res.* import com.tangem.core.ui.windowsize.WindowSizeType +@Composable +fun MarketsListItemPlaceholder() { + if (LocalRedesignEnabled.current) { + MarketsListItemPlaceholderV2() + } else { + MarketsListItemPlaceholderV1() + } +} + @Suppress("LongMethod") @Composable -fun MarketsListItemPlaceholder() { +private fun MarketsListItemPlaceholderV1() { val density = LocalDensity.current val windowSize = LocalWindowSize.current val sp12 = with(density) { 12.sp.toDp() } @@ -84,11 +90,71 @@ fun MarketsListItemPlaceholder() { } } +@Suppress("LongMethod") +@Composable +private fun MarketsListItemPlaceholderV2() { + val windowSize = LocalWindowSize.current + Row( + modifier = Modifier.padding( + horizontal = 12.dp, + vertical = 14.dp, + ), + verticalAlignment = Alignment.CenterVertically, + ) { + CircleShimmer(modifier = Modifier.size(40.dp)) + + SpacerW(4.dp) + + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(4.dp), + horizontalAlignment = Alignment.Start, + ) { + RectangleShimmer( + modifier = Modifier + .width(96.dp) + .height(20.dp), + radius = TangemTheme.dimens2.x25, + ) + + RectangleShimmer( + modifier = Modifier + .width(46.dp) + .height(16.dp), + radius = TangemTheme.dimens2.x25, + ) + } + + if (windowSize.widthAtLeast(WindowSizeType.Small)) { + SpacerW(10.dp) + + Column( + verticalArrangement = Arrangement.spacedBy(4.dp), + horizontalAlignment = Alignment.End, + ) { + RectangleShimmer( + modifier = Modifier + .width(56.dp) + .height(20.dp), + radius = TangemTheme.dimens2.x25, + ) + + RectangleShimmer( + modifier = Modifier + .width(46.dp) + .height(16.dp), + radius = TangemTheme.dimens2.x25, + ) + } + } + } +} + @Preview(showBackground = true, widthDp = 360, name = "normal") @Preview(showBackground = true, widthDp = 360, name = "normal night", uiMode = Configuration.UI_MODE_NIGHT_YES) @Preview(showBackground = true, widthDp = 320, name = "small width") @Composable -private fun Preview() { +private fun PreviewV1() { TangemThemePreview { Column(Modifier.background(TangemTheme.colors.background.tertiary)) { repeat(20) { @@ -96,4 +162,20 @@ private fun Preview() { } } } +} + +@Preview(showBackground = true, widthDp = 360, name = "normal") +@Preview(showBackground = true, widthDp = 360, name = "normal night", uiMode = Configuration.UI_MODE_NIGHT_YES) +@Preview(showBackground = true, widthDp = 320, name = "small width") +@Composable +private fun PreviewV2() { + TangemThemePreviewRedesign { + CompositionLocalProvider(LocalRedesignEnabled provides true) { + Column(Modifier.background(TangemTheme.colors2.surface.level3)) { + repeat(20) { + MarketsListItemPlaceholder() + } + } + } + } } \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/pager/PagerIndicator.kt b/core/ui/src/main/java/com/tangem/core/ui/components/pager/PagerIndicator.kt index 1f87b768f3..e2f223a394 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/pager/PagerIndicator.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/pager/PagerIndicator.kt @@ -21,12 +21,8 @@ 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 com.tangem.core.ui.components.haze.hazeEffectTangem -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 dev.chrisbanes.haze.HazeStyle import kotlin.math.abs import kotlin.math.roundToInt @@ -44,15 +40,6 @@ private val SMALL_DOT_SIZE = DpSize(4.dp, 4.dp) @Composable fun PagerIndicator(pagerState: PagerState, modifier: Modifier = Modifier) { - if (LocalRedesignEnabled.current) { - PagerIndicatorV2(pagerState, modifier) - } else { - PagerIndicatorV1(pagerState, modifier) - } -} - -@Composable -private fun PagerIndicatorV1(pagerState: PagerState, modifier: Modifier = Modifier) { val colors = PagerIndicatorColors( active = TangemTheme.colors.control.key, inactive = TangemTheme.colors.text.tertiary, @@ -65,21 +52,6 @@ private fun PagerIndicatorV1(pagerState: PagerState, modifier: Modifier = Modifi ) } -@Composable -private fun PagerIndicatorV2(pagerState: PagerState, modifier: Modifier = Modifier) { - val colors = PagerIndicatorColors( - active = TangemTheme.colors2.graphic.neutral.primary, - inactive = TangemTheme.colors2.graphic.neutral.tertiary, - overlay = TangemTheme.colors2.tabs.backgroundSecondary.copy(alpha = .1f), - ) - PagerIndicatorContent( - pagerState = pagerState, - colors = colors, - modifier = modifier, - boxModifier = Modifier.hazeEffectTangem(style = HazeStyle(blurRadius = 22.dp, tint = null)), - ) -} - @Composable private fun rememberPagerIndicatorAnimationState(pagerState: PagerState): PagerIndicatorAnimationState { val density = LocalDensity.current @@ -291,7 +263,7 @@ private class DotSizeParams private constructor( @Preview(showBackground = true) @Composable -private fun PagerIndicatorPreviewV1() { +private fun PagerIndicatorPreviewV() { TangemThemePreview { Column( Modifier @@ -306,23 +278,6 @@ private fun PagerIndicatorPreviewV1() { } } -@Preview(showBackground = true) -@Composable -private fun PagerIndicatorPreviewV2() { - TangemThemePreviewRedesign { - Column( - Modifier - .background(TangemTheme.colors.background.primary) - .padding(20.dp), - verticalArrangement = Arrangement.spacedBy(10.dp), - ) { - listOf(0, 1, 2, 3, 4).forEach { page -> - PagerIndicator(rememberPagerState(page) { 5 }) - } - } - } -} - @Preview(showBackground = true) @Composable private fun PagerIndicator6ItemsPreview() { 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 ad4bc15824..40de998c46 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 @@ -54,18 +54,14 @@ private val SMALL_DOT_SIZE = DpSize(4.dp, 4.dp) * * @param pagerState state of the pager to observe * @param modifier modifier for styling - * @param hasBackground whether to show a background behind the indicators - * @param activeIndicatorColor color for the active page indicator - * @param inactiveIndicatorColor color for the inactive page indicators + * @param colors colors of indicators(active/inactive) and overlay */ @Suppress("LongMethod", "CyclomaticComplexMethod") @Composable fun TangemPagerIndicator( pagerState: PagerState, modifier: Modifier = Modifier, - hasBackground: Boolean = false, - activeIndicatorColor: Color = TangemTheme.colors2.graphic.neutral.primary, - inactiveIndicatorColor: Color = TangemTheme.colors2.graphic.neutral.tertiary, + colors: PagerIndicatorColors = TangemPagerIndicatorColors, ) { val totalPages = pagerState.pageCount val currentIndex = pagerState.currentPage @@ -131,11 +127,13 @@ fun TangemPagerIndicator( Box( modifier = modifier - .conditionalCompose(hasBackground) { - background( - color = TangemTheme.colors2.tabs.backgroundSecondary, - shape = CircleShape, - ) + .conditionalCompose(colors.overlay != null) { + colors.overlay?.let { overlay -> + background( + color = overlay, + shape = CircleShape, + ) + } ?: this } .padding(TangemTheme.dimens2.x3), contentAlignment = Alignment.Center, @@ -162,8 +160,8 @@ fun TangemPagerIndicator( index = index, currentIndex = currentIndex, totalPages = totalPages, - activeColor = activeIndicatorColor, - inactiveColor = inactiveIndicatorColor, + activeColor = colors.active, + inactiveColor = colors.inactive, modifier = Modifier.graphicsLayer { alpha = dotAlpha }, ) } @@ -297,6 +295,22 @@ private fun Dot( } } +val TangemPagerIndicatorColors: PagerIndicatorColors + @Composable + @ReadOnlyComposable + get() = PagerIndicatorColors( + active = TangemTheme.colors2.graphic.neutral.primary, + inactive = TangemTheme.colors2.graphic.neutral.tertiary, + overlay = null, + ) + +@Immutable +data class PagerIndicatorColors( + val active: Color, + val inactive: Color, + val overlay: Color?, +) + // region Preview @Composable @Preview(showBackground = true) @@ -312,7 +326,13 @@ private fun TangemPagerIndicator_Preview(@PreviewParameter(TangemPagerIndicatorP repeat(params) { index -> TangemPagerIndicator( pagerState = rememberPagerState(index) { params }, - hasBackground = index % 2 == 0, + colors = TangemPagerIndicatorColors.copy( + overlay = if (index % 2 == 0) { + TangemTheme.colors2.tabs.backgroundSecondary + } else { + null + }, + ), ) } } diff --git a/core/ui/src/main/java/com/tangem/core/ui/ds/button/TangemButtonInternal.kt b/core/ui/src/main/java/com/tangem/core/ui/ds/button/TangemButtonInternal.kt index af41dd86cc..751a37c088 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/ds/button/TangemButtonInternal.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/ds/button/TangemButtonInternal.kt @@ -208,7 +208,7 @@ private fun TangemButtonIcon( visible = isVisible, modifier = Modifier.size(size = size.toContentSize()), ) { - val wrappedIconRes = remember(this) { requireNotNull(iconRes) } + val wrappedIconRes = remember(iconRes) { requireNotNull(iconRes) } Icon( painter = painterResource(id = wrappedIconRes), contentDescription = null, diff --git a/core/ui/src/main/java/com/tangem/core/ui/ds/tabs/TangemTab.kt b/core/ui/src/main/java/com/tangem/core/ui/ds/tabs/TangemTab.kt index 54d39c5104..15dccb3a1d 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/ds/tabs/TangemTab.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/ds/tabs/TangemTab.kt @@ -59,7 +59,6 @@ fun TangemTab( shape = shape, ) .clip(shape = shape) - .padding(all = TangemTheme.dimens2.x3) .toggleable( value = isChecked, onValueChange = onCheckedChange, @@ -67,7 +66,8 @@ fun TangemTab( role = Role.Checkbox, interactionSource = remember { MutableInteractionSource() }, indication = ripple(), - ), + ) + .padding(all = TangemTheme.dimens2.x3), ) { Text( text = text.resolveReference(), diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/news/details/DefaultNewsDetailsComponent.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/news/details/DefaultNewsDetailsComponent.kt index 38bef9331e..1d31f11fe9 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/news/details/DefaultNewsDetailsComponent.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/news/details/DefaultNewsDetailsComponent.kt @@ -1,9 +1,16 @@ package com.tangem.features.feed.components.news.details +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Icon import androidx.compose.runtime.Composable import androidx.compose.runtime.State import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.vectorResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.decompose.model.getOrCreateModel @@ -12,7 +19,13 @@ import com.tangem.core.ui.components.appbar.TangemTopAppBar import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM import com.tangem.core.ui.components.bottomsheets.state.BottomSheetState import com.tangem.core.ui.decompose.ComposableModularBottomSheetContentComponent +import com.tangem.core.ui.ds.topbar.TangemTopBar +import com.tangem.core.ui.ds.topbar.TangemTopBarType +import com.tangem.core.ui.extensions.clickableSingle +import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.res.LocalMainBottomSheetColor +import com.tangem.core.ui.res.LocalRedesignEnabled +import com.tangem.core.ui.res.TangemTheme import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.markets.TokenMarketParams import com.tangem.domain.news.model.NewsListConfig @@ -32,21 +45,65 @@ internal class DefaultNewsDetailsComponent( override fun Title(bottomSheetState: State) { val background = LocalMainBottomSheetColor.current.value val state by newsDetailsModel.state.collectAsStateWithLifecycle() - TangemTopAppBar( - containerColor = background, - title = null, - startButton = TopAppBarButtonUM.Icon( - iconRes = R.drawable.ic_back_24, - onClicked = state.onBackClick, - isEnabled = bottomSheetState.value == BottomSheetState.EXPANDED, - ), - endButton = TopAppBarButtonUM.Icon( - iconRes = R.drawable.ic_share_24, - onClicked = state.onShareClick, - isEnabled = bottomSheetState.value == BottomSheetState.EXPANDED && - state.articlesStateUM is ArticlesStateUM.Content, - ), - ) + if (LocalRedesignEnabled.current) { + TangemTopBar( + title = resourceReference(R.string.common_news), + type = TangemTopBarType.BottomSheet, + startContent = { + Icon( + imageVector = ImageVector.vectorResource(id = R.drawable.ic_arrow_back_28), + contentDescription = null, + tint = TangemTheme.colors2.graphic.neutral.primary, + modifier = Modifier + .size(TangemTheme.dimens2.x11) + .background( + color = TangemTheme.colors2.button.backgroundSecondary, + shape = CircleShape, + ) + .clickableSingle( + onClick = state.onBackClick, + enabled = bottomSheetState.value == BottomSheetState.EXPANDED, + ) + .padding(TangemTheme.dimens2.x2), + ) + }, + endContent = { + Icon( + imageVector = ImageVector.vectorResource(id = R.drawable.ic_share_new_24), + contentDescription = null, + tint = TangemTheme.colors2.graphic.neutral.primary, + modifier = Modifier + .size(TangemTheme.dimens2.x11) + .background( + color = TangemTheme.colors2.button.backgroundSecondary, + shape = CircleShape, + ) + .clickableSingle( + onClick = state.onShareClick, + enabled = bottomSheetState.value == BottomSheetState.EXPANDED && + state.articlesStateUM is ArticlesStateUM.Content, + ) + .padding(TangemTheme.dimens2.x2_5), + ) + }, + ) + } else { + TangemTopAppBar( + containerColor = background, + title = null, + startButton = TopAppBarButtonUM.Icon( + iconRes = R.drawable.ic_back_24, + onClicked = state.onBackClick, + isEnabled = bottomSheetState.value == BottomSheetState.EXPANDED, + ), + endButton = TopAppBarButtonUM.Icon( + iconRes = R.drawable.ic_share_24, + onClicked = state.onShareClick, + isEnabled = bottomSheetState.value == BottomSheetState.EXPANDED && + state.articlesStateUM is ArticlesStateUM.Content, + ), + ) + } } @Composable diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/news/list/DefaultNewsListComponent.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/news/list/DefaultNewsListComponent.kt index 73676ae03b..13505b2b0a 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/news/list/DefaultNewsListComponent.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/news/list/DefaultNewsListComponent.kt @@ -1,9 +1,16 @@ package com.tangem.features.feed.components.news.list +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Icon import androidx.compose.runtime.Composable import androidx.compose.runtime.State import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.vectorResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.decompose.model.getOrCreateModel @@ -12,8 +19,14 @@ import com.tangem.core.ui.components.appbar.TangemTopAppBar import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM import com.tangem.core.ui.components.bottomsheets.state.BottomSheetState import com.tangem.core.ui.decompose.ComposableModularBottomSheetContentComponent +import com.tangem.core.ui.ds.topbar.TangemTopBar +import com.tangem.core.ui.ds.topbar.TangemTopBarType +import com.tangem.core.ui.extensions.clickableSingle +import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringResourceSafe import com.tangem.core.ui.res.LocalMainBottomSheetColor +import com.tangem.core.ui.res.LocalRedesignEnabled +import com.tangem.core.ui.res.TangemTheme import com.tangem.domain.news.model.NewsListConfig import com.tangem.features.feed.model.news.list.NewsListModel import com.tangem.features.feed.ui.news.list.NewsListContent @@ -30,15 +43,40 @@ internal class DefaultNewsListComponent( override fun Title(bottomSheetState: State) { val background = LocalMainBottomSheetColor.current.value val state by newsListModel.state.collectAsStateWithLifecycle() - TangemTopAppBar( - containerColor = background, - title = stringResourceSafe(R.string.common_news), - startButton = TopAppBarButtonUM.Icon( - iconRes = R.drawable.ic_back_24, - onClicked = state.onBackClick, - isEnabled = bottomSheetState.value == BottomSheetState.EXPANDED, - ), - ) + if (LocalRedesignEnabled.current) { + TangemTopBar( + title = resourceReference(R.string.common_news), + type = TangemTopBarType.BottomSheet, + startContent = { + Icon( + imageVector = ImageVector.vectorResource(id = R.drawable.ic_arrow_back_28), + contentDescription = null, + tint = TangemTheme.colors2.graphic.neutral.primary, + modifier = Modifier + .size(TangemTheme.dimens2.x11) + .background( + color = TangemTheme.colors2.button.backgroundSecondary, + shape = CircleShape, + ) + .clickableSingle( + onClick = state.onBackClick, + enabled = bottomSheetState.value == BottomSheetState.EXPANDED, + ) + .padding(TangemTheme.dimens2.x2), + ) + }, + ) + } else { + TangemTopAppBar( + containerColor = background, + title = stringResourceSafe(R.string.common_news), + startButton = TopAppBarButtonUM.Icon( + iconRes = R.drawable.ic_back_24, + onClicked = state.onBackClick, + isEnabled = bottomSheetState.value == BottomSheetState.EXPANDED, + ), + ) + } } @Composable diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/model/market/details/MarketsTokenDetailsModel.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/model/market/details/MarketsTokenDetailsModel.kt index e371378488..e155e80515 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/model/market/details/MarketsTokenDetailsModel.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/model/market/details/MarketsTokenDetailsModel.kt @@ -48,6 +48,7 @@ import com.tangem.features.feed.model.converter.ShortArticleToArticleConfigUMCon import com.tangem.features.feed.model.market.details.analytics.MarketDetailsAnalyticsEvent import com.tangem.features.feed.model.market.details.converter.DescriptionConverter import com.tangem.features.feed.model.market.details.converter.ExchangeItemStateConverter +import com.tangem.features.feed.model.market.details.converter.ExchangeItemStateConverterV2 import com.tangem.features.feed.model.market.details.converter.TokenMarketInfoConverter import com.tangem.features.feed.model.market.details.formatter.* import com.tangem.features.feed.model.market.details.state.QuotesStateUpdater @@ -78,7 +79,7 @@ internal class MarketsTokenDetailsModel @Inject constructor( getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, getUserCountryUseCase: GetUserCountryUseCase, paramsContainer: ParamsContainer, - designFeatureToggles: DesignFeatureToggles, + private val designFeatureToggles: DesignFeatureToggles, private val getTokenPriceChartUseCase: GetTokenPriceChartUseCase, private val getTokenMarketInfoUseCase: GetTokenMarketInfoUseCase, private val getTokenFullQuotesUseCase: GetTokenFullQuotesUseCase, @@ -704,9 +705,15 @@ internal class MarketsTokenDetailsModel @Inject constructor( ExchangesBottomSheetContent.Error(onRetryClick = { onListedOnClick(exchangesCount) }) }, ifRight = { list -> - ExchangesBottomSheetContent.Content( - exchangeItems = ExchangeItemStateConverter.convertList(list).toImmutableList(), - ) + if (designFeatureToggles.isRedesignEnabled) { + ExchangesBottomSheetContent.ContentV2( + exchangeItemsV2 = ExchangeItemStateConverterV2.convertList(list).toImmutableList(), + ) + } else { + ExchangesBottomSheetContent.ContentV1( + exchangeItems = ExchangeItemStateConverter.convertList(list).toImmutableList(), + ) + } }, ) diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/model/market/details/converter/ExchangeItemStateConverterV2.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/model/market/details/converter/ExchangeItemStateConverterV2.kt new file mode 100644 index 0000000000..b6e852ab8f --- /dev/null +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/model/market/details/converter/ExchangeItemStateConverterV2.kt @@ -0,0 +1,60 @@ +package com.tangem.features.feed.model.market.details.converter + +import com.tangem.core.ui.components.audits.AuditLabelUM +import com.tangem.core.ui.components.currency.icon.CurrencyIconState +import com.tangem.core.ui.ds.image.TangemIconUM +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.format.bigdecimal.compact +import com.tangem.core.ui.format.bigdecimal.fiat +import com.tangem.core.ui.format.bigdecimal.format +import com.tangem.domain.markets.TokenMarketExchange +import com.tangem.domain.markets.TokenMarketExchange.TrustScore +import com.tangem.features.feed.impl.R +import com.tangem.features.feed.ui.market.detailed.state.ExchangeItemUM +import com.tangem.utils.converter.Converter + +internal object ExchangeItemStateConverterV2 : Converter { + + override fun convert(value: TokenMarketExchange): ExchangeItemUM.Content { + return ExchangeItemUM.Content( + id = value.id, + title = stringReference(value.name), + subTitle = stringReference(value = if (value.isCentralized) "CEX" else "DEX"), + icon = TangemIconUM.Currency( + CurrencyIconState.CoinIcon( + url = value.imageUrl, + fallbackResId = R.drawable.ic_alert_24, + isGrayscale = false, + shouldShowCustomBadge = false, + ), + ), + volumeInUsd = stringReference( + value.volumeInUsd.format { + fiat( + fiatCurrencyCode = "USD", + fiatCurrencySymbol = "$", + ).compact() + }, + ), + auditLabel = value.trustScore.toAuditLabelUM(), + ) + } + + private fun TrustScore.toAuditLabelUM(): AuditLabelUM { + return when (this) { + TrustScore.Risky -> AuditLabelUM( + text = resourceReference(id = R.string.markets_token_details_exchange_trust_score_risky), + type = AuditLabelUM.Type.Prohibition, + ) + TrustScore.Caution -> AuditLabelUM( + text = resourceReference(id = R.string.markets_token_details_exchange_trust_score_caution), + type = AuditLabelUM.Type.Warning, + ) + TrustScore.Trusted -> AuditLabelUM( + text = resourceReference(id = R.string.markets_token_details_exchange_trust_score_trusted), + type = AuditLabelUM.Type.Permit, + ) + } + } +} \ No newline at end of file diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/EarnContent.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/EarnContent.kt index 82c0a9cfb6..5f9756b351 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/EarnContent.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/EarnContent.kt @@ -6,7 +6,6 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.* import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider @@ -14,21 +13,19 @@ import androidx.compose.runtime.mutableStateOf 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.layout.onFirstVisible import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.style.TextAlign 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.* -import com.tangem.core.ui.components.buttons.SecondarySmallButton -import com.tangem.core.ui.components.buttons.SmallButtonConfig import com.tangem.core.ui.components.currency.icon.CurrencyIconState import com.tangem.core.ui.components.list.InfiniteListHandler import com.tangem.core.ui.decorations.roundedShapeItemDecoration -import com.tangem.core.ui.extensions.* +import com.tangem.core.ui.extensions.conditional +import com.tangem.core.ui.extensions.conditionalCompose +import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.extensions.stringResourceSafe import com.tangem.core.ui.res.* import com.tangem.features.feed.ui.earn.components.* import com.tangem.features.feed.ui.earn.state.* @@ -348,66 +345,6 @@ private fun FilterButtonsShimmer(modifier: Modifier = Modifier) { } } -@Composable -private fun BestOpportunitiesEmpty(modifier: Modifier = Modifier) { - Column( - modifier = modifier - .fillMaxWidth() - .padding(horizontal = 16.dp) - .background( - color = TangemTheme.colors.background.action, - shape = TangemTheme.shapes.roundedCornersXMedium, - ) - .padding(vertical = 32.dp, horizontal = 12.dp), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Icon( - modifier = Modifier - .fillMaxWidth(), - painter = painterResource(R.drawable.ic_empty_64), - contentDescription = null, - tint = Color.Unspecified, - ) - SpacerH(24.dp) - Text( - modifier = Modifier - .padding(horizontal = 32.dp), - text = stringResourceSafe(R.string.earn_empty), - style = TangemTheme.typography.body2, - color = TangemTheme.colors.text.tertiary, - textAlign = TextAlign.Center, - ) - } -} - -@Composable -private fun BestOpportunitiesEmptyFiltered(onClearFilterClick: () -> Unit, modifier: Modifier = Modifier) { - Column( - modifier = modifier - .fillMaxWidth() - .padding(horizontal = 16.dp) - .background( - color = TangemTheme.colors.background.action, - shape = TangemTheme.shapes.roundedCornersXMedium, - ) - .padding(vertical = 32.dp, horizontal = 12.dp), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Text( - text = stringResourceSafe(R.string.earn_no_results), - style = TangemTheme.typography.body2, - color = TangemTheme.colors.text.tertiary, - ) - SpacerH(12.dp) - SecondarySmallButton( - config = SmallButtonConfig( - text = resourceReference(R.string.earn_clear_filter), - onClick = onClearFilterClick, - ), - ) - } -} - @Composable private fun SectionHeader(title: String, modifier: Modifier = Modifier) { if (LocalRedesignEnabled.current) { diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/BestOpportunitiesEmpty.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/BestOpportunitiesEmpty.kt new file mode 100644 index 0000000000..eaee4b4be9 --- /dev/null +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/BestOpportunitiesEmpty.kt @@ -0,0 +1,93 @@ +package com.tangem.features.feed.ui.earn.components + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.tangem.core.ui.R +import com.tangem.core.ui.components.SpacerH +import com.tangem.core.ui.extensions.stringResourceSafe +import com.tangem.core.ui.res.LocalRedesignEnabled +import com.tangem.core.ui.res.TangemTheme + +@Composable +internal fun BestOpportunitiesEmpty(modifier: Modifier = Modifier) { + if (LocalRedesignEnabled.current) { + BestOpportunitiesEmptyV2(modifier) + } else { + BestOpportunitiesEmptyV1(modifier) + } +} + +@Composable +private fun BestOpportunitiesEmptyV1(modifier: Modifier = Modifier) { + Column( + modifier = modifier + .fillMaxWidth() + .padding(horizontal = 16.dp) + .background( + color = TangemTheme.colors.background.action, + shape = TangemTheme.shapes.roundedCornersXMedium, + ) + .padding(vertical = 32.dp, horizontal = 12.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Icon( + modifier = Modifier + .fillMaxWidth(), + painter = painterResource(R.drawable.ic_empty_64), + contentDescription = null, + tint = Color.Unspecified, + ) + SpacerH(TangemTheme.dimens2.x6) + Text( + modifier = Modifier + .padding(horizontal = TangemTheme.dimens2.x8), + text = stringResourceSafe(R.string.earn_empty), + style = TangemTheme.typography.body2, + color = TangemTheme.colors.text.tertiary, + textAlign = TextAlign.Center, + ) + } +} + +@Composable +private fun BestOpportunitiesEmptyV2(modifier: Modifier = Modifier) { + Column( + modifier = modifier + .fillMaxWidth() + .padding(horizontal = TangemTheme.dimens2.x4) + .background( + color = TangemTheme.colors2.surface.level3, + shape = RoundedCornerShape(TangemTheme.dimens2.x5), + ) + .padding(vertical = TangemTheme.dimens2.x8, horizontal = TangemTheme.dimens2.x3), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Icon( + modifier = Modifier + .fillMaxWidth(), + painter = painterResource(R.drawable.ic_empty_64), + contentDescription = null, + tint = TangemTheme.colors2.graphic.neutral.quaternary, + ) + SpacerH(TangemTheme.dimens2.x5) + Text( + modifier = Modifier.padding(horizontal = TangemTheme.dimens2.x8), + text = stringResourceSafe(R.string.earn_empty), + style = TangemTheme.typography2.bodyRegular14, + color = TangemTheme.colors2.text.neutral.secondary, + textAlign = TextAlign.Center, + ) + } +} \ No newline at end of file diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/BestOpportunitiesEmptyFiltered.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/BestOpportunitiesEmptyFiltered.kt new file mode 100644 index 0000000000..87314ee2f0 --- /dev/null +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/BestOpportunitiesEmptyFiltered.kt @@ -0,0 +1,89 @@ +package com.tangem.features.feed.ui.earn.components + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +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.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.tangem.core.ui.R +import com.tangem.core.ui.components.SpacerH +import com.tangem.core.ui.components.buttons.SecondarySmallButton +import com.tangem.core.ui.components.buttons.SmallButtonConfig +import com.tangem.core.ui.ds.button.* +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.stringResourceSafe +import com.tangem.core.ui.res.LocalRedesignEnabled +import com.tangem.core.ui.res.TangemTheme + +@Composable +internal fun BestOpportunitiesEmptyFiltered(onClearFilterClick: () -> Unit, modifier: Modifier = Modifier) { + if (LocalRedesignEnabled.current) { + BestOpportunitiesEmptyFilteredV2(onClearFilterClick, modifier) + } else { + BestOpportunitiesEmptyFilteredV1(onClearFilterClick, modifier) + } +} + +@Composable +private fun BestOpportunitiesEmptyFilteredV2(onClearFilterClick: () -> Unit, modifier: Modifier = Modifier) { + Column( + modifier = modifier + .fillMaxWidth() + .padding(horizontal = TangemTheme.dimens2.x4) + .background( + color = TangemTheme.colors2.surface.level3, + shape = RoundedCornerShape(TangemTheme.dimens2.x5), + ) + .padding(vertical = TangemTheme.dimens2.x8, horizontal = TangemTheme.dimens2.x3), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Text( + text = stringResourceSafe(R.string.earn_no_results), + style = TangemTheme.typography2.bodyRegular14, + color = TangemTheme.colors2.text.neutral.secondary, + ) + SpacerH(TangemTheme.dimens2.x2) + TangemButton( + buttonUM = TangemButtonUM( + text = resourceReference(R.string.earn_clear_filter), + onClick = onClearFilterClick, + type = TangemButtonType.Secondary, + size = TangemButtonSize.X8, + shape = TangemButtonShape.Rounded, + ), + ) + } +} + +@Composable +private fun BestOpportunitiesEmptyFilteredV1(onClearFilterClick: () -> Unit, modifier: Modifier = Modifier) { + Column( + modifier = modifier + .fillMaxWidth() + .padding(horizontal = 16.dp) + .background( + color = TangemTheme.colors.background.action, + shape = TangemTheme.shapes.roundedCornersXMedium, + ) + .padding(vertical = 32.dp, horizontal = 12.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Text( + text = stringResourceSafe(R.string.earn_no_results), + style = TangemTheme.typography.body2, + color = TangemTheme.colors.text.tertiary, + ) + SpacerH(12.dp) + SecondarySmallButton( + config = SmallButtonConfig( + text = resourceReference(R.string.earn_clear_filter), + onClick = onClearFilterClick, + ), + ) + } +} \ No newline at end of file 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 961de3106d..dff1428685 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 @@ -1,57 +1,54 @@ package com.tangem.features.feed.ui.earn.components -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.background import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Text +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Icon import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.vectorResource +import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent -import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet -import com.tangem.core.ui.ds.button.SecondaryTangemButton -import com.tangem.core.ui.ds.button.TangemButtonShape -import com.tangem.core.ui.ds.button.TangemButtonSize -import com.tangem.core.ui.extensions.stringResourceSafe +import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetType +import com.tangem.core.ui.ds.topbar.TangemTopBar +import com.tangem.core.ui.ds.topbar.TangemTopBarType +import com.tangem.core.ui.extensions.clickableSingle +import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.res.TangemTheme import com.tangem.features.feed.impl.R @Composable internal inline fun EarnFilterBottomSheet( config: TangemBottomSheetConfig, - crossinline content: @Composable ColumnScope.(T) -> Unit, + crossinline content: @Composable (T) -> Unit, ) { TangemBottomSheet( config = config, + type = TangemBottomSheetType.Modal, containerColor = TangemTheme.colors2.surface.level3, title = { - Box( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = TangemTheme.dimens.spacing24) - .padding(bottom = TangemTheme.dimens.spacing12), - contentAlignment = Alignment.Center, - ) { - Text( - text = stringResourceSafe(R.string.earn_filter_by), - style = TangemTheme.typography2.headingSemibold17, - color = TangemTheme.colors2.text.neutral.primary, - textAlign = TextAlign.Center, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) - SecondaryTangemButton( - modifier = Modifier.align(Alignment.CenterEnd), - onClick = config.onDismissRequest, - iconRes = R.drawable.ic_close_24, - size = TangemButtonSize.X9, - shape = TangemButtonShape.Rounded, - ) - } + TangemTopBar( + title = resourceReference(R.string.earn_filter_by), + type = TangemTopBarType.BottomSheet, + endContent = { + Icon( + imageVector = ImageVector.vectorResource(id = R.drawable.ic_close_24), + contentDescription = null, + tint = TangemTheme.colors2.graphic.neutral.primary, + modifier = Modifier + .size(TangemTheme.dimens2.x11) + .background( + color = TangemTheme.colors2.button.backgroundSecondary, + shape = CircleShape, + ) + .clickableSingle(onClick = config.onDismissRequest) + .padding(TangemTheme.dimens2.x2_5), + ) + }, + ) }, content = content, ) 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 8a0233f7b8..befac566af 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 @@ -119,9 +119,10 @@ private fun ContentV2(content: EarnFilterByNetworkBottomSheetContentUM) { Column( modifier = Modifier - .padding(horizontal = 16.dp) + .padding(horizontal = TangemTheme.dimens2.x4) + .padding(bottom = TangemTheme.dimens2.x4) .verticalScroll(rememberScrollState()), - verticalArrangement = Arrangement.spacedBy(12.dp), + verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x3), ) { NetworksTypesBlock( allMyNetworks = allMyNetworks, 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 396599caca..9c8a7d4381 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 @@ -93,7 +93,9 @@ private fun ContentV1(content: EarnFilterByTypeBottomSheetContentUM) { @Composable private fun ContentV2(content: EarnFilterByTypeBottomSheetContentUM) { CardFilterBlock( - modifier = Modifier.padding(horizontal = 16.dp), + modifier = Modifier + .padding(horizontal = TangemTheme.dimens2.x4) + .padding(bottom = TangemTheme.dimens2.x4), ) { EarnFilterTypeUM.entries.forEachIndexed { index, type -> TangemRowContainer( diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/FeedListLoading.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/FeedListLoading.kt index 73294fe9f8..14ef1324cc 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/FeedListLoading.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/FeedListLoading.kt @@ -9,14 +9,15 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.tangem.common.ui.markets.MarketsListItemPlaceholder -import com.tangem.features.feed.ui.feed.components.articles.DefaultLoadingArticle -import com.tangem.features.feed.ui.feed.components.articles.TrendingLoadingArticle import com.tangem.core.ui.components.RectangleShimmer import com.tangem.core.ui.components.SpacerH import com.tangem.core.ui.components.block.BlockCard import com.tangem.core.ui.components.block.TangemBlockCardColors +import com.tangem.core.ui.res.LocalRedesignEnabled import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.features.feed.ui.feed.components.articles.DefaultLoadingArticle +import com.tangem.features.feed.ui.feed.components.articles.TrendingLoadingArticle @Composable internal fun FeedListLoading(modifier: Modifier = Modifier) { @@ -35,70 +36,142 @@ internal fun FeedListLoading(modifier: Modifier = Modifier) { @Composable internal fun MarketLoadingBlock() { - RectangleShimmer( - modifier = Modifier - .padding(start = 16.dp) - .size(width = 104.dp, height = 18.dp), - ) - SpacerH(15.dp) - ChartsLoading(modifier = Modifier.padding(horizontal = 16.dp)) - SpacerH(35.dp) -} - -@Composable -internal fun MarketPulseLoadingBlock() { - RectangleShimmer( - modifier = Modifier - .padding(start = 16.dp) - .size(width = 104.dp, height = 18.dp), - ) - SpacerH(15.dp) - LazyRow( - modifier = Modifier.padding(vertical = 4.dp), - verticalAlignment = Alignment.CenterVertically, - contentPadding = PaddingValues(16.dp), - horizontalArrangement = Arrangement.spacedBy(8.dp), - state = rememberLazyListState(), - ) { - items(DEFAULT_CHART_SIZE_IN_MARKET) { - RectangleShimmer(modifier = Modifier.size(width = 124.dp, height = 36.dp)) - } - } - SpacerH(16.dp) - ChartsLoading(modifier = Modifier.padding(horizontal = 16.dp)) - SpacerH(32.dp) -} - -@Composable -internal fun NewsLoadingBlock() { - Column { + if (LocalRedesignEnabled.current) { + RectangleShimmer( + modifier = Modifier + .padding(start = 16.dp, top = 16.dp) + .size(width = 132.dp, height = 24.dp), + radius = TangemTheme.dimens2.x25, + ) + SpacerH(20.dp) + ChartsLoading(modifier = Modifier.padding(horizontal = 16.dp)) + SpacerH(40.dp) + } else { RectangleShimmer( modifier = Modifier .padding(start = 16.dp) .size(width = 104.dp, height = 18.dp), ) SpacerH(15.dp) - TrendingLoadingArticle(modifier = Modifier.padding(horizontal = 16.dp)) - SpacerH(12.dp) - LazyRow( - verticalAlignment = Alignment.CenterVertically, - contentPadding = PaddingValues(16.dp), - horizontalArrangement = Arrangement.spacedBy(12.dp), - state = rememberLazyListState(), - ) { - items(DEFAULT_CHART_SIZE_IN_MARKET) { - DefaultLoadingArticle() - } - } + ChartsLoading(modifier = Modifier.padding(horizontal = 16.dp)) SpacerH(35.dp) } } +@Composable +internal fun MarketPulseLoadingBlock() { + if (LocalRedesignEnabled.current) { + RectangleShimmer( + modifier = Modifier + .padding(start = 16.dp, top = 16.dp) + .size(width = 132.dp, height = 24.dp), + radius = TangemTheme.dimens2.x25, + ) + SpacerH(15.dp) + LazyRow( + modifier = Modifier.padding(vertical = 4.dp), + verticalAlignment = Alignment.CenterVertically, + contentPadding = PaddingValues(16.dp), + horizontalArrangement = Arrangement.spacedBy(6.dp), + state = rememberLazyListState(), + ) { + items(DEFAULT_CHART_SIZE_IN_MARKET) { + RectangleShimmer( + modifier = Modifier.size(width = 112.dp, height = 36.dp), + radius = TangemTheme.dimens2.x25, + ) + } + } + SpacerH(16.dp) + ChartsLoading(modifier = Modifier.padding(horizontal = 16.dp)) + SpacerH(32.dp) + } else { + RectangleShimmer( + modifier = Modifier + .padding(start = 16.dp) + .size(width = 104.dp, height = 18.dp), + ) + SpacerH(15.dp) + LazyRow( + modifier = Modifier.padding(vertical = 4.dp), + verticalAlignment = Alignment.CenterVertically, + contentPadding = PaddingValues(16.dp), + horizontalArrangement = Arrangement.spacedBy(8.dp), + state = rememberLazyListState(), + ) { + items(DEFAULT_CHART_SIZE_IN_MARKET) { + RectangleShimmer(modifier = Modifier.size(width = 124.dp, height = 36.dp)) + } + } + SpacerH(16.dp) + ChartsLoading(modifier = Modifier.padding(horizontal = 16.dp)) + SpacerH(32.dp) + } +} + +@Composable +internal fun NewsLoadingBlock() { + if (LocalRedesignEnabled.current) { + Column { + RectangleShimmer( + modifier = Modifier + .padding(start = 16.dp, top = 16.dp) + .size(width = 132.dp, height = 24.dp), + radius = TangemTheme.dimens2.x25, + ) + SpacerH(20.dp) + TrendingLoadingArticle(modifier = Modifier.padding(horizontal = 16.dp)) + SpacerH(12.dp) + LazyRow( + verticalAlignment = Alignment.CenterVertically, + contentPadding = PaddingValues(horizontal = 16.dp), + horizontalArrangement = Arrangement.spacedBy(12.dp), + state = rememberLazyListState(), + ) { + items(DEFAULT_CHART_SIZE_IN_MARKET) { + DefaultLoadingArticle() + } + } + SpacerH(40.dp) + } + } else { + Column { + RectangleShimmer( + modifier = Modifier + .padding(start = 16.dp) + .size(width = 104.dp, height = 18.dp), + ) + SpacerH(15.dp) + TrendingLoadingArticle(modifier = Modifier.padding(horizontal = 16.dp)) + SpacerH(12.dp) + LazyRow( + verticalAlignment = Alignment.CenterVertically, + contentPadding = PaddingValues(16.dp), + horizontalArrangement = Arrangement.spacedBy(12.dp), + state = rememberLazyListState(), + ) { + items(DEFAULT_CHART_SIZE_IN_MARKET) { + DefaultLoadingArticle() + } + } + SpacerH(35.dp) + } + } +} + @Composable private fun ChartsLoading(modifier: Modifier = Modifier) { + val isRedesignEnabled = LocalRedesignEnabled.current BlockCard( modifier = modifier, - colors = TangemBlockCardColors.copy(containerColor = TangemTheme.colors.background.action), + colors = TangemBlockCardColors.copy( + containerColor = if (isRedesignEnabled) { + TangemTheme.colors2.surface.level3 + } else { + TangemTheme.colors.background.action + }, + + ), ) { Column( modifier = Modifier 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 11360bacd7..b24607dc57 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 @@ -25,7 +25,9 @@ import com.tangem.core.ui.components.SpacerH import com.tangem.core.ui.components.UnableToLoadData import com.tangem.core.ui.components.block.BlockCard import com.tangem.core.ui.components.block.TangemBlockCardColors +import com.tangem.core.ui.ds.tabs.TangemTab 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.model.market.list.state.SortByTypeUM import com.tangem.features.feed.ui.feed.state.FeedListCallbacks @@ -34,6 +36,7 @@ import com.tangem.features.feed.ui.feed.state.MarketChartUM @Composable internal fun MarketBlock(marketChart: MarketChartUM?, feedListCallbacks: FeedListCallbacks) { + val isRedesignEnabled = LocalRedesignEnabled.current AnimatedContent( targetState = marketChart, label = "MarketBlockChartAnimation", @@ -49,8 +52,16 @@ internal fun MarketBlock(marketChart: MarketChartUM?, feedListCallbacks: FeedLis title = { Text( text = stringResourceSafe(R.string.markets_common_title), - style = TangemTheme.typography.h3, - color = TangemTheme.colors.text.primary1, + style = if (isRedesignEnabled) { + TangemTheme.typography2.headingSemibold20 + } else { + TangemTheme.typography.h3 + }, + color = if (isRedesignEnabled) { + TangemTheme.colors2.text.neutral.primary + } else { + TangemTheme.colors.text.primary1 + }, overflow = TextOverflow.Ellipsis, maxLines = 1, ) @@ -76,8 +87,10 @@ internal fun MarketBlock(marketChart: MarketChartUM?, feedListCallbacks: FeedLis } } +@Suppress("LongMethod") @Composable internal fun MarketPulseBlock(marketChartConfig: MarketChartConfig, feedListCallbacks: FeedListCallbacks) { + val isRedesignEnabled = LocalRedesignEnabled.current val onSeeAllClick by rememberUpdatedState { feedListCallbacks.onMarketOpenClick(marketChartConfig.currentSortByType) } @@ -86,8 +99,16 @@ internal fun MarketPulseBlock(marketChartConfig: MarketChartConfig, feedListCall title = { Text( text = stringResourceSafe(R.string.markets_pulse_common_title), - style = TangemTheme.typography.h3, - color = TangemTheme.colors.text.primary1, + style = if (isRedesignEnabled) { + TangemTheme.typography2.headingSemibold20 + } else { + TangemTheme.typography.h3 + }, + color = if (isRedesignEnabled) { + TangemTheme.colors2.text.neutral.primary + } else { + TangemTheme.colors.text.primary1 + }, overflow = TextOverflow.Ellipsis, maxLines = 1, ) @@ -98,9 +119,13 @@ internal fun MarketPulseBlock(marketChartConfig: MarketChartConfig, feedListCall ) LazyRow( - modifier = Modifier.padding(vertical = 4.dp), + modifier = Modifier.padding(vertical = if (isRedesignEnabled) 12.dp else 4.dp), verticalAlignment = Alignment.CenterVertically, - contentPadding = PaddingValues(16.dp), + contentPadding = if (isRedesignEnabled) { + PaddingValues(horizontal = 16.dp, vertical = 6.dp) + } else { + PaddingValues(16.dp) + }, horizontalArrangement = Arrangement.spacedBy(8.dp), state = rememberLazyListState(), ) { @@ -108,16 +133,22 @@ internal fun MarketPulseBlock(marketChartConfig: MarketChartConfig, feedListCall items = marketChartConfig.getFilterPreset(), key = SortByTypeUM::name, ) { sortByTypeUM -> - ChartsFilterChip( - sortByTypeUM = sortByTypeUM, - isSelected = sortByTypeUM == marketChartConfig.currentSortByType, - onClick = { feedListCallbacks.onSortTypeClick(sortByTypeUM) }, - ) + if (isRedesignEnabled) { + TangemTab( + text = sortByTypeUM.text, + isChecked = sortByTypeUM == marketChartConfig.currentSortByType, + onCheckedChange = { feedListCallbacks.onSortTypeClick(sortByTypeUM) }, + ) + } else { + ChartsFilterChip( + sortByTypeUM = sortByTypeUM, + isSelected = sortByTypeUM == marketChartConfig.currentSortByType, + onClick = { feedListCallbacks.onSortTypeClick(sortByTypeUM) }, + ) + } } } - SpacerH(12.dp) - AnimatedContent( targetState = marketChartConfig.currentSortByType, label = "MarketPulseChartAnimation", @@ -141,9 +172,16 @@ private fun Charts( onItemClick: (MarketsListItemUM) -> Unit, modifier: Modifier = Modifier, ) { + val isRedesignEnabled = LocalRedesignEnabled.current BlockCard( modifier = modifier, - colors = TangemBlockCardColors.copy(containerColor = TangemTheme.colors.background.action), + colors = TangemBlockCardColors.copy( + containerColor = if (isRedesignEnabled) { + TangemTheme.colors2.surface.level3 + } else { + TangemTheme.colors.background.action + }, + ), ) { Column(modifier = Modifier.fillMaxWidth()) { when (marketChart) { diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/ExchangesBottomSheet.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/ExchangesBottomSheet.kt index 8b6dc00d33..7d88242f03 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/ExchangesBottomSheet.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/ExchangesBottomSheet.kt @@ -2,28 +2,31 @@ package com.tangem.features.feed.ui.market.detailed.components import android.content.res.Configuration import androidx.annotation.StringRes -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.systemBars +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.layout.layoutId import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.res.vectorResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider +import androidx.compose.ui.unit.dp +import com.tangem.core.ui.components.CircleShimmer +import com.tangem.core.ui.components.RectangleShimmer +import com.tangem.core.ui.components.SpacerH import com.tangem.core.ui.components.SpacerH12 import com.tangem.core.ui.components.appbar.TangemTopAppBar import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM @@ -35,16 +38,22 @@ import com.tangem.core.ui.components.buttons.SmallButtonConfig import com.tangem.core.ui.components.currency.icon.CurrencyIconState import com.tangem.core.ui.components.token.TokenItem import com.tangem.core.ui.components.token.state.TokenItemState -import com.tangem.core.ui.extensions.TextReference -import com.tangem.core.ui.extensions.resolveReference -import com.tangem.core.ui.extensions.resourceReference -import com.tangem.core.ui.extensions.stringReference -import com.tangem.core.ui.extensions.stringResourceSafe +import com.tangem.core.ui.decorations.roundedShapeItemDecoration +import com.tangem.core.ui.ds.button.* +import com.tangem.core.ui.ds.image.TangemIcon +import com.tangem.core.ui.ds.row.TangemRowContainer +import com.tangem.core.ui.ds.row.TangemRowLayoutId +import com.tangem.core.ui.ds.topbar.TangemTopBar +import com.tangem.core.ui.ds.topbar.TangemTopBarType +import com.tangem.core.ui.extensions.* +import com.tangem.core.ui.res.LocalRedesignEnabled import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview import com.tangem.features.feed.impl.R +import com.tangem.features.feed.ui.market.detailed.state.ExchangeItemUM import com.tangem.features.feed.ui.market.detailed.state.ExchangesBottomSheetContent import kotlinx.collections.immutable.toImmutableList +import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet as TangemBottomSheetV2 /** * Exchanges bottom sheet @@ -55,6 +64,15 @@ import kotlinx.collections.immutable.toImmutableList */ @Composable internal fun ExchangesBottomSheet(config: TangemBottomSheetConfig) { + if (LocalRedesignEnabled.current) { + ExchangesBottomSheetV2(config) + } else { + ExchangesBottomSheetV1(config) + } +} + +@Composable +private fun ExchangesBottomSheetV1(config: TangemBottomSheetConfig) { val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() } TangemBottomSheet( @@ -98,6 +116,77 @@ internal fun ExchangesBottomSheet(config: TangemBottomSheetConfig) { ) } +@Composable +private fun ExchangesBottomSheetV2(config: TangemBottomSheetConfig) { + val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() } + + TangemBottomSheetV2( + config = config, + title = { content -> + TangemTopBar( + title = resourceReference(content.titleResId), + type = TangemTopBarType.BottomSheet, + startContent = { + Icon( + imageVector = ImageVector.vectorResource(id = R.drawable.ic_arrow_back_28), + contentDescription = null, + tint = TangemTheme.colors2.graphic.neutral.primary, + modifier = Modifier + .size(TangemTheme.dimens2.x11) + .background( + color = TangemTheme.colors2.button.backgroundSecondary, + shape = CircleShape, + ) + .clickableSingle(onClick = config.onDismissRequest) + .padding(TangemTheme.dimens2.x2), + ) + }, + ) + }, + content = { content -> + Box { + LazyColumn( + modifier = Modifier.fillMaxSize(), + contentPadding = PaddingValues(bottom = bottomBarHeight), + ) { + item(key = "subtitle") { + Subtitle( + subtitleRes = content.subtitleResId, + volumeReference = content.volumeReference, + modifier = Modifier.padding(horizontal = TangemTheme.dimens2.x7), + ) + } + + if (content.exchangeItemsV2.isNotEmpty()) { + val lastIndex = content.exchangeItemsV2.lastIndex + itemsIndexed( + items = content.exchangeItemsV2, + key = { _, item -> item.id }, + ) { index, item -> + ExchangeItemRow( + exchangeItemUM = item, + modifier = Modifier + .roundedShapeItemDecoration( + currentIndex = index, + lastIndex = lastIndex, + backgroundColor = TangemTheme.colors2.surface.level3, + ), + ) + } + } + } + + if (content is ExchangesBottomSheetContent.Error) { + Error( + content = content, + modifier = Modifier.align(Alignment.Center), + ) + } + } + }, + ) +} + @Composable private fun Title(@StringRes textResId: Int, onBackClick: () -> Unit) { TangemTopAppBar( @@ -120,17 +209,36 @@ private fun Subtitle(@StringRes subtitleRes: Int, volumeReference: TextReference @Composable private fun SubtitleText(textReference: TextReference) { - Text( - text = textReference.resolveReference(), - color = TangemTheme.colors.text.tertiary, - overflow = TextOverflow.Ellipsis, - maxLines = 1, - style = TangemTheme.typography.body2, - ) + if (LocalRedesignEnabled.current) { + Text( + text = textReference.resolveReference(), + color = TangemTheme.colors2.text.neutral.secondary, + overflow = TextOverflow.Ellipsis, + maxLines = 1, + style = TangemTheme.typography2.captionSemibold12, + ) + } else { + Text( + text = textReference.resolveReference(), + color = TangemTheme.colors.text.tertiary, + overflow = TextOverflow.Ellipsis, + maxLines = 1, + style = TangemTheme.typography.body2, + ) + } } @Composable private fun Error(content: ExchangesBottomSheetContent.Error, modifier: Modifier = Modifier) { + if (LocalRedesignEnabled.current) { + ErrorV2(content, modifier) + } else { + ErrorV1(content, modifier) + } +} + +@Composable +private fun ErrorV1(content: ExchangesBottomSheetContent.Error, modifier: Modifier = Modifier) { Column( modifier = modifier, verticalArrangement = Arrangement.Center, @@ -154,6 +262,155 @@ private fun Error(content: ExchangesBottomSheetContent.Error, modifier: Modifier } } +@Composable +private fun ErrorV2(content: ExchangesBottomSheetContent.Error, modifier: Modifier = Modifier) { + Column( + modifier = modifier, + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Text( + text = stringResourceSafe(id = content.message), + color = TangemTheme.colors2.text.neutral.tertiary, + textAlign = TextAlign.Center, + style = TangemTheme.typography2.bodyRegular14, + ) + + SpacerH(8.dp) + + TangemButton( + buttonUM = TangemButtonUM( + text = resourceReference(com.tangem.core.ui.R.string.try_to_load_data_again_button_title), + onClick = content.onRetryClick, + type = TangemButtonType.Secondary, + size = TangemButtonSize.X8, + shape = TangemButtonShape.Rounded, + ), + ) + } +} + +@Composable +private fun ExchangeItemRow(exchangeItemUM: ExchangeItemUM, modifier: Modifier = Modifier) { + when (exchangeItemUM) { + is ExchangeItemUM.Content -> { + ExchangeItemRowContent(exchangeItemUM, modifier) + } + is ExchangeItemUM.Loading -> { + ExchangeItemRowPlaceholder(modifier) + } + } +} + +@Composable +private fun ExchangeItemRowContent(exchangeItemUM: ExchangeItemUM.Content, modifier: Modifier = Modifier) { + TangemRowContainer( + modifier = modifier, + contentPadding = PaddingValues(horizontal = 12.dp, vertical = 14.dp), + ) { + TangemIcon( + tangemIconUM = exchangeItemUM.icon, + modifier = Modifier + .layoutId(layoutId = TangemRowLayoutId.HEAD) + .size(TangemTheme.dimens2.x10), + ) + + Text( + modifier = Modifier + .padding(start = TangemTheme.dimens2.x2) + .layoutId(TangemRowLayoutId.START_TOP), + text = exchangeItemUM.title.resolveReference(), + style = TangemTheme.typography2.bodySemibold16, + color = TangemTheme.colors2.text.neutral.primary, + ) + + Text( + modifier = Modifier + .padding(start = TangemTheme.dimens2.x2) + .layoutId(TangemRowLayoutId.START_BOTTOM), + text = exchangeItemUM.subTitle.resolveReference(), + style = TangemTheme.typography2.captionSemibold12, + color = TangemTheme.colors2.text.neutral.secondary, + ) + + Text( + modifier = Modifier + .padding(start = TangemTheme.dimens2.x2) + .layoutId(TangemRowLayoutId.END_TOP), + text = exchangeItemUM.volumeInUsd.resolveReference(), + style = TangemTheme.typography2.bodySemibold16, + color = TangemTheme.colors2.text.neutral.primary, + ) + + Text( + modifier = Modifier + .background( + color = getColorByTrustValue(exchangeItemUM.auditLabel.type).copy(alpha = .1f), + shape = CircleShape, + ) + .padding(vertical = 2.dp, horizontal = 6.dp) + .layoutId(TangemRowLayoutId.END_BOTTOM), + text = exchangeItemUM.auditLabel.text.resolveReference(), + style = TangemTheme.typography2.captionSemibold11, + color = getColorByTrustValue(exchangeItemUM.auditLabel.type), + ) + } +} + +@Composable +private fun ExchangeItemRowPlaceholder(modifier: Modifier = Modifier) { + TangemRowContainer( + modifier = modifier, + contentPadding = PaddingValues(horizontal = 12.dp, vertical = 14.dp), + ) { + CircleShimmer( + modifier = Modifier + .size(40.dp) + .layoutId(TangemRowLayoutId.HEAD), + ) + RectangleShimmer( + modifier = Modifier + .width(108.dp) + .height(20.dp) + .padding(start = 4.dp) + .layoutId(TangemRowLayoutId.START_TOP), + ) + RectangleShimmer( + modifier = Modifier + .width(52.dp) + .height(16.dp) + .padding(start = 4.dp) + .layoutId(TangemRowLayoutId.START_BOTTOM), + ) + RectangleShimmer( + modifier = Modifier + .width(106.dp) + .height(20.dp) + .padding(start = 4.dp) + .layoutId(TangemRowLayoutId.END_TOP), + ) + RectangleShimmer( + modifier = Modifier + .width(52.dp) + .height(16.dp) + .padding(start = 4.dp) + .layoutId(TangemRowLayoutId.END_BOTTOM), + ) + } +} + +@Composable +private fun getColorByTrustValue(type: AuditLabelUM.Type): Color { + return when (type) { + AuditLabelUM.Type.Prohibition -> TangemTheme.colors2.fill.status.attention + AuditLabelUM.Type.Warning -> TangemTheme.colors2.fill.status.warning + AuditLabelUM.Type.Permit, + AuditLabelUM.Type.Info, + AuditLabelUM.Type.General, + -> TangemTheme.colors2.fill.status.accent + } +} + @Preview @Preview(name = "Dark Theme", uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable @@ -175,7 +432,7 @@ private class ExchangesBottomSheetContentProvider : CollectionPreviewParameterPr listOf( ExchangesBottomSheetContent.Loading(exchangesCount = 13), ExchangesBottomSheetContent.Error(onRetryClick = {}), - ExchangesBottomSheetContent.Content( + ExchangesBottomSheetContent.ContentV1( exchangeItems = List(size = 13) { index -> TokenItemState.Content( id = index.toString(), diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/InfoBottomSheet.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/InfoBottomSheet.kt index 345f000aa3..394cf45ce7 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/InfoBottomSheet.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/InfoBottomSheet.kt @@ -1,30 +1,52 @@ package com.tangem.features.feed.ui.market.detailed.components -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.systemBars +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Icon +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.layout.layoutId import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.res.vectorResource import com.tangem.core.ui.components.SpacerH import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig +import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetType import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheetTitle import com.tangem.core.ui.components.notifications.Notification import com.tangem.core.ui.components.notifications.NotificationConfig +import com.tangem.core.ui.ds.row.TangemRowContainer +import com.tangem.core.ui.ds.row.TangemRowLayoutId +import com.tangem.core.ui.ds.topbar.TangemTopBar +import com.tangem.core.ui.ds.topbar.TangemTopBarType import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.clickableSingle import com.tangem.core.ui.extensions.resolveReference +import com.tangem.core.ui.extensions.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.market.detailed.state.InfoBottomSheetContent import dev.jeziellago.compose.markdowntext.MarkdownText +import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet as TangemBottomSheetV2 @Composable internal fun InfoBottomSheet(config: TangemBottomSheetConfig) { + if (LocalRedesignEnabled.current) { + InfoBottomSheetV2(config) + } else { + InfoBottomSheetV1(config) + } +} + +@Composable +private fun InfoBottomSheetV1(config: TangemBottomSheetConfig) { val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() } TangemBottomSheet( @@ -62,6 +84,89 @@ internal fun InfoBottomSheet(config: TangemBottomSheetConfig) { ) } +@Suppress("LongMethod") +@Composable +private fun InfoBottomSheetV2(config: TangemBottomSheetConfig) { + val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() } + + TangemBottomSheetV2( + config = config, + type = TangemBottomSheetType.Modal, + containerColor = TangemTheme.colors2.surface.level3, + title = { content -> + TangemTopBar( + title = content.title, + type = TangemTopBarType.BottomSheet, + endContent = { + Icon( + imageVector = ImageVector.vectorResource(id = R.drawable.ic_close_24), + contentDescription = null, + tint = TangemTheme.colors2.graphic.neutral.primary, + modifier = Modifier + .size(TangemTheme.dimens2.x11) + .background( + color = TangemTheme.colors2.button.backgroundSecondary, + shape = CircleShape, + ) + .clickableSingle(onClick = config.onDismissRequest) + .padding(TangemTheme.dimens2.x2_5), + ) + }, + ) + }, + content = { content -> + Column( + modifier = Modifier + .verticalScroll(rememberScrollState()) + .padding(horizontal = TangemTheme.dimens2.x4), + ) { + MarkdownText( + modifier = Modifier.padding(bottom = TangemTheme.dimens2.x3), + markdown = content.body.resolveReference(), + disableLinkMovementMethod = true, + linkifyMask = 0, + syntaxHighlightColor = TangemTheme.colors2.text.neutral.secondary, + style = TangemTheme.typography2.bodyRegular16.copy( + TangemTheme.colors2.text.neutral.secondary, + ), + ) + + if (content.generatedAINotificationUM != null) { + TangemRowContainer( + modifier = Modifier + .background( + color = TangemTheme.colors2.surface.level4, + shape = RoundedCornerShape(TangemTheme.dimens2.x5), + ) + .clickableSingle(onClick = content.generatedAINotificationUM.onClick), + contentPadding = PaddingValues(TangemTheme.dimens2.x3), + ) { + Icon( + modifier = Modifier + .size(TangemTheme.dimens2.x10) + .padding(TangemTheme.dimens2.x1) + .layoutId(TangemRowLayoutId.HEAD), + tint = TangemTheme.colors2.markers.iconBlue, + contentDescription = null, + imageVector = ImageVector.vectorResource(R.drawable.ic_magic_28), + ) + + Text( + modifier = Modifier + .padding(start = TangemTheme.dimens2.x1) + .layoutId(TangemRowLayoutId.START_TOP), + text = stringResourceSafe(R.string.information_generated_with_ai), + style = TangemTheme.typography2.captionSemibold12, + color = TangemTheme.colors2.text.neutral.primary, + ) + } + } + SpacerH(bottomBarHeight) + } + }, + ) +} + @Composable private fun AdditionalInfoNotification(onClick: () -> Unit, modifier: Modifier = Modifier) { Notification( diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/SecurityScoreBottomSheet.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/SecurityScoreBottomSheet.kt index fc40da9bcc..884352769f 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/SecurityScoreBottomSheet.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/SecurityScoreBottomSheet.kt @@ -1,42 +1,71 @@ package com.tangem.features.feed.ui.market.detailed.components import android.content.res.Configuration -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable +import androidx.compose.foundation.* import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.* -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.material3.ripple import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.drawWithCache +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.geometry.Size +import androidx.compose.ui.graphics.BlendMode +import androidx.compose.ui.graphics.CompositingStrategy +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.layout.layoutId import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.vectorResource import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.util.fastForEach import androidx.compose.ui.util.fastForEachIndexed import coil.compose.SubcomposeAsyncImage import coil.request.ImageRequest import com.tangem.core.ui.components.* import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig +import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetType import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheetTitle import com.tangem.core.ui.components.inputrow.inner.DividerContainer import com.tangem.core.ui.decorations.roundedShapeItemDecoration +import com.tangem.core.ui.ds.row.TangemRowContainer +import com.tangem.core.ui.ds.row.TangemRowLayoutId +import com.tangem.core.ui.ds.topbar.TangemTopBar +import com.tangem.core.ui.ds.topbar.TangemTopBarType +import com.tangem.core.ui.extensions.clickableSingle import com.tangem.core.ui.extensions.resolveReference +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.features.feed.impl.R import com.tangem.features.feed.ui.market.detailed.preview.SecurityScorePreviewData import com.tangem.features.feed.ui.market.detailed.state.SecurityScoreBottomSheetContent +import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet as TangemBottomSheetV2 @Composable internal fun SecurityScoreBottomSheet(config: TangemBottomSheetConfig) { + if (LocalRedesignEnabled.current) { + SecurityScoreBottomSheetV2(config) + } else { + SecurityScoreBottomSheetV1(config) + } +} + +@Composable +private fun SecurityScoreBottomSheetV1(config: TangemBottomSheetConfig) { val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() } TangemBottomSheet( @@ -82,6 +111,62 @@ internal fun SecurityScoreBottomSheet(config: TangemBottomSheetConfig) { ) } +@Composable +private fun SecurityScoreBottomSheetV2(config: TangemBottomSheetConfig) { + val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() } + + TangemBottomSheetV2( + config = config, + type = TangemBottomSheetType.Modal, + title = { content -> + TangemTopBar( + title = content.title, + type = TangemTopBarType.BottomSheet, + endContent = { + Icon( + imageVector = ImageVector.vectorResource(id = R.drawable.ic_close_24), + contentDescription = null, + tint = TangemTheme.colors2.graphic.neutral.primary, + modifier = Modifier + .size(TangemTheme.dimens2.x11) + .background( + color = TangemTheme.colors2.button.backgroundSecondary, + shape = CircleShape, + ) + .clickableSingle(onClick = config.onDismissRequest) + .padding(TangemTheme.dimens2.x2_5), + ) + }, + ) + }, + content = { content -> + Column( + modifier = Modifier + .verticalScroll(rememberScrollState()) + .padding(horizontal = TangemTheme.dimens2.x4), + ) { + Text( + text = content.description.resolveReference(), + style = TangemTheme.typography2.bodyRegular15.copy( + color = TangemTheme.colors2.text.neutral.tertiary, + ), + ) + SpacerH12() + content.providers.fastForEach { provider -> + SecurityScoreProviderRowV2( + providerUM = provider, + onLinkClick = { content.onProviderLinkClick(provider) }, + ) + SpacerH(TangemTheme.dimens2.x2) + } + + SpacerH16() + SpacerH(bottomBarHeight) + } + }, + ) +} + @Composable private fun SecurityScoreProviderRow( providerUM: SecurityScoreBottomSheetContent.SecurityScoreProviderUM, @@ -145,17 +230,91 @@ private fun SecurityScoreProviderRow( horizontalSpacing = TangemTheme.dimens.spacing3, ) - UrlBlock(providerUM) + UrlBlockV1(providerUM) } } } @Composable -private fun UrlBlock(providerUM: SecurityScoreBottomSheetContent.SecurityScoreProviderUM) { +private fun SecurityScoreProviderRowV2( + providerUM: SecurityScoreBottomSheetContent.SecurityScoreProviderUM, + onLinkClick: () -> Unit, +) { + TangemRowContainer( + modifier = Modifier + .background( + color = TangemTheme.colors2.surface.level4, + shape = RoundedCornerShape(TangemTheme.dimens2.x5), + ) + .border( + width = 1.dp, + color = TangemTheme.colors2.border.neutral.primary, + shape = RoundedCornerShape(TangemTheme.dimens2.x5), + ), + ) { + SubcomposeAsyncImage( + modifier = Modifier + .size(size = TangemTheme.dimens.size40) + .clip(TangemTheme.shapes.roundedCorners8) + .layoutId(TangemRowLayoutId.HEAD), + model = ImageRequest.Builder(context = LocalContext.current) + .data(providerUM.iconUrl) + .crossfade(enable = true) + .allowHardware(false) + .build(), + loading = { RectangleShimmer(radius = TangemTheme.dimens2.x3) }, + error = { RectangleShimmer(radius = TangemTheme.dimens2.x3) }, + contentDescription = null, + ) + + Text( + modifier = Modifier + .padding(start = TangemTheme.dimens2.x2) + .layoutId(TangemRowLayoutId.START_TOP), + text = providerUM.name, + style = TangemTheme.typography2.bodySemibold16, + color = TangemTheme.colors2.text.neutral.primary, + ) + + providerUM.lastAuditDate?.let { auditDate -> + Text( + modifier = Modifier + .padding(start = TangemTheme.dimens2.x2) + .layoutId(TangemRowLayoutId.START_BOTTOM), + text = auditDate, + style = TangemTheme.typography2.captionSemibold12, + color = TangemTheme.colors2.text.neutral.secondary, + ) + } + + StarBlock( + score = providerUM.score, + modifier = Modifier + .padding(start = TangemTheme.dimens2.x2) + .clickableSingle(onClick = onLinkClick) + .layoutId(TangemRowLayoutId.END_TOP), + ) + + UrlBlockV2( + modifier = Modifier + .padding(start = TangemTheme.dimens2.x2) + .clickableSingle(onClick = onLinkClick) + .layoutId(TangemRowLayoutId.END_BOTTOM), + providerUM = providerUM, + ) + } +} + +@Composable +private fun UrlBlockV1( + providerUM: SecurityScoreBottomSheetContent.SecurityScoreProviderUM, + modifier: Modifier = Modifier, +) { val urlData = providerUM.urlData val rootHost = urlData?.rootHost if (urlData != null && rootHost != null) { Row( + modifier = modifier, horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4), ) { Text( @@ -174,10 +333,75 @@ private fun UrlBlock(providerUM: SecurityScoreBottomSheetContent.SecurityScorePr } } +@Composable +private fun UrlBlockV2( + providerUM: SecurityScoreBottomSheetContent.SecurityScoreProviderUM, + modifier: Modifier = Modifier, +) { + val urlData = providerUM.urlData + val rootHost = urlData?.rootHost + if (urlData != null && rootHost != null) { + Row( + modifier = modifier, + horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x0_5), + ) { + Text( + text = urlData.rootHost, + style = TangemTheme.typography2.captionSemibold12, + color = TangemTheme.colors2.text.neutral.secondary, + ) + Icon( + modifier = Modifier + .size(TangemTheme.dimens2.x4), + imageVector = ImageVector.vectorResource(id = R.drawable.ic_arrow_top_right_24), + contentDescription = null, + tint = TangemTheme.colors2.markers.iconGray, + ) + } + } +} + +@Suppress("MagicNumber") +@Composable +fun StarBlock(score: Float, modifier: Modifier = Modifier) { + val grayColor = TangemTheme.colors2.markers.iconGray + val percentage = score / 5 + Row( + modifier = modifier, + horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x1), + verticalAlignment = Alignment.CenterVertically, + ) { + Text( + text = score.toString(), + style = TangemTheme.typography2.bodySemibold16, + color = TangemTheme.colors2.text.neutral.primary, + ) + Icon( + modifier = Modifier + .requiredSize(TangemTheme.dimens2.x5) + .graphicsLayer(compositingStrategy = CompositingStrategy.Offscreen) + .drawWithCache { + onDrawWithContent { + drawContent() + drawRect( + color = grayColor, + topLeft = Offset(x = size.width * percentage, y = 0f), + size = Size(size.width * (1 - percentage), size.height), + blendMode = BlendMode.SrcIn, + ) + } + }, + imageVector = ImageVector.vectorResource(R.drawable.ic_star_filled_20), + contentDescription = null, + tint = TangemTheme.colors2.markers.iconBlue, + ) + } +} + @Preview(showBackground = true, widthDp = 360) @Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable -private fun SecurityScoreBottomSheetPreview() { +private fun SecurityScoreBottomSheetPreviewV1() { TangemThemePreview { SecurityScoreBottomSheet( config = TangemBottomSheetConfig( @@ -187,4 +411,21 @@ private fun SecurityScoreBottomSheetPreview() { ), ) } +} + +@Preview(showBackground = true, widthDp = 360) +@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun SecurityScoreBottomSheetPreviewV2() { + TangemThemePreviewRedesign { + CompositionLocalProvider(LocalRedesignEnabled provides true) { + SecurityScoreBottomSheet( + config = TangemBottomSheetConfig( + isShown = true, + onDismissRequest = {}, + content = SecurityScorePreviewData.bottomSheetContent, + ), + ) + } + } } \ No newline at end of file diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/state/ExchangeItemUM.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/state/ExchangeItemUM.kt new file mode 100644 index 0000000000..8a8c912f5d --- /dev/null +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/state/ExchangeItemUM.kt @@ -0,0 +1,23 @@ +package com.tangem.features.feed.ui.market.detailed.state + +import androidx.compose.runtime.Immutable +import com.tangem.core.ui.components.audits.AuditLabelUM +import com.tangem.core.ui.ds.image.TangemIconUM +import com.tangem.core.ui.extensions.TextReference + +@Immutable +internal sealed interface ExchangeItemUM { + + val id: String + + data class Content( + override val id: String, + val title: TextReference, + val subTitle: TextReference, + val icon: TangemIconUM, + val volumeInUsd: TextReference, + val auditLabel: AuditLabelUM, + ) : ExchangeItemUM + + data class Loading(override val id: String) : ExchangeItemUM +} \ No newline at end of file diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/state/ExchangesBottomSheetContent.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/state/ExchangesBottomSheetContent.kt index 2647413b82..3ffbb348d9 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/state/ExchangesBottomSheetContent.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/state/ExchangesBottomSheetContent.kt @@ -1,6 +1,7 @@ package com.tangem.features.feed.ui.market.detailed.state import androidx.annotation.StringRes +import androidx.compose.runtime.Immutable import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent import com.tangem.core.ui.components.token.state.TokenItemState import com.tangem.core.ui.extensions.TextReference @@ -18,6 +19,7 @@ import kotlinx.collections.immutable.toImmutableList * [REDACTED_AUTHOR] */ +@Immutable internal sealed interface ExchangesBottomSheetContent : TangemBottomSheetConfigContent { /** Title of bottom sheet. Like, app bar. */ @@ -39,6 +41,8 @@ internal sealed interface ExchangesBottomSheetContent : TangemBottomSheetConfigC /** Exchange items */ val exchangeItems: ImmutableList + val exchangeItemsV2: ImmutableList + /** * Loading state * @@ -49,6 +53,10 @@ internal sealed interface ExchangesBottomSheetContent : TangemBottomSheetConfigC override val exchangeItems: ImmutableList get() = List(size = exchangesCount) { index -> TokenItemState.Loading(id = "loading#$index") } .toImmutableList() + + override val exchangeItemsV2: ImmutableList + get() = List(size = exchangesCount) { index -> ExchangeItemUM.Loading(id = "loading#$index") } + .toImmutableList() } /** @@ -56,8 +64,14 @@ internal sealed interface ExchangesBottomSheetContent : TangemBottomSheetConfigC * * @property exchangeItems exchanges */ - data class Content( + data class ContentV1( override val exchangeItems: ImmutableList, + override val exchangeItemsV2: ImmutableList = persistentListOf(), + ) : ExchangesBottomSheetContent + + data class ContentV2( + override val exchangeItemsV2: ImmutableList, + override val exchangeItems: ImmutableList = persistentListOf(), ) : ExchangesBottomSheetContent /** Error state */ @@ -65,6 +79,7 @@ internal sealed interface ExchangesBottomSheetContent : TangemBottomSheetConfigC val onRetryClick: () -> Unit, ) : ExchangesBottomSheetContent { override val exchangeItems: ImmutableList = persistentListOf() + override val exchangeItemsV2: ImmutableList = persistentListOf() @StringRes val message: Int = R.string.markets_loading_error_title 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 518b25e6a6..87ee61acdf 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 @@ -15,6 +15,8 @@ import androidx.compose.ui.unit.dp import com.tangem.core.ui.components.UnableToLoadData import com.tangem.core.ui.components.haze.hazeSourceTangem import com.tangem.core.ui.components.pager.PagerIndicator +import com.tangem.core.ui.ds.TangemPagerIndicator +import com.tangem.core.ui.ds.TangemPagerIndicatorColors import com.tangem.core.ui.extensions.conditionalCompose import com.tangem.core.ui.res.* import com.tangem.features.feed.ui.news.details.components.ArticleDetail @@ -105,12 +107,24 @@ private fun Content(state: NewsDetailsUM, background: Color) { ) } if (state.articles.size > 1) { - PagerIndicator( - pagerState = pagerState, - modifier = Modifier - .align(Alignment.BottomCenter) - .windowInsetsPadding(WindowInsets.navigationBars), - ) + if (isRedesignEnabled) { + TangemPagerIndicator( + pagerState = pagerState, + modifier = Modifier + .align(Alignment.BottomCenter) + .windowInsetsPadding(WindowInsets.navigationBars), + colors = TangemPagerIndicatorColors.copy( + overlay = TangemTheme.colors2.tabs.backgroundSecondary.copy(alpha = .1f), + ), + ) + } else { + PagerIndicator( + pagerState = pagerState, + modifier = Modifier + .align(Alignment.BottomCenter) + .windowInsetsPadding(WindowInsets.navigationBars), + ) + } } } } 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 ce6a92843e..7f37764ee5 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 @@ -28,6 +28,7 @@ internal fun RelatedTokensBlock( onItemClick: ((MarketsListItemUM) -> Unit)?, modifier: Modifier = Modifier, ) { + val isRedesignEnabled = LocalRedesignEnabled.current val isVisible = remember(relatedTokensUM) { when (relatedTokensUM) { is RelatedTokensUM.Content -> relatedTokensUM.items.isNotEmpty() @@ -40,7 +41,7 @@ internal fun RelatedTokensBlock( Column(modifier = modifier) { SpacerH(40.dp) - if (LocalRedesignEnabled.current) { + if (isRedesignEnabled) { Text( modifier = Modifier.padding(horizontal = 8.dp), text = stringResourceSafe(R.string.news_related_tokens), @@ -58,7 +59,11 @@ internal fun RelatedTokensBlock( BlockCard( colors = TangemBlockCardColors.copy( - containerColor = TangemTheme.colors.background.action, + containerColor = if (isRedesignEnabled) { + TangemTheme.colors2.surface.level3 + } else { + TangemTheme.colors.background.action + }, ), ) { Column(modifier = Modifier.fillMaxWidth()) {