From bd699c5bd9100958ba8749d93acbf63b423ecd5d Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 27 Jan 2026 16:32:21 +0700 Subject: [PATCH] Updated on 2026-08-14 --- .../archived/ArchivedAccountListModel.kt | 15 +--- .../portfolio/add/impl/model/AddTokenModel.kt | 18 ++++- .../model/CheckCurrencyUnsupportedDelegate.kt | 77 +++++++++++++++++++ .../add/impl/model/ChooseNetworkModel.kt | 72 +---------------- .../portfolio/add/impl/model/AddTokenModel.kt | 18 ++++- .../model/CheckCurrencyUnsupportedDelegate.kt | 77 +++++++++++++++++++ .../add/impl/model/ChooseNetworkModel.kt | 71 +---------------- 7 files changed, 193 insertions(+), 155 deletions(-) create mode 100644 features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/market/details/portfolio/add/impl/model/CheckCurrencyUnsupportedDelegate.kt create mode 100644 features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/CheckCurrencyUnsupportedDelegate.kt diff --git a/features/account/impl/src/main/java/com/tangem/features/account/archived/ArchivedAccountListModel.kt b/features/account/impl/src/main/java/com/tangem/features/account/archived/ArchivedAccountListModel.kt index d0ef646fb1..6b888f2693 100644 --- a/features/account/impl/src/main/java/com/tangem/features/account/archived/ArchivedAccountListModel.kt +++ b/features/account/impl/src/main/java/com/tangem/features/account/archived/ArchivedAccountListModel.kt @@ -9,7 +9,6 @@ import com.tangem.core.decompose.navigation.Router import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.core.res.R import com.tangem.core.ui.extensions.resourceReference -import com.tangem.core.ui.extensions.wrappedList import com.tangem.core.ui.message.DialogMessage import com.tangem.core.ui.message.EventMessageAction import com.tangem.core.ui.message.ToastMessage @@ -135,19 +134,11 @@ internal class ArchivedAccountListModel @Inject constructor( val featureError = AccountFeatureError.ArchivedAccountList.FailedToRecoverAccount(cause = error) logError(error = featureError) - val messageText = resourceReference( - id = R.string.universal_error, - formatArgs = wrappedList(featureError.errorCode), - ) - val message = DialogMessage( + val dialogMessage = DialogMessage( title = resourceReference(R.string.common_something_went_wrong), - message = messageText, - firstAction = EventMessageAction( - title = resourceReference(R.string.common_ok), - onClick = {}, - ), + message = resourceReference(R.string.account_generic_error_dialog_message), ) - messageSender.send(message) + messageSender.send(dialogMessage) } private fun logError(error: AccountFeatureError, params: Map = emptyMap()) { diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/market/details/portfolio/add/impl/model/AddTokenModel.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/market/details/portfolio/add/impl/model/AddTokenModel.kt index b8547e0118..2e8b332e31 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/market/details/portfolio/add/impl/model/AddTokenModel.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/market/details/portfolio/add/impl/model/AddTokenModel.kt @@ -37,6 +37,7 @@ internal class AddTokenModel @Inject constructor( private val analyticsEventHandler: AnalyticsEventHandler, private val manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase, private val getAccountCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase, + private val checkCurrencyUnsupportedDelegate: CheckCurrencyUnsupportedDelegate, ) : Model() { private val params = paramsContainer.require() @@ -69,14 +70,25 @@ internal class AddTokenModel @Inject constructor( private fun onAddClick(selectedNetwork: SelectedNetwork, selectedPortfolio: SelectedPortfolio) = modelScope.launch(dispatchers.default) { val um = uiState.value ?: return@launch + + val cryptoCurrency = selectedNetwork.cryptoCurrency + val account = selectedPortfolio.account.account.account + val accountId = account.accountId + val isMainNetwork = selectedNetwork.selectedNetwork.contractAddress == null + + val unsupportedCurrency = checkCurrencyUnsupportedDelegate.checkCurrencyUnsupportedState( + userWalletId = accountId.userWalletId, + rawNetworkId = selectedNetwork.selectedNetwork.networkId, + isMainNetwork = isMainNetwork, + ) + + if (unsupportedCurrency != null) return@launch + uiState.value = um.toggleProgress(true) val blockchainNames = listOf(selectedNetwork.selectedNetwork) .mapNotNull { BlockchainUtils.getNetworkInfo(it.networkId)?.name } analyticsEventHandler.send(analyticsEventBuilder.addToPortfolioContinue(blockchainNames)) - val cryptoCurrency = selectedNetwork.cryptoCurrency - val account = selectedPortfolio.account.account.account - val accountId = account.accountId manageCryptoCurrenciesUseCase(accountId = accountId, add = cryptoCurrency) .onLeft { throwable -> processError(error = throwable) diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/market/details/portfolio/add/impl/model/CheckCurrencyUnsupportedDelegate.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/market/details/portfolio/add/impl/model/CheckCurrencyUnsupportedDelegate.kt new file mode 100644 index 0000000000..8ba89fb021 --- /dev/null +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/market/details/portfolio/add/impl/model/CheckCurrencyUnsupportedDelegate.kt @@ -0,0 +1,77 @@ +package com.tangem.features.feed.components.market.details.portfolio.add.impl.model + +import arrow.core.getOrElse +import com.tangem.core.decompose.ui.UiMessageSender +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.extensions.wrappedList +import com.tangem.core.ui.message.DialogMessage +import com.tangem.core.ui.message.SnackbarMessage +import com.tangem.domain.managetokens.CheckCurrencyUnsupportedUseCase +import com.tangem.domain.managetokens.model.CurrencyUnsupportedState +import com.tangem.domain.models.wallet.UserWalletId +import com.tangem.features.feed.impl.R +import timber.log.Timber +import javax.inject.Inject + +class CheckCurrencyUnsupportedDelegate @Inject constructor( + private val checkCurrencyUnsupportedUseCase: CheckCurrencyUnsupportedUseCase, + private val messageSender: UiMessageSender, +) { + + suspend fun checkCurrencyUnsupportedState( + userWalletId: UserWalletId, + rawNetworkId: String, + isMainNetwork: Boolean, + ): CurrencyUnsupportedState? { + val result = checkCurrencyUnsupportedUseCase( + userWalletId = userWalletId, + networkId = rawNetworkId, + isMainNetwork = isMainNetwork, + ).getOrElse { throwable -> + Timber.e( + throwable, + """ + Failed to check currency unsupported state + |- User wallet ID: $userWalletId + |- Network ID: $rawNetworkId + |- Is main network: $isMainNetwork + """.trimIndent(), + ) + + val message = SnackbarMessage( + message = throwable.localizedMessage?.let(::stringReference) + ?: resourceReference(R.string.common_error), + ) + messageSender.send(message) + + null + } + + if (result != null) { + showUnsupportedWarning(result) + } + return result + } + + private fun showUnsupportedWarning(unsupportedState: CurrencyUnsupportedState) { + val message = DialogMessage( + message = when (unsupportedState) { + is CurrencyUnsupportedState.Token.NetworkTokensUnsupported -> resourceReference( + id = R.string.alert_manage_tokens_unsupported_message, + formatArgs = wrappedList(unsupportedState.networkName), + ) + is CurrencyUnsupportedState.Token.UnsupportedCurve -> resourceReference( + id = R.string.alert_manage_tokens_unsupported_curve_message, + formatArgs = wrappedList(unsupportedState.networkName), + ) + is CurrencyUnsupportedState.UnsupportedNetwork -> resourceReference( + id = R.string.alert_manage_tokens_unsupported_curve_message, + formatArgs = wrappedList(unsupportedState.networkName), + ) + }, + ) + + messageSender.send(message) + } +} \ No newline at end of file diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/market/details/portfolio/add/impl/model/ChooseNetworkModel.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/market/details/portfolio/add/impl/model/ChooseNetworkModel.kt index 4d51ae620c..5dc3fc5a62 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/market/details/portfolio/add/impl/model/ChooseNetworkModel.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/market/details/portfolio/add/impl/model/ChooseNetworkModel.kt @@ -1,38 +1,25 @@ package com.tangem.features.feed.components.market.details.portfolio.add.impl.model -import arrow.core.getOrElse import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer -import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.core.ui.components.rows.model.BlockchainRowUM -import com.tangem.core.ui.extensions.resourceReference -import com.tangem.core.ui.extensions.stringReference -import com.tangem.core.ui.extensions.wrappedList -import com.tangem.core.ui.message.DialogMessage -import com.tangem.core.ui.message.SnackbarMessage -import com.tangem.domain.managetokens.CheckCurrencyUnsupportedUseCase -import com.tangem.domain.managetokens.model.CurrencyUnsupportedState import com.tangem.domain.markets.TokenMarketInfo -import com.tangem.domain.models.wallet.UserWalletId import com.tangem.features.feed.components.market.details.portfolio.add.impl.ChooseNetworkComponent import com.tangem.features.feed.components.market.details.portfolio.add.impl.ui.state.ChooseNetworkUM import com.tangem.features.feed.components.market.details.portfolio.impl.model.BlockchainRowUMConverter -import com.tangem.features.feed.impl.R import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch -import timber.log.Timber import javax.inject.Inject @ModelScoped @Suppress("LongParameterList") internal class ChooseNetworkModel @Inject constructor( paramsContainer: ParamsContainer, - private val messageSender: UiMessageSender, - private val checkCurrencyUnsupportedUseCase: CheckCurrencyUnsupportedUseCase, + private val checkCurrencyUnsupportedDelegate: CheckCurrencyUnsupportedDelegate, override val dispatchers: CoroutineDispatcherProvider, ) : Model() { @@ -61,66 +48,13 @@ internal class ChooseNetworkModel @Inject constructor( private fun checkNetwork(row: BlockchainRowUM, network: TokenMarketInfo.Network) = modelScope.launch { val selectedWalletId = params.selectedPortfolio.userWallet.walletId - val unsupportedState = checkCurrencyUnsupportedState( + val unsupportedState = checkCurrencyUnsupportedDelegate.checkCurrencyUnsupportedState( userWalletId = selectedWalletId, rawNetworkId = row.id, isMainNetwork = row.isMainNetwork, ) - if (unsupportedState != null) { - showUnsupportedWarning(unsupportedState) - } else { + if (unsupportedState == null) { params.callbacks.onNetworkSelected(network) } } - - private suspend fun checkCurrencyUnsupportedState( - userWalletId: UserWalletId, - rawNetworkId: String, - isMainNetwork: Boolean, - ): CurrencyUnsupportedState? { - return checkCurrencyUnsupportedUseCase( - userWalletId = userWalletId, - networkId = rawNetworkId, - isMainNetwork = isMainNetwork, - ).getOrElse { throwable -> - Timber.e( - throwable, - """ - Failed to check currency unsupported state - |- User wallet ID: $userWalletId - |- Network ID: $rawNetworkId - |- Is main network: $isMainNetwork - """.trimIndent(), - ) - - val message = SnackbarMessage( - message = throwable.localizedMessage?.let(::stringReference) - ?: resourceReference(R.string.common_error), - ) - messageSender.send(message) - - null - } - } - - private fun showUnsupportedWarning(unsupportedState: CurrencyUnsupportedState) { - val message = DialogMessage( - message = when (unsupportedState) { - is CurrencyUnsupportedState.Token.NetworkTokensUnsupported -> resourceReference( - id = R.string.alert_manage_tokens_unsupported_message, - formatArgs = wrappedList(unsupportedState.networkName), - ) - is CurrencyUnsupportedState.Token.UnsupportedCurve -> resourceReference( - id = R.string.alert_manage_tokens_unsupported_curve_message, - formatArgs = wrappedList(unsupportedState.networkName), - ) - is CurrencyUnsupportedState.UnsupportedNetwork -> resourceReference( - id = R.string.alert_manage_tokens_unsupported_curve_message, - formatArgs = wrappedList(unsupportedState.networkName), - ) - }, - ) - - messageSender.send(message) - } } \ No newline at end of file diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/AddTokenModel.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/AddTokenModel.kt index c00c3f15da..f6ac24e4dd 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/AddTokenModel.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/AddTokenModel.kt @@ -37,6 +37,7 @@ internal class AddTokenModel @Inject constructor( private val analyticsEventHandler: AnalyticsEventHandler, private val manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase, private val getAccountCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase, + private val checkCurrencyUnsupportedDelegate: CheckCurrencyUnsupportedDelegate, ) : Model() { private val params = paramsContainer.require() @@ -69,14 +70,25 @@ internal class AddTokenModel @Inject constructor( private fun onAddClick(selectedNetwork: SelectedNetwork, selectedPortfolio: SelectedPortfolio) = modelScope.launch(dispatchers.default) { val um = uiState.value ?: return@launch + + val cryptoCurrency = selectedNetwork.cryptoCurrency + val account = selectedPortfolio.account.account.account + val accountId = account.accountId + val isMainNetwork = selectedNetwork.selectedNetwork.contractAddress == null + + val unsupportedCurrency = checkCurrencyUnsupportedDelegate.checkCurrencyUnsupportedState( + userWalletId = accountId.userWalletId, + rawNetworkId = selectedNetwork.selectedNetwork.networkId, + isMainNetwork = isMainNetwork, + ) + + if (unsupportedCurrency != null) return@launch + uiState.value = um.toggleProgress(true) val blockchainNames = listOf(selectedNetwork.selectedNetwork) .mapNotNull { BlockchainUtils.getNetworkInfo(it.networkId)?.name } analyticsEventHandler.send(analyticsEventBuilder.addToPortfolioContinue(blockchainNames)) - val cryptoCurrency = selectedNetwork.cryptoCurrency - val account = selectedPortfolio.account.account.account - val accountId = account.accountId manageCryptoCurrenciesUseCase(accountId = accountId, add = cryptoCurrency) .onLeft { error -> processError(error = error) diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/CheckCurrencyUnsupportedDelegate.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/CheckCurrencyUnsupportedDelegate.kt new file mode 100644 index 0000000000..a61f7cd842 --- /dev/null +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/CheckCurrencyUnsupportedDelegate.kt @@ -0,0 +1,77 @@ +package com.tangem.features.markets.portfolio.add.impl.model + +import arrow.core.getOrElse +import com.tangem.core.decompose.ui.UiMessageSender +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.extensions.wrappedList +import com.tangem.core.ui.message.DialogMessage +import com.tangem.core.ui.message.SnackbarMessage +import com.tangem.domain.managetokens.CheckCurrencyUnsupportedUseCase +import com.tangem.domain.managetokens.model.CurrencyUnsupportedState +import com.tangem.domain.models.wallet.UserWalletId +import com.tangem.features.markets.impl.R +import timber.log.Timber +import javax.inject.Inject + +class CheckCurrencyUnsupportedDelegate @Inject constructor( + private val checkCurrencyUnsupportedUseCase: CheckCurrencyUnsupportedUseCase, + private val messageSender: UiMessageSender, +) { + + suspend fun checkCurrencyUnsupportedState( + userWalletId: UserWalletId, + rawNetworkId: String, + isMainNetwork: Boolean, + ): CurrencyUnsupportedState? { + val result = checkCurrencyUnsupportedUseCase( + userWalletId = userWalletId, + networkId = rawNetworkId, + isMainNetwork = isMainNetwork, + ).getOrElse { throwable -> + Timber.e( + throwable, + """ + Failed to check currency unsupported state + |- User wallet ID: $userWalletId + |- Network ID: $rawNetworkId + |- Is main network: $isMainNetwork + """.trimIndent(), + ) + + val message = SnackbarMessage( + message = throwable.localizedMessage?.let(::stringReference) + ?: resourceReference(R.string.common_error), + ) + messageSender.send(message) + + null + } + + if (result != null) { + showUnsupportedWarning(result) + } + return result + } + + private fun showUnsupportedWarning(unsupportedState: CurrencyUnsupportedState) { + val message = DialogMessage( + message = when (unsupportedState) { + is CurrencyUnsupportedState.Token.NetworkTokensUnsupported -> resourceReference( + id = R.string.alert_manage_tokens_unsupported_message, + formatArgs = wrappedList(unsupportedState.networkName), + ) + is CurrencyUnsupportedState.Token.UnsupportedCurve -> resourceReference( + id = R.string.alert_manage_tokens_unsupported_curve_message, + formatArgs = wrappedList(unsupportedState.networkName), + ) + is CurrencyUnsupportedState.UnsupportedNetwork -> resourceReference( + id = R.string.alert_manage_tokens_unsupported_curve_message, + formatArgs = wrappedList(unsupportedState.networkName), + ) + }, + ) + + messageSender.send(message) + } +} \ No newline at end of file diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/ChooseNetworkModel.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/ChooseNetworkModel.kt index 1d1ecc80d0..4834f7cbbb 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/ChooseNetworkModel.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/ChooseNetworkModel.kt @@ -1,21 +1,10 @@ package com.tangem.features.markets.portfolio.add.impl.model -import arrow.core.getOrElse import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer -import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.core.ui.components.rows.model.BlockchainRowUM -import com.tangem.core.ui.extensions.resourceReference -import com.tangem.core.ui.extensions.stringReference -import com.tangem.core.ui.extensions.wrappedList -import com.tangem.core.ui.message.DialogMessage -import com.tangem.core.ui.message.SnackbarMessage -import com.tangem.domain.managetokens.CheckCurrencyUnsupportedUseCase -import com.tangem.domain.managetokens.model.CurrencyUnsupportedState import com.tangem.domain.markets.TokenMarketInfo -import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.features.markets.impl.R import com.tangem.features.markets.portfolio.add.impl.ChooseNetworkComponent import com.tangem.features.markets.portfolio.add.impl.ui.state.ChooseNetworkUM import com.tangem.features.markets.portfolio.impl.model.BlockchainRowUMConverter @@ -24,15 +13,13 @@ import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch -import timber.log.Timber import javax.inject.Inject @ModelScoped @Suppress("LongParameterList") internal class ChooseNetworkModel @Inject constructor( paramsContainer: ParamsContainer, - private val messageSender: UiMessageSender, - private val checkCurrencyUnsupportedUseCase: CheckCurrencyUnsupportedUseCase, + private val checkCurrencyUnsupportedDelegate: CheckCurrencyUnsupportedDelegate, override val dispatchers: CoroutineDispatcherProvider, ) : Model() { @@ -61,65 +48,13 @@ internal class ChooseNetworkModel @Inject constructor( private fun checkNetwork(row: BlockchainRowUM, network: TokenMarketInfo.Network) = modelScope.launch { val selectedWalletId = params.selectedPortfolio.userWallet.walletId - val unsupportedState = checkCurrencyUnsupportedState( + val unsupportedState = checkCurrencyUnsupportedDelegate.checkCurrencyUnsupportedState( userWalletId = selectedWalletId, rawNetworkId = row.id, isMainNetwork = row.isMainNetwork, ) - if (unsupportedState != null) { - showUnsupportedWarning(unsupportedState) - } else { + if (unsupportedState == null) { params.callbacks.onNetworkSelected(network) } } - - private suspend fun checkCurrencyUnsupportedState( - userWalletId: UserWalletId, - rawNetworkId: String, - isMainNetwork: Boolean, - ): CurrencyUnsupportedState? { - return checkCurrencyUnsupportedUseCase( - userWalletId = userWalletId, - networkId = rawNetworkId, - isMainNetwork = isMainNetwork, - ).getOrElse { error -> - Timber.e( - error, - """ - Failed to check currency unsupported state - |- User wallet ID: $userWalletId - |- Network ID: $rawNetworkId - |- Is main network: $isMainNetwork - """.trimIndent(), - ) - - val message = SnackbarMessage( - message = error.localizedMessage?.let(::stringReference) ?: resourceReference(R.string.common_error), - ) - messageSender.send(message) - - null - } - } - - private fun showUnsupportedWarning(unsupportedState: CurrencyUnsupportedState) { - val message = DialogMessage( - message = when (unsupportedState) { - is CurrencyUnsupportedState.Token.NetworkTokensUnsupported -> resourceReference( - id = R.string.alert_manage_tokens_unsupported_message, - formatArgs = wrappedList(unsupportedState.networkName), - ) - is CurrencyUnsupportedState.Token.UnsupportedCurve -> resourceReference( - id = R.string.alert_manage_tokens_unsupported_curve_message, - formatArgs = wrappedList(unsupportedState.networkName), - ) - is CurrencyUnsupportedState.UnsupportedNetwork -> resourceReference( - id = R.string.alert_manage_tokens_unsupported_curve_message, - formatArgs = wrappedList(unsupportedState.networkName), - ) - }, - ) - - messageSender.send(message) - } } \ No newline at end of file