From 80d00dfb6bd38a4188f6307422367c2440f41986 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 26 Mar 2025 22:17:53 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../com/tangem/core/ui/components/Spacers.kt | 5 + .../core}/ui/components/UnableToLoadData.kt | 6 +- .../components/currency/icon/CurrencyIcon.kt | 4 +- .../currency/icon/CurrencyIconIconBadge.kt | 32 ++ .../{IconBadge.kt => CurrencyIconTopBadge.kt} | 24 +- .../core/ui/components/fields/SearchBar.kt | 43 ++- .../res/drawable/ic_nft_placeholder_76.xml | 16 + .../ui/components/MarketTokenDetailsChart.kt | 2 +- .../ui/components/TokenMarketDetailsBody.kt | 2 +- .../ui/components/MarketsListLazyColumn.kt | 1 + .../entity/NFTCollectionAssetUM.kt | 9 + .../entity/NFTCollectionAssetsListUM.kt | 16 + .../nft/collections/entity/NFTCollectionUM.kt | 14 + .../collections/entity/NFTCollectionsUM.kt | 29 ++ .../entity/NFTCollectionsWarningUM.kt | 5 + .../nft/collections/entity/NFTSalePriceUM.kt | 10 + .../nft/collections/ui/NFTCollection.kt | 178 ++++++++++ .../nft/collections/ui/NFTCollectionAsset.kt | 100 ++++++ .../ui/NFTCollectionAssetLoading.kt | 47 +++ .../collections/ui/NFTCollectionWarning.kt | 14 + .../collections/ui/NFTCollectionsContent.kt | 318 ++++++++++++++++++ .../nft/collections/ui/NFTCollectionsEmpty.kt | 74 ++++ .../collections/ui/NFTCollectionsFailed.kt | 54 +++ .../nft/collections/ui/NFTSalePrice.kt | 40 +++ .../onramp/tokenlist/ui/OnrampTokenList.kt | 14 +- .../wallet/ui/components/WalletNFTItem.kt | 2 +- 26 files changed, 1003 insertions(+), 56 deletions(-) rename {features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl => core/ui/src/main/java/com/tangem/core}/ui/components/UnableToLoadData.kt (88%) create mode 100644 core/ui/src/main/java/com/tangem/core/ui/components/currency/icon/CurrencyIconIconBadge.kt rename core/ui/src/main/java/com/tangem/core/ui/components/currency/icon/{IconBadge.kt => CurrencyIconTopBadge.kt} (66%) create mode 100644 core/ui/src/main/res/drawable/ic_nft_placeholder_76.xml create mode 100644 features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTCollectionAssetUM.kt create mode 100644 features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTCollectionAssetsListUM.kt create mode 100644 features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTCollectionUM.kt create mode 100644 features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTCollectionsUM.kt create mode 100644 features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTCollectionsWarningUM.kt create mode 100644 features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTSalePriceUM.kt create mode 100644 features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollection.kt create mode 100644 features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionAsset.kt create mode 100644 features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionAssetLoading.kt create mode 100644 features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionWarning.kt create mode 100644 features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionsContent.kt create mode 100644 features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionsEmpty.kt create mode 100644 features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionsFailed.kt create mode 100644 features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTSalePrice.kt diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/Spacers.kt b/core/ui/src/main/java/com/tangem/core/ui/components/Spacers.kt index 99230c1853..131ca91e00 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/Spacers.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/Spacers.kt @@ -14,6 +14,11 @@ fun SpacerH(height: Dp, modifier: Modifier = Modifier) { Spacer(modifier = modifier.height(height)) } +@Composable +fun SpacerH2(modifier: Modifier = Modifier) { + SpacerH(2.dp, modifier) +} + @Composable fun SpacerH4(modifier: Modifier = Modifier) { SpacerH(4.dp, modifier) diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/UnableToLoadData.kt b/core/ui/src/main/java/com/tangem/core/ui/components/UnableToLoadData.kt similarity index 88% rename from features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/UnableToLoadData.kt rename to core/ui/src/main/java/com/tangem/core/ui/components/UnableToLoadData.kt index c96d848bac..19f8e5fcbd 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/UnableToLoadData.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/UnableToLoadData.kt @@ -1,4 +1,4 @@ -package com.tangem.features.markets.tokenlist.impl.ui.components +package com.tangem.core.ui.components import android.content.res.Configuration import androidx.compose.foundation.layout.Arrangement @@ -8,16 +8,16 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview +import com.tangem.core.ui.R import com.tangem.core.ui.components.buttons.SecondarySmallButton import com.tangem.core.ui.components.buttons.SmallButtonConfig import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringResourceSafe import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview -import com.tangem.features.markets.impl.R @Composable -internal fun UnableToLoadData(onRetryClick: () -> Unit, modifier: Modifier = Modifier) { +fun UnableToLoadData(onRetryClick: () -> Unit, modifier: Modifier = Modifier) { Column( modifier = modifier, verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12), diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/currency/icon/CurrencyIcon.kt b/core/ui/src/main/java/com/tangem/core/ui/components/currency/icon/CurrencyIcon.kt index a9a7677136..4727ba9759 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/currency/icon/CurrencyIcon.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/currency/icon/CurrencyIcon.kt @@ -109,7 +109,7 @@ private fun BoxScope.ContentIconContainer( ) if (icon.topBadgeIconResId != null && shouldShowTopBadge) { - TopBadge( + CurrencyIconTopBadge( modifier = Modifier .offset(x = networkBadgeOffset, y = -networkBadgeOffset) .align(Alignment.TopEnd), @@ -120,7 +120,7 @@ private fun BoxScope.ContentIconContainer( } if (icon.showCustomBadge) { - BottomBadge( + CurrencyIconBottomBadge( modifier = Modifier.align(Alignment.BottomEnd), ) } diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/currency/icon/CurrencyIconIconBadge.kt b/core/ui/src/main/java/com/tangem/core/ui/components/currency/icon/CurrencyIconIconBadge.kt new file mode 100644 index 0000000000..b074076629 --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/components/currency/icon/CurrencyIconIconBadge.kt @@ -0,0 +1,32 @@ +package com.tangem.core.ui.components.currency.icon + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.tangem.core.ui.res.TangemTheme + +@Composable +internal fun CurrencyIconBottomBadge(modifier: Modifier = Modifier) { + Box( + modifier = modifier + .size(TangemTheme.dimens.size12) + .background( + color = TangemTheme.colors.background.primary, + shape = CircleShape, + ), + ) { + Box( + modifier = Modifier + .padding(all = TangemTheme.dimens.spacing2) + .matchParentSize() + .background( + color = TangemTheme.colors.icon.informative, + shape = CircleShape, + ), + ) + } +} \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/currency/icon/IconBadge.kt b/core/ui/src/main/java/com/tangem/core/ui/components/currency/icon/CurrencyIconTopBadge.kt similarity index 66% rename from core/ui/src/main/java/com/tangem/core/ui/components/currency/icon/IconBadge.kt rename to core/ui/src/main/java/com/tangem/core/ui/components/currency/icon/CurrencyIconTopBadge.kt index 09e597f7a6..03057d495d 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/currency/icon/IconBadge.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/currency/icon/CurrencyIconTopBadge.kt @@ -14,7 +14,7 @@ import androidx.compose.ui.res.painterResource import com.tangem.core.ui.res.TangemTheme @Composable -internal fun TopBadge( +fun CurrencyIconTopBadge( @DrawableRes iconResId: Int, alpha: Float, colorFilter: ColorFilter?, @@ -38,26 +38,4 @@ internal fun TopBadge( contentDescription = null, ) } -} - -@Composable -internal fun BottomBadge(modifier: Modifier = Modifier) { - Box( - modifier = modifier - .size(TangemTheme.dimens.size12) - .background( - color = TangemTheme.colors.background.primary, - shape = CircleShape, - ), - ) { - Box( - modifier = Modifier - .padding(all = TangemTheme.dimens.spacing2) - .matchParentSize() - .background( - color = TangemTheme.colors.icon.informative, - shape = CircleShape, - ), - ) - } } \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/fields/SearchBar.kt b/core/ui/src/main/java/com/tangem/core/ui/components/fields/SearchBar.kt index 9863c30ba0..d69616e5d6 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/fields/SearchBar.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/fields/SearchBar.kt @@ -11,6 +11,7 @@ import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.* import androidx.compose.runtime.Composable +import androidx.compose.runtime.Stable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusManager @@ -36,7 +37,11 @@ import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview @Composable -fun SearchBar(state: SearchBarUM, modifier: Modifier = Modifier, colors: TextFieldColors = TangemSearchBarColors) { +fun SearchBar( + state: SearchBarUM, + modifier: Modifier = Modifier, + colors: TextFieldColors = TangemSearchBarDefaults.defaultTextFieldColors, +) { val keyboardController = LocalSoftwareKeyboardController.current val focusManager = LocalFocusManager.current val interactionSource = remember { MutableInteractionSource() } @@ -161,18 +166,30 @@ private fun ClearButton( } } -private val TangemSearchBarColors: TextFieldColors - @Composable - get() = TextFieldDefaults.colors().copy( - focusedContainerColor = TangemTheme.colors.field.primary, - unfocusedContainerColor = TangemTheme.colors.field.primary, - focusedTextColor = TangemTheme.colors.text.primary1, - unfocusedTextColor = TangemTheme.colors.text.primary1, - cursorColor = TangemTheme.colors.icon.primary1, - focusedIndicatorColor = Color.Transparent, - unfocusedIndicatorColor = Color.Transparent, - disabledIndicatorColor = Color.Transparent, - ) +object TangemSearchBarDefaults { + val defaultTextFieldColors: TextFieldColors + @Composable @Stable get() = TextFieldDefaults.colors().copy( + focusedContainerColor = TangemTheme.colors.field.primary, + unfocusedContainerColor = TangemTheme.colors.field.primary, + focusedTextColor = TangemTheme.colors.text.primary1, + unfocusedTextColor = TangemTheme.colors.text.primary1, + cursorColor = TangemTheme.colors.icon.primary1, + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + disabledIndicatorColor = Color.Transparent, + ) + val secondaryTextFieldColors: TextFieldColors + @Composable @Stable get() = TextFieldDefaults.colors().copy( + focusedContainerColor = TangemTheme.colors.field.focused, + unfocusedContainerColor = TangemTheme.colors.field.focused, + focusedTextColor = TangemTheme.colors.text.primary1, + unfocusedTextColor = TangemTheme.colors.text.primary1, + cursorColor = TangemTheme.colors.icon.primary1, + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + disabledIndicatorColor = Color.Transparent, + ) +} // region Previews @Preview(widthDp = 328) diff --git a/core/ui/src/main/res/drawable/ic_nft_placeholder_76.xml b/core/ui/src/main/res/drawable/ic_nft_placeholder_76.xml new file mode 100644 index 0000000000..6e6a840d1f --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_nft_placeholder_76.xml @@ -0,0 +1,16 @@ + + + + + diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/MarketTokenDetailsChart.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/MarketTokenDetailsChart.kt index 39970e9671..076b704bb8 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/MarketTokenDetailsChart.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/MarketTokenDetailsChart.kt @@ -16,7 +16,7 @@ import com.tangem.common.ui.charts.state.MarketChartLook import com.tangem.common.ui.charts.state.rememberMarketChartState import com.tangem.core.ui.res.TangemTheme import com.tangem.features.markets.details.impl.ui.state.MarketsTokenDetailsUM -import com.tangem.features.markets.tokenlist.impl.ui.components.UnableToLoadData +import com.tangem.core.ui.components.UnableToLoadData @Composable internal fun MarketTokenDetailsChart( diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/TokenMarketDetailsBody.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/TokenMarketDetailsBody.kt index 0d04d56bbe..b796c0f38a 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/TokenMarketDetailsBody.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/TokenMarketDetailsBody.kt @@ -9,7 +9,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import com.tangem.core.ui.res.TangemTheme import com.tangem.features.markets.details.impl.ui.state.MarketsTokenDetailsUM -import com.tangem.features.markets.tokenlist.impl.ui.components.UnableToLoadData +import com.tangem.core.ui.components.UnableToLoadData internal fun LazyListScope.tokenMarketDetailsBody( state: MarketsTokenDetailsUM.Body, diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListLazyColumn.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListLazyColumn.kt index 703e2eae67..6fcc3b1195 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListLazyColumn.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListLazyColumn.kt @@ -10,6 +10,7 @@ import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalDensity +import com.tangem.core.ui.components.UnableToLoadData import com.tangem.core.ui.components.buttons.SecondarySmallButton import com.tangem.core.ui.components.buttons.SmallButtonConfig import com.tangem.core.ui.components.list.InfiniteListHandler diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTCollectionAssetUM.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTCollectionAssetUM.kt new file mode 100644 index 0000000000..fc75d29651 --- /dev/null +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTCollectionAssetUM.kt @@ -0,0 +1,9 @@ +package com.tangem.features.nft.collections.entity + +internal data class NFTCollectionAssetUM( + val id: String, + val name: String, + val imageUrl: String?, + val price: NFTSalePriceUM, + val onItemClick: () -> Unit, +) \ No newline at end of file diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTCollectionAssetsListUM.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTCollectionAssetsListUM.kt new file mode 100644 index 0000000000..7b0147b03a --- /dev/null +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTCollectionAssetsListUM.kt @@ -0,0 +1,16 @@ +package com.tangem.features.nft.collections.entity + +import androidx.compose.runtime.Immutable +import kotlinx.collections.immutable.ImmutableList + +@Immutable +internal sealed class NFTCollectionAssetsListUM { + data object Collapsed : NFTCollectionAssetsListUM() + + @Immutable + sealed class Expanded : NFTCollectionAssetsListUM() { + data class Loading(val itemsCount: Int) : Expanded() + data class Failed(val onRetryClick: () -> Unit) : Expanded() + data class Content(val items: ImmutableList) : Expanded() + } +} \ No newline at end of file diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTCollectionUM.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTCollectionUM.kt new file mode 100644 index 0000000000..8e3375906b --- /dev/null +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTCollectionUM.kt @@ -0,0 +1,14 @@ +package com.tangem.features.nft.collections.entity + +import androidx.annotation.DrawableRes +import com.tangem.core.ui.extensions.TextReference + +internal data class NFTCollectionUM( + val id: String, + val name: String, + @DrawableRes val networkIconId: Int, + val logoUrl: String?, + val description: TextReference, + val assets: NFTCollectionAssetsListUM, + val onExpandClick: () -> Unit, +) \ No newline at end of file diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTCollectionsUM.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTCollectionsUM.kt new file mode 100644 index 0000000000..394144b65d --- /dev/null +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTCollectionsUM.kt @@ -0,0 +1,29 @@ +package com.tangem.features.nft.collections.entity + +import androidx.compose.runtime.Immutable +import com.tangem.core.ui.components.fields.entity.SearchBarUM +import kotlinx.collections.immutable.ImmutableList + +@Immutable +internal sealed class NFTCollectionsUM { + + data class Empty( + val onReceiveClick: () -> Unit, + ) : NFTCollectionsUM() + + data class Loading( + val onReceiveClick: () -> Unit, + ) : NFTCollectionsUM() + + data class Failed( + val onRetryClick: () -> Unit, + val onReceiveClick: () -> Unit, + ) : NFTCollectionsUM() + + data class Content( + val search: SearchBarUM, + val collections: ImmutableList, + val warnings: ImmutableList, + val onReceiveClick: () -> Unit, + ) : NFTCollectionsUM() +} \ No newline at end of file diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTCollectionsWarningUM.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTCollectionsWarningUM.kt new file mode 100644 index 0000000000..f0bdc22aaa --- /dev/null +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTCollectionsWarningUM.kt @@ -0,0 +1,5 @@ +package com.tangem.features.nft.collections.entity + +import com.tangem.core.ui.components.notifications.NotificationConfig + +internal data class NFTCollectionsWarningUM(val config: NotificationConfig) \ No newline at end of file diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTSalePriceUM.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTSalePriceUM.kt new file mode 100644 index 0000000000..8747a49f55 --- /dev/null +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/entity/NFTSalePriceUM.kt @@ -0,0 +1,10 @@ +package com.tangem.features.nft.collections.entity + +import androidx.compose.runtime.Immutable + +@Immutable +internal sealed class NFTSalePriceUM { + data object Loading : NFTSalePriceUM() + data object Failed : NFTSalePriceUM() + data class Content(val price: String) : NFTSalePriceUM() +} \ No newline at end of file diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollection.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollection.kt new file mode 100644 index 0000000000..32f7159f78 --- /dev/null +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollection.kt @@ -0,0 +1,178 @@ +package com.tangem.features.nft.collections.ui + +import android.content.res.Configuration +import androidx.compose.animation.core.animateFloatAsState +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.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.rotate +import androidx.compose.ui.res.painterResource +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 coil.compose.SubcomposeAsyncImage +import com.tangem.core.ui.components.RectangleShimmer +import com.tangem.core.ui.components.currency.icon.CurrencyIconTopBadge +import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.resolveReference +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.features.nft.collections.entity.NFTCollectionAssetsListUM +import com.tangem.features.nft.collections.entity.NFTCollectionUM +import com.tangem.features.nft.impl.R + +private const val CHEVRON_ROTATION_EXPANDED = 180f +private const val CHEVRON_ROTATION_COLLAPSED = 0f + +@Composable +internal fun NFTCollection(state: NFTCollectionUM, modifier: Modifier = Modifier) { + val isExpanded = state.assets is NFTCollectionAssetsListUM.Expanded + + Column( + modifier = modifier, + ) { + Row( + modifier = Modifier + .clickable(onClick = state.onExpandClick) + .padding( + vertical = TangemTheme.dimens.spacing16, + horizontal = TangemTheme.dimens.spacing12, + ), + verticalAlignment = Alignment.CenterVertically, + ) { + Logo(state) + + Text(state) + + val rotation by animateFloatAsState( + targetValue = if (isExpanded) { + CHEVRON_ROTATION_EXPANDED + } else { + CHEVRON_ROTATION_COLLAPSED + }, + label = "chevron_rotation", + ) + + Icon( + modifier = Modifier + .rotate(rotation) + .size(TangemTheme.dimens.size24), + painter = painterResource(id = R.drawable.ic_chevron_24), + tint = if (isExpanded) { + TangemTheme.colors.icon.primary1 + } else { + TangemTheme.colors.icon.inactive + }, + contentDescription = null, + ) + } + } +} + +@Composable +private fun Logo(state: NFTCollectionUM) { + val networkBadgeOffset = TangemTheme.dimens.spacing6 + + Box( + modifier = Modifier, + ) { + SubcomposeAsyncImage( + modifier = Modifier + .align(Alignment.CenterStart) + .size(TangemTheme.dimens.size36), + model = state.logoUrl, + loading = { + RectangleShimmer(radius = TangemTheme.dimens.radius8) + }, + error = { + Box( + modifier = Modifier + .clip(shape = TangemTheme.shapes.roundedCorners8) + .background(TangemTheme.colors.field.primary), + ) + }, + contentDescription = null, + ) + CurrencyIconTopBadge( + modifier = Modifier + .offset(x = networkBadgeOffset, y = -networkBadgeOffset) + .align(Alignment.TopEnd), + iconResId = state.networkIconId, + alpha = 1f, + colorFilter = null, + ) + } +} + +@Composable +private fun RowScope.Text(state: NFTCollectionUM) { + Column( + modifier = Modifier + .weight(1f) + .padding( + horizontal = TangemTheme.dimens.spacing12, + ), + ) { + Text( + modifier = Modifier, + text = state.name, + style = TangemTheme.typography.subtitle2, + color = TangemTheme.colors.text.primary1, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + Text( + modifier = Modifier + .padding(top = TangemTheme.dimens.spacing2), + text = state.description.resolveReference(), + style = TangemTheme.typography.caption2, + color = TangemTheme.colors.text.tertiary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } +} + +@Preview(widthDp = 360, showBackground = true) +@Preview(widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun Preview_NFTCollection(@PreviewParameter(NFTCollectionProvider::class) item: NFTCollectionUM) { + TangemThemePreview { + NFTCollection( + state = item, + ) + } +} + +private class NFTCollectionProvider : CollectionPreviewParameterProvider( + collection = listOf( + NFTCollectionUM( + id = "item1", + name = "Nethers", + logoUrl = "", + networkIconId = R.drawable.img_eth_22, + description = TextReference.Str("3 items"), + assets = NFTCollectionAssetsListUM.Collapsed, + onExpandClick = { }, + ), + NFTCollectionUM( + id = "item2", + name = "Nethers", + logoUrl = "", + networkIconId = R.drawable.img_eth_22, + description = TextReference.Str("3 items"), + assets = NFTCollectionAssetsListUM.Expanded.Loading( + itemsCount = 3, + ), + onExpandClick = { }, + ), + ), +) \ No newline at end of file diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionAsset.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionAsset.kt new file mode 100644 index 0000000000..9951cd16a7 --- /dev/null +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionAsset.kt @@ -0,0 +1,100 @@ +package com.tangem.features.nft.collections.ui + +import android.content.res.Configuration +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.aspectRatio +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +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 coil.compose.SubcomposeAsyncImage +import com.tangem.core.ui.components.RectangleShimmer +import com.tangem.core.ui.components.SpacerH12 +import com.tangem.core.ui.components.SpacerH2 +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.features.nft.collections.entity.NFTCollectionAssetUM +import com.tangem.features.nft.collections.entity.NFTSalePriceUM + +@Composable +internal fun NFTCollectionAsset(state: NFTCollectionAssetUM, modifier: Modifier = Modifier) { + Column( + modifier = modifier + .clickable { state.onItemClick() }, + ) { + SubcomposeAsyncImage( + modifier = Modifier + .aspectRatio(1f), + model = state.imageUrl, + loading = { + RectangleShimmer(radius = TangemTheme.dimens.radius16) + }, + error = { + Box( + modifier = Modifier + .clip(shape = TangemTheme.shapes.roundedCornersXMedium) + .background(TangemTheme.colors.field.primary), + ) + }, + contentDescription = null, + ) + SpacerH12() + Text( + text = state.name, + style = TangemTheme.typography.subtitle2, + color = TangemTheme.colors.text.primary1, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + SpacerH2() + NFTSalePrice( + state = state.price, + ) + } +} + +@Preview(widthDp = 180, showBackground = true) +@Preview(widthDp = 180, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun Preview_NFTCollectionAsset( + @PreviewParameter(NFTCollectionAssetProvider::class) state: NFTCollectionAssetUM, +) { + TangemThemePreview { + NFTCollectionAsset( + state = state, + ) + } +} + +private class NFTCollectionAssetProvider : CollectionPreviewParameterProvider( + collection = listOf( + NFTCollectionAssetUM( + id = "item1", + name = "Nethers #0853", + imageUrl = "img", + price = NFTSalePriceUM.Loading, + onItemClick = { }, + ), + NFTCollectionAssetUM( + id = "item2", + name = "Nethers #0854", + imageUrl = "img", + price = NFTSalePriceUM.Failed, + onItemClick = { }, + ), + NFTCollectionAssetUM( + id = "item3", + name = "Nethers #0855", + imageUrl = "img", + price = NFTSalePriceUM.Content("0.05 ETH"), + onItemClick = { }, + ), + ), +) \ No newline at end of file diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionAssetLoading.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionAssetLoading.kt new file mode 100644 index 0000000000..66bf216ad7 --- /dev/null +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionAssetLoading.kt @@ -0,0 +1,47 @@ +package com.tangem.features.nft.collections.ui + +import android.content.res.Configuration +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.width +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import com.tangem.core.ui.components.* +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview + +@Composable +internal fun NFTCollectionAssetLoading(modifier: Modifier = Modifier) { + Column( + modifier = modifier, + ) { + RectangleShimmer( + modifier = Modifier + .aspectRatio(1f), + ) + SpacerH12() + TextShimmer( + modifier = Modifier + .width(TangemTheme.dimens.size86), + style = TangemTheme.typography.subtitle2, + textSizeHeight = true, + ) + SpacerH2() + TextShimmer( + modifier = Modifier + .width(TangemTheme.dimens.size48), + style = TangemTheme.typography.caption2, + textSizeHeight = true, + ) + } +} + +@Preview(widthDp = 180, showBackground = true) +@Preview(widthDp = 180, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun Preview_NFTCollectionAsset() { + TangemThemePreview { + NFTCollectionAssetLoading() + } +} \ No newline at end of file diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionWarning.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionWarning.kt new file mode 100644 index 0000000000..337e675026 --- /dev/null +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionWarning.kt @@ -0,0 +1,14 @@ +package com.tangem.features.nft.collections.ui + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.tangem.core.ui.components.notifications.Notification +import com.tangem.features.nft.collections.entity.NFTCollectionsWarningUM + +@Composable +internal fun NFTCollectionWarning(state: NFTCollectionsWarningUM, modifier: Modifier = Modifier) { + Notification( + modifier = modifier, + config = state.config, + ) +} \ No newline at end of file diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionsContent.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionsContent.kt new file mode 100644 index 0000000000..6a1b002cf4 --- /dev/null +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionsContent.kt @@ -0,0 +1,318 @@ +package com.tangem.features.nft.collections.ui + +import android.content.res.Configuration +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListScope +import androidx.compose.foundation.lazy.rememberLazyListState +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.tooling.preview.Preview +import androidx.compose.ui.util.fastForEach +import com.tangem.core.ui.components.PrimaryButton +import com.tangem.core.ui.components.UnableToLoadData +import com.tangem.core.ui.components.fields.SearchBar +import com.tangem.core.ui.components.fields.TangemSearchBarDefaults +import com.tangem.core.ui.components.fields.entity.SearchBarUM +import com.tangem.core.ui.components.notifications.NotificationConfig +import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.stringResourceSafe +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.features.nft.collections.entity.* +import com.tangem.features.nft.collections.entity.NFTCollectionAssetUM +import com.tangem.features.nft.collections.entity.NFTCollectionAssetsListUM +import com.tangem.features.nft.collections.entity.NFTCollectionUM +import com.tangem.features.nft.collections.entity.NFTCollectionsUM +import com.tangem.features.nft.collections.entity.NFTSalePriceUM +import com.tangem.features.nft.impl.R +import kotlinx.collections.immutable.persistentListOf + +@Suppress("LongMethod") +@Composable +internal fun NFTCollectionsContent(state: NFTCollectionsUM.Content, modifier: Modifier = Modifier) { + val listState = rememberLazyListState() + + Box( + modifier = modifier + .fillMaxSize() + .background(TangemTheme.colors.background.secondary) + .padding( + start = TangemTheme.dimens.spacing16, + end = TangemTheme.dimens.spacing16, + bottom = TangemTheme.dimens.spacing16, + ), + ) { + Column( + modifier = Modifier, + ) { + SearchBar( + state = state.search, + colors = TangemSearchBarDefaults.secondaryTextFieldColors, + ) + state.warnings.fastForEach { + NFTCollectionWarning( + modifier = Modifier + .padding(top = TangemTheme.dimens.spacing16), + state = it, + ) + } + LazyColumn( + modifier = Modifier + .padding( + top = TangemTheme.dimens.spacing16, + ) + .clip(TangemTheme.shapes.roundedCornersXMedium) + .background(TangemTheme.colors.background.primary), + state = listState, + ) { + state.collections.fastForEach { collection -> + item(key = collection.id) { + NFTCollection( + modifier = Modifier.fillMaxWidth(), + state = collection, + ) + } + when (val assets = collection.assets) { + is NFTCollectionAssetsListUM.Collapsed -> Unit + is NFTCollectionAssetsListUM.Expanded.Loading -> { + assetsListLoading( + collectionId = collection.id, + content = assets, + ) + } + is NFTCollectionAssetsListUM.Expanded.Failed -> { + assetsListFailed( + collectionId = collection.id, + content = assets, + ) + } + is NFTCollectionAssetsListUM.Expanded.Content -> { + assetsListContent( + collectionId = collection.id, + content = assets, + ) + } + } + } + } + } + PrimaryButton( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.BottomCenter), + text = stringResourceSafe(R.string.nft_collections_receive), + onClick = { }, + ) + } +} + +private fun LazyListScope.assetsListLoading( + collectionId: String, + content: NFTCollectionAssetsListUM.Expanded.Loading, +) { + val itemsCount = content.itemsCount + val rowCount = (itemsCount + 1) / 2 + repeat(rowCount) { rowIndex -> + item( + key = "loading_${collectionId}_$rowIndex", + ) { + val paddingValues = PaddingValues( + start = TangemTheme.dimens.spacing6, + top = TangemTheme.dimens.spacing6, + end = TangemTheme.dimens.spacing6, + bottom = TangemTheme.dimens.spacing20, + ) + Row( + modifier = Modifier + .padding(TangemTheme.dimens.spacing6) + .animateItem(), + ) { + NFTCollectionAssetLoading( + modifier = Modifier + .weight(1f) + .padding(paddingValues), + ) + if (rowIndex == rowCount - 1 && itemsCount % 2 != 0) { + Box( + modifier = Modifier + .weight(1f) + .padding(paddingValues), + ) + } else { + NFTCollectionAssetLoading( + modifier = Modifier + .weight(1f) + .padding(paddingValues), + ) + } + } + } + } +} + +private fun LazyListScope.assetsListFailed(collectionId: String, content: NFTCollectionAssetsListUM.Expanded.Failed) { + item( + key = "failed_$collectionId", + ) { + Box( + modifier = Modifier + .fillMaxWidth() + .height(TangemTheme.dimens.size142), + contentAlignment = Alignment.Center, + ) { + UnableToLoadData( + onRetryClick = content.onRetryClick, + ) + } + } +} + +private fun LazyListScope.assetsListContent( + collectionId: String, + content: NFTCollectionAssetsListUM.Expanded.Content, +) { + val items = content.items + val itemsCount = items.size + val rowCount = (itemsCount + 1) / 2 + repeat(rowCount) { rowIndex -> + val item1 = items[rowIndex * 2] + val item2 = items.getOrNull(rowIndex * 2 + 1) + item( + key = "content_${collectionId}_${item1.id}_${item2?.id}", + ) { + val paddingValues = PaddingValues( + start = TangemTheme.dimens.spacing6, + top = TangemTheme.dimens.spacing6, + end = TangemTheme.dimens.spacing6, + bottom = TangemTheme.dimens.spacing20, + ) + Row( + modifier = Modifier + .padding(TangemTheme.dimens.spacing6) + .animateItem(), + ) { + NFTCollectionAsset( + modifier = Modifier + .weight(1f) + .padding(paddingValues), + state = item1, + ) + if (item2 == null) { + Box( + modifier = Modifier + .weight(1f) + .padding(paddingValues), + ) + } else { + NFTCollectionAsset( + modifier = Modifier + .weight(1f) + .padding(paddingValues), + state = item2, + ) + } + } + } + } +} + +@Suppress("LongMethod") +@Preview(widthDp = 360, showBackground = true) +@Preview(widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun Preview_NFTCollectionsContent() { + TangemThemePreview { + NFTCollectionsContent( + state = NFTCollectionsUM.Content( + search = SearchBarUM( + placeholderText = resourceReference(R.string.common_search), + query = "", + onQueryChange = {}, + isActive = false, + onActiveChange = { }, + ), + collections = persistentListOf( + NFTCollectionUM( + id = "item1", + name = "Nethers", + logoUrl = "", + networkIconId = R.drawable.img_eth_22, + description = TextReference.Str("3 items"), + assets = NFTCollectionAssetsListUM.Collapsed, + onExpandClick = { }, + ), + NFTCollectionUM( + id = "item2", + name = "Nethers", + logoUrl = "", + networkIconId = R.drawable.img_eth_22, + description = TextReference.Str("3 items"), + assets = NFTCollectionAssetsListUM.Expanded.Loading( + itemsCount = 1, + ), + onExpandClick = { }, + ), + NFTCollectionUM( + id = "item3", + name = "Nethers", + logoUrl = "", + networkIconId = R.drawable.img_eth_22, + description = TextReference.Str("3 items"), + assets = NFTCollectionAssetsListUM.Expanded.Failed( + onRetryClick = { }, + ), + onExpandClick = { }, + ), + NFTCollectionUM( + id = "item4", + name = "Nethers", + logoUrl = "", + networkIconId = R.drawable.img_eth_22, + description = TextReference.Str("3 items"), + assets = NFTCollectionAssetsListUM.Expanded.Content( + items = persistentListOf( + NFTCollectionAssetUM( + id = "item1", + name = "Nethers #0854", + imageUrl = "img", + price = NFTSalePriceUM.Content("0.05 ETH"), + onItemClick = { }, + ), + NFTCollectionAssetUM( + id = "item2", + name = "Nethers #0855", + imageUrl = "img", + price = NFTSalePriceUM.Loading, + onItemClick = { }, + ), + NFTCollectionAssetUM( + id = "item3", + name = "Nethers #0856", + imageUrl = "img", + price = NFTSalePriceUM.Failed, + onItemClick = { }, + ), + ), + ), + onExpandClick = { }, + ), + ), + warnings = persistentListOf( + NFTCollectionsWarningUM( + config = NotificationConfig( + title = TextReference.Res(R.string.nft_collections_warning_title), + subtitle = TextReference.Res(R.string.nft_collections_warning_subtitle), + iconResId = R.drawable.ic_alert_triangle_20, + ), + ), + ), + onReceiveClick = { }, + ), + ) + } +} \ No newline at end of file diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionsEmpty.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionsEmpty.kt new file mode 100644 index 0000000000..1376f56e72 --- /dev/null +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionsEmpty.kt @@ -0,0 +1,74 @@ +package com.tangem.features.nft.collections.ui + +import android.content.res.Configuration +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.* +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import com.tangem.core.ui.components.PrimaryButton +import com.tangem.core.ui.extensions.stringResourceSafe +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.features.nft.collections.entity.NFTCollectionsUM +import com.tangem.features.nft.impl.R + +@Composable +internal fun NFTCollectionsEmpty(state: NFTCollectionsUM.Empty, modifier: Modifier = Modifier) { + Box( + modifier = modifier + .fillMaxSize() + .padding(TangemTheme.dimens.spacing16), + ) { + Column( + modifier = Modifier + .padding(TangemTheme.dimens.spacing16) + .align(Alignment.Center), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Image( + painter = painterResource(R.drawable.ic_nft_placeholder_76), + contentDescription = null, + ) + Text( + modifier = Modifier.padding(top = TangemTheme.dimens.spacing24), + text = stringResource(R.string.nft_collections_empty_title), + style = TangemTheme.typography.h3, + color = TangemTheme.colors.text.primary1, + textAlign = TextAlign.Center, + ) + Text( + modifier = Modifier.padding(top = TangemTheme.dimens.spacing8), + text = stringResource(R.string.nft_collections_empty_description), + style = TangemTheme.typography.body1, + color = TangemTheme.colors.text.secondary, + textAlign = TextAlign.Center, + ) + PrimaryButton( + modifier = Modifier + .padding(top = TangemTheme.dimens.spacing48) + .wrapContentWidth(), + text = stringResourceSafe(R.string.nft_collections_receive), + onClick = state.onReceiveClick, + ) + } + } +} + +@Preview(widthDp = 360, showBackground = true) +@Preview(widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun Preview_NFTCollectionsEmpty() { + TangemThemePreview { + NFTCollectionsEmpty( + state = NFTCollectionsUM.Empty( + onReceiveClick = { }, + ), + ) + } +} \ No newline at end of file diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionsFailed.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionsFailed.kt new file mode 100644 index 0000000000..f16d193537 --- /dev/null +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTCollectionsFailed.kt @@ -0,0 +1,54 @@ +package com.tangem.features.nft.collections.ui + +import android.content.res.Configuration +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import com.tangem.core.ui.components.PrimaryButton +import com.tangem.core.ui.components.UnableToLoadData +import com.tangem.core.ui.extensions.stringResourceSafe +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.features.nft.collections.entity.NFTCollectionsUM +import com.tangem.features.nft.impl.R + +@Composable +internal fun NFTCollectionsFailed(state: NFTCollectionsUM.Failed, modifier: Modifier = Modifier) { + Box( + modifier = modifier + .fillMaxSize() + .padding(TangemTheme.dimens.spacing16), + ) { + UnableToLoadData( + modifier = Modifier + .align(Alignment.Center), + onRetryClick = state.onRetryClick, + ) + PrimaryButton( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.BottomCenter), + text = stringResourceSafe(R.string.nft_collections_receive), + onClick = { }, + ) + } +} + +@Preview(widthDp = 360, showBackground = true) +@Preview(widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun Preview_NFTCollectionsFailed() { + TangemThemePreview { + NFTCollectionsFailed( + state = NFTCollectionsUM.Failed( + onRetryClick = { }, + onReceiveClick = { }, + ), + ) + } +} \ No newline at end of file diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTSalePrice.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTSalePrice.kt new file mode 100644 index 0000000000..ce4a1db2cf --- /dev/null +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/collections/ui/NFTSalePrice.kt @@ -0,0 +1,40 @@ +package com.tangem.features.nft.collections.ui + +import androidx.compose.foundation.layout.width +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextOverflow +import com.tangem.core.ui.components.TextShimmer +import com.tangem.core.ui.res.TangemTheme +import com.tangem.features.nft.collections.entity.NFTSalePriceUM + +@Composable +internal fun NFTSalePrice(state: NFTSalePriceUM, modifier: Modifier = Modifier) { + when (state) { + is NFTSalePriceUM.Content -> { + Text( + modifier = modifier, + text = state.price, + style = TangemTheme.typography.caption2, + color = TangemTheme.colors.text.tertiary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } + is NFTSalePriceUM.Failed -> { + Text( + modifier = modifier, + text = "", + style = TangemTheme.typography.caption2, + ) + } + is NFTSalePriceUM.Loading -> { + TextShimmer( + modifier = modifier + .width(TangemTheme.dimens.size48), + style = TangemTheme.typography.caption2, + ) + } + } +} \ No newline at end of file diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/tokenlist/ui/OnrampTokenList.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/tokenlist/ui/OnrampTokenList.kt index 679abe3866..c45da297d2 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/tokenlist/ui/OnrampTokenList.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/tokenlist/ui/OnrampTokenList.kt @@ -6,11 +6,9 @@ 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.material3.TextFieldDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.key import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp @@ -18,6 +16,7 @@ import androidx.compose.ui.util.fastForEachIndexed import com.tangem.common.ui.notifications.NotificationUM import com.tangem.core.ui.components.SpacerH12 import com.tangem.core.ui.components.fields.SearchBar +import com.tangem.core.ui.components.fields.TangemSearchBarDefaults import com.tangem.core.ui.components.fields.entity.SearchBarUM import com.tangem.core.ui.components.notifications.Notification import com.tangem.core.ui.components.tokenlist.TokenListItem @@ -74,16 +73,7 @@ internal fun TokenList(state: TokenListUM, modifier: Modifier = Modifier) { private fun SearchBar(searchBarUM: SearchBarUM) { SearchBar( state = searchBarUM, - colors = TextFieldDefaults.colors().copy( - focusedContainerColor = TangemTheme.colors.field.focused, - unfocusedContainerColor = TangemTheme.colors.field.focused, - focusedTextColor = TangemTheme.colors.text.primary1, - unfocusedTextColor = TangemTheme.colors.text.primary1, - cursorColor = TangemTheme.colors.icon.primary1, - focusedIndicatorColor = Color.Transparent, - unfocusedIndicatorColor = Color.Transparent, - disabledIndicatorColor = Color.Transparent, - ), + colors = TangemSearchBarDefaults.secondaryTextFieldColors, ) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletNFTItem.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletNFTItem.kt index 850b0d78ab..7f2a8515b7 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletNFTItem.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletNFTItem.kt @@ -394,7 +394,7 @@ private fun RowContentContainer( @Preview(widthDp = 360) @Preview(widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable -private fun Preview_WalletNFTItem_InLight(@PreviewParameter(WalletNFTItemProvider::class) state: WalletNFTItemUM) { +private fun Preview_WalletNFTItem(@PreviewParameter(WalletNFTItemProvider::class) state: WalletNFTItemUM) { TangemThemePreview { WalletNFTItem( state = state,