From dd9d7f2e45ae9e2bb59cec3ec4bd6c14d20f92f1 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 21 Aug 2023 19:14:02 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../tangem/core/ui/components/SettingsRow.kt | 74 ++++++++++++++++++ .../presentation/common/WalletPreviewData.kt | 36 ++++++--- .../common/component/TokenItem.kt | 25 ++++-- .../common/state/TokenItemState.kt | 6 +- .../wallet/state/ActionsBottomSheetConfig.kt | 17 +++++ .../wallet/state/TokenActionButtonConfig.kt | 18 +++++ .../wallet/state/WalletMultiCurrencyState.kt | 1 + .../state/factory/TokenActionsProvider.kt | 52 +++++++++++++ .../factory/WalletSkeletonStateConverter.kt | 1 + .../state/factory/WalletStateFactory.kt | 25 ++++-- .../presentation/wallet/ui/WalletScreen.kt | 16 +++- .../ui/components/TokenActionsBottomSheet.kt | 76 +++++++++++++++++++ ...ryptoCurrencyStatusToTokenItemConverter.kt | 3 +- .../wallet/viewmodels/WalletClickIntents.kt | 8 +- .../wallet/viewmodels/WalletViewModel.kt | 30 ++++++-- 15 files changed, 351 insertions(+), 37 deletions(-) create mode 100644 core/ui/src/main/java/com/tangem/core/ui/components/SettingsRow.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/ActionsBottomSheetConfig.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/TokenActionButtonConfig.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/TokenActionsProvider.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/TokenActionsBottomSheet.kt diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/SettingsRow.kt b/core/ui/src/main/java/com/tangem/core/ui/components/SettingsRow.kt new file mode 100644 index 0000000000..823a93b8e3 --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/components/SettingsRow.kt @@ -0,0 +1,74 @@ +package com.tangem.core.ui.components + +import androidx.annotation.DrawableRes +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.animateColorAsState +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.material.Icon +import androidx.compose.material.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.graphics.Color +import androidx.compose.ui.res.painterResource +import com.tangem.core.ui.res.TangemTheme + +/** + * [Show in Figma](https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?type=design&node-id=281-248&mode=design&t=bXqehWPHyATKcZEW-4) + * */ +@Composable +fun SimpleSettingsRow( + title: String, + @DrawableRes icon: Int, + onItemsClick: () -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + subtitle: String? = null, +) { + Row( + modifier = modifier + .height(TangemTheme.dimens.size56) + .fillMaxWidth() + .clickable( + onClick = { + if (enabled) { + onItemsClick() + } + }, + ), + horizontalArrangement = Arrangement.Start, + verticalAlignment = Alignment.CenterVertically, + ) { + val textColor: Color by animateColorAsState( + targetValue = if (enabled) { + TangemTheme.colors.text.primary1 + } else { + TangemTheme.colors.text.secondary + }, + ) + Icon( + painter = painterResource(id = icon), + contentDescription = null, + modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing20), + tint = textColor, + ) + Column(modifier = Modifier.padding(end = TangemTheme.dimens.spacing20)) { + Text( + text = title, + style = TangemTheme.typography.subtitle1, + color = textColor, + ) + AnimatedVisibility( + visible = !subtitle.isNullOrEmpty(), + ) { + Text( + text = subtitle ?: "", + style = TangemTheme.typography.body2, + color = TangemTheme.colors.text.secondary, + ) + } + } + } +} \ No newline at end of file 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 aaa70af11f..f076a7996d 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 @@ -18,6 +18,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.* import com.tangem.feature.wallet.presentation.wallet.state.components.* import com.tangem.feature.wallet.presentation.wallet.state.components.WalletTokensListState.TokensListItemState import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.flow.MutableStateFlow import java.util.UUID @@ -99,7 +100,8 @@ internal object WalletPreviewData { ), ), isTestnet = false, - onClick = {}, + onItemClick = {}, + onItemLongClick = {}, ) } @@ -126,7 +128,8 @@ internal object WalletPreviewData { ), ), isTestnet = false, - onClick = {}, + onItemClick = {}, + onItemLongClick = {}, ) } @@ -258,15 +261,25 @@ internal object WalletPreviewData { ) } - private val manageButtons by lazy { - persistentListOf( - WalletManageButton.Buy(onClick = {}), - WalletManageButton.Send(onClick = {}), - WalletManageButton.Receive(onClick = {}), - WalletManageButton.Exchange(onClick = {}), - WalletManageButton.CopyAddress(onClick = {}), - ) - } + val actionsBottomSheet = ActionsBottomSheetConfig( + isShow = true, + onDismissRequest = {}, + actions = listOf( + TokenActionButtonConfig( + text = "Send", + iconResId = R.drawable.ic_share_24, + onClick = {}, + ), + ).toImmutableList(), + ) + + private val manageButtons = persistentListOf( + WalletManageButton.Buy(onClick = {}), + WalletManageButton.Send(onClick = {}), + WalletManageButton.Receive(onClick = {}), + WalletManageButton.Exchange(onClick = {}), + WalletManageButton.CopyAddress(onClick = {}), + ) val multicurrencyWalletScreenState by lazy { WalletMultiCurrencyState.Content( @@ -336,6 +349,7 @@ internal object WalletPreviewData { WalletNotification.ScanCard(onClick = {}), ), bottomSheetConfig = bottomSheet, + tokenActionsBottomSheet = actionsBottomSheet, ) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/TokenItem.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/TokenItem.kt index b3cdc8cda7..84efe5f86a 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/TokenItem.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/TokenItem.kt @@ -4,8 +4,10 @@ import androidx.annotation.DrawableRes import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape @@ -21,7 +23,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.ColorMatrix +import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview @@ -65,11 +69,18 @@ internal fun TokenItem(state: TokenItemState, modifier: Modifier = Modifier) { } } +@OptIn(ExperimentalFoundationApi::class) @Composable private fun ContentTokenItem(content: TokenItemState.Content, modifier: Modifier = Modifier) { + val hapticFeedback = LocalHapticFeedback.current InternalTokenItem( - modifier = modifier, - onClick = content.onClick, + modifier = modifier.combinedClickable( + onClick = content.onItemClick, + onLongClick = { + hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) + content.onItemLongClick() + }, + ), name = content.name, tokenIconUrl = content.tokenIconUrl, tokenIconResId = content.tokenIconResId, @@ -300,15 +311,15 @@ private fun InternalTokenItem( options: @Composable ConstraintLayoutScope.(ref: ConstrainedLayoutReference) -> Unit, modifier: Modifier = Modifier, isTestnet: Boolean = false, - onClick: (() -> Unit)? = null, ) { - BaseSurface( - modifier = modifier, - onClick = onClick, + Box( + modifier = modifier + .defaultMinSize(minHeight = TOKEN_ITEM_HEIGHT) + .background(color = TangemTheme.colors.background.primary), ) { ConstraintLayout( modifier = Modifier - .fillMaxWidth() + .fillMaxSize() .padding( horizontal = TangemTheme.dimens.spacing14, vertical = TangemTheme.dimens.spacing4, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/state/TokenItemState.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/state/TokenItemState.kt index 90645c7c40..d732e148c0 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/state/TokenItemState.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/state/TokenItemState.kt @@ -28,7 +28,8 @@ internal sealed interface TokenItemState { * @property hasPending pending tx in blockchain * @property tokenOptions state for token options * @property isTestnet indicates whether the token is from test network or not - * @property onClick callback which will be called when an item is clicked + * @property onItemClick callback which will be called when an item is clicked + * @property onItemLongClick callback which will be called when an item is long clicked */ data class Content( override val id: String, @@ -40,7 +41,8 @@ internal sealed interface TokenItemState { val hasPending: Boolean, val tokenOptions: TokenOptionsState, val isTestnet: Boolean, - val onClick: () -> Unit, + val onItemClick: () -> Unit, + val onItemLongClick: () -> Unit, ) : TokenItemState /** diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/ActionsBottomSheetConfig.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/ActionsBottomSheetConfig.kt new file mode 100644 index 0000000000..cb7e79cee3 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/ActionsBottomSheetConfig.kt @@ -0,0 +1,17 @@ +package com.tangem.feature.wallet.presentation.wallet.state + +import kotlinx.collections.immutable.ImmutableList + +/** + * Config for the token actions bottom sheet + * + * @property isShow flag that determine if bottom sheet is shown + * @property onDismissRequest lambda be invoked when bottom sheet is dismissed + * @property actions actions + * + */ +internal data class ActionsBottomSheetConfig( + val isShow: Boolean, + val onDismissRequest: () -> Unit, + val actions: ImmutableList, +) \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/TokenActionButtonConfig.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/TokenActionButtonConfig.kt new file mode 100644 index 0000000000..934bfd6230 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/TokenActionButtonConfig.kt @@ -0,0 +1,18 @@ +package com.tangem.feature.wallet.presentation.wallet.state + +import androidx.annotation.DrawableRes + +/** + * Action button config + * + * @property text text + * @property iconResId icon resource id + * @property onClick lambda be invoked when action component is clicked + * @property enabled enabled + */ +data class TokenActionButtonConfig( + val text: String, + @DrawableRes val iconResId: Int, + val onClick: () -> Unit, + val enabled: Boolean = true, +) \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletMultiCurrencyState.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletMultiCurrencyState.kt index 87d675cd95..def8561d02 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletMultiCurrencyState.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletMultiCurrencyState.kt @@ -22,6 +22,7 @@ internal sealed class WalletMultiCurrencyState : WalletState.ContentState() { override val notifications: ImmutableList, override val bottomSheetConfig: WalletBottomSheetConfig?, override val tokensListState: WalletTokensListState, + val tokenActionsBottomSheet: ActionsBottomSheetConfig?, ) : WalletMultiCurrencyState() data class Locked( diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/TokenActionsProvider.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/TokenActionsProvider.kt new file mode 100644 index 0000000000..f9a7dbfc4e --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/TokenActionsProvider.kt @@ -0,0 +1,52 @@ +package com.tangem.feature.wallet.presentation.wallet.state.factory + +import com.tangem.common.Provider +import com.tangem.feature.wallet.impl.R +import com.tangem.feature.wallet.presentation.common.state.TokenItemState +import com.tangem.feature.wallet.presentation.wallet.state.TokenActionButtonConfig +import com.tangem.feature.wallet.presentation.wallet.state.WalletState +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.toImmutableList + +/** + * Converter from loaded [TokenItemState.Content] to ImmutableList<[TokenActionButtonConfig]> + * + * @property currentStateProvider current ui state provider + * + */ +@Suppress("UnusedPrivateMember") +internal class TokenActionsProvider( + private val currentStateProvider: Provider, +) { + + @Suppress("UnusedPrivateMember") + fun provideActions(tokenId: String): ImmutableList { + // TODO: [REDACTED_JIRA] + return mockTokenActionButtonConfig().toImmutableList() + } + + private fun mockTokenActionButtonConfig(): List { + return listOf( + TokenActionButtonConfig( + text = "Send", + iconResId = R.drawable.ic_plus_24, + onClick = {}, + ), + TokenActionButtonConfig( + text = "Buy", + iconResId = R.drawable.ic_plus_24, + onClick = {}, + ), + TokenActionButtonConfig( + text = "Sell", + iconResId = R.drawable.ic_plus_24, + onClick = {}, + ), + TokenActionButtonConfig( + text = "Swap", + iconResId = R.drawable.ic_plus_24, + onClick = {}, + ), + ) + } +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletSkeletonStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletSkeletonStateConverter.kt index 39f68f74c4..10026ccc62 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletSkeletonStateConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletSkeletonStateConverter.kt @@ -51,6 +51,7 @@ internal class WalletSkeletonStateConverter( tokensListState = WalletTokensListState.Loading(), notifications = persistentListOf(), bottomSheetConfig = null, + tokenActionsBottomSheet = null, ) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletStateFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletStateFactory.kt index c7d6ed7cd6..200a79c740 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletStateFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletStateFactory.kt @@ -14,6 +14,7 @@ import com.tangem.domain.txhistory.models.TxHistoryListError import com.tangem.domain.txhistory.models.TxHistoryStateError import com.tangem.domain.wallets.models.UserWallet import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory +import com.tangem.feature.wallet.presentation.wallet.state.ActionsBottomSheetConfig import com.tangem.feature.wallet.presentation.wallet.state.WalletMultiCurrencyState import com.tangem.feature.wallet.presentation.wallet.state.WalletSingleCurrencyState import com.tangem.feature.wallet.presentation.wallet.state.WalletState @@ -45,6 +46,7 @@ internal class WalletStateFactory( private val clickIntents: WalletClickIntents, ) { + private val tokenActionsProvider by lazy { TokenActionsProvider(currentStateProvider = currentStateProvider) } private val skeletonConverter by lazy { WalletSkeletonStateConverter(currentStateProvider, clickIntents) } private val loadedTokensListConverter by lazy { @@ -119,29 +121,29 @@ internal class WalletStateFactory( fun getStateAfterContentRefreshing(): WalletState = refreshStateConverter.convert(Unit) - fun getStateWithOpenBottomSheet(content: WalletBottomSheetConfig.BottomSheetContentConfig): WalletState { + fun getStateWithOpenWalletBottomSheet(content: WalletBottomSheetConfig.BottomSheetContentConfig): WalletState { return when (val state = currentStateProvider() as WalletState.ContentState) { is WalletMultiCurrencyState.Content -> state.copy( bottomSheetConfig = WalletBottomSheetConfig( isShow = true, - onDismissRequest = clickIntents::onBottomSheetDismiss, + onDismissRequest = clickIntents::onDismissBottomSheet, content = content, ), ) is WalletMultiCurrencyState.Locked -> state.copy( isBottomSheetShow = true, - onBottomSheetDismiss = clickIntents::onBottomSheetDismiss, + onBottomSheetDismiss = clickIntents::onDismissBottomSheet, ) is WalletSingleCurrencyState.Content -> state.copy( bottomSheetConfig = WalletBottomSheetConfig( isShow = true, - onDismissRequest = clickIntents::onBottomSheetDismiss, + onDismissRequest = clickIntents::onDismissBottomSheet, content = content, ), ) is WalletSingleCurrencyState.Locked -> state.copy( isBottomSheetShow = true, - onBottomSheetDismiss = clickIntents::onBottomSheetDismiss, + onBottomSheetDismiss = clickIntents::onDismissBottomSheet, ) } } @@ -159,6 +161,19 @@ internal class WalletStateFactory( } } + fun getStateWithTokenActionBottomSheet(tokenId: String): WalletState { + return when (val state = currentStateProvider() as WalletState.ContentState) { + is WalletMultiCurrencyState.Content -> state.copy( + tokenActionsBottomSheet = ActionsBottomSheetConfig( + isShow = true, + actions = tokenActionsProvider.provideActions(tokenId = tokenId), + onDismissRequest = clickIntents::onDismissActionsBottomSheet, + ), + ) + else -> state + } + } + fun getLoadingTxHistoryState(itemsCountEither: Either): WalletState { return loadingTransactionsStateConverter.convert(value = itemsCountEither) } 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 8c94b30d15..fa7dc84810 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 @@ -23,6 +23,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.WalletMultiCurrencySt import com.tangem.feature.wallet.presentation.wallet.state.WalletSingleCurrencyState import com.tangem.feature.wallet.presentation.wallet.state.WalletState import com.tangem.feature.wallet.presentation.wallet.state.components.WalletTokensListState +import com.tangem.feature.wallet.presentation.wallet.ui.components.TokenActionsBottomSheet import com.tangem.feature.wallet.presentation.wallet.ui.components.WalletsList import com.tangem.feature.wallet.presentation.wallet.ui.components.common.* import com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency.organizeButton @@ -122,12 +123,23 @@ private fun WalletContent(state: WalletState.ContentState) { } } - val bottomSheetConfig = state.bottomSheetConfig + WalletBottomSheets(state = state) + + WalletSideEffects(lazyListState = walletsListState, walletsListConfig = state.walletsListConfig) +} + +@Composable +private fun WalletBottomSheets(state: WalletState) { + val bottomSheetConfig = (state as? WalletState.ContentState)?.bottomSheetConfig if (bottomSheetConfig != null && bottomSheetConfig.isShow) { WalletBottomSheet(config = bottomSheetConfig) } - WalletSideEffects(lazyListState = walletsListState, walletsListConfig = state.walletsListConfig) + (state as? WalletMultiCurrencyState.Content)?.let { multiCurrencyState -> + if (multiCurrencyState.tokenActionsBottomSheet != null && multiCurrencyState.tokenActionsBottomSheet.isShow) { + TokenActionsBottomSheet(config = multiCurrencyState.tokenActionsBottomSheet) + } + } } // region Preview diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/TokenActionsBottomSheet.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/TokenActionsBottomSheet.kt new file mode 100644 index 0000000000..a79d41bb23 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/TokenActionsBottomSheet.kt @@ -0,0 +1,76 @@ +package com.tangem.feature.wallet.presentation.wallet.ui.components + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.material3.BottomSheetDefaults +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.rememberModalBottomSheetState +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +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.SimpleSettingsRow +import com.tangem.core.ui.res.TangemTheme +import com.tangem.feature.wallet.presentation.common.WalletPreviewData +import com.tangem.feature.wallet.presentation.wallet.state.ActionsBottomSheetConfig +import com.tangem.feature.wallet.presentation.wallet.state.TokenActionButtonConfig +import kotlinx.collections.immutable.ImmutableList + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +internal fun TokenActionsBottomSheet(config: ActionsBottomSheetConfig) { + ModalBottomSheet( + onDismissRequest = config.onDismissRequest, + sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true), + containerColor = TangemTheme.colors.background.primary, + dragHandle = { BottomSheetDefaults.DragHandle() }, + ) { + ActionsBottomSheetContent(config.actions) + } +} + +@Composable +private fun ActionsBottomSheetContent(actions: ImmutableList) { + Column( + modifier = Modifier.background(TangemTheme.colors.background.primary), + ) { + actions.forEach { action -> + SimpleSettingsRow( + title = action.text, + icon = action.iconResId, + enabled = action.enabled, + onItemsClick = action.onClick, + ) + } + } +} + +@Preview +@Composable +private fun ActionsBottomSheetContent_Light( + @PreviewParameter(ActionsBottomSheetContentConfigProvider::class) + config: ActionsBottomSheetConfig, +) { + TangemTheme(isDark = false) { + // Use preview of content because ModalBottomSheet isn't supported in Preview mode + ActionsBottomSheetContent(actions = config.actions) + } +} + +@Preview +@Composable +private fun ActionsBottomSheetContent_Dark( + @PreviewParameter(ActionsBottomSheetContentConfigProvider::class) + config: ActionsBottomSheetConfig, +) { + TangemTheme(isDark = false) { + // Use preview of content because ModalBottomSheet isn't supported in Preview mode + ActionsBottomSheetContent(actions = config.actions) + } +} + +private class ActionsBottomSheetContentConfigProvider : CollectionPreviewParameterProvider( + collection = listOf(WalletPreviewData.actionsBottomSheet), +) \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/utils/CryptoCurrencyStatusToTokenItemConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/utils/CryptoCurrencyStatusToTokenItemConverter.kt index 292c7aca8e..5c860ab3e5 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/utils/CryptoCurrencyStatusToTokenItemConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/utils/CryptoCurrencyStatusToTokenItemConverter.kt @@ -51,7 +51,8 @@ internal class CryptoCurrencyStatusToTokenItemConverter( ) }, isTestnet = currency.network.isTestnet, - onClick = { clickIntents.onTokenClick(currency) }, + onItemClick = { clickIntents.onTokenItemClick(currency) }, + onItemLongClick = { clickIntents.onTokenItemLongClick(currency) }, ) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletClickIntents.kt index ccb9eeeb22..ad201200ed 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletClickIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletClickIntents.kt @@ -35,9 +35,13 @@ internal interface WalletClickIntents : TxHistoryClickIntents { fun onUnlockWalletNotificationClick() - fun onBottomSheetDismiss() + fun onDismissBottomSheet() - fun onTokenClick(currency: CryptoCurrency) + fun onTokenItemClick(currency: CryptoCurrency) + + fun onTokenItemLongClick(currency: CryptoCurrency) + + fun onDismissActionsBottomSheet() fun onRenameClick(userWalletId: UserWalletId, name: String) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt index af6c22462d..551b652d6d 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt @@ -296,7 +296,7 @@ internal class WalletViewModel @Inject constructor( override fun onBackupCardClick() = router.openOnboardingScreen() override fun onCriticalWarningAlreadySignedHashesClick() { - uiState = stateFactory.getStateWithOpenBottomSheet( + uiState = stateFactory.getStateWithOpenWalletBottomSheet( content = WalletBottomSheetConfig.BottomSheetContentConfig.CriticalWarningAlreadySignedHashes( onOkClick = {}, onCancelClick = {}, @@ -309,7 +309,7 @@ internal class WalletViewModel @Inject constructor( } override fun onLikeTangemAppClick() { - uiState = stateFactory.getStateWithOpenBottomSheet( + uiState = stateFactory.getStateWithOpenWalletBottomSheet( content = WalletBottomSheetConfig.BottomSheetContentConfig.LikeTangemApp( onRateTheAppClick = ::onRateTheAppClick, onShareClick = ::onShareClick, @@ -445,7 +445,7 @@ internal class WalletViewModel @Inject constructor( "Impossible to unlock wallet if state isn't WalletLockedState" } - uiState = stateFactory.getStateWithOpenBottomSheet( + uiState = stateFactory.getStateWithOpenWalletBottomSheet( content = when (state) { is WalletMultiCurrencyState.Locked -> state.bottomSheetConfig.content is WalletSingleCurrencyState.Locked -> state.bottomSheetConfig.content @@ -453,12 +453,14 @@ internal class WalletViewModel @Inject constructor( ) } - override fun onBottomSheetDismiss() { - uiState = stateFactory.getStateWithClosedBottomSheet() + override fun onTokenItemClick(currency: CryptoCurrency) { + router.openTokenDetails(currency = currency) } - override fun onTokenClick(currency: CryptoCurrency) { - router.openTokenDetails(currency = currency) + override fun onTokenItemLongClick(currency: CryptoCurrency) { + uiState = stateFactory.getStateWithTokenActionBottomSheet( + tokenId = currency.id.value, + ) } override fun onRenameClick(userWalletId: UserWalletId, name: String) { @@ -484,4 +486,18 @@ internal class WalletViewModel @Inject constructor( initialValue = AppCurrency.Default, ) } + + override fun onDismissBottomSheet() { + uiState = stateFactory.getStateWithClosedBottomSheet() + } + + override fun onDismissActionsBottomSheet() { + (uiState as? WalletMultiCurrencyState.Content)?.let { state -> + uiState = state.copy( + tokenActionsBottomSheet = state.tokenActionsBottomSheet?.copy( + isShow = false, + ), + ) + } + } } \ No newline at end of file