From d4b7aa85e144099f67ddedb3a159ba0e7c52a4d4 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 12 Mar 2026 07:42:59 +0100 Subject: [PATCH] Updated on 2026-08-14 --- .../main/res/drawable/ic_chewron_down_20.xml | 9 + .../main/res/drawable/ic_staking_new_16.xml | 9 + .../ShortArticleToArticleConfigUMConverter.kt | 5 +- .../UpdateTrendingNewsStateTransformer.kt | 3 +- .../details/MarketsTokenDetailsModel.kt | 2 +- .../features/feed/ui/earn/EarnContent.kt | 360 +++++++++++++----- .../ui/earn/components/CardFilterBlock.kt | 30 ++ .../earn/components/EarnFilterBottomSheet.kt | 55 +++ .../EarnFilterByNetworkBottomSheet.kt | 202 +++++++++- .../components/EarnFilterByTypeBottomSheet.kt | 90 ++++- .../feed/ui/earn/components/EarnListItem.kt | 201 +++++++++- .../ui/earn/components/EarnListPlaceholder.kt | 98 +++-- .../feed/ui/earn/components/FilterButtons.kt | 115 ++++++ .../feed/ui/earn/components/MostlyUsedCard.kt | 2 +- .../earn/components/MostlyUsedPlaceholder.kt | 73 +++- .../feed/ui/feed/components/BlockHeader.kt | 51 ++- .../feed/ui/feed/components/EarnBlock.kt | 101 ++++- .../presentation/wallet/ui/WalletScreen2.kt | 2 +- 18 files changed, 1225 insertions(+), 183 deletions(-) create mode 100644 core/ui/src/main/res/drawable/ic_chewron_down_20.xml create mode 100644 core/ui/src/main/res/drawable/ic_staking_new_16.xml create mode 100644 features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/CardFilterBlock.kt create mode 100644 features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/EarnFilterBottomSheet.kt create mode 100644 features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/FilterButtons.kt diff --git a/core/ui/src/main/res/drawable/ic_chewron_down_20.xml b/core/ui/src/main/res/drawable/ic_chewron_down_20.xml new file mode 100644 index 0000000000..37be4f7583 --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_chewron_down_20.xml @@ -0,0 +1,9 @@ + + + diff --git a/core/ui/src/main/res/drawable/ic_staking_new_16.xml b/core/ui/src/main/res/drawable/ic_staking_new_16.xml new file mode 100644 index 0000000000..99ee618856 --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_staking_new_16.xml @@ -0,0 +1,9 @@ + + + diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/model/converter/ShortArticleToArticleConfigUMConverter.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/model/converter/ShortArticleToArticleConfigUMConverter.kt index 204c185109..b565dd823c 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/model/converter/ShortArticleToArticleConfigUMConverter.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/model/converter/ShortArticleToArticleConfigUMConverter.kt @@ -8,7 +8,6 @@ import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.news.ShortArticle import com.tangem.features.feed.ui.feed.components.articles.ArticleConfigUM import com.tangem.features.feed.ui.utils.mapFormattedDate -import com.tangem.utils.Provider import com.tangem.utils.converter.Converter import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableSet @@ -16,7 +15,7 @@ import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toPersistentSet internal class ShortArticleToArticleConfigUMConverter( - private val isTrending: Provider?, + private val isTrending: Boolean?, ) : Converter, ImmutableList> { override fun convert(value: List): ImmutableList { @@ -25,7 +24,7 @@ internal class ShortArticleToArticleConfigUMConverter( id = shortArticle.id, title = shortArticle.title, score = shortArticle.score, - isTrending = isTrending?.invoke() ?: shortArticle.isTrending, + isTrending = isTrending ?: shortArticle.isTrending, tags = buildArticleTags(shortArticle), createdAt = mapFormattedDate(shortArticle.createdAt), isViewed = shortArticle.viewed, diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/model/feed/state/transformers/UpdateTrendingNewsStateTransformer.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/model/feed/state/transformers/UpdateTrendingNewsStateTransformer.kt index 33c625fb7f..3306ce27b9 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/model/feed/state/transformers/UpdateTrendingNewsStateTransformer.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/model/feed/state/transformers/UpdateTrendingNewsStateTransformer.kt @@ -9,7 +9,6 @@ import com.tangem.features.feed.model.feed.analytics.FeedAnalyticsEvent import com.tangem.features.feed.ui.feed.state.FeedListUM import com.tangem.features.feed.ui.feed.state.NewsUM import com.tangem.features.feed.ui.feed.state.NewsUMState -import com.tangem.utils.Provider import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toPersistentList import org.joda.time.DateTime @@ -92,6 +91,6 @@ internal class UpdateTrendingNewsStateTransformer( } private fun getShortArticleConfigConverter(isTrending: Boolean): ShortArticleToArticleConfigUMConverter { - return ShortArticleToArticleConfigUMConverter(isTrending = Provider { isTrending }) + return ShortArticleToArticleConfigUMConverter(isTrending = isTrending) } } \ No newline at end of file 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 819d362a4a..a63fc181a1 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 @@ -151,7 +151,7 @@ internal class MarketsTokenDetailsModel @Inject constructor( ) private val shortArticleToArticleConfigUMConverter by lazy { - ShortArticleToArticleConfigUMConverter(isTrending = Provider { false }) + ShortArticleToArticleConfigUMConverter(isTrending = false) } private val descriptionConverter = DescriptionConverter( 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 9ff14d6bc1..82c0a9cfb6 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 @@ -5,6 +5,7 @@ import androidx.compose.animation.AnimatedContent 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 @@ -21,25 +22,15 @@ 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.SmallButtonShimmer -import com.tangem.core.ui.components.SpacerH -import com.tangem.core.ui.components.SpacerWMax -import com.tangem.core.ui.components.UnableToLoadData +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.buttons.common.TangemButtonIconPosition 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.res.LocalMainBottomSheetColor -import com.tangem.core.ui.res.TangemColorPalette -import com.tangem.core.ui.res.TangemTheme -import com.tangem.core.ui.res.TangemThemePreview -import com.tangem.features.feed.ui.earn.components.EarnItemPlaceholder -import com.tangem.features.feed.ui.earn.components.EarnListItem -import com.tangem.features.feed.ui.earn.components.MostlyUsedCard -import com.tangem.features.feed.ui.earn.components.MostlyUsedPlaceholder +import com.tangem.core.ui.res.* +import com.tangem.features.feed.ui.earn.components.* import com.tangem.features.feed.ui.earn.state.* import kotlinx.collections.immutable.persistentListOf @@ -51,6 +42,7 @@ internal fun EarnContent(state: EarnUM, modifier: Modifier = Modifier) { val density = LocalDensity.current val bottomBarHeight = with(density) { WindowInsets.systemBars.getBottom(this).toDp() } val listState = rememberLazyListState() + val isRedesignEnabled = LocalRedesignEnabled.current if (state.bestOpportunities is EarnBestOpportunitiesUM.Content) { PaginationHandler( @@ -69,7 +61,9 @@ internal fun EarnContent(state: EarnUM, modifier: Modifier = Modifier) { item(key = "mostly_used_header") { SectionHeader( title = stringResourceSafe(R.string.earn_mostly_used), - modifier = Modifier.padding(top = 16.dp), + modifier = Modifier.padding( + top = if (isRedesignEnabled) 10.dp else 16.dp, + ), ) } @@ -83,7 +77,9 @@ internal fun EarnContent(state: EarnUM, modifier: Modifier = Modifier) { item(key = "best_opportunities_header") { SectionHeader( title = stringResourceSafe(R.string.earn_best_opportunities), - modifier = Modifier.padding(top = 20.dp), + modifier = Modifier.padding( + top = if (isRedesignEnabled) 32.dp else 20.dp, + ), ) } @@ -97,14 +93,17 @@ internal fun EarnContent(state: EarnUM, modifier: Modifier = Modifier) { ) } - bestOpportunitiesItems( - state = state.bestOpportunities, - ) + if (isRedesignEnabled) { + bestOpportunitiesItemsV2(state = state.bestOpportunities) + } else { + bestOpportunitiesItemsV1(state = state.bestOpportunities) + } } } @Composable private fun MostlyUsedContent(state: EarnListUM, onScroll: () -> Unit) { + val isRedesignEnabled = LocalRedesignEnabled.current AnimatedContent( targetState = state, contentKey = { it::class.java }, @@ -115,10 +114,7 @@ private fun MostlyUsedContent(state: EarnListUM, onScroll: () -> Unit) { } is EarnListUM.Content -> { LazyRow( - contentPadding = PaddingValues( - horizontal = 16.dp, - vertical = 12.dp, - ), + contentPadding = PaddingValues(horizontal = 16.dp, vertical = 12.dp), horizontalArrangement = Arrangement.spacedBy(8.dp), ) { itemsIndexed( @@ -127,12 +123,7 @@ private fun MostlyUsedContent(state: EarnListUM, onScroll: () -> Unit) { ) { index, item -> val cardModifier = Modifier.conditional( condition = index == FOURTH_ITEM_INDEX, - modifier = { - onFirstVisible( - minFractionVisible = 0.5f, - callback = onScroll, - ) - }, + modifier = { onFirstVisible(minFractionVisible = 0.5f, callback = onScroll) }, ) MostlyUsedCard( modifier = cardModifier, @@ -147,15 +138,24 @@ private fun MostlyUsedContent(state: EarnListUM, onScroll: () -> Unit) { modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 12.dp) - .background( - color = TangemTheme.colors.background.action, - shape = TangemTheme.shapes.roundedCornersXMedium, + .conditionalCompose( + condition = isRedesignEnabled, + modifier = { + background( + color = TangemTheme.colors2.surface.level3, + shape = RoundedCornerShape(TangemTheme.dimens2.x4), + ) + }, + otherModifier = { + background( + color = TangemTheme.colors.background.action, + shape = TangemTheme.shapes.roundedCornersXMedium, + ) + }, ) .padding(vertical = 32.dp, horizontal = 12.dp), contentAlignment = Alignment.Center, - ) { - UnableToLoadData(onRetryClick = animatedState.onRetryClicked) - } + ) { UnableToLoadData(onRetryClick = animatedState.onRetryClicked) } } EarnListUM.Empty -> Unit // no need to handle } @@ -179,7 +179,7 @@ private fun BestOpportunitiesFilters( } } -private fun LazyListScope.bestOpportunitiesItems(state: EarnBestOpportunitiesUM) { +private fun LazyListScope.bestOpportunitiesItemsV1(state: EarnBestOpportunitiesUM) { when (state) { is EarnBestOpportunitiesUM.Loading -> { val lastIndex = PLACEHOLDER_ITEMS_COUNT - 1 @@ -187,7 +187,7 @@ private fun LazyListScope.bestOpportunitiesItems(state: EarnBestOpportunitiesUM) count = PLACEHOLDER_ITEMS_COUNT, key = { "placeholder_$it" }, ) { index -> - EarnItemPlaceholder( + EarnItemPlaceholderV1( modifier = Modifier .roundedShapeItemDecoration( currentIndex = index, @@ -249,56 +249,102 @@ private fun LazyListScope.bestOpportunitiesItems(state: EarnBestOpportunitiesUM) } } -@Composable -private fun FilterButtons( - earnFilterUM: EarnFilterUM, - onNetworkFilterClick: () -> Unit, - onTypeFilterClick: () -> Unit, - modifier: Modifier = Modifier, -) { - Row( - modifier = modifier.padding(horizontal = 16.dp), - ) { - SecondarySmallButton( - config = SmallButtonConfig( - text = when (earnFilterUM.selectedNetworkFilter) { - is EarnFilterNetworkUM.AllNetworks -> TextReference.Res(R.string.earn_filter_all_networks) - is EarnFilterNetworkUM.MyNetworks -> TextReference.Res(R.string.earn_filter_my_networks) - is EarnFilterNetworkUM.Network -> TextReference.Str(earnFilterUM.selectedNetworkFilter.text) - }, - onClick = onNetworkFilterClick, - icon = TangemButtonIconPosition.End(iconResId = R.drawable.ic_chevron_24), - isEnabled = earnFilterUM.isNetworkFilterEnabled, - ), - ) - - SpacerWMax() - - SecondarySmallButton( - config = SmallButtonConfig( - text = earnFilterUM.selectedTypeFilter.text, - onClick = onTypeFilterClick, - icon = TangemButtonIconPosition.End(iconResId = R.drawable.ic_chevron_24), - isEnabled = earnFilterUM.isTypeFilterEnabled, - ), - ) +private fun LazyListScope.bestOpportunitiesItemsV2(state: EarnBestOpportunitiesUM) { + when (state) { + is EarnBestOpportunitiesUM.Loading -> { + val lastIndex = PLACEHOLDER_ITEMS_COUNT - 1 + items( + count = PLACEHOLDER_ITEMS_COUNT, + key = { "placeholder_$it" }, + ) { index -> + EarnItemPlaceholderV2( + modifier = Modifier + .roundedShapeItemDecoration( + currentIndex = index, + lastIndex = lastIndex, + backgroundColor = TangemTheme.colors2.surface.level3, + ), + ) + } + } + is EarnBestOpportunitiesUM.Empty -> { + item(key = "best_opportunities_empty") { + SpacerH(12.dp) + BestOpportunitiesEmpty() // TODO in [REDACTED_TASK_KEY] + } + } + is EarnBestOpportunitiesUM.EmptyFiltered -> { + item(key = "best_opportunities_empty_filtered") { + SpacerH(12.dp) + BestOpportunitiesEmptyFiltered(onClearFilterClick = state.onClearFilterClick) // TODO in [REDACTED_TASK_KEY] + } + } + is EarnBestOpportunitiesUM.Content -> { + if (state.items.isNotEmpty()) { + val lastIndex = state.items.lastIndex + itemsIndexed( + items = state.items, + key = { _, item -> "${item.tokenName}-${item.network}" }, + ) { index, item -> + EarnListItem( + item = item, + modifier = Modifier + .roundedShapeItemDecoration( + currentIndex = index, + lastIndex = lastIndex, + backgroundColor = TangemTheme.colors2.surface.level3, + ), + ) + } + } + } + is EarnBestOpportunitiesUM.Error -> { + item(key = "best_opportunities_error") { + SpacerH(12.dp) + Box( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp) + .background( + color = TangemTheme.colors2.surface.level3, + shape = RoundedCornerShape(TangemTheme.dimens2.x5), + ) + .padding(vertical = 142.dp, horizontal = 114.dp), + contentAlignment = Alignment.Center, + ) { + UnableToLoadData(onRetryClick = state.onRetryClicked) + } + } + } } } @Composable private fun FilterButtonsShimmer(modifier: Modifier = Modifier) { - Row( - modifier = modifier.padding(horizontal = 16.dp), - ) { - SmallButtonShimmer( - modifier = Modifier.width(110.dp), - ) - - SpacerWMax() - - SmallButtonShimmer( - modifier = Modifier.width(90.dp), - ) + Row(modifier = modifier.padding(horizontal = 16.dp, vertical = 4.dp)) { + if (LocalRedesignEnabled.current) { + RectangleShimmer( + modifier = Modifier + .width(130.dp) + .height(36.dp), + radius = TangemTheme.dimens2.x25, + ) + SpacerWMax() + RectangleShimmer( + modifier = Modifier + .width(106.dp) + .height(36.dp), + radius = TangemTheme.dimens2.x25, + ) + } else { + SmallButtonShimmer( + modifier = Modifier.width(110.dp), + ) + SpacerWMax() + SmallButtonShimmer( + modifier = Modifier.width(90.dp), + ) + } } } @@ -364,14 +410,25 @@ private fun BestOpportunitiesEmptyFiltered(onClearFilterClick: () -> Unit, modif @Composable private fun SectionHeader(title: String, modifier: Modifier = Modifier) { - Text( - modifier = modifier - .fillMaxWidth() - .padding(start = 20.dp, end = 16.dp), - text = title, - style = TangemTheme.typography.h3, - color = TangemTheme.colors.text.primary1, - ) + if (LocalRedesignEnabled.current) { + Text( + modifier = modifier + .fillMaxWidth() + .padding(horizontal = 24.dp), + text = title, + style = TangemTheme.typography2.headingSemibold20, + color = TangemTheme.colors2.text.neutral.primary, + ) + } else { + Text( + modifier = modifier + .fillMaxWidth() + .padding(start = 20.dp, end = 16.dp), + text = title, + style = TangemTheme.typography.h3, + color = TangemTheme.colors.text.primary1, + ) + } } @Composable @@ -392,7 +449,7 @@ private fun PaginationHandler(listState: LazyListState, state: EarnBestOpportuni @Preview(showBackground = true, widthDp = 360) @Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable -private fun EarnContentPreview() { +private fun EarnContentPreviewV1() { TangemThemePreview { val background = TangemTheme.colors.background.tertiary CompositionLocalProvider( @@ -434,7 +491,49 @@ private fun EarnContentPreview() { @Preview(showBackground = true, widthDp = 360) @Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable -private fun EarnContentLoadingPreview() { +private fun EarnContentPreviewV2() { + TangemThemePreviewRedesign { + val background = TangemTheme.colors2.surface.level3 + CompositionLocalProvider( + LocalMainBottomSheetColor provides remember { mutableStateOf(background) }, + ) { + EarnContent( + state = previewEarnUM( + mostlyUsed = EarnListUM.Content( + items = persistentListOf( + previewEarnListItemUM(), + previewEarnListItemUM( + tokenName = "Cosmos", + symbol = "ATOM", + network = "Cosmos", + ), + ), + ), + bestOpportunities = EarnBestOpportunitiesUM.Content( + items = persistentListOf( + previewEarnListItemUM( + tokenName = "Cosmos Hub", + symbol = "ATOM", + network = "Cosmos network", + ), + previewEarnListItemUM( + tokenName = "Tether", + symbol = "USDT", + network = "Ethereum Network", + ), + ), + onLoadMore = {}, + ), + ), + ) + } + } +} + +@Preview(showBackground = true, widthDp = 360) +@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun EarnContentLoadingPreviewV1() { TangemThemePreview { val background = TangemTheme.colors.background.tertiary CompositionLocalProvider( @@ -453,7 +552,26 @@ private fun EarnContentLoadingPreview() { @Preview(showBackground = true, widthDp = 360) @Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable -private fun EarnContentErrorPreview() { +private fun EarnContentLoadingPreviewV2() { + TangemThemePreviewRedesign { + val background = TangemTheme.colors2.surface.level3 + CompositionLocalProvider( + LocalMainBottomSheetColor provides remember { mutableStateOf(background) }, + ) { + EarnContent( + state = previewEarnUM( + mostlyUsed = EarnListUM.Error(onRetryClicked = {}), + bestOpportunities = EarnBestOpportunitiesUM.Loading, + ), + ) + } + } +} + +@Preview(showBackground = true, widthDp = 360) +@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun EarnContentErrorPreviewV1() { TangemThemePreview { val background = TangemTheme.colors.background.tertiary CompositionLocalProvider( @@ -481,7 +599,35 @@ private fun EarnContentErrorPreview() { @Preview(showBackground = true, widthDp = 360) @Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable -private fun EarnContentEmptyPreview() { +private fun EarnContentErrorPreviewV2() { + TangemThemePreviewRedesign { + val background = TangemTheme.colors2.surface.level3 + CompositionLocalProvider( + LocalMainBottomSheetColor provides remember { mutableStateOf(background) }, + ) { + EarnContent( + state = previewEarnUM( + mostlyUsed = EarnListUM.Content( + items = persistentListOf( + previewEarnListItemUM(), + previewEarnListItemUM( + tokenName = "Cosmos", + symbol = "ATOM", + network = "Cosmos", + ), + ), + ), + bestOpportunities = EarnBestOpportunitiesUM.Error(onRetryClicked = {}), + ), + ) + } + } +} + +@Preview(showBackground = true, widthDp = 360) +@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun EarnContentEmptyPreviewV1() { TangemThemePreview { val background = TangemTheme.colors.background.tertiary CompositionLocalProvider( @@ -506,6 +652,34 @@ private fun EarnContentEmptyPreview() { } } +@Preview(showBackground = true, widthDp = 360) +@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun EarnContentEmptyPreviewV2() { + TangemThemePreviewRedesign { + val background = TangemTheme.colors2.surface.level3 + CompositionLocalProvider( + LocalMainBottomSheetColor provides remember { mutableStateOf(background) }, + ) { + EarnContent( + state = previewEarnUM( + mostlyUsed = EarnListUM.Content( + items = persistentListOf( + previewEarnListItemUM(), + previewEarnListItemUM( + tokenName = "Cosmos", + symbol = "ATOM", + network = "Cosmos", + ), + ), + ), + bestOpportunities = EarnBestOpportunitiesUM.Empty, + ), + ) + } + } +} + @Composable private fun previewEarnListItemUM( tokenName: String = "USDC", 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 new file mode 100644 index 0000000000..56cb167e10 --- /dev/null +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/CardFilterBlock.kt @@ -0,0 +1,30 @@ +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 +internal fun CardFilterBlock(modifier: Modifier = Modifier, content: @Composable ColumnScope.() -> Unit) { + Column( + modifier = modifier + .fillMaxWidth() + .background( + color = TangemTheme.colors2.surface.level2, + shape = RoundedCornerShape(TangemTheme.dimens2.x5), + ) + .border( + width = 1.dp, + color = TangemTheme.colors2.border.neutral.primary, + shape = RoundedCornerShape(TangemTheme.dimens2.x5), + ), + content = content, + ) +} \ 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 new file mode 100644 index 0000000000..947d8e8e1b --- /dev/null +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/EarnFilterBottomSheet.kt @@ -0,0 +1,55 @@ +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.layout.padding +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +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.res.TangemTheme +import com.tangem.features.feed.impl.R + +@Composable +internal inline fun EarnFilterBottomSheet( + config: TangemBottomSheetConfig, + crossinline content: @Composable ColumnScope.(T) -> Unit, +) { + TangemBottomSheet( + config = config, + 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, + ) + SecondaryTangemButton( + modifier = Modifier.align(Alignment.CenterEnd), + onClick = config.onDismissRequest, + iconRes = R.drawable.ic_close_24, + size = TangemButtonSize.X9, + shape = TangemButtonShape.Rounded, + ) + } + }, + content = content, + ) +} \ No newline at end of file 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 fc3da1e441..78dd407f9d 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 @@ -1,9 +1,7 @@ package com.tangem.features.feed.ui.earn.components import android.content.res.Configuration -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable +import androidx.compose.foundation.* import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListScope @@ -15,11 +13,13 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.layout.layoutId import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.vectorResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.util.fastForEachIndexed import com.tangem.core.ui.components.SpacerH import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet @@ -28,28 +28,53 @@ import com.tangem.core.ui.components.inputrow.inner.DividerContainer import com.tangem.core.ui.components.rows.RowContentContainer import com.tangem.core.ui.components.rows.RowText import com.tangem.core.ui.decorations.roundedShapeItemDecoration +import com.tangem.core.ui.ds.checkbox.TangemCheckbox +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.extensions.resolveReference 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 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.earn.state.EarnFilterByNetworkBottomSheetContentUM import com.tangem.features.feed.ui.earn.state.EarnFilterNetworkUM +import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList @Composable internal fun EarnFilterByNetworkBottomSheet(config: TangemBottomSheetConfig) { + if (LocalRedesignEnabled.current) { + EarnFilterByNetworkBottomSheetV2(config = config) + } else { + EarnFilterByNetworkBottomSheetV1(config = config) + } +} + +@Composable +private fun EarnFilterByNetworkBottomSheetV1(config: TangemBottomSheetConfig) { TangemBottomSheet( config = config, titleText = resourceReference(R.string.earn_filter_by), containerColor = TangemTheme.colors.background.tertiary, - content = { Content(it) }, + content = { ContentV1(it) }, ) } @Composable -private fun Content(content: EarnFilterByNetworkBottomSheetContentUM) { +private fun EarnFilterByNetworkBottomSheetV2(config: TangemBottomSheetConfig) { + EarnFilterBottomSheet( + config = config, + content = { ContentV2(it) }, + ) +} + +@Composable +private fun ContentV1(content: EarnFilterByNetworkBottomSheetContentUM) { val allMyNetworks = remember(content) { content.networks.filterIsInstance() + content.networks.filterIsInstance() @@ -79,6 +104,132 @@ private fun Content(content: EarnFilterByNetworkBottomSheetContentUM) { } } +@Composable +private fun ContentV2(content: EarnFilterByNetworkBottomSheetContentUM) { + val allMyNetworks = remember(content) { + (content.networks.filterIsInstance() + + content.networks.filterIsInstance()).toImmutableList() + } + val specificNetworks = remember(content) { + content + .networks + .filterIsInstance() + .toImmutableList() + } + + Column( + modifier = Modifier + .padding(horizontal = 16.dp) + .verticalScroll(rememberScrollState()), + verticalArrangement = Arrangement.spacedBy(12.dp), + ) { + NetworksTypesBlock( + allMyNetworks = allMyNetworks, + onOptionClick = content.onOptionClick, + ) + + SpecificNetworksBlock( + specificNetworks = specificNetworks, + onOptionClick = content.onOptionClick, + ) + } +} + +@Composable +private fun NetworksTypesBlock( + allMyNetworks: ImmutableList, + onOptionClick: (EarnFilterNetworkUM) -> Unit, +) { + CardFilterBlock { + allMyNetworks.fastForEachIndexed { index, item -> + TangemRowContainer( + modifier = Modifier + .roundedShapeItemDecoration( + currentIndex = index, + lastIndex = allMyNetworks.lastIndex, + addDefaultPadding = false, + ) + .clickable { onOptionClick(item) }, + contentPadding = PaddingValues(horizontal = 12.dp, vertical = 12.dp), + ) { + Text( + modifier = Modifier.layoutId(layoutId = TangemRowLayoutId.START_TOP), + text = when (item) { + is EarnFilterNetworkUM.AllNetworks -> TextReference.Res(R.string.earn_filter_all_networks) + is EarnFilterNetworkUM.MyNetworks -> TextReference.Res(R.string.earn_filter_my_networks) + is EarnFilterNetworkUM.Network -> TextReference.Str(item.text) + }.resolveReference(), + style = TangemTheme.typography2.bodySemibold16, + color = TangemTheme.colors2.text.neutral.primary, + ) + + TangemCheckbox( + modifier = Modifier + .padding(start = 8.dp) + .layoutId(layoutId = TangemRowLayoutId.TAIL), + isChecked = item.isSelected, + onCheckedChange = { onOptionClick(item) }, + ) + } + } + } +} + +@Composable +private fun SpecificNetworksBlock( + specificNetworks: ImmutableList, + onOptionClick: (EarnFilterNetworkUM) -> Unit, +) { + if (specificNetworks.isNotEmpty()) { + CardFilterBlock { + Text( + modifier = Modifier + .padding(horizontal = 16.dp) + .padding(top = 16.dp, bottom = 8.dp), + text = stringResourceSafe(id = R.string.earn_filter_networks), + style = TangemTheme.typography2.bodyRegular14, + color = TangemTheme.colors2.text.neutral.tertiary, + ) + specificNetworks.fastForEachIndexed { index, item -> + TangemRowContainer( + modifier = Modifier + .roundedShapeItemDecoration( + currentIndex = index, + lastIndex = specificNetworks.lastIndex, + addDefaultPadding = false, + ) + .clickable { onOptionClick(item) }, + contentPadding = PaddingValues(horizontal = 12.dp, vertical = 12.dp), + ) { + Image( + modifier = Modifier + .size(40.dp) + .layoutId(TangemRowLayoutId.HEAD), + imageVector = ImageVector.vectorResource(item.iconRes), + contentDescription = item.symbol, + ) + Text( + modifier = Modifier + .padding(start = 8.dp) + .layoutId(layoutId = TangemRowLayoutId.START_TOP), + text = item.text, + style = TangemTheme.typography2.bodySemibold16, + color = TangemTheme.colors2.text.neutral.primary, + ) + + TangemCheckbox( + modifier = Modifier + .padding(start = 8.dp) + .layoutId(layoutId = TangemRowLayoutId.TAIL), + isChecked = item.isSelected, + onCheckedChange = { onOptionClick(item) }, + ) + } + } + } + } +} + private fun LazyListScope.allMyNetworksList( allMyNetworks: List, onOptionClicked: (EarnFilterNetworkUM) -> Unit, @@ -201,7 +352,7 @@ private fun LazyListScope.specificNetworksList( @Preview(widthDp = 360, heightDp = 800) @Preview(widthDp = 360, heightDp = 800, uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable -private fun Preview() { +private fun PreviewV1() { TangemThemePreview( alwaysShowBottomSheets = true, ) { @@ -235,4 +386,43 @@ private fun Preview() { ) } } +} + +@Preview(widthDp = 360, heightDp = 800) +@Preview(widthDp = 360, heightDp = 800, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun PreviewV2() { + TangemThemePreviewRedesign( + alwaysShowBottomSheets = true, + ) { + Box(Modifier.background(TangemTheme.colors.background.secondary)) { + EarnFilterByNetworkBottomSheet( + TangemBottomSheetConfig( + isShown = true, + onDismissRequest = {}, + content = EarnFilterByNetworkBottomSheetContentUM( + networks = persistentListOf( + EarnFilterNetworkUM.AllNetworks(isSelected = true), + EarnFilterNetworkUM.MyNetworks(isSelected = false), + EarnFilterNetworkUM.Network( + id = "ethereum", + text = "Ethereum", + symbol = "ETH", + iconRes = R.drawable.img_btc_22, + isSelected = false, + ), + EarnFilterNetworkUM.Network( + id = "polygon", + text = "Polygon", + symbol = "MATIC", + iconRes = R.drawable.img_btc_22, + isSelected = false, + ), + ), + onOptionClick = {}, + ), + ), + ) + } + } } \ No newline at end of file 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 7790ff977e..4a77e0adbd 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 @@ -5,34 +5,61 @@ import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.layoutId import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet import com.tangem.core.ui.components.inputrow.InputRowChecked import com.tangem.core.ui.components.inputrow.inner.DividerContainer import com.tangem.core.ui.decorations.roundedShapeItemDecoration +import com.tangem.core.ui.ds.checkbox.TangemCheckbox +import com.tangem.core.ui.ds.row.TangemRowContainer +import com.tangem.core.ui.ds.row.TangemRowLayoutId +import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.extensions.resourceReference +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.earn.state.EarnFilterByTypeBottomSheetContentUM import com.tangem.features.feed.ui.earn.state.EarnFilterTypeUM @Composable internal fun EarnFilterByTypeBottomSheet(config: TangemBottomSheetConfig) { + if (LocalRedesignEnabled.current) { + EarnFilterByTypeBottomSheetV2(config) + } else { + EarnFilterByTypeBottomSheetV1(config) + } +} + +@Composable +private fun EarnFilterByTypeBottomSheetV1(config: TangemBottomSheetConfig) { TangemBottomSheet( config = config, titleText = resourceReference(R.string.earn_filter_by), containerColor = TangemTheme.colors.background.tertiary, - content = { Content(it) }, + content = { ContentV1(it) }, ) } @Composable -private fun Content(content: EarnFilterByTypeBottomSheetContentUM) { +private fun EarnFilterByTypeBottomSheetV2(config: TangemBottomSheetConfig) { + EarnFilterBottomSheet( + config = config, + content = { ContentV2(it) }, + ) +} + +@Composable +private fun ContentV1(content: EarnFilterByTypeBottomSheetContentUM) { Column( modifier = Modifier .padding( @@ -62,10 +89,45 @@ private fun Content(content: EarnFilterByTypeBottomSheetContentUM) { } } +@Composable +private fun ContentV2(content: EarnFilterByTypeBottomSheetContentUM) { + CardFilterBlock( + modifier = Modifier.padding(horizontal = 16.dp), + ) { + EarnFilterTypeUM.entries.forEachIndexed { index, type -> + TangemRowContainer( + modifier = Modifier + .roundedShapeItemDecoration( + currentIndex = index, + lastIndex = EarnFilterTypeUM.entries.lastIndex, + addDefaultPadding = false, + ) + .clickable { content.onOptionClick(type) }, + contentPadding = PaddingValues(horizontal = TangemTheme.dimens2.x4, vertical = TangemTheme.dimens2.x3), + ) { + Text( + modifier = Modifier.layoutId(layoutId = TangemRowLayoutId.START_TOP), + text = type.text.resolveReference(), + style = TangemTheme.typography2.bodySemibold16, + color = TangemTheme.colors2.text.neutral.primary, + ) + + TangemCheckbox( + modifier = Modifier + .padding(start = 8.dp) + .layoutId(layoutId = TangemRowLayoutId.TAIL), + isChecked = type == content.selectedOption, + onCheckedChange = { content.onOptionClick(type) }, + ) + } + } + } +} + @Preview(widthDp = 360, heightDp = 640) @Preview(widthDp = 360, heightDp = 640, uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable -private fun Preview() { +private fun PreviewV1() { TangemThemePreview( alwaysShowBottomSheets = true, ) { @@ -82,4 +144,26 @@ private fun Preview() { ) } } +} + +@Preview(widthDp = 360, heightDp = 640) +@Preview(widthDp = 360, heightDp = 640, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun PreviewV2() { + TangemThemePreviewRedesign( + alwaysShowBottomSheets = true, + ) { + Box(Modifier.background(TangemTheme.colors.background.secondary)) { + EarnFilterByTypeBottomSheet( + TangemBottomSheetConfig( + isShown = true, + onDismissRequest = {}, + content = EarnFilterByTypeBottomSheetContentUM( + selectedOption = EarnFilterTypeUM.All, + onOptionClick = {}, + ), + ), + ) + } + } } \ No newline at end of file diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/EarnListItem.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/EarnListItem.kt index 5f9a56de50..6e4e9799cb 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/EarnListItem.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/EarnListItem.kt @@ -4,12 +4,16 @@ import android.content.res.Configuration import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* +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.draw.clip import androidx.compose.ui.graphics.RectangleShape +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.layout.layoutId +import androidx.compose.ui.res.vectorResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -18,15 +22,33 @@ import com.tangem.core.ui.components.SpacerH import com.tangem.core.ui.components.SpacerW import com.tangem.core.ui.components.currency.icon.CurrencyIcon import com.tangem.core.ui.components.currency.icon.CurrencyIconState +import com.tangem.core.ui.ds.image.TangemIcon +import com.tangem.core.ui.ds.image.TangemIconUM +import com.tangem.core.ui.ds.row.TangemRowContainer +import com.tangem.core.ui.ds.row.TangemRowLayoutId +import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.extensions.stringReference -import com.tangem.core.ui.res.TangemColorPalette -import com.tangem.core.ui.res.TangemTheme -import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.core.ui.res.* import com.tangem.features.feed.ui.earn.state.EarnListItemUM @Composable internal fun EarnListItem(item: EarnListItemUM, modifier: Modifier = Modifier) { + if (LocalRedesignEnabled.current) { + EarnListItemV2( + item = item, + modifier = modifier, + ) + } else { + EarnListItemV1( + item = item, + modifier = modifier, + ) + } +} + +@Composable +private fun EarnListItemV1(item: EarnListItemUM, modifier: Modifier = Modifier) { Row( modifier = modifier .fillMaxWidth() @@ -82,27 +104,117 @@ internal fun EarnListItem(item: EarnListItemUM, modifier: Modifier = Modifier) { } } +@Composable +private fun EarnListItemV2(item: EarnListItemUM, modifier: Modifier = Modifier) { + TangemRowContainer( + modifier = modifier.clickable { item.onItemClick() }, + contentPadding = PaddingValues(12.dp), + content = { + TangemIcon( + tangemIconUM = TangemIconUM.Currency(item.currencyIconState), + modifier = Modifier + .layoutId(layoutId = TangemRowLayoutId.HEAD) + .padding(end = TangemTheme.dimens2.x2), + ) + + TokenTitle( + modifier = Modifier + .layoutId(layoutId = TangemRowLayoutId.START_TOP) + .padding(end = TangemTheme.dimens2.x2), + name = item.tokenName.resolveReference(), + symbol = item.symbol.resolveReference(), + ) + + Text( + modifier = Modifier + .layoutId(layoutId = TangemRowLayoutId.START_BOTTOM) + .padding(end = TangemTheme.dimens2.x2), + text = item.network.resolveReference(), + color = TangemTheme.colors2.text.neutral.secondary, + style = TangemTheme.typography2.captionSemibold12, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + + Text( + modifier = Modifier.layoutId(layoutId = TangemRowLayoutId.END_TOP), + text = item.earnValue.resolveReference(), + color = TangemTheme.colors2.text.neutral.primary, + style = TangemTheme.typography2.bodySemibold16, + maxLines = 1, + ) + + ModeBlock( + modifier = Modifier.layoutId(layoutId = TangemRowLayoutId.END_BOTTOM), + earnType = item.earnType, + ) + }, + ) +} + @Composable private fun TokenTitle(name: String, symbol: String, modifier: Modifier = Modifier) { Row(modifier = modifier) { - Text( - modifier = Modifier - .weight(1f, fill = false) - .alignByBaseline(), - text = name, - color = TangemTheme.colors.text.primary1, - style = TangemTheme.typography.subtitle2, - maxLines = 1, - overflow = TextOverflow.Ellipsis, + if (LocalRedesignEnabled.current) { + Text( + modifier = Modifier + .weight(1f, fill = false) + .alignByBaseline(), + text = name, + color = TangemTheme.colors2.text.neutral.primary, + style = TangemTheme.typography2.bodySemibold16, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + SpacerW(4.dp) + Text( + modifier = Modifier.alignByBaseline(), + text = symbol, + color = TangemTheme.colors2.text.neutral.secondary, + style = TangemTheme.typography2.captionSemibold12, + maxLines = 1, + overflow = TextOverflow.Visible, + ) + } else { + Text( + modifier = Modifier + .weight(1f, fill = false) + .alignByBaseline(), + text = name, + color = TangemTheme.colors.text.primary1, + style = TangemTheme.typography.subtitle2, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + SpacerW(4.dp) + Text( + modifier = Modifier.alignByBaseline(), + text = symbol, + color = TangemTheme.colors.text.tertiary, + style = TangemTheme.typography.body2, + maxLines = 1, + overflow = TextOverflow.Visible, + ) + } + } +} + +@Composable +private fun ModeBlock(earnType: TextReference, modifier: Modifier = Modifier) { + Row( + modifier = modifier, + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(2.dp), + ) { + Icon( + imageVector = ImageVector.vectorResource(R.drawable.ic_staking_new_16), + tint = TangemTheme.colors2.markers.iconGray, + contentDescription = null, ) - SpacerW(4.dp) Text( - modifier = Modifier.alignByBaseline(), - text = symbol, - color = TangemTheme.colors.text.tertiary, - style = TangemTheme.typography.body2, - maxLines = 1, - overflow = TextOverflow.Visible, + text = earnType.resolveReference(), + style = TangemTheme.typography2.captionSemibold12, + color = TangemTheme.colors2.text.neutral.tertiary, ) } } @@ -110,7 +222,7 @@ private fun TokenTitle(name: String, symbol: String, modifier: Modifier = Modifi @Preview(showBackground = true, widthDp = 360) @Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable -private fun EarnListItemPreview() { +private fun EarnListItemPreviewV1() { TangemThemePreview { Column(modifier = Modifier.background(TangemTheme.colors.background.primary)) { EarnListItem( @@ -151,4 +263,53 @@ private fun EarnListItemPreview() { ) } } +} + +@Preview(showBackground = true, widthDp = 360) +@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun EarnListItemPreviewV2() { + TangemThemePreviewRedesign { + Column(modifier = Modifier.background(TangemTheme.colors.background.primary)) { + SpacerH(12.dp) + EarnListItem( + item = EarnListItemUM( + network = stringReference("Ethereum"), + symbol = stringReference("ETH"), + tokenName = stringReference("Ethereum"), + currencyIconState = CurrencyIconState.TokenIcon( + url = null, + topBadgeIconResId = R.drawable.img_eth_22, + fallbackTint = TangemColorPalette.Black, + fallbackBackground = TangemColorPalette.Meadow, + isGrayscale = false, + shouldShowCustomBadge = false, + ), + earnValue = stringReference("APY 8.50%"), + earnType = stringReference("Yield"), + onItemClick = {}, + ), + ) + SpacerH(12.dp) + EarnListItem( + item = EarnListItemUM( + network = stringReference("Ethereum"), + symbol = stringReference("USDT"), + tokenName = stringReference("Tether"), + currencyIconState = CurrencyIconState.TokenIcon( + url = null, + topBadgeIconResId = R.drawable.img_eth_22, + fallbackTint = TangemColorPalette.Black, + fallbackBackground = TangemColorPalette.Meadow, + isGrayscale = false, + shouldShowCustomBadge = false, + ), + earnValue = stringReference("APY 8.50%"), + earnType = stringReference("Yield"), + onItemClick = {}, + ), + ) + SpacerH(12.dp) + } + } } \ No newline at end of file diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/EarnListPlaceholder.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/EarnListPlaceholder.kt index 0f988ac0bb..021838ec9a 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/EarnListPlaceholder.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/EarnListPlaceholder.kt @@ -8,27 +8,13 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview 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.SpacerW -import com.tangem.core.ui.components.SpacerWMax +import com.tangem.core.ui.components.* import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.core.ui.res.TangemThemePreviewRedesign @Composable -internal fun EarnListPlaceholder(modifier: Modifier = Modifier, placeholderCount: Int = PLACEHOLDER_ITEMS_COUNT) { - Column( - modifier = modifier.fillMaxSize(), - ) { - repeat(placeholderCount) { - EarnItemPlaceholder() - } - } -} - -@Composable -internal fun EarnItemPlaceholder(modifier: Modifier = Modifier) { +internal fun EarnItemPlaceholderV1(modifier: Modifier = Modifier) { Row( modifier = modifier .fillMaxWidth() @@ -38,9 +24,7 @@ internal fun EarnItemPlaceholder(modifier: Modifier = Modifier) { ), verticalAlignment = Alignment.CenterVertically, ) { - CircleShimmer( - modifier = Modifier.size(36.dp), - ) + CircleShimmer(modifier = Modifier.size(36.dp)) SpacerW(12.dp) @@ -91,18 +75,86 @@ internal fun EarnItemPlaceholder(modifier: Modifier = Modifier) { } } +@Composable +internal fun EarnItemPlaceholderV2(modifier: Modifier = Modifier) { + Row( + modifier = modifier + .fillMaxWidth() + .padding(12.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + CircleShimmer(modifier = Modifier.size(40.dp)) + + SpacerW(4.dp) + + Column(modifier = Modifier.weight(1f)) { + Row(modifier = Modifier.fillMaxWidth()) { + RectangleShimmer( + modifier = Modifier + .width(96.dp) + .height(20.dp), + radius = TangemTheme.dimens2.x25, + ) + SpacerWMax() + RectangleShimmer( + modifier = Modifier + .width(56.dp) + .height(20.dp), + radius = TangemTheme.dimens2.x25, + ) + } + + SpacerH(4.dp) + + Row(modifier = Modifier.fillMaxWidth()) { + RectangleShimmer( + modifier = Modifier + .width(46.dp) + .height(16.dp), + radius = TangemTheme.dimens2.x25, + ) + SpacerWMax() + RectangleShimmer( + modifier = Modifier + .width(46.dp) + .height(16.dp), + radius = TangemTheme.dimens2.x25, + ) + } + } + } +} + private const val PLACEHOLDER_ITEMS_COUNT = 8 @Preview(showBackground = true, widthDp = 360) @Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable -private fun EarnListPlaceholderPreview() { +private fun EarnListPlaceholderPreviewV1() { TangemThemePreview { - Box( + Column( modifier = Modifier .background(TangemTheme.colors.background.tertiary), ) { - EarnListPlaceholder() + repeat(PLACEHOLDER_ITEMS_COUNT) { + EarnItemPlaceholderV1() + } + } + } +} + +@Preview(showBackground = true, widthDp = 360) +@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun EarnListPlaceholderPreviewV2() { + TangemThemePreviewRedesign { + Column( + modifier = Modifier + .background(TangemTheme.colors2.surface.level3), + ) { + repeat(PLACEHOLDER_ITEMS_COUNT) { + EarnItemPlaceholderV2() + } } } } \ No newline at end of file diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/FilterButtons.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/FilterButtons.kt new file mode 100644 index 0000000000..72d3494f1f --- /dev/null +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/FilterButtons.kt @@ -0,0 +1,115 @@ +package com.tangem.features.feed.ui.earn.components + +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.tangem.core.ui.R +import com.tangem.core.ui.components.SpacerWMax +import com.tangem.core.ui.components.buttons.SecondarySmallButton +import com.tangem.core.ui.components.buttons.SmallButtonConfig +import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition +import com.tangem.core.ui.ds.button.PrimaryInverseTangemButton +import com.tangem.core.ui.ds.button.TangemButtonShape +import com.tangem.core.ui.ds.button.TangemButtonSize +import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.res.LocalRedesignEnabled +import com.tangem.features.feed.ui.earn.state.EarnFilterNetworkUM +import com.tangem.features.feed.ui.earn.state.EarnFilterUM + +@Composable +internal fun FilterButtons( + earnFilterUM: EarnFilterUM, + onNetworkFilterClick: () -> Unit, + onTypeFilterClick: () -> Unit, + modifier: Modifier = Modifier, +) { + if (LocalRedesignEnabled.current) { + FilterButtonsV2( + earnFilterUM = earnFilterUM, + onNetworkFilterClick = onNetworkFilterClick, + onTypeFilterClick = onTypeFilterClick, + modifier = modifier, + ) + } else { + FilterButtonsV1( + earnFilterUM = earnFilterUM, + onNetworkFilterClick = onNetworkFilterClick, + onTypeFilterClick = onTypeFilterClick, + modifier = modifier, + ) + } +} + +@Composable +private fun FilterButtonsV1( + earnFilterUM: EarnFilterUM, + onNetworkFilterClick: () -> Unit, + onTypeFilterClick: () -> Unit, + modifier: Modifier = Modifier, +) { + Row( + modifier = modifier.padding(horizontal = 16.dp), + ) { + SecondarySmallButton( + config = SmallButtonConfig( + text = when (earnFilterUM.selectedNetworkFilter) { + is EarnFilterNetworkUM.AllNetworks -> TextReference.Res(R.string.earn_filter_all_networks) + is EarnFilterNetworkUM.MyNetworks -> TextReference.Res(R.string.earn_filter_my_networks) + is EarnFilterNetworkUM.Network -> TextReference.Str(earnFilterUM.selectedNetworkFilter.text) + }, + onClick = onNetworkFilterClick, + icon = TangemButtonIconPosition.End(iconResId = R.drawable.ic_chevron_24), + isEnabled = earnFilterUM.isNetworkFilterEnabled, + ), + ) + + SpacerWMax() + + SecondarySmallButton( + config = SmallButtonConfig( + text = earnFilterUM.selectedTypeFilter.text, + onClick = onTypeFilterClick, + icon = TangemButtonIconPosition.End(iconResId = R.drawable.ic_chevron_24), + isEnabled = earnFilterUM.isTypeFilterEnabled, + ), + ) + } +} + +@Composable +private fun FilterButtonsV2( + earnFilterUM: EarnFilterUM, + onNetworkFilterClick: () -> Unit, + onTypeFilterClick: () -> Unit, + modifier: Modifier = Modifier, +) { + Row(modifier = modifier.padding(horizontal = 16.dp, vertical = 4.dp)) { + PrimaryInverseTangemButton( + text = when (earnFilterUM.selectedNetworkFilter) { + is EarnFilterNetworkUM.AllNetworks -> TextReference.Res(R.string.earn_filter_all_networks) + is EarnFilterNetworkUM.MyNetworks -> TextReference.Res(R.string.earn_filter_my_networks) + is EarnFilterNetworkUM.Network -> TextReference.Str(earnFilterUM.selectedNetworkFilter.text) + }, + onClick = onNetworkFilterClick, + iconRes = R.drawable.ic_chewron_down_20, + iconPosition = com.tangem.core.ui.ds.button.TangemButtonIconPosition.End, + size = TangemButtonSize.X9, + shape = TangemButtonShape.Rounded, + enabled = earnFilterUM.isNetworkFilterEnabled, + ) + + SpacerWMax() + + PrimaryInverseTangemButton( + text = earnFilterUM.selectedTypeFilter.text, + onClick = onTypeFilterClick, + iconRes = R.drawable.ic_chewron_down_20, + iconPosition = com.tangem.core.ui.ds.button.TangemButtonIconPosition.End, + size = TangemButtonSize.X9, + shape = TangemButtonShape.Rounded, + enabled = earnFilterUM.isTypeFilterEnabled, + ) + } +} \ No newline at end of file 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 5ce51b2458..b9c88ee004 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 @@ -44,7 +44,7 @@ internal fun MostlyUsedCard(item: EarnListItemUM, onClick: () -> Unit, modifier: private fun MostlyUsedCardV2(item: EarnListItemUM, onClick: () -> Unit, modifier: Modifier = Modifier) { OpportunitiesBG( modifier = modifier - .width(148.dp) + .width(178.dp) .clip(TangemTheme.shapes.roundedCornersXMedium) .clickable(onClick = onClick), icon = TangemIconUM.Currency(item.currencyIconState), diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/MostlyUsedPlaceholder.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/MostlyUsedPlaceholder.kt index ef300fa0b0..e27c045736 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/MostlyUsedPlaceholder.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/earn/components/MostlyUsedPlaceholder.kt @@ -2,14 +2,9 @@ package com.tangem.features.feed.ui.earn.components import android.content.res.Configuration import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview @@ -17,27 +12,36 @@ 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.res.LocalRedesignEnabled import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.core.ui.res.TangemThemePreviewRedesign @Composable -internal fun MostlyUsedPlaceholder(modifier: Modifier = Modifier) { +internal fun MostlyUsedPlaceholder( + modifier: Modifier = Modifier, + contentPadding: PaddingValues = PaddingValues( + horizontal = 16.dp, + vertical = 12.dp, + ), +) { LazyRow( modifier = modifier, - contentPadding = PaddingValues( - horizontal = 16.dp, - vertical = 12.dp, - ), + contentPadding = contentPadding, horizontalArrangement = Arrangement.spacedBy(8.dp), ) { items(PLACEHOLDER_ITEMS_COUNT) { - MostlyUsedItemPlaceholder() + if (LocalRedesignEnabled.current) { + MostlyUsedItemPlaceholderV2() + } else { + MostlyUsedItemPlaceholderV1() + } } } } @Composable -fun MostlyUsedItemPlaceholder(modifier: Modifier = Modifier) { +private fun MostlyUsedItemPlaceholderV1(modifier: Modifier = Modifier) { Column( modifier = modifier .width(148.dp) @@ -69,13 +73,52 @@ fun MostlyUsedItemPlaceholder(modifier: Modifier = Modifier) { } } +@Composable +private fun MostlyUsedItemPlaceholderV2(modifier: Modifier = Modifier) { + Column( + modifier = modifier + .width(178.dp) + .height(130.dp) + .background( + color = TangemTheme.colors2.surface.level3, + shape = RoundedCornerShape(TangemTheme.dimens2.x4), + ) + .padding(12.dp), + ) { + CircleShimmer(modifier = Modifier.size(40.dp)) + SpacerH(22.dp) + RectangleShimmer( + modifier = Modifier + .width(56.dp) + .height(20.dp), + radius = TangemTheme.dimens2.x25, + ) + SpacerH(4.dp) + RectangleShimmer( + modifier = Modifier + .width(46.dp) + .height(16.dp), + radius = TangemTheme.dimens2.x25, + ) + } +} + private const val PLACEHOLDER_ITEMS_COUNT = 3 @Preview(showBackground = true, widthDp = 360) @Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable -private fun MostlyUsedPlaceholderPreview() { +private fun MostlyUsedPlaceholderPreviewV1() { TangemThemePreview { MostlyUsedPlaceholder() } +} + +@Preview(showBackground = true, widthDp = 360) +@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun MostlyUsedPlaceholderPreviewV2() { + TangemThemePreviewRedesign { + MostlyUsedPlaceholder() + } } \ 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 9fd9997c5b..a1183e5467 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 @@ -2,10 +2,15 @@ package com.tangem.features.feed.ui.feed.components import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* +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.vector.ImageVector +import androidx.compose.ui.res.vectorResource import androidx.compose.ui.unit.dp import com.tangem.core.ui.R import com.tangem.core.ui.components.RectangleShimmer @@ -13,6 +18,9 @@ import com.tangem.core.ui.components.SpacerW import com.tangem.core.ui.components.buttons.SecondarySmallButton import com.tangem.core.ui.components.buttons.SmallButtonConfig import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.stringResourceSafe +import com.tangem.core.ui.res.LocalRedesignEnabled +import com.tangem.core.ui.res.TangemTheme @Composable internal fun Header( @@ -21,6 +29,7 @@ internal fun Header( shouldShowSeeAll: Boolean, title: @Composable () -> Unit, ) { + val isRedesignEnabled = LocalRedesignEnabled.current AnimatedContent(isLoading) { animatedState -> Row( modifier = Modifier @@ -30,19 +39,47 @@ internal fun Header( verticalAlignment = Alignment.CenterVertically, ) { if (animatedState) { - RectangleShimmer(modifier = Modifier.size(width = 104.dp, height = 18.dp)) + if (isRedesignEnabled) { + RectangleShimmer( + modifier = Modifier.size(width = 130.dp, height = 24.dp), + radius = TangemTheme.dimens2.x25, + ) + } else { + RectangleShimmer(modifier = Modifier.size(width = 104.dp, height = 18.dp)) + } } else { Box(modifier = Modifier.weight(1f)) { title() } SpacerW(8.dp) AnimatedVisibility(shouldShowSeeAll) { - SecondarySmallButton( - config = SmallButtonConfig( - text = TextReference.Res(R.string.common_see_all), - onClick = onSeeAllClick, - ), - ) + if (isRedesignEnabled) { + Row( + modifier = Modifier + .padding(start = 8.dp) + .clickable(onClick = onSeeAllClick), + verticalAlignment = Alignment.CenterVertically, + ) { + Text( + text = stringResourceSafe(R.string.common_see_all), + color = TangemTheme.colors2.text.neutral.primary, + style = TangemTheme.typography2.bodySemibold16, + ) + Icon( + modifier = Modifier.size(24.dp), + imageVector = ImageVector.vectorResource(R.drawable.ic_chevron_small_right_24), + tint = TangemTheme.colors2.markers.iconGray, + contentDescription = null, + ) + } + } else { + SecondarySmallButton( + config = SmallButtonConfig( + text = TextReference.Res(R.string.common_see_all), + onClick = onSeeAllClick, + ), + ) + } } } } diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/EarnBlock.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/EarnBlock.kt index d97e6bd7a3..b2984c929c 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/EarnBlock.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/EarnBlock.kt @@ -1,9 +1,9 @@ package com.tangem.features.feed.ui.feed.components import androidx.compose.animation.AnimatedContent -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -16,9 +16,12 @@ 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.extensions.stringResourceSafe +import com.tangem.core.ui.res.LocalRedesignEnabled import com.tangem.core.ui.res.TangemTheme +import com.tangem.features.feed.ui.earn.components.EarnItemPlaceholderV1 import com.tangem.features.feed.ui.earn.components.EarnListItem -import com.tangem.features.feed.ui.earn.components.EarnListPlaceholder +import com.tangem.features.feed.ui.earn.components.MostlyUsedCard +import com.tangem.features.feed.ui.earn.components.MostlyUsedPlaceholder import com.tangem.features.feed.ui.earn.state.EarnListItemUM import com.tangem.features.feed.ui.earn.state.EarnListUM import kotlinx.collections.immutable.ImmutableList @@ -26,7 +29,15 @@ import kotlinx.collections.immutable.ImmutableList @Composable internal fun EarnBlock(onSeeAllClick: () -> Unit, earnListUM: EarnListUM, modifier: Modifier = Modifier) { if (earnListUM is EarnListUM.Empty) return + if (LocalRedesignEnabled.current) { + EarnBlockV2(onSeeAllClick = onSeeAllClick, earnListUM = earnListUM, modifier = modifier) + } else { + EarnBlockV1(onSeeAllClick = onSeeAllClick, earnListUM = earnListUM, modifier = modifier) + } +} +@Composable +private fun EarnBlockV1(onSeeAllClick: () -> Unit, earnListUM: EarnListUM, modifier: Modifier = Modifier) { Column(modifier = modifier) { Header( title = { @@ -56,7 +67,11 @@ internal fun EarnBlock(onSeeAllClick: () -> Unit, earnListUM: EarnListUM, modifi when (earnListUM) { is EarnListUM.Content -> EarnContentBlock(items = earnListUM.items) is EarnListUM.Error -> EarnErrorBlock(onRetryClick = earnListUM.onRetryClicked) - EarnListUM.Loading -> EarnListPlaceholder(placeholderCount = PLACEHOLDER_ITEM_COUNT) + EarnListUM.Loading -> { + repeat(PLACEHOLDER_ITEM_COUNT) { + EarnItemPlaceholderV1() + } + } EarnListUM.Empty -> Unit } } @@ -65,6 +80,55 @@ internal fun EarnBlock(onSeeAllClick: () -> Unit, earnListUM: EarnListUM, modifi } } +@Composable +private fun EarnBlockV2(onSeeAllClick: () -> Unit, earnListUM: EarnListUM, modifier: Modifier = Modifier) { + Column(modifier = modifier) { + Header( + title = { + Text( + text = stringResourceSafe(R.string.markets_earn_common_title), + style = TangemTheme.typography2.headingSemibold20, + color = TangemTheme.colors2.text.neutral.primary, + overflow = TextOverflow.Ellipsis, + maxLines = 1, + ) + }, + onSeeAllClick = onSeeAllClick, + isLoading = earnListUM is EarnListUM.Loading, + shouldShowSeeAll = earnListUM is EarnListUM.Content, + ) + + SpacerH(12.dp) + AnimatedContent( + targetState = earnListUM, + contentKey = { it::class.java }, + ) { earnListUM -> + when (earnListUM) { + is EarnListUM.Content -> EarnContentBlock(items = earnListUM.items) + is EarnListUM.Error -> { + BlockCard( + modifier = Modifier.padding(horizontal = 16.dp), + colors = TangemBlockCardColors.copy(containerColor = TangemTheme.colors2.surface.level3), + ) { + EarnErrorBlock(onRetryClick = earnListUM.onRetryClicked) + } + } + EarnListUM.Loading -> { + MostlyUsedPlaceholder( + contentPadding = PaddingValues( + start = 16.dp, + end = 16.dp, + bottom = 8.dp, + ), + ) + } + EarnListUM.Empty -> Unit + } + } + SpacerH(32.dp) + } +} + @Composable private fun EarnErrorBlock(onRetryClick: () -> Unit) { UnableToLoadData( @@ -77,9 +141,30 @@ private fun EarnErrorBlock(onRetryClick: () -> Unit) { @Composable private fun EarnContentBlock(items: ImmutableList) { - Column(modifier = Modifier.fillMaxWidth()) { - items.fastForEach { item -> - EarnListItem(item = item) + if (LocalRedesignEnabled.current) { + LazyRow( + contentPadding = PaddingValues( + start = 16.dp, + end = 16.dp, + bottom = 8.dp, + ), + horizontalArrangement = Arrangement.spacedBy(8.dp), + ) { + items( + items = items, + key = { item -> "${item.tokenName}-${item.network}" }, + ) { item -> + MostlyUsedCard( + item = item, + onClick = item.onItemClick, + ) + } + } + } else { + Column(modifier = Modifier.fillMaxWidth()) { + items.fastForEach { item -> + EarnListItem(item = item) + } } } } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen2.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen2.kt index 0d552f2757..7ca5c1dbf1 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen2.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen2.kt @@ -304,7 +304,7 @@ private inline fun BaseScaffoldWithMarkets( val peekHeight = bottomSheetHeaderHeightProvider() + TangemTheme.dimens2.x3 + bottomBarHeight val coroutineScope = rememberCoroutineScope() - val background = TangemTheme.colors2.surface.level3 + val background = TangemTheme.colors2.surface.level2 val bottomSheetState = rememberTangemStandardBottomSheetState() val scaffoldState = rememberTangemBottomSheetScaffoldState(bottomSheetState = bottomSheetState)