From 776cb482adf6cc02a7ad90d08f7df0381a7604a6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 26 Sep 2023 13:20:05 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../tap/di/domain/TokensDomainModule.kt | 10 +++ core/ui/src/main/res/drawable/ic_trash_24.xml | 9 +++ .../tokens/GetCryptoCurrencyActionsUseCase.kt | 12 ++- .../IsCryptoCurrencyCoinCouldHideUseCase.kt | 17 +++++ .../domain/tokens/model/TokenActionsState.kt | 2 + .../wallet/state/WalletAlertState.kt | 7 ++ .../presentation/wallet/state/WalletEvent.kt | 6 ++ .../state/factory/TokenActionsProvider.kt | 5 ++ .../presentation/wallet/ui/WalletAlert.kt | 36 +++++++++ .../wallet/ui/WalletEventEffect.kt | 9 +++ .../wallet/viewmodels/WalletClickIntents.kt | 4 + .../wallet/viewmodels/WalletViewModel.kt | 74 +++++++++++++++++++ 12 files changed, 189 insertions(+), 2 deletions(-) create mode 100644 core/ui/src/main/res/drawable/ic_trash_24.xml create mode 100644 domain/tokens/src/main/kotlin/com/tangem/domain/tokens/IsCryptoCurrencyCoinCouldHideUseCase.kt diff --git a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt index 352c3c3353..42546775f3 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt @@ -157,4 +157,14 @@ internal object TokensDomainModule { fun provideGetCurrenciesUseCase(currenciesRepository: CurrenciesRepository): GetCryptoCurrenciesUseCase { return GetCryptoCurrenciesUseCase(currenciesRepository = currenciesRepository) } + + @Provides + @ViewModelScoped + fun provideIsCryptoCurrencyCoinCouldHideUseCase( + currenciesRepository: CurrenciesRepository, + ): IsCryptoCurrencyCoinCouldHideUseCase { + return IsCryptoCurrencyCoinCouldHideUseCase( + currenciesRepository = currenciesRepository, + ) + } } \ No newline at end of file diff --git a/core/ui/src/main/res/drawable/ic_trash_24.xml b/core/ui/src/main/res/drawable/ic_trash_24.xml new file mode 100644 index 0000000000..7e35d65875 --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_trash_24.xml @@ -0,0 +1,9 @@ + + + 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 159bcda144..6727184224 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 @@ -39,7 +39,7 @@ class GetCryptoCurrencyActionsUseCase( return TokenActionsState( walletId = userWalletId, cryptoCurrencyStatus = cryptoCurrencyStatus, - states = createListOfActions(userWalletId, cryptoCurrencyStatus.currency), + states = createListOfActions(userWalletId, cryptoCurrencyStatus), ) } @@ -49,8 +49,13 @@ class GetCryptoCurrencyActionsUseCase( */ private suspend fun createListOfActions( userWalletId: UserWalletId, - cryptoCurrency: CryptoCurrency, + cryptoCurrencyStatus: CryptoCurrencyStatus, ): List { + val cryptoCurrency = cryptoCurrencyStatus.currency + if (cryptoCurrencyStatus.value is CryptoCurrencyStatus.MissedDerivation) { + return listOf(TokenActionsState.ActionState.HideToken(true)) + } + val activeList = mutableListOf() val disabledList = mutableListOf() @@ -85,6 +90,9 @@ class GetCryptoCurrencyActionsUseCase( disabledList.add(TokenActionsState.ActionState.Sell(false)) } + // hide + activeList.add(TokenActionsState.ActionState.HideToken(true)) + return activeList + disabledList } diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/IsCryptoCurrencyCoinCouldHideUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/IsCryptoCurrencyCoinCouldHideUseCase.kt new file mode 100644 index 0000000000..0dc5716838 --- /dev/null +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/IsCryptoCurrencyCoinCouldHideUseCase.kt @@ -0,0 +1,17 @@ +package com.tangem.domain.tokens + +import com.tangem.domain.tokens.model.CryptoCurrency +import com.tangem.domain.tokens.repository.CurrenciesRepository +import com.tangem.domain.wallets.models.UserWalletId + +class IsCryptoCurrencyCoinCouldHideUseCase( + private val currenciesRepository: CurrenciesRepository, +) { + + suspend operator fun invoke(userWalletId: UserWalletId, cryptoCurrencyCoin: CryptoCurrency.Coin): Boolean { + return currenciesRepository.getMultiCurrencyWalletCurrenciesSync( + userWalletId = userWalletId, + refresh = false, + ).none { it is CryptoCurrency.Token && it.network == cryptoCurrencyCoin.network } + } +} \ No newline at end of file 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 96f2678982..f52641b2c8 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 @@ -23,5 +23,7 @@ data class TokenActionsState( data class Swap(override val enabled: Boolean) : ActionState() data class Send(override val enabled: Boolean) : ActionState() + + data class HideToken(override val enabled: Boolean) : ActionState() } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletAlertState.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletAlertState.kt index 4bcdd07368..7e6692060a 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletAlertState.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/WalletAlertState.kt @@ -1,9 +1,16 @@ package com.tangem.feature.wallet.presentation.wallet.state import androidx.compose.runtime.Immutable +import com.tangem.core.ui.extensions.TextReference @Immutable internal sealed class WalletAlertState { data class WalletAlreadySignedHashes(val onUnderstandClick: () -> Unit) : WalletAlertState() + + data class DefaultAlert( + val title: TextReference, + val message: TextReference, + val onActionClick: (() -> Unit)?, + ) : WalletAlertState() } \ No newline at end of file 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 d399e75ad4..99a30916b8 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 @@ -12,6 +12,12 @@ internal sealed class WalletEvent { data class ShowToast(val text: TextReference) : WalletEvent() + data class ShowAlert( + val title: TextReference, + val message: TextReference, + val onActionClick: (() -> Unit)?, + ) : WalletEvent() + data class CopyAddress(val address: String) : WalletEvent() data class ShowWalletAlreadySignedHashesMessage(val onUnderstandClick: () -> Unit) : WalletEvent() 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 e10de613d6..7f86a56e66 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 @@ -72,6 +72,11 @@ internal class TokenActionsProvider(private val clickIntents: WalletClickIntents icon = R.drawable.ic_copy_24 action = { clickIntents.onCopyAddressClick(cryptoCurrencyStatus) } } + is TokenActionsState.ActionState.HideToken -> { + title = resourceReference(R.string.token_details_hide_token) + icon = R.drawable.ic_trash_24 + action = { clickIntents.onHideTokensClick(cryptoCurrencyStatus) } + } } return TokenActionButtonConfig( text = title, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletAlert.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletAlert.kt index 5b5a6a7e5e..74582e01c7 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletAlert.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletAlert.kt @@ -4,6 +4,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource import com.tangem.core.ui.components.BasicDialog import com.tangem.core.ui.components.DialogButton +import com.tangem.core.ui.extensions.resolveReference import com.tangem.feature.wallet.impl.R import com.tangem.feature.wallet.presentation.wallet.state.WalletAlertState @@ -13,6 +14,9 @@ internal fun WalletAlert(config: WalletAlertState, onDismiss: () -> Unit) { is WalletAlertState.WalletAlreadySignedHashes -> { WalletAlreadySignedHashesAlert(config = config, onDismiss = onDismiss) } + is WalletAlertState.DefaultAlert -> { + DefaultAlert(config = config, onDismiss = onDismiss) + } } } @@ -31,4 +35,36 @@ private fun WalletAlreadySignedHashesAlert(config: WalletAlertState.WalletAlread title = stringResource(id = R.string.warning_important_security_info, "\u26A0"), dismissButton = DialogButton(title = stringResource(id = R.string.common_cancel), onClick = onDismiss), ) +} + +@Composable +private fun DefaultAlert(config: WalletAlertState.DefaultAlert, onDismiss: () -> Unit) { + val confirmButton: DialogButton + val dismissButton: DialogButton? + if (config.onActionClick != null) { + confirmButton = DialogButton( + title = stringResource(id = R.string.common_ok), + onClick = { + config.onActionClick.invoke() + onDismiss() + }, + ) + dismissButton = DialogButton( + title = stringResource(id = R.string.common_cancel), + onClick = onDismiss, + ) + } else { + confirmButton = DialogButton( + title = stringResource(id = R.string.common_ok), + onClick = onDismiss, + ) + dismissButton = null + } + BasicDialog( + message = config.message.resolveReference(), + confirmButton = confirmButton, + onDismissDialog = onDismiss, + title = config.title.resolveReference(), + dismissButton = dismissButton, + ) } \ No newline at end of file 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 8f1fa60262..7eebc553dd 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 @@ -52,6 +52,15 @@ internal fun WalletEventEffect( WalletAlertState.WalletAlreadySignedHashes(onUnderstandClick = value.onUnderstandClick), ) } + is WalletEvent.ShowAlert -> { + onAlertConfigSet( + WalletAlertState.DefaultAlert( + title = value.title, + message = value.message, + onActionClick = value.onActionClick, + ), + ) + } is WalletEvent.RateApp -> { val reviewManager = ReviewManagerFactory.create(context) val requestTask = reviewManager.requestReviewFlow() 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 59acf7726c..d7c3ac8444 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 @@ -55,6 +55,10 @@ internal interface WalletClickIntents { fun onCopyAddressClick(cryptoCurrencyStatus: CryptoCurrencyStatus) + fun onHideTokensClick(cryptoCurrencyStatus: CryptoCurrencyStatus) + + fun onPerformHideToken(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 c0c5c48f98..809cc098e1 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 @@ -19,6 +19,8 @@ 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.TextReference +import com.tangem.core.ui.extensions.WrappedList import com.tangem.core.ui.extensions.resourceReference import com.tangem.crypto.hdWallet.DerivationPath import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase @@ -106,6 +108,8 @@ internal class WalletViewModel @Inject constructor( private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase, private val isBalanceHiddenUseCase: IsBalanceHiddenUseCase, private val listenToFlipsUseCase: ListenToFlipsUseCase, + private val removeCurrencyUseCase: RemoveCurrencyUseCase, + private val isCryptoCurrencyCoinCouldHide: IsCryptoCurrencyCoinCouldHideUseCase, private val walletManagersFacade: WalletManagersFacade, private val reduxStateHolder: ReduxStateHolder, private val dispatchers: CoroutineDispatcherProvider, @@ -764,6 +768,34 @@ internal class WalletViewModel @Inject constructor( } } + override fun onPerformHideToken(cryptoCurrencyStatus: CryptoCurrencyStatus) { + val state = uiState as? WalletState.ContentState ?: return + val userWallet = getWallet(state.walletsListConfig.selectedWalletIndex) + viewModelScope.launch(dispatchers.io) { + removeCurrencyUseCase(userWallet.walletId, cryptoCurrencyStatus.currency) + .fold( + ifLeft = { + showSnackbar(resourceReference(R.string.common_error)) + }, + ifRight = { + onDismissActionsBottomSheet() + }, + ) + } + } + + override fun onHideTokensClick(cryptoCurrencyStatus: CryptoCurrencyStatus) { + viewModelScope.launch(dispatchers.main) { + val state = uiState as? WalletState.ContentState ?: return@launch + val userWallet = getWallet(state.walletsListConfig.selectedWalletIndex) + uiState = stateFactory.getStateAndTriggerEvent( + state = uiState, + event = getHideTokeAlert(userWallet.walletId, cryptoCurrencyStatus), + setUiState = { uiState = it }, + ) + } + } + override fun onDismissBottomSheet() { uiState = stateFactory.getStateWithClosedBottomSheet() } @@ -778,6 +810,48 @@ internal class WalletViewModel @Inject constructor( } } + private suspend fun getHideTokeAlert( + userWalletId: UserWalletId, + cryptoCurrencyStatus: CryptoCurrencyStatus, + ): WalletEvent.ShowAlert { + val currency = cryptoCurrencyStatus.currency + return if (currency is CryptoCurrency.Coin && !isCryptoCurrencyCoinCouldHide(userWalletId, currency)) { + WalletEvent.ShowAlert( + title = resourceReference( + id = R.string.token_details_unable_hide_alert_title, + formatArgs = WrappedList(listOf(cryptoCurrencyStatus.currency.name)), + ), + message = resourceReference( + id = R.string.token_details_unable_hide_alert_message, + formatArgs = WrappedList( + listOf( + cryptoCurrencyStatus.currency.name, + cryptoCurrencyStatus.currency.network.name, + ), + ), + ), + onActionClick = null, + ) + } else { + WalletEvent.ShowAlert( + title = resourceReference( + id = R.string.token_details_hide_alert_title, + formatArgs = WrappedList(listOf(cryptoCurrencyStatus.currency.name)), + ), + message = resourceReference(R.string.token_details_hide_alert_message), + onActionClick = { onPerformHideToken(cryptoCurrencyStatus) }, + ) + } + } + + private fun showSnackbar(message: TextReference) { + uiState = stateFactory.getStateAndTriggerEvent( + state = uiState, + event = WalletEvent.ShowToast(message), + setUiState = { uiState = it }, + ) + } + private fun getContentItemsUpdates(index: Int) { /* * When wallet is changed it's necessary to stop the last jobs.