diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt index 095b4f721e..cc04f6f0ba 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt @@ -75,6 +75,8 @@ class GetCryptoCurrencyActionsUseCase( } else { add(TokenActionsState.ActionState.Buy(false)) } + + addFirst(TokenActionsState.ActionState.CopyAddress(true)) } } diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/model/TokenActionsState.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/model/TokenActionsState.kt index d755f0c68b..96f2678982 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/model/TokenActionsState.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/model/TokenActionsState.kt @@ -14,6 +14,8 @@ data class TokenActionsState( data class Buy(override val enabled: Boolean) : ActionState() + data class CopyAddress(override val enabled: Boolean) : ActionState() + data class Sell(override val enabled: Boolean) : ActionState() data class Receive(override val enabled: Boolean) : ActionState() diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsActionButtonsConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsActionButtonsConverter.kt index 3cd4b2e4de..ce22626609 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsActionButtonsConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsActionButtonsConverter.kt @@ -23,7 +23,7 @@ internal class TokenDetailsActionButtonsConverter( private fun List.mapToManageButtons(): ImmutableList { return this - .map { action -> + .mapNotNull { action -> when (action) { is TokenActionsState.ActionState.Buy -> { TokenDetailsActionButton.Buy(enabled = action.enabled, onClick = clickIntents::onBuyClick) @@ -40,6 +40,9 @@ internal class TokenDetailsActionButtonsConverter( is TokenActionsState.ActionState.Swap -> { TokenDetailsActionButton.Swap(enabled = action.enabled, onClick = clickIntents::onSwapClick) } + else -> { + null + } } } .toImmutableList() diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletEvent.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletEvent.kt index 61c176f094..1c1ccaaceb 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletEvent.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletEvent.kt @@ -9,4 +9,8 @@ internal sealed class WalletEvent { data class ChangeWallet(val index: Int) : WalletEvent() data class ShowError(val text: TextReference) : WalletEvent() + + data class ShowToast(val text: TextReference) : WalletEvent() + + data class CopyAddress(val address: String) : WalletEvent() } \ No newline at end of file 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 index d3e51d1d76..e10de613d6 100644 --- 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 @@ -1,5 +1,6 @@ package com.tangem.feature.wallet.presentation.wallet.state.factory +import com.tangem.common.extensions.isZero import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resourceReference import com.tangem.domain.tokens.model.CryptoCurrencyStatus @@ -22,14 +23,21 @@ internal class TokenActionsProvider(private val clickIntents: WalletClickIntents fun provideActions(tokenActions: TokenActionsState): ImmutableList { return tokenActions.states - .map { mapTokenActionState(it, tokenActions.cryptoCurrencyStatus) } + .mapNotNull { + mapTokenActionState(it, tokenActions.cryptoCurrencyStatus) + } .toImmutableList() } private fun mapTokenActionState( actionsState: TokenActionsState.ActionState, cryptoCurrencyStatus: CryptoCurrencyStatus, - ): TokenActionButtonConfig { + ): TokenActionButtonConfig? { + if (actionsState is TokenActionsState.ActionState.Send && + cryptoCurrencyStatus.value.amount?.isZero() == true + ) { + return null + } val title: TextReference val icon: Int val action: () -> Unit @@ -59,6 +67,11 @@ internal class TokenActionsProvider(private val clickIntents: WalletClickIntents icon = R.drawable.ic_exchange_horizontal_24 action = { clickIntents.onSwapClick(cryptoCurrencyStatus) } } + is TokenActionsState.ActionState.CopyAddress -> { + title = resourceReference(R.string.common_copy_address) + icon = R.drawable.ic_copy_24 + action = { clickIntents.onCopyAddressClick(cryptoCurrencyStatus) } + } } return TokenActionButtonConfig( text = title, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletCryptoCurrencyActionsConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletCryptoCurrencyActionsConverter.kt index e347773cc5..eb2400e286 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletCryptoCurrencyActionsConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/WalletCryptoCurrencyActionsConverter.kt @@ -53,7 +53,9 @@ internal class WalletCryptoCurrencyActionsConverter( onClick = { clickIntents.onSingleCurrencySendClick(cryptoCurrencyStatus) }, ) } - is TokenActionsState.ActionState.Swap -> null + else -> { + null + } } } .toPersistentList() diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletEventEffect.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletEventEffect.kt index 7406cf8cab..914ae8de38 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletEventEffect.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletEventEffect.kt @@ -1,9 +1,12 @@ package com.tangem.feature.wallet.presentation.wallet.ui +import android.widget.Toast import androidx.compose.foundation.lazy.LazyListState import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalClipboardManager import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.AnnotatedString import com.tangem.core.ui.event.EventEffect import com.tangem.core.ui.event.StateEvent import com.tangem.core.ui.extensions.resolveReference @@ -16,7 +19,9 @@ internal fun WalletEventEffect( event: StateEvent, onAutoScrollSet: () -> Unit, ) { + val context = LocalContext.current val resources = LocalContext.current.resources + val clipboardManager = LocalClipboardManager.current EventEffect( event = event, onTrigger = { value -> @@ -28,6 +33,12 @@ internal fun WalletEventEffect( is WalletEvent.ShowError -> { snackbarHostState.showSnackbar(message = value.text.resolveReference(resources)) } + is WalletEvent.ShowToast -> { + Toast.makeText(context, value.text.resolveReference(resources), Toast.LENGTH_SHORT).show() + } + is WalletEvent.CopyAddress -> { + clipboardManager.setText(AnnotatedString(value.address)) + } } }, ) 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 index 7037bcdd39..bf7208a505 100644 --- 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 @@ -38,12 +38,14 @@ private fun ActionsBottomSheetContent(actions: ImmutableList - SimpleSettingsRow( - title = action.text.resolveReference(), - icon = action.iconResId, - enabled = action.enabled, - onItemsClick = action.onClick, - ) + if (action.enabled) { + SimpleSettingsRow( + title = action.text.resolveReference(), + icon = action.iconResId, + enabled = action.enabled, + onItemsClick = action.onClick, + ) + } } } } 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 4e7d1b3d34..de962fb838 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 @@ -51,6 +51,8 @@ internal interface WalletClickIntents { fun onReceiveClick(cryptoCurrencyStatus: CryptoCurrencyStatus) + fun onCopyAddressClick(cryptoCurrencyStatus: CryptoCurrencyStatus) + fun onSellClick(cryptoCurrencyStatus: CryptoCurrencyStatus) fun onManageTokensClick() 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 3cd1221d97..3621c26e28 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 @@ -5,6 +5,7 @@ import androidx.paging.cachedIn import arrow.core.getOrElse import com.tangem.blockchain.blockchains.cardano.CardanoUtils import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchain.common.address.AddressType import com.tangem.common.Provider import com.tangem.common.card.EllipticCurve import com.tangem.common.doOnFailure @@ -16,6 +17,7 @@ import com.tangem.core.navigation.AppScreen import com.tangem.core.ui.components.bottomsheets.tokenreceive.AddressModel import com.tangem.core.ui.components.bottomsheets.tokenreceive.TokenReceiveBottomSheetConfig import com.tangem.core.ui.components.marketprice.MarketPriceBlockState +import com.tangem.core.ui.extensions.resourceReference import com.tangem.crypto.hdWallet.DerivationPath import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency @@ -45,6 +47,7 @@ import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.models.UserWalletId import com.tangem.domain.wallets.usecase.* +import com.tangem.feature.wallet.impl.R import com.tangem.feature.wallet.presentation.common.state.TokenItemState import com.tangem.feature.wallet.presentation.router.InnerWalletRouter import com.tangem.feature.wallet.presentation.wallet.analytics.PortfolioEvent @@ -595,6 +598,32 @@ internal class WalletViewModel @Inject constructor( } } + override fun onCopyAddressClick(cryptoCurrencyStatus: CryptoCurrencyStatus) { + val state = uiState as? WalletState.ContentState ?: return + + viewModelScope.launch(dispatchers.main) { + val userWallet = getWallet(index = state.walletsListConfig.selectedWalletIndex) + + val defaultAddress = walletManagersFacade.getAddress( + userWalletId = userWallet.walletId, + network = cryptoCurrencyStatus.currency.network, + ).find { it.type == AddressType.Default } + + defaultAddress?.value?.let { address -> + uiState = stateFactory.getStateAndTriggerEvent( + state = uiState, + event = WalletEvent.CopyAddress(address), + setUiState = { uiState = it }, + ) + uiState = stateFactory.getStateAndTriggerEvent( + state = uiState, + event = WalletEvent.ShowToast(resourceReference(R.string.wallet_notification_address_copied)), + setUiState = { uiState = it }, + ) + } + } + } + override fun onSellClick(cryptoCurrencyStatus: CryptoCurrencyStatus) { reduxStateHolder.dispatch( TradeCryptoAction.New.Sell(