From e2ce1e4a9708be853006f27999d8e1f140f60bfb Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 19 Jul 2023 21:59:22 +0800 Subject: [PATCH] Updated on 2026-08-14 --- .../components/notifications/Notification.kt | 65 +++++-- .../notifications/NotificationState.kt | 34 +++- .../com/tangem/core/ui/res/TangemDimens.kt | 1 + .../presentation/common/WalletPreviewData.kt | 13 +- .../wallet/state/WalletBottomSheetConfig.kt | 79 +++++++++ .../wallet/state/WalletNotification.kt | 120 +++++++++++-- .../wallet/state/WalletStateHolder.kt | 5 + .../presentation/wallet/ui/WalletScreen.kt | 9 +- .../wallet/ui/components/WalletBottomSheet.kt | 161 ++++++++++++++++++ 9 files changed, 448 insertions(+), 39 deletions(-) create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletBottomSheetConfig.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletBottomSheet.kt diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/notifications/Notification.kt b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/Notification.kt index 9d4f2cf480..76b7894881 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/notifications/Notification.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/Notification.kt @@ -19,6 +19,8 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider import com.tangem.core.ui.R import com.tangem.core.ui.components.SpacerH2 +import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.res.TangemColorPalette import com.tangem.core.ui.res.TangemTheme @@ -43,10 +45,10 @@ fun Notification(state: NotificationState, modifier: Modifier = Modifier) { ) .clickable( enabled = when (state) { - is NotificationState.Simple -> false - is NotificationState.Action -> true + is NotificationState.Clickable -> true + is NotificationState.Simple, is NotificationState.Closable -> false }, - onClick = if (state is NotificationState.Action) { + onClick = if (state is NotificationState.Clickable) { state.onClick } else { {} @@ -67,12 +69,23 @@ fun Notification(state: NotificationState, modifier: Modifier = Modifier) { ) NotificationInfoBlock( - title = state.title, - subtitle = state.subtitle, + title = state.title.resolveReference(), + subtitle = state.subtitle?.resolveReference(), modifier = Modifier.align(alignment = Alignment.CenterStart), ) - if (state is NotificationState.Action) { + if (state is NotificationState.Closable) { + Icon( + modifier = Modifier + .size(size = TangemTheme.dimens.size20) + .align(alignment = Alignment.TopEnd), + painter = painterResource(id = R.drawable.ic_close_24), + contentDescription = null, + tint = TangemTheme.colors.icon.informative, + ) + } + + if (state is NotificationState.Clickable) { Icon( modifier = Modifier .size(size = TangemTheme.dimens.size20) @@ -149,30 +162,50 @@ private fun Preview_WarningNotification_Dark( private class NotificationStateProvider : CollectionPreviewParameterProvider( collection = listOf( NotificationState.Simple( - title = "Your wallet hasn’t been backed up", - subtitle = "Lorem ipsum dolor sit amet, consectetur " + - "adipiscing elit, sed do eiusmod tempor incididunt ut labore et...", + title = TextReference.Str(value = "Your wallet hasn’t been backed up"), + subtitle = TextReference.Str( + value = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt " + + "ut labore et...", + ), iconResId = R.drawable.img_attention_20, ), NotificationState.Simple( - title = "Your wallet hasn’t been backed up", + title = TextReference.Str("Your wallet hasn’t been backed up"), subtitle = null, iconResId = R.drawable.ic_alert_circle_24, tint = TangemColorPalette.Amaranth, ), - NotificationState.Action( - title = "Your wallet hasn’t been backed up", - subtitle = "Lorem ipsum dolor sit amet, consectetur " + - "adipiscing elit, sed do eiusmod tempor incididunt ut labore et...", + NotificationState.Clickable( + title = TextReference.Str(value = "Your wallet hasn’t been backed up"), + subtitle = TextReference.Str( + value = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt " + + "ut labore et...", + ), iconResId = R.drawable.img_attention_20, onClick = {}, ), - NotificationState.Action( - title = "Your wallet hasn’t been backed up", + NotificationState.Clickable( + title = TextReference.Str(value = "Your wallet hasn’t been backed up"), subtitle = null, iconResId = R.drawable.ic_alert_circle_24, tint = TangemColorPalette.Amaranth, onClick = {}, ), + NotificationState.Closable( + title = TextReference.Str(value = "Your wallet hasn’t been backed up"), + subtitle = TextReference.Str( + value = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt " + + "ut labore et...", + ), + iconResId = R.drawable.img_attention_20, + onCloseClick = {}, + ), + NotificationState.Closable( + title = TextReference.Str(value = "Your wallet hasn’t been backed up"), + subtitle = null, + iconResId = R.drawable.ic_alert_circle_24, + tint = TangemColorPalette.Amaranth, + onCloseClick = {}, + ), ), ) \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/notifications/NotificationState.kt b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/NotificationState.kt index 065fa1e125..f787e62a66 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/notifications/NotificationState.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/NotificationState.kt @@ -2,6 +2,7 @@ package com.tangem.core.ui.components.notifications import androidx.annotation.DrawableRes import androidx.compose.ui.graphics.Color +import com.tangem.core.ui.extensions.TextReference /** * Notification component state @@ -14,8 +15,8 @@ import androidx.compose.ui.graphics.Color [REDACTED_AUTHOR] */ sealed class NotificationState( - open val title: String, - open val subtitle: String? = null, + open val title: TextReference, + open val subtitle: TextReference? = null, @DrawableRes open val iconResId: Int, open val tint: Color? = null, ) { @@ -29,8 +30,8 @@ sealed class NotificationState( * @property tint icon tint */ data class Simple( - override val title: String, - override val subtitle: String? = null, + override val title: TextReference, + override val subtitle: TextReference? = null, @DrawableRes override val iconResId: Int, override val tint: Color? = null, ) : NotificationState(title, subtitle, iconResId, tint) @@ -42,13 +43,30 @@ sealed class NotificationState( * @property subtitle subtitle * @property iconResId icon resource id * @property tint icon tint - * @param onClick lambda be invoked when notification component is clicked + * @property onClick lambda be invoked when notification component is clicked */ - data class Action( - override val title: String, - override val subtitle: String? = null, + data class Clickable( + override val title: TextReference, + override val subtitle: TextReference? = null, @DrawableRes override val iconResId: Int, override val tint: Color? = null, val onClick: () -> Unit, ) : NotificationState(title, subtitle, iconResId, tint) + + /** + * Closable notification state + * + * @property title title + * @property subtitle subtitle + * @property iconResId icon resource id + * @property tint icon tint + * @property onCloseClick lambda be invoked when close button is clicked + */ + data class Closable( + override val title: TextReference, + override val subtitle: TextReference? = null, + @DrawableRes override val iconResId: Int, + override val tint: Color? = null, + val onCloseClick: (() -> Unit)? = null, + ) : NotificationState(title, subtitle, iconResId, tint) } \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt b/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt index a78bd58dbd..8e17a060f2 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt @@ -102,6 +102,7 @@ data class TangemDimens internal constructor( val spacing34: Dp = 34.dp, val spacing36: Dp = 34.dp, val spacing38: Dp = 38.dp, + val spacing40: Dp = 40.dp, val spacing44: Dp = 44.dp, val spacing50: Dp = 50.dp, val spacing52: Dp = 52.dp, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt index bc2443bc0e..3e1d581e0c 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt @@ -200,6 +200,15 @@ internal object WalletPreviewData { ), ) + val bottomSheet = WalletBottomSheetConfig( + isShow = false, + onDismissRequest = {}, + content = WalletBottomSheetConfig.BottomSheetContentConfig.UnlockWallets( + onUnlockClick = {}, + onScanClick = {}, + ), + ) + private val manageButtons = persistentListOf( WalletManageButton.Buy(onClick = {}), WalletManageButton.Send(onClick = {}), @@ -268,9 +277,10 @@ internal object WalletPreviewData { notifications = persistentListOf( WalletNotification.UnreachableNetworks, WalletNotification.LikeTangemApp(onClick = {}), - WalletNotification.NeedToBackup(onClick = {}), + WalletNotification.BackupCard(onClick = {}), WalletNotification.ScanCard(onClick = {}), ), + bottomSheet = bottomSheet, onOrganizeTokensClick = {}, ) @@ -303,6 +313,7 @@ internal object WalletPreviewData { ), notifications = persistentListOf(WalletNotification.LikeTangemApp(onClick = {})), buttons = manageButtons.map(WalletManageButton::config).toPersistentList(), + bottomSheet = bottomSheet, marketPriceBlockState = MarketPriceBlockState.Content( currencyName = "BTC", price = "98900.12$", diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletBottomSheetConfig.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletBottomSheetConfig.kt new file mode 100644 index 0000000000..5aafcd4464 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletBottomSheetConfig.kt @@ -0,0 +1,79 @@ +package com.tangem.feature.wallet.presentation.wallet.state + +import androidx.annotation.DrawableRes +import androidx.compose.ui.graphics.Color +import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.WrappedList +import com.tangem.core.ui.res.TangemColorPalette +import com.tangem.feature.wallet.impl.R + +/** + * Wallet bottom sheet config + * + * @property isShow flag that determine if bottom sheet is shown + * @property onDismissRequest lambda be invoked when bottom sheet is dismissed + * @property content content config + * +[REDACTED_AUTHOR] + */ +// TODO: Finalize notification strings [REDACTED_JIRA] +internal data class WalletBottomSheetConfig( + val isShow: Boolean, + val onDismissRequest: () -> Unit, + val content: BottomSheetContentConfig, +) { + + sealed class BottomSheetContentConfig( + open val title: TextReference, + open val subtitle: TextReference, + @DrawableRes open val iconResId: Int, + open val tint: Color? = null, + val primaryButtonConfig: ButtonConfig, + val secondaryButtonConfig: ButtonConfig? = null, + ) { + + data class ButtonConfig(val text: String, val onClick: () -> Unit, @DrawableRes val iconResId: Int? = null) + + data class UnlockWallets( + val onUnlockClick: () -> Unit, + val onScanClick: () -> Unit, + ) : BottomSheetContentConfig( + title = TextReference.Str(value = "Unlock needed"), + subtitle = TextReference.Str( + value = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor " + + "incididunt ut labore et dolore magna aliqua.", + ), + iconResId = R.drawable.ic_locked_24, + tint = TangemColorPalette.Black, + primaryButtonConfig = ButtonConfig(text = "Unlock", onClick = onUnlockClick), + secondaryButtonConfig = ButtonConfig( + text = "Scan card", + onClick = onScanClick, + iconResId = R.drawable.ic_tangem_24, + ), + ) + + data class LikeTangemApp( + val onRateTheAppClick: () -> Unit, + val onShareClick: () -> Unit, + ) : BottomSheetContentConfig( + title = TextReference.Str(value = "Like Tangem App?"), + subtitle = TextReference.Str(value = "How was your experience with our app? Let us know:"), + iconResId = R.drawable.ic_star_24, + tint = TangemColorPalette.Tangerine, + primaryButtonConfig = ButtonConfig(text = "Rate the app", onClick = onRateTheAppClick), + secondaryButtonConfig = ButtonConfig(text = "Share feedback", onClick = onShareClick), + ) + + data class MultiWalletAlreadySignedHashes(val onLearnClick: () -> Unit) : BottomSheetContentConfig( + title = TextReference.Res( + id = R.string.warning_important_security_info, + formatArgs = WrappedList(listOf("\u26A0")), + ), + subtitle = TextReference.Res(id = R.string.warning_signed_tx_previously), + iconResId = R.drawable.img_attention_20, + tint = null, + primaryButtonConfig = ButtonConfig(text = "Learn more", onClick = onLearnClick), + ) + } +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletNotification.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletNotification.kt index 39e760dd4f..66079037c6 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletNotification.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletNotification.kt @@ -1,6 +1,8 @@ package com.tangem.feature.wallet.presentation.wallet.state import com.tangem.core.ui.components.notifications.NotificationState +import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.WrappedList import com.tangem.core.ui.res.TangemColorPalette import com.tangem.feature.wallet.impl.R @@ -11,26 +13,107 @@ import com.tangem.feature.wallet.impl.R * [REDACTED_AUTHOR] */ +// TODO: Finalize notification strings [REDACTED_JIRA] sealed class WalletNotification(open val state: NotificationState) { + /** Clickable notification */ + sealed interface Clickable { + + /** Lambda be invoked when notification is clicked */ + val onClick: () -> Unit + } + + /** "Development card" notification */ + object DevCard : WalletNotification( + state = NotificationState.Simple( + title = TextReference.Res(id = R.string.common_warning), + subtitle = TextReference.Res(id = R.string.alert_developer_card), + iconResId = R.drawable.ic_alert_circle_24, + tint = TangemColorPalette.Amaranth, + ), + ) + + /** "Test card" notification */ + object TestCard : WalletNotification( + state = NotificationState.Simple( + title = TextReference.Res(id = R.string.common_warning), + subtitle = TextReference.Res(id = R.string.warning_testnet_card_message), + iconResId = R.drawable.ic_alert_circle_24, + tint = TangemColorPalette.Amaranth, + ), + ) + + /** "Demo card" notification */ + object DemoCard : WalletNotification( + state = NotificationState.Simple( + title = TextReference.Res(id = R.string.common_warning), + subtitle = TextReference.Res(id = R.string.alert_demo_message), + iconResId = R.drawable.ic_alert_circle_24, + tint = TangemColorPalette.Amaranth, + ), + ) + + /** "Card verification failed" notification */ + object CardVerificationFailed : WalletNotification( + state = NotificationState.Simple( + title = TextReference.Res(id = R.string.warning_failed_to_verify_card_title), + subtitle = TextReference.Res(id = R.string.warning_failed_to_verify_card_message), + iconResId = R.drawable.ic_alert_circle_24, + tint = TangemColorPalette.Amaranth, + ), + ) + + /** + * "Wallet already signed hashes" notification + * + * @property onClick lambda be invoked when notification is clicked + */ + data class WalletAlreadySignedHashes(override val onClick: () -> Unit) : Clickable, WalletNotification( + state = NotificationState.Clickable( + title = TextReference.Res(id = R.string.common_warning), + subtitle = TextReference.Res(id = R.string.alert_card_signed_transactions), + iconResId = R.drawable.img_attention_20, + onClick = onClick, + tint = null, + ), + ) + + /** + * "Multi wallet already signed hashes" notification + * + * @property onClick lambda be invoked when notification is clicked + */ + data class MultiWalletAlreadySignedHashes(override val onClick: () -> Unit) : Clickable, WalletNotification( + state = NotificationState.Clickable( + title = TextReference.Res( + id = R.string.warning_important_security_info, + formatArgs = WrappedList(listOf("\u26A0")), + ), + subtitle = TextReference.Res(id = R.string.warning_signed_tx_previously), + iconResId = R.drawable.img_attention_20, + onClick = onClick, + tint = null, + ), + ) + /** * "Backup the card" notification * * @property onClick lambda be invoked when notification is clicked */ - data class NeedToBackup(val onClick: () -> Unit) : WalletNotification( - state = NotificationState.Action( - title = "Backup your card", - iconResId = R.drawable.ic_alert_circle_24, + data class BackupCard(override val onClick: () -> Unit) : Clickable, WalletNotification( + state = NotificationState.Clickable( + title = TextReference.Str(value = "Backup your card"), + iconResId = R.drawable.img_attention_20, onClick = onClick, - tint = TangemColorPalette.Amaranth, + tint = null, ), ) /** "Unreachable networks" notification */ object UnreachableNetworks : WalletNotification( state = NotificationState.Simple( - title = "Some networks are unreachable", + title = TextReference.Str(value = "Some networks are unreachable"), iconResId = R.drawable.img_attention_20, tint = null, ), @@ -41,9 +124,9 @@ sealed class WalletNotification(open val state: NotificationState) { * * @property onClick lambda be invoked when notification is clicked */ - data class LikeTangemApp(val onClick: () -> Unit) : WalletNotification( - state = NotificationState.Action( - title = "Like Tangem App?", + data class LikeTangemApp(override val onClick: () -> Unit) : Clickable, WalletNotification( + state = NotificationState.Clickable( + title = TextReference.Str(value = "Like Tangem App?"), iconResId = R.drawable.ic_star_24, onClick = onClick, tint = TangemColorPalette.Tangerine, @@ -55,11 +138,24 @@ sealed class WalletNotification(open val state: NotificationState) { * * @property onClick lambda be invoked when notification is clicked */ - data class ScanCard(val onClick: () -> Unit) : WalletNotification( - state = NotificationState.Action( - title = "Scan your card to continue", + data class ScanCard(override val onClick: () -> Unit) : Clickable, WalletNotification( + state = NotificationState.Clickable( + title = TextReference.Str(value = "Scan your card to continue"), iconResId = R.drawable.ic_tangem_24, onClick = onClick, ), ) + + /** + * "Unlock wallets" notification + * + * @property onClick lambda be invoked when notification is clicked + */ + data class UnlockWallets(override val onClick: () -> Unit) : Clickable, WalletNotification( + state = NotificationState.Clickable( + title = TextReference.Str(value = "Unlock needed"), + iconResId = R.drawable.ic_locked_24, + onClick = onClick, + ), + ) } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletStateHolder.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletStateHolder.kt index c4b9c37ee8..66785bd0ee 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletStateHolder.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletStateHolder.kt @@ -23,6 +23,7 @@ internal sealed class WalletStateHolder( open val pullToRefreshConfig: WalletPullToRefreshConfig, open val contentItems: ImmutableList, open val notifications: ImmutableList, + open val bottomSheet: WalletBottomSheetConfig? = null, ) { /** @@ -43,6 +44,7 @@ internal sealed class WalletStateHolder( override val pullToRefreshConfig: WalletPullToRefreshConfig, override val contentItems: ImmutableList, override val notifications: ImmutableList, + override val bottomSheet: WalletBottomSheetConfig, val onOrganizeTokensClick: () -> Unit, ) : WalletStateHolder( onBackClick = onBackClick, @@ -50,6 +52,7 @@ internal sealed class WalletStateHolder( walletsListConfig = walletsListConfig, pullToRefreshConfig = pullToRefreshConfig, contentItems = contentItems, + bottomSheet = bottomSheet, notifications = notifications, ) @@ -72,6 +75,7 @@ internal sealed class WalletStateHolder( override val pullToRefreshConfig: WalletPullToRefreshConfig, override val contentItems: ImmutableList, override val notifications: ImmutableList, + override val bottomSheet: WalletBottomSheetConfig, val buttons: ImmutableList, val marketPriceBlockState: MarketPriceBlockState, ) : WalletStateHolder( @@ -81,5 +85,6 @@ internal sealed class WalletStateHolder( pullToRefreshConfig = pullToRefreshConfig, contentItems = contentItems, notifications = notifications, + bottomSheet = bottomSheet, ) } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt index 42f5485b26..5f825b106f 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt @@ -13,16 +13,16 @@ import androidx.compose.material.pullrefresh.PullRefreshIndicator import androidx.compose.material.pullrefresh.pullRefresh import androidx.compose.material.pullrefresh.rememberPullRefreshState import androidx.compose.material3.* -import androidx.compose.runtime.Composable +import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider +import com.tangem.core.ui.components.buttons.HorizontalActionChips import com.tangem.core.ui.components.buttons.actions.ActionButtonConfig import com.tangem.core.ui.components.buttons.actions.RoundedActionButton -import com.tangem.core.ui.components.buttons.HorizontalActionChips import com.tangem.core.ui.components.marketprice.MarketPriceBlock import com.tangem.core.ui.components.notifications.Notification import com.tangem.core.ui.components.transactions.Transaction @@ -34,6 +34,7 @@ import com.tangem.feature.wallet.presentation.common.component.TokenItem import com.tangem.feature.wallet.presentation.common.state.TokenItemState import com.tangem.feature.wallet.presentation.wallet.state.WalletContentItemState import com.tangem.feature.wallet.presentation.wallet.state.WalletStateHolder +import com.tangem.feature.wallet.presentation.wallet.ui.components.WalletBottomSheet import com.tangem.feature.wallet.presentation.wallet.ui.components.WalletTopBar import com.tangem.feature.wallet.presentation.wallet.ui.components.WalletsList import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.TransactionsBlockGroupTitle @@ -159,6 +160,10 @@ internal fun WalletScreen(state: WalletStateHolder) { ) } } + + state.bottomSheet?.let { bottomSheetConfig -> + if (bottomSheetConfig.isShow) WalletBottomSheet(config = bottomSheetConfig) + } } @Composable diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletBottomSheet.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletBottomSheet.kt new file mode 100644 index 0000000000..45b7a7a752 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletBottomSheet.kt @@ -0,0 +1,161 @@ +package com.tangem.feature.wallet.presentation.wallet.ui.components + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.* +import androidx.compose.material3.* +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.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider +import com.tangem.core.ui.components.PrimaryButton +import com.tangem.core.ui.components.PrimaryButtonIconStart +import com.tangem.core.ui.components.SecondaryButton +import com.tangem.core.ui.components.SecondaryButtonIconStart +import com.tangem.core.ui.extensions.resolveReference +import com.tangem.core.ui.res.TangemTheme +import com.tangem.feature.wallet.presentation.common.WalletPreviewData +import com.tangem.feature.wallet.presentation.wallet.state.WalletBottomSheetConfig + +/** + * Wallet bottom sheet with detail notification information + * + * @param config component config + * +[REDACTED_AUTHOR] + */ +@OptIn(ExperimentalMaterial3Api::class) +@Composable +internal fun WalletBottomSheet(config: WalletBottomSheetConfig) { + ModalBottomSheet( + onDismissRequest = config.onDismissRequest, + sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true), + containerColor = TangemTheme.colors.background.primary, + dragHandle = { BottomSheetDefaults.DragHandle() }, + ) { + BottomSheetContent(config = config.content) + } +} + +@Composable +private fun BottomSheetContent(config: WalletBottomSheetConfig.BottomSheetContentConfig) { + Column( + modifier = Modifier + .padding(horizontal = TangemTheme.dimens.spacing16) + .padding(top = TangemTheme.dimens.spacing40, bottom = TangemTheme.dimens.spacing16), + verticalArrangement = Arrangement.spacedBy(space = TangemTheme.dimens.spacing40), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + val iconTint = config.tint + if (iconTint != null) { + Icon( + painter = painterResource(id = config.iconResId), + contentDescription = null, + modifier = Modifier.size(size = TangemTheme.dimens.size48), + tint = iconTint, + ) + } else { + Image( + painter = painterResource(id = config.iconResId), + contentDescription = null, + modifier = Modifier.size(size = TangemTheme.dimens.size48), + ) + } + + Text( + text = config.title.resolveReference(), + color = TangemTheme.colors.text.primary1, + textAlign = TextAlign.Center, + style = TangemTheme.typography.h2, + ) + + Text( + text = config.subtitle.resolveReference(), + color = TangemTheme.colors.text.secondary, + textAlign = TextAlign.Center, + style = TangemTheme.typography.body2, + ) + + Column(verticalArrangement = Arrangement.spacedBy(space = TangemTheme.dimens.spacing10)) { + val buttonModifier = Modifier.fillMaxWidth() + PrimaryButton(config = config.primaryButtonConfig, modifier = buttonModifier) + + if (config.secondaryButtonConfig != null) { + SecondaryButton(config = config.secondaryButtonConfig, modifier = buttonModifier) + } + } + } +} + +@Composable +private fun PrimaryButton( + config: WalletBottomSheetConfig.BottomSheetContentConfig.ButtonConfig, + modifier: Modifier = Modifier, +) { + if (config.iconResId == null) { + PrimaryButton( + text = config.text, + onClick = config.onClick, + modifier = modifier, + ) + } else { + PrimaryButtonIconStart( + text = config.text, + iconResId = config.iconResId, + onClick = config.onClick, + modifier = modifier, + ) + } +} + +@Composable +private fun SecondaryButton( + config: WalletBottomSheetConfig.BottomSheetContentConfig.ButtonConfig, + modifier: Modifier = Modifier, +) { + if (config.iconResId == null) { + SecondaryButton( + text = config.text, + onClick = config.onClick, + modifier = modifier, + ) + } else { + SecondaryButtonIconStart( + text = config.text, + iconResId = config.iconResId, + onClick = config.onClick, + modifier = modifier, + ) + } +} + +@Preview +@Composable +private fun WalletBottomSheetContent_Light( + @PreviewParameter(WalletBottomSheetConfigProvider::class) + config: WalletBottomSheetConfig, +) { + TangemTheme(isDark = false) { + // Use preview of content because ModalBottomSheet isn't supported in Preview mode + BottomSheetContent(config = config.content) + } +} + +@Preview +@Composable +private fun WalletBottomSheetContent_Dark( + @PreviewParameter(WalletBottomSheetConfigProvider::class) + config: WalletBottomSheetConfig, +) { + TangemTheme(isDark = false) { + // Use preview of content because ModalBottomSheet isn't supported in Preview mode + BottomSheetContent(config = config.content) + } +} + +private class WalletBottomSheetConfigProvider : CollectionPreviewParameterProvider( + collection = listOf(WalletPreviewData.bottomSheet), +) \ No newline at end of file