From dea7034aadc42ddd78fc2e6ebb826013f5d40c20 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 20 Feb 2026 11:56:20 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../alerts/TransactionErrorAlertConverter.kt | 56 ------ .../alerts/TransactionErrorDialogFactory.kt | 83 ++++++++ .../ui/alerts/models/AlertDemoModeUM.kt | 13 -- .../alerts/models/AlertTransactionErrorUM.kt | 21 -- .../tangem/common/ui/alerts/models/AlertUM.kt | 12 -- .../v2/common/ui/OnboardingDialogUM.kt | 11 +- .../selecttoken/model/OnrampOperationModel.kt | 16 +- .../send/v2/common/SendConfirmAlertFactory.kt | 32 +--- .../impl/presentation/model/StakingModel.kt | 19 +- .../state/StakingStateController.kt | 14 -- .../impl/presentation/state/StakingUiState.kt | 3 - .../state/events/StakingAlertUM.kt | 121 ++++++------ .../presentation/state/events/StakingEvent.kt | 13 -- .../state/events/StakingEventFactory.kt | 44 ++--- .../presentation/ui/StakingEventEffect.kt | 80 -------- .../impl/presentation/ui/StakingScreen.kt | 7 - .../swap/v2/impl/common/SwapAlertFactory.kt | 33 +--- .../SwapTransactionErrorStateConverter.kt | 19 +- .../tangem/feature/swap/model/SwapModel.kt | 179 +++++++++++------- .../tangem/feature/swap/models/SwapAlertUM.kt | 61 +++--- .../feature/swap/models/SwapStateHolder.kt | 4 - .../swap/models/states/events/SwapEvent.kt | 9 - .../tangem/feature/swap/ui/StateBuilder.kt | 118 ------------ .../tangem/feature/swap/ui/SwapEventEffect.kt | 61 ------ .../feature/swap/ui/SwapScreenContent.kt | 4 - .../impl/common/YieldSupplyAlertFactory.kt | 32 +--- 26 files changed, 349 insertions(+), 716 deletions(-) delete mode 100644 common/ui/src/main/java/com/tangem/common/ui/alerts/TransactionErrorAlertConverter.kt create mode 100644 common/ui/src/main/java/com/tangem/common/ui/alerts/TransactionErrorDialogFactory.kt delete mode 100644 common/ui/src/main/java/com/tangem/common/ui/alerts/models/AlertDemoModeUM.kt delete mode 100644 common/ui/src/main/java/com/tangem/common/ui/alerts/models/AlertTransactionErrorUM.kt delete mode 100644 common/ui/src/main/java/com/tangem/common/ui/alerts/models/AlertUM.kt delete mode 100644 features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingEvent.kt delete mode 100644 features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingEventEffect.kt delete mode 100644 features/swap/impl/src/main/java/com/tangem/feature/swap/models/states/events/SwapEvent.kt delete mode 100644 features/swap/impl/src/main/java/com/tangem/feature/swap/ui/SwapEventEffect.kt diff --git a/common/ui/src/main/java/com/tangem/common/ui/alerts/TransactionErrorAlertConverter.kt b/common/ui/src/main/java/com/tangem/common/ui/alerts/TransactionErrorAlertConverter.kt deleted file mode 100644 index 89855cf6ce..0000000000 --- a/common/ui/src/main/java/com/tangem/common/ui/alerts/TransactionErrorAlertConverter.kt +++ /dev/null @@ -1,56 +0,0 @@ -package com.tangem.common.ui.alerts - -import com.tangem.common.ui.alerts.models.AlertDemoModeUM -import com.tangem.common.ui.alerts.models.AlertTransactionErrorUM -import com.tangem.common.ui.alerts.models.AlertUM -import com.tangem.core.ui.R -import com.tangem.core.ui.extensions.resourceReference -import com.tangem.core.ui.extensions.wrappedList -import com.tangem.domain.transaction.error.SendTransactionError -import com.tangem.utils.converter.Converter - -class TransactionErrorAlertConverter( - private val popBackStack: () -> Unit, - private val onFailedTxEmailClick: (String) -> Unit, -) : Converter { - override fun convert(value: SendTransactionError): AlertUM? { - return when (value) { - is SendTransactionError.DemoCardError -> AlertDemoModeUM( - onConfirmClick = popBackStack, - ) - is SendTransactionError.TangemSdkError -> AlertTransactionErrorUM( - code = value.code.toString(), - cause = null, - causeTextReference = resourceReference(value.messageRes, wrappedList(value.args)), - onConfirmClick = { onFailedTxEmailClick(value.code.toString()) }, - ) - is SendTransactionError.BlockchainSdkError -> AlertTransactionErrorUM( - code = value.code.toString(), - cause = value.message, - onConfirmClick = { onFailedTxEmailClick("${value.code}: ${value.message.orEmpty()}") }, - ) - is SendTransactionError.DataError -> AlertTransactionErrorUM( - code = "", - cause = value.message, - onConfirmClick = { onFailedTxEmailClick(value.message.orEmpty()) }, - ) - is SendTransactionError.NetworkError -> AlertTransactionErrorUM( - code = value.code.orEmpty(), - cause = value.message.orEmpty(), - onConfirmClick = { onFailedTxEmailClick(value.message.orEmpty()) }, - ) - is SendTransactionError.UnknownError -> AlertTransactionErrorUM( - code = "", - cause = value.ex?.localizedMessage, - onConfirmClick = { onFailedTxEmailClick(value.ex?.localizedMessage.orEmpty()) }, - ) - is SendTransactionError.CreateAccountUnderfunded -> AlertTransactionErrorUM( - code = "", - cause = null, - causeTextReference = resourceReference(R.string.no_account_polkadot, wrappedList(value.amount)), - onConfirmClick = popBackStack, - ) - else -> null - } - } -} \ No newline at end of file diff --git a/common/ui/src/main/java/com/tangem/common/ui/alerts/TransactionErrorDialogFactory.kt b/common/ui/src/main/java/com/tangem/common/ui/alerts/TransactionErrorDialogFactory.kt new file mode 100644 index 0000000000..c5476fa263 --- /dev/null +++ b/common/ui/src/main/java/com/tangem/common/ui/alerts/TransactionErrorDialogFactory.kt @@ -0,0 +1,83 @@ +package com.tangem.common.ui.alerts + +import com.tangem.common.ui.R +import com.tangem.core.ui.extensions.TextReference +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.domain.transaction.error.SendTransactionError +import javax.inject.Inject + +class TransactionErrorDialogFactory @Inject constructor() { + + fun create( + error: SendTransactionError, + popBackStack: () -> Unit, + onFailedTxEmailClick: (String) -> Unit, + ): DialogMessage? { + return when (error) { + is SendTransactionError.DemoCardError -> demoModeDialog(popBackStack) + is SendTransactionError.TangemSdkError -> transactionErrorDialog( + causeTextReference = resourceReference(error.messageRes, wrappedList(error.args)), + code = error.code.toString(), + onConfirmClick = { onFailedTxEmailClick(error.code.toString()) }, + ) + is SendTransactionError.BlockchainSdkError -> transactionErrorDialog( + cause = error.message, + code = error.code.toString(), + onConfirmClick = { onFailedTxEmailClick("${error.code}: ${error.message.orEmpty()}") }, + ) + is SendTransactionError.DataError -> transactionErrorDialog( + cause = error.message, + code = "", + onConfirmClick = { onFailedTxEmailClick(error.message.orEmpty()) }, + ) + is SendTransactionError.NetworkError -> transactionErrorDialog( + cause = error.message.orEmpty(), + code = error.code.orEmpty(), + onConfirmClick = { onFailedTxEmailClick(error.message.orEmpty()) }, + ) + is SendTransactionError.UnknownError -> transactionErrorDialog( + cause = error.ex?.localizedMessage, + code = "", + onConfirmClick = { onFailedTxEmailClick(error.ex?.localizedMessage.orEmpty()) }, + ) + is SendTransactionError.CreateAccountUnderfunded -> transactionErrorDialog( + causeTextReference = resourceReference( + R.string.no_account_polkadot, + wrappedList(error.amount), + ), + code = "", + onConfirmClick = popBackStack, + ) + else -> null + } + } + + private fun demoModeDialog(onConfirmClick: () -> Unit): DialogMessage = DialogMessage( + title = resourceReference(id = R.string.warning_demo_mode_title), + message = resourceReference(id = R.string.warning_demo_mode_message), + firstAction = EventMessageAction( + title = resourceReference(id = R.string.common_ok), + onClick = onConfirmClick, + ), + ) + + private fun transactionErrorDialog( + cause: String? = null, + causeTextReference: TextReference? = null, + code: String, + onConfirmClick: () -> Unit, + ): DialogMessage = DialogMessage( + title = resourceReference(id = R.string.send_alert_transaction_failed_title), + message = resourceReference( + id = R.string.send_alert_transaction_failed_text, + formatArgs = wrappedList(causeTextReference ?: cause.orEmpty(), code), + ), + firstAction = EventMessageAction( + title = resourceReference(id = R.string.common_support), + onClick = onConfirmClick, + ), + ) +} \ No newline at end of file diff --git a/common/ui/src/main/java/com/tangem/common/ui/alerts/models/AlertDemoModeUM.kt b/common/ui/src/main/java/com/tangem/common/ui/alerts/models/AlertDemoModeUM.kt deleted file mode 100644 index e63ccb0229..0000000000 --- a/common/ui/src/main/java/com/tangem/common/ui/alerts/models/AlertDemoModeUM.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.tangem.common.ui.alerts.models - -import com.tangem.common.ui.R -import com.tangem.core.ui.extensions.TextReference -import com.tangem.core.ui.extensions.resourceReference - -data class AlertDemoModeUM( - override val onConfirmClick: () -> Unit, -) : AlertUM { - override val confirmButtonText: TextReference = resourceReference(id = R.string.common_ok) - override val title: TextReference = resourceReference(id = R.string.warning_demo_mode_title) - override val message: TextReference = resourceReference(id = R.string.warning_demo_mode_message) -} \ No newline at end of file diff --git a/common/ui/src/main/java/com/tangem/common/ui/alerts/models/AlertTransactionErrorUM.kt b/common/ui/src/main/java/com/tangem/common/ui/alerts/models/AlertTransactionErrorUM.kt deleted file mode 100644 index 6d9cea587a..0000000000 --- a/common/ui/src/main/java/com/tangem/common/ui/alerts/models/AlertTransactionErrorUM.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.tangem.common.ui.alerts.models - -import com.tangem.common.ui.R -import com.tangem.core.ui.extensions.TextReference -import com.tangem.core.ui.extensions.resourceReference -import com.tangem.core.ui.extensions.wrappedList - -data class AlertTransactionErrorUM( - val code: String, - val cause: String?, - val causeTextReference: TextReference? = null, - override val onConfirmClick: () -> Unit, -) : AlertUM { - override val title: TextReference = resourceReference(id = R.string.send_alert_transaction_failed_title) - override val message: TextReference = resourceReference( - id = R.string.send_alert_transaction_failed_text, - formatArgs = wrappedList(causeTextReference ?: cause.orEmpty(), code), - ) - override val confirmButtonText: TextReference = - resourceReference(id = R.string.common_support) -} \ No newline at end of file diff --git a/common/ui/src/main/java/com/tangem/common/ui/alerts/models/AlertUM.kt b/common/ui/src/main/java/com/tangem/common/ui/alerts/models/AlertUM.kt deleted file mode 100644 index 1cf955bebe..0000000000 --- a/common/ui/src/main/java/com/tangem/common/ui/alerts/models/AlertUM.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.tangem.common.ui.alerts.models - -import androidx.compose.runtime.Immutable -import com.tangem.core.ui.extensions.TextReference - -@Immutable -interface AlertUM { - val title: TextReference? - val message: TextReference - val confirmButtonText: TextReference - val onConfirmClick: (() -> Unit)? -} \ No newline at end of file diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/common/ui/OnboardingDialogUM.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/common/ui/OnboardingDialogUM.kt index 53e6ba8d82..f6f073d569 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/common/ui/OnboardingDialogUM.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/common/ui/OnboardingDialogUM.kt @@ -1,15 +1,14 @@ package com.tangem.features.onboarding.v2.common.ui -import com.tangem.common.ui.alerts.models.AlertUM import com.tangem.core.ui.extensions.TextReference internal data class OnboardingDialogUM( - override val title: TextReference, - override val message: TextReference, + val title: TextReference, + val message: TextReference, val dismissButtonText: TextReference, - override val confirmButtonText: TextReference, + val confirmButtonText: TextReference, val dismissWarningColor: Boolean = false, - override val onConfirmClick: () -> Unit, + val onConfirmClick: () -> Unit, val onDismissButtonClick: () -> Unit, val onDismiss: () -> Unit, -) : AlertUM \ No newline at end of file +) \ No newline at end of file diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selecttoken/model/OnrampOperationModel.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selecttoken/model/OnrampOperationModel.kt index fedeec4e55..a9ac694ab9 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selecttoken/model/OnrampOperationModel.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/selecttoken/model/OnrampOperationModel.kt @@ -3,7 +3,6 @@ package com.tangem.features.onramp.selecttoken.model import arrow.core.getOrElse import com.tangem.common.routing.AppRoute import com.tangem.common.routing.AppRouter -import com.tangem.common.ui.alerts.models.AlertDemoModeUM import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.core.analytics.models.event.MainScreenAnalyticsEvent @@ -13,8 +12,8 @@ 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.navigation.url.UrlOpener +import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.message.DialogMessage -import com.tangem.core.ui.message.EventMessageAction import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.demo.IsDemoCardUseCase @@ -159,18 +158,9 @@ internal class OnrampOperationModel @Inject constructor( private fun showErrorIfDemoModeOrElse(action: () -> Unit) { if (selectedUserWallet is UserWallet.Cold && isDemoCardUseCase(cardId = selectedUserWallet.cardId)) { - val alertUM = AlertDemoModeUM(onConfirmClick = {}) - val message = DialogMessage( - title = alertUM.title, - message = alertUM.message, - firstActionBuilder = { - EventMessageAction( - title = alertUM.confirmButtonText, - onClick = alertUM.onConfirmClick, - ) - }, - secondActionBuilder = { cancelAction() }, + title = resourceReference(id = R.string.warning_demo_mode_title), + message = resourceReference(id = R.string.warning_demo_mode_message), ) messageSender.send(message) diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/common/SendConfirmAlertFactory.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/common/SendConfirmAlertFactory.kt index 78b805b69a..9a9ee70d57 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/common/SendConfirmAlertFactory.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/common/SendConfirmAlertFactory.kt @@ -1,7 +1,6 @@ package com.tangem.features.send.v2.common -import com.tangem.common.ui.alerts.TransactionErrorAlertConverter -import com.tangem.common.ui.alerts.models.AlertDemoModeUM +import com.tangem.common.ui.alerts.TransactionErrorDialogFactory import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.core.ui.extensions.resourceReference @@ -14,6 +13,7 @@ import javax.inject.Inject @ModelScoped internal class SendConfirmAlertFactory @Inject constructor( private val messageSender: UiMessageSender, + private val transactionErrorDialogFactory: TransactionErrorDialogFactory, ) { fun getGenericErrorState(onFailedTxEmailClick: () -> Unit, popBack: () -> Unit = {}) { @@ -31,34 +31,16 @@ internal class SendConfirmAlertFactory @Inject constructor( } fun getSendTransactionErrorState( - error: SendTransactionError?, + error: SendTransactionError, popBack: () -> Unit, onFailedTxEmailClick: (String) -> Unit, ) { - val transactionErrorAlertConverter = TransactionErrorAlertConverter( + val errorDialog = transactionErrorDialogFactory.create( + error = error, popBackStack = popBack, onFailedTxEmailClick = onFailedTxEmailClick, - ) + ) ?: return - val errorAlert = error?.let { transactionErrorAlertConverter.convert(error) } ?: return - val onConfirmClick = errorAlert.onConfirmClick ?: return - - messageSender.send( - DialogMessage( - title = errorAlert.title, - message = errorAlert.message, - firstActionBuilder = { - EventMessageAction( - title = errorAlert.confirmButtonText, - onClick = onConfirmClick, - ) - }, - secondActionBuilder = if (errorAlert !is AlertDemoModeUM) { - { cancelAction() } - } else { - null - }, - ), - ) + messageSender.send(errorDialog) } } \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt index 3ace74e0f1..2ef0911b14 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt @@ -67,7 +67,6 @@ import com.tangem.features.staking.impl.navigation.InnerStakingRouter import com.tangem.features.staking.impl.presentation.state.* import com.tangem.features.staking.impl.presentation.state.bottomsheet.InfoType import com.tangem.features.staking.impl.presentation.state.events.StakingAlertUM -import com.tangem.features.staking.impl.presentation.state.events.StakingEvent import com.tangem.features.staking.impl.presentation.state.events.StakingEventFactory import com.tangem.features.staking.impl.presentation.state.helpers.StakingBalanceUpdater import com.tangem.features.staking.impl.presentation.state.helpers.StakingFeeLoader @@ -249,7 +248,7 @@ internal class StakingModel @Inject constructor( private val stakingEventFactory: StakingEventFactory get() = StakingEventFactory( - stateController = stateController, + messageSender = messageSender, popBackStack = ::onBackClick, onFailedTxEmailClick = ::onFailedTxEmailClick, ) @@ -503,11 +502,7 @@ internal class StakingModel @Inject constructor( cryptoCurrencyStatus = cryptoCurrencyStatus, ), ) - stateController.updateEvent( - StakingEvent.ShowAlert( - StakingAlertUM.FeeIncreased(stateController::dismissAlert), - ), - ) + messageSender.send(StakingAlertUM.feeIncreased {}) updateNotifications() }, onTransactionExpired = { @@ -571,9 +566,7 @@ internal class StakingModel @Inject constructor( override fun onAmountEnterClick() { if (integration.preferredTargets.isEmpty()) { - stateController.updateEvent( - StakingEvent.ShowAlert(StakingAlertUM.NoAvailableValidators), - ) + messageSender.send(StakingAlertUM.noAvailableValidators()) } else { if (uiState.value.actionType is StakingActionCommonType.Enter) { stateController.updateAll( @@ -1047,11 +1040,7 @@ internal class StakingModel @Inject constructor( } override fun showPrimaryClickAlert() { - stateController.updateEvent( - StakingEvent.ShowAlert( - StakingAlertUM.StakeMoreClickUnavailable(cryptoCurrencyStatus.currency), - ), - ) + messageSender.send(StakingAlertUM.stakeMoreClickUnavailable(cryptoCurrencyStatus.currency)) } override fun onOpenLearnMoreAboutApproveClick() { diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateController.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateController.kt index 00409eed5c..7a02bd36ef 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateController.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingStateController.kt @@ -3,12 +3,9 @@ package com.tangem.features.staking.impl.presentation.state import com.tangem.common.ui.amountScreen.models.AmountState import com.tangem.common.ui.navigationButtons.NavigationButtonsState import com.tangem.core.navigation.url.UrlOpener -import com.tangem.core.ui.event.consumedEvent -import com.tangem.core.ui.event.triggeredEvent import com.tangem.core.ui.extensions.TextReference import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType -import com.tangem.features.staking.impl.presentation.state.events.StakingEvent import com.tangem.features.staking.impl.presentation.state.stub.StakingClickIntentsStub import com.tangem.features.staking.impl.presentation.state.transformers.SetButtonsStateTransformer import com.tangem.features.staking.impl.presentation.state.transformers.SetTitleTransformer @@ -72,16 +69,6 @@ internal class StakingStateController @Inject constructor( mutableUiState.update(function = titleTransformer::transform) } - fun updateEvent(event: StakingEvent?) { - mutableUiState.update { - it.copy(event = event?.let { triggeredEvent(event, ::dismissAlert) } ?: consumedEvent()) - } - } - - fun dismissAlert() { - mutableUiState.update { it.copy(event = consumedEvent()) } - } - private fun getInitialState(): StakingUiState { return StakingUiState( title = TextReference.EMPTY, @@ -98,7 +85,6 @@ internal class StakingStateController @Inject constructor( rewardsValidatorsState = StakingStates.RewardsValidatorsState.Empty(), confirmationState = StakingStates.ConfirmationState.Empty(), isBalanceHidden = false, - event = consumedEvent(), bottomSheetConfig = null, actionType = StakingActionCommonType.Enter(skipEnterAmount = false), buttonsState = NavigationButtonsState.Empty, diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingUiState.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingUiState.kt index 699729948f..8624ce9a72 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingUiState.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingUiState.kt @@ -6,14 +6,12 @@ import com.tangem.common.ui.navigationButtons.NavigationButtonsState import com.tangem.common.ui.notifications.NotificationUM import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.core.ui.components.list.RoundedListWithDividersItemData -import com.tangem.core.ui.event.StateEvent import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig import com.tangem.domain.models.staking.PendingAction import com.tangem.domain.staking.model.StakingTarget import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType import com.tangem.features.staking.impl.presentation.state.bottomsheet.InfoType -import com.tangem.features.staking.impl.presentation.state.events.StakingEvent import com.tangem.features.staking.impl.presentation.model.StakingClickIntents import kotlinx.collections.immutable.ImmutableList import java.math.BigDecimal @@ -40,7 +38,6 @@ internal data class StakingUiState( val bottomSheetConfig: TangemBottomSheetConfig?, val actionType: StakingActionCommonType, val buttonsState: NavigationButtonsState, - val event: StateEvent, val balanceState: BalanceState?, val showColdWalletInteractionIcon: Boolean, val shouldShowHoldToConfirmButton: Boolean, diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingAlertUM.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingAlertUM.kt index 3e757a6adc..acba4a78d1 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingAlertUM.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingAlertUM.kt @@ -1,85 +1,74 @@ package com.tangem.features.staking.impl.presentation.state.events -import androidx.compose.runtime.Immutable -import com.tangem.common.ui.alerts.models.AlertUM -import com.tangem.core.ui.extensions.TextReference 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.domain.models.currency.CryptoCurrency import com.tangem.features.staking.impl.R -@Immutable -internal sealed class StakingAlertUM : AlertUM { +internal object StakingAlertUM { - data class GenericError( - override val onConfirmClick: () -> Unit, - ) : StakingAlertUM() { - override val title: TextReference = resourceReference(R.string.common_error) - override val message: TextReference = resourceReference(R.string.common_unknown_error) - override val confirmButtonText: TextReference = resourceReference(id = R.string.common_support) - } + fun genericError(onConfirmClick: () -> Unit): DialogMessage = DialogMessage( + title = resourceReference(R.string.common_error), + message = resourceReference(R.string.common_unknown_error), + firstAction = EventMessageAction( + title = resourceReference(id = R.string.common_support), + onClick = onConfirmClick, + ), + ) - data class StakingError( - val code: String, - override val onConfirmClick: () -> Unit, - ) : StakingAlertUM() { - override val title: TextReference = resourceReference(R.string.common_error) - override val message: TextReference = resourceReference(R.string.generic_error_code, wrappedList(code)) - override val confirmButtonText: TextReference = resourceReference(id = R.string.common_support) - } + fun stakingError(code: String, onConfirmClick: () -> Unit): DialogMessage = DialogMessage( + title = resourceReference(R.string.common_error), + message = resourceReference(R.string.generic_error_code, wrappedList(code)), + firstAction = EventMessageAction( + title = resourceReference(id = R.string.common_support), + onClick = onConfirmClick, + ), + ) - data object NoAvailableValidators : StakingAlertUM() { - override val title = resourceReference(R.string.common_error) - override val message = resourceReference(R.string.staking_no_validators_error_message) - override val confirmButtonText = resourceReference(R.string.common_ok) - override val onConfirmClick = null - } + fun noAvailableValidators(): DialogMessage = DialogMessage( + title = resourceReference(R.string.common_error), + message = resourceReference(R.string.staking_no_validators_error_message), + ) - data class FeeIncreased( - override val onConfirmClick: () -> Unit, - ) : StakingAlertUM() { - override val title: TextReference? = null - override val message: TextReference = resourceReference(id = R.string.send_notification_high_fee_title) - override val confirmButtonText: TextReference = resourceReference(id = R.string.common_ok) - } + fun feeIncreased(onConfirmClick: () -> Unit): DialogMessage = DialogMessage( + title = null, + message = resourceReference(id = R.string.send_notification_high_fee_title), + firstAction = EventMessageAction( + title = resourceReference(id = R.string.common_ok), + onClick = onConfirmClick, + ), + ) - data object ValidatorsUnavailable : StakingAlertUM() { - override val onConfirmClick: (() -> Unit)? = null - override val title: TextReference = resourceReference(id = R.string.staking_error_no_validators_title) - override val message: TextReference = resourceReference(id = R.string.staking_error_no_validators_message) - override val confirmButtonText: TextReference = resourceReference(id = R.string.common_ok) - } + fun validatorsUnavailable(): DialogMessage = DialogMessage( + title = resourceReference(id = R.string.staking_error_no_validators_title), + message = resourceReference(id = R.string.staking_error_no_validators_message), + ) - data class StakeMoreClickUnavailable( - val cryptoCurrency: CryptoCurrency, - ) : StakingAlertUM() { - override val onConfirmClick: (() -> Unit)? = null - override val title: TextReference? = null - override val message: TextReference = resourceReference( + fun stakeMoreClickUnavailable(cryptoCurrency: CryptoCurrency): DialogMessage = DialogMessage( + title = null, + message = resourceReference( id = R.string.staking_stake_more_button_unavailability_reason, wrappedList(cryptoCurrency.name, cryptoCurrency.symbol), - ) - override val confirmButtonText: TextReference = resourceReference(id = R.string.common_ok) - } + ), + ) - data class RewardsMinimumRequirementsError( - val cryptoCurrencyName: String, - val cryptoAmountValue: String, - ) : StakingAlertUM() { - override val onConfirmClick: (() -> Unit)? = null - override val title: TextReference? = null - override val message: TextReference = resourceReference( - id = R.string.staking_details_min_rewards_notification, - formatArgs = wrappedList(cryptoCurrencyName, cryptoAmountValue), + fun rewardsMinimumRequirementsError(cryptoCurrencyName: String, cryptoAmountValue: String): DialogMessage = + DialogMessage( + title = null, + message = resourceReference( + id = R.string.staking_details_min_rewards_notification, + formatArgs = wrappedList(cryptoCurrencyName, cryptoAmountValue), + ), ) - override val confirmButtonText: TextReference = resourceReference(id = R.string.common_ok) - } - data class NetworkFeeUpdated( - override val onConfirmClick: () -> Unit, - ) : StakingAlertUM() { - override val title: TextReference = resourceReference(R.string.staking_alert_network_fee_updated_title) - override val message: TextReference = resourceReference(R.string.staking_alert_network_fee_updated_message) - override val confirmButtonText: TextReference = resourceReference(id = R.string.common_ok) - } + fun networkFeeUpdated(onConfirmClick: () -> Unit): DialogMessage = DialogMessage( + title = resourceReference(R.string.staking_alert_network_fee_updated_title), + message = resourceReference(R.string.staking_alert_network_fee_updated_message), + firstAction = EventMessageAction( + title = resourceReference(id = R.string.common_ok), + onClick = onConfirmClick, + ), + ) } \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingEvent.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingEvent.kt deleted file mode 100644 index 7e7700595e..0000000000 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingEvent.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.tangem.features.staking.impl.presentation.state.events - -import androidx.compose.runtime.Immutable -import com.tangem.common.ui.alerts.models.AlertUM -import com.tangem.core.ui.extensions.TextReference - -@Immutable -internal sealed class StakingEvent { - - data class ShowSnackBar(val text: TextReference) : StakingEvent() - - data class ShowAlert(val alert: AlertUM) : StakingEvent() -} \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingEventFactory.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingEventFactory.kt index 4ba7fb1dd9..fd94adadd2 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingEventFactory.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingEventFactory.kt @@ -1,69 +1,63 @@ package com.tangem.features.staking.impl.presentation.state.events -import com.tangem.common.ui.alerts.TransactionErrorAlertConverter +import com.tangem.common.ui.alerts.TransactionErrorDialogFactory +import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.domain.staking.model.stakekit.StakingError import com.tangem.domain.transaction.error.SendTransactionError -import com.tangem.features.staking.impl.presentation.state.StakingStateController internal class StakingEventFactory( - private val stateController: StakingStateController, + private val messageSender: UiMessageSender, private val popBackStack: () -> Unit, private val onFailedTxEmailClick: (String) -> Unit, + private val transactionErrorDialogFactory: TransactionErrorDialogFactory = TransactionErrorDialogFactory(), ) { fun createGenericErrorAlert(error: String) { - val alert = StakingEvent.ShowAlert( - StakingAlertUM.GenericError( + messageSender.send( + StakingAlertUM.genericError( onConfirmClick = { onFailedTxEmailClick(error) }, ), ) - stateController.updateEvent(alert) } fun createSendTransactionErrorAlert(error: SendTransactionError?) { val alert = error?.let { - TransactionErrorAlertConverter( + transactionErrorDialogFactory.create( + error = error, popBackStack = popBackStack, onFailedTxEmailClick = onFailedTxEmailClick, - ).convert(error) - }?.let { - StakingEvent.ShowAlert(it) + ) } - stateController.updateEvent(alert) + alert?.let { messageSender.send(it) } } fun createStakingErrorAlert(error: StakingError) { - val alert = StakingEvent.ShowAlert( - StakingAlertUM.StakingError( + messageSender.send( + StakingAlertUM.stakingError( code = error.toString(), onConfirmClick = { onFailedTxEmailClick(error.toString()) }, ), ) - stateController.updateEvent(alert) } fun createStakingValidatorsUnavailableAlert() { - val alert = StakingEvent.ShowAlert(alert = StakingAlertUM.ValidatorsUnavailable) - stateController.updateEvent(alert) + messageSender.send(StakingAlertUM.validatorsUnavailable()) } fun createStakingRewardsMinimumRequirementsErrorAlert(cryptoCurrencyName: String, cryptoAmountValue: String) { - stateController.updateEvent( - StakingEvent.ShowAlert( - alert = StakingAlertUM.RewardsMinimumRequirementsError( - cryptoCurrencyName = cryptoCurrencyName, - cryptoAmountValue = cryptoAmountValue, - ), + messageSender.send( + StakingAlertUM.rewardsMinimumRequirementsError( + cryptoCurrencyName = cryptoCurrencyName, + cryptoAmountValue = cryptoAmountValue, ), ) } fun createNetworkFeeUpdatedAlert(onConfirm: () -> Unit) { - val alert = StakingEvent.ShowAlert( - alert = StakingAlertUM.NetworkFeeUpdated( + messageSender.send( + StakingAlertUM.networkFeeUpdated( onConfirmClick = onConfirm, ), ) - stateController.updateEvent(alert) } } \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingEventEffect.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingEventEffect.kt deleted file mode 100644 index 96234a843e..0000000000 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingEventEffect.kt +++ /dev/null @@ -1,80 +0,0 @@ -package com.tangem.features.staking.impl.presentation.ui - -import androidx.compose.material3.SnackbarHostState -import androidx.compose.runtime.* -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalSoftwareKeyboardController -import com.tangem.common.ui.alerts.models.AlertUM -import com.tangem.core.ui.components.BasicDialog -import com.tangem.core.ui.components.DialogButtonUM -import com.tangem.core.ui.event.EventEffect -import com.tangem.core.ui.event.StateEvent -import com.tangem.core.ui.extensions.resolveReference -import com.tangem.core.ui.extensions.stringResourceSafe -import com.tangem.features.staking.impl.R -import com.tangem.features.staking.impl.presentation.state.events.StakingEvent - -@Composable -internal fun StakingEventEffect(event: StateEvent, snackbarHostState: SnackbarHostState) { - val resources = LocalContext.current.resources - var alertConfig by remember { mutableStateOf(value = null) } - - val keyboardController = LocalSoftwareKeyboardController.current - LaunchedEffect(key1 = alertConfig) { - keyboardController?.hide() - } - - alertConfig?.let { - StakingAlert(state = it, onDismiss = { alertConfig = null }) - } - - EventEffect( - event = event, - onTrigger = { value -> - when (value) { - is StakingEvent.ShowSnackBar -> { - snackbarHostState.showSnackbar(message = value.text.resolveReference(resources)) - } - is StakingEvent.ShowAlert -> { - alertConfig = value.alert - } - } - }, - ) -} - -@Composable -internal fun StakingAlert(state: AlertUM, onDismiss: () -> Unit) { - val confirmButton: DialogButtonUM - val dismissButton: DialogButtonUM? - - val onActionClick = state.onConfirmClick - if (onActionClick != null) { - confirmButton = DialogButtonUM( - title = state.confirmButtonText.resolveReference(), - onClick = { - onActionClick() - onDismiss() - }, - ) - - dismissButton = DialogButtonUM( - title = stringResourceSafe(id = R.string.common_cancel), - onClick = onDismiss, - ) - } else { - confirmButton = DialogButtonUM( - title = state.confirmButtonText.resolveReference(), - onClick = onDismiss, - ) - dismissButton = null - } - - BasicDialog( - message = state.message.resolveReference(), - confirmButton = confirmButton, - onDismissDialog = onDismiss, - title = state.title?.resolveReference(), - dismissButton = dismissButton, - ) -} \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingScreen.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingScreen.kt index 0196216ea0..836d37dec7 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingScreen.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingScreen.kt @@ -7,7 +7,6 @@ import androidx.compose.animation.core.tween import androidx.compose.animation.togetherWith import androidx.compose.foundation.background import androidx.compose.foundation.layout.* -import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -39,7 +38,6 @@ import kotlinx.coroutines.flow.withIndex @Composable internal fun StakingScreen(uiState: StakingUiState) { - val snackbarHostState = remember { SnackbarHostState() } val confirmationState = uiState.confirmationState as? StakingStates.ConfirmationState.Data BackHandler(onBack = uiState.clickIntents::onPrevClick) @@ -71,11 +69,6 @@ internal fun StakingScreen(uiState: StakingUiState) { ) StakingBottomSheet(bottomSheetConfig = uiState.bottomSheetConfig) } - - StakingEventEffect( - event = uiState.event, - snackbarHostState = snackbarHostState, - ) } @Composable diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/common/SwapAlertFactory.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/common/SwapAlertFactory.kt index 0994844d9b..79c2503262 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/common/SwapAlertFactory.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/common/SwapAlertFactory.kt @@ -1,7 +1,6 @@ package com.tangem.features.swap.v2.impl.common -import com.tangem.common.ui.alerts.TransactionErrorAlertConverter -import com.tangem.common.ui.alerts.models.AlertDemoModeUM +import com.tangem.common.ui.alerts.TransactionErrorDialogFactory import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.core.ui.extensions.resourceReference @@ -25,6 +24,7 @@ internal class SwapAlertFactory @Inject constructor( private val saveBlockchainErrorUseCase: SaveBlockchainErrorUseCase, private val getWalletMetaInfoUseCase: GetWalletMetaInfoUseCase, private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase, + private val transactionErrorDialogFactory: TransactionErrorDialogFactory, ) { fun getGenericErrorState(expressError: ExpressError, onFailedTxEmailClick: () -> Unit, popBack: () -> Unit = {}) { uiMessageSender.send( @@ -44,36 +44,21 @@ internal class SwapAlertFactory @Inject constructor( ) } + @Suppress("CanBeNonNullable") fun getSendTransactionErrorState( error: SendTransactionError?, popBack: () -> Unit, onFailedTxEmailClick: (String) -> Unit, ) { - val transactionErrorAlertConverter = TransactionErrorAlertConverter( + if (error == null) return + + val errorDialog = transactionErrorDialogFactory.create( + error = error, popBackStack = popBack, onFailedTxEmailClick = onFailedTxEmailClick, - ) + ) ?: return - val errorAlert = error?.let { transactionErrorAlertConverter.convert(error) } ?: return - val onConfirmClick = errorAlert.onConfirmClick ?: return - - uiMessageSender.send( - DialogMessage.Companion( - title = errorAlert.title, - message = errorAlert.message, - firstActionBuilder = { - EventMessageAction( - title = errorAlert.confirmButtonText, - onClick = onConfirmClick, - ) - }, - secondActionBuilder = if (errorAlert !is AlertDemoModeUM) { - { cancelAction() } - } else { - null - }, - ), - ) + uiMessageSender.send(errorDialog) } suspend fun onFailedTxEmailClick( diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/converters/SwapTransactionErrorStateConverter.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/converters/SwapTransactionErrorStateConverter.kt index 646e3a3218..653bb2b5e3 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/converters/SwapTransactionErrorStateConverter.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/converters/SwapTransactionErrorStateConverter.kt @@ -1,7 +1,7 @@ package com.tangem.feature.swap.converters -import com.tangem.common.ui.alerts.TransactionErrorAlertConverter -import com.tangem.common.ui.alerts.models.AlertUM +import com.tangem.common.ui.alerts.TransactionErrorDialogFactory +import com.tangem.core.ui.message.DialogMessage import com.tangem.domain.transaction.error.SendTransactionError import com.tangem.feature.swap.domain.models.ui.SwapTransactionState import com.tangem.feature.swap.models.SwapAlertUM @@ -11,24 +11,25 @@ import com.tangem.utils.converter.Converter internal class SwapTransactionErrorStateConverter( private val onDismiss: () -> Unit, private val onSupportClick: (String) -> Unit, -) : Converter { - override fun convert(value: SwapTransactionState.Error): AlertUM? { + private val transactionErrorDialogFactory: TransactionErrorDialogFactory = TransactionErrorDialogFactory(), +) : Converter { + override fun convert(value: SwapTransactionState.Error): DialogMessage? { return when (value) { is SwapTransactionState.Error.TransactionError -> { when (val error = value.error) { is SendTransactionError.UserCancelledError -> return null - null -> SwapAlertUM.GenericError(onDismiss) - else -> TransactionErrorAlertConverter(onDismiss, onSupportClick).convert(error) + null -> SwapAlertUM.genericError(onDismiss) + else -> transactionErrorDialogFactory.create(error, onDismiss, onSupportClick) } } is SwapTransactionState.Error.ExpressError -> { - SwapAlertUM.ExpressErrorAlert( + SwapAlertUM.expressErrorAlert( message = getExpressErrorMessage(value.error), onConfirmClick = { onSupportClick(value.error.code.toString()) }, ) } - SwapTransactionState.Error.UnknownError -> SwapAlertUM.GenericError(onDismiss) - is SwapTransactionState.Error.TangemPayWithdrawalError -> SwapAlertUM.GenericError( + SwapTransactionState.Error.UnknownError -> SwapAlertUM.genericError(onDismiss) + is SwapTransactionState.Error.TangemPayWithdrawalError -> SwapAlertUM.genericError( onConfirmClick = { onSupportClick(value.txId) }, ) } diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt index fb4e74e1ff..b929ec77f6 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt @@ -23,11 +23,21 @@ import com.tangem.core.analytics.models.Basic 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.navigation.url.UrlOpener import com.tangem.core.ui.HoldToConfirmButtonFeatureToggles import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.combinedReference import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.extensions.toWrappedList +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.utils.InputNumberFormatter +import com.tangem.core.ui.utils.parseBigDecimal +import com.tangem.feature.swap.converters.SwapTransactionErrorStateConverter +import com.tangem.feature.swap.models.SwapAlertUM import com.tangem.datasource.local.appsflyer.AppsFlyerStore import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles import com.tangem.domain.account.status.model.AccountCryptoCurrencyStatus @@ -165,6 +175,7 @@ internal class SwapModel @Inject constructor( private val getTangemPayCustomerIdUseCase: GetTangemPayCustomerIdUseCase, private val appsFlyerStore: AppsFlyerStore, private val holdToConfirmButtonFeatureToggles: HoldToConfirmButtonFeatureToggles, + private val messageSender: UiMessageSender, ) : Model() { private val params = paramsContainer.require() @@ -349,7 +360,8 @@ internal class SwapModel @Inject constructor( } if (fromAccountStatus == null) { - uiState = stateBuilder.addAlert(uiState = uiState, onDismiss = swapRouter::back) + showAlert() + swapRouter.back() } else { fromAccountCurrencyStatus = fromAccountStatus toAccountCurrencyStatus = toAccountStatus @@ -367,7 +379,8 @@ internal class SwapModel @Inject constructor( } if (fromStatus == null) { - uiState = stateBuilder.addAlert(uiState = uiState, onDismiss = swapRouter::back) + showAlert() + swapRouter.back() } else { initialFromStatus = fromStatus initialToStatus = toStatus @@ -1032,7 +1045,7 @@ internal class SwapModel @Inject constructor( val fee = getSelectedFee() if (fee == null && tangemPayInput?.isWithdrawal != true) { - makeDefaultAlert(resourceReference(R.string.swapping_fee_estimation_error_text)) + showAlert(resourceReference(R.string.swapping_fee_estimation_error_text)) modelScope.launch { delay(SWAP_IN_PROGRESS_DELAY) startLoadingQuotesFromLastState() @@ -1058,7 +1071,7 @@ internal class SwapModel @Inject constructor( when (swapTransactionState) { is SwapTransactionState.TxSent -> { if (fee == null) { - makeDefaultAlert(resourceReference(R.string.swapping_fee_estimation_error_text)) + showAlert(resourceReference(R.string.swapping_fee_estimation_error_text)) return@onSuccess } sendSuccessSwapEvent( @@ -1102,21 +1115,11 @@ internal class SwapModel @Inject constructor( swapRouter.openScreen(SwapNavScreen.Success) } SwapTransactionState.DemoMode -> { - uiState = stateBuilder.createDemoModeAlert( - uiState = uiState, - onDismiss = { uiState = stateBuilder.clearAlert(uiState) }, - isReverseSwapPossible = isReverseSwapPossible(), - ) + showDemoModeAlert() } is SwapTransactionState.Error -> { startLoadingQuotesFromLastState() - uiState = stateBuilder.createErrorTransactionAlert( - uiState = uiState, - error = swapTransactionState, - onDismiss = { uiState = stateBuilder.clearAlert(uiState) }, - onSupportClick = ::onFailedTxEmailClick, - isReverseSwapPossible = isReverseSwapPossible(), - ) + showTransactionErrorAlert(swapTransactionState) } is SwapTransactionState.TangemPayWithdrawalData -> { processTangemPayWithdrawal(swapTransactionState = swapTransactionState) @@ -1125,7 +1128,7 @@ internal class SwapModel @Inject constructor( }.onFailure { error -> Timber.e(error) startLoadingQuotesFromLastState() - makeDefaultAlert() + showAlert() } } } @@ -1217,7 +1220,7 @@ internal class SwapModel @Inject constructor( } val feeForPermission = when (val fee = approveDataModel.fee) { TxFeeState.Empty -> { - makeDefaultAlert(resourceReference(R.string.swapping_fee_estimation_error_text)) + showAlert(resourceReference(R.string.swapping_fee_estimation_error_text)) Timber.e("Fee should not be Empty") return@launch } @@ -1247,29 +1250,19 @@ internal class SwapModel @Inject constructor( startLoadingQuotesFromLastState(isSilent = true) } is SwapTransactionState.Error -> { - uiState = stateBuilder.createErrorTransactionAlert( - uiState = uiState, - error = swapTransactionState, - onDismiss = { uiState = stateBuilder.clearAlert(uiState) }, - onSupportClick = ::onFailedTxEmailClick, - isReverseSwapPossible = isReverseSwapPossible(), - ) + showTransactionErrorAlert(swapTransactionState) } SwapTransactionState.DemoMode -> { - uiState = stateBuilder.createDemoModeAlert( - uiState = uiState, - onDismiss = { uiState = stateBuilder.clearAlert(uiState) }, - isReverseSwapPossible = isReverseSwapPossible(), - ) + showDemoModeAlert() } is SwapTransactionState.TangemPayWithdrawalData -> { processTangemPayWithdrawal(swapTransactionState = swapTransactionState) } } - }.onFailure { makeDefaultAlert() } + }.onFailure { showAlert() } }.onFailure { error -> Timber.e(error.message.orEmpty()) - makeDefaultAlert() + showAlert() } } } @@ -1652,12 +1645,94 @@ internal class SwapModel @Inject constructor( return inputNumberFormatter.getValidatedNumberWithFixedDecimals(amount, maxDecimals) } - private fun makeDefaultAlert() { - uiState = stateBuilder.addAlert(uiState) + private fun showAlert(message: TextReference = resourceReference(R.string.common_unknown_error)) { + messageSender.send(SwapAlertUM.genericError(onConfirmClick = { }, message = message)) } - private fun makeDefaultAlert(message: TextReference) { - uiState = stateBuilder.addAlert(uiState, message) + private fun showDemoModeAlert() { + messageSender.send( + DialogMessage( + title = resourceReference(id = R.string.warning_demo_mode_title), + message = resourceReference(id = R.string.warning_demo_mode_message), + firstAction = EventMessageAction( + title = resourceReference(id = R.string.common_ok), + onClick = {}, + ), + ), + ) + } + + private fun showTransactionErrorAlert( + error: SwapTransactionState.Error, + onSupportClick: (String) -> Unit = ::onFailedTxEmailClick, + ) { + val errorAlert = SwapTransactionErrorStateConverter( + onDismiss = {}, + onSupportClick = onSupportClick, + ).convert(error) + errorAlert?.let { messageSender.send(it) } + } + + private fun onTangemPaySupportClick(txId: String) { + modelScope.launch { + val metaInfo = getWalletMetaInfoUseCase(userWallet.walletId).getOrNull() ?: return@launch + val customerId = getTangemPayCustomerIdUseCase(userWallet.walletId).getOrNull().orEmpty() + val email = FeedbackEmailType.Visa.Withdrawal( + walletMetaInfo = metaInfo, + customerId = customerId, + providerName = dataState.selectedProvider?.name.orEmpty(), + txId = txId, + ) + sendFeedbackEmailUseCase(email) + } + } + + private fun showSwapInfoAlert(isPriceImpact: Boolean, token: String, provider: SwapProvider) { + messageSender.send( + SwapAlertUM.informationAlert( + message = buildSwapInfoMessage(isPriceImpact, token, provider), + onConfirmClick = {}, + ), + ) + } + + private fun buildSwapInfoMessage(isPriceImpact: Boolean, token: String, provider: SwapProvider): TextReference { + val slippage = provider.slippage?.let { "${it.parseBigDecimal(1)}%" } + val messages = buildList { + when (provider.type) { + ExchangeProviderType.CEX -> { + if (slippage != null) { + add( + resourceReference( + id = R.string.swapping_alert_cex_description_with_slippage, + formatArgs = wrappedList(token, slippage), + ), + ) + } else { + add(resourceReference(R.string.swapping_alert_cex_description, wrappedList(token))) + } + } + ExchangeProviderType.DEX, + ExchangeProviderType.DEX_BRIDGE, + -> { + if (isPriceImpact) { + add(resourceReference(R.string.swapping_high_price_impact_description)) + add(stringReference("\n\n")) + } + if (slippage != null) { + add( + resourceReference( + id = R.string.swapping_alert_dex_description_with_slippage, + formatArgs = wrappedList(slippage), + ), + ) + } else { + add(resourceReference(R.string.swapping_alert_dex_description, wrappedList(token))) + } + } + } + } + return combinedReference(messages.toWrappedList()) } @Suppress("LongMethod", "CyclomaticComplexMethod") @@ -1777,14 +1852,7 @@ internal class SwapModel @Inject constructor( val selectedProvider = dataState.selectedProvider ?: return@UiActions val currencySymbol = dataState.toCryptoCurrency?.currency?.symbol ?: return@UiActions val isPriceImpact = uiState.priceImpact is PriceImpact.Value - uiState = stateBuilder.createAlert( - uiState = uiState, - isPriceImpact = isPriceImpact, - token = currencySymbol, - provider = selectedProvider, - isReverseSwapPossible = isReverseSwapPossible(), - onDismiss = { uiState = stateBuilder.clearAlert(uiState) }, - ) + showSwapInfoAlert(isPriceImpact, currencySymbol, selectedProvider) }, onLinkClick = urlOpener::openUrl, onSelectTokenClick = { @@ -2090,31 +2158,12 @@ internal class SwapModel @Inject constructor( } private fun onTangemPayWithdrawalError(txId: String?) { - uiState = stateBuilder.createErrorTransactionAlert( - uiState = uiState, + showTransactionErrorAlert( error = SwapTransactionState.Error.TangemPayWithdrawalError(txId.orEmpty()), - onDismiss = { uiState = stateBuilder.clearAlert(uiState) }, - onSupportClick = { - val customerId = getTangemPayCustomerIdUseCase(userWallet.walletId).getOrNull() ?: "Unknown" - onTangemPaySupportClick(customerId = customerId, txId = txId) - }, - isReverseSwapPossible = isReverseSwapPossible(), + onSupportClick = ::onTangemPaySupportClick, ) } - private fun onTangemPaySupportClick(customerId: String, txId: String?) { - modelScope.launch { - val metaInfo = getWalletMetaInfoUseCase(userWallet.walletId).getOrNull() ?: return@launch - val email = FeedbackEmailType.Visa.Withdrawal( - walletMetaInfo = metaInfo, - customerId = customerId, - providerName = dataState.selectedProvider?.name.orEmpty(), - txId = txId.orEmpty(), - ) - sendFeedbackEmailUseCase(email) - } - } - private fun onFailedTxEmailClick(errorMessage: String) { modelScope.launch { val transaction = dataState.swapDataModel?.transaction diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/models/SwapAlertUM.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/models/SwapAlertUM.kt index bb84996732..fcf6277b98 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/models/SwapAlertUM.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/models/SwapAlertUM.kt @@ -1,38 +1,43 @@ package com.tangem.feature.swap.models -import com.tangem.common.ui.alerts.models.AlertUM import com.tangem.core.ui.R import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.message.DialogMessage +import com.tangem.core.ui.message.EventMessageAction -sealed class SwapAlertUM : AlertUM { +internal object SwapAlertUM { - data class GenericError( - override val onConfirmClick: (() -> Unit), - override val message: TextReference = resourceReference(R.string.common_unknown_error), - ) : SwapAlertUM() { - override val title: TextReference? = null - override val confirmButtonText: TextReference = - resourceReference(id = R.string.common_support) - } + fun genericError( + onConfirmClick: () -> Unit, + message: TextReference = resourceReference(R.string.common_unknown_error), + ): DialogMessage = DialogMessage( + title = null, + message = message, + firstAction = EventMessageAction( + title = resourceReference(id = R.string.common_support), + onClick = onConfirmClick, + ), + ) - data class ExpressErrorAlert( - override val message: TextReference = resourceReference(R.string.common_unknown_error), - override val onConfirmClick: (() -> Unit), - ) : SwapAlertUM() { - override val title: TextReference? = null - override val confirmButtonText: TextReference = - resourceReference(id = R.string.common_support) - } + fun expressErrorAlert( + message: TextReference = resourceReference(R.string.common_unknown_error), + onConfirmClick: () -> Unit, + ): DialogMessage = DialogMessage( + title = null, + message = message, + firstAction = EventMessageAction( + title = resourceReference(id = R.string.common_support), + onClick = onConfirmClick, + ), + ) - data class InformationAlert( - override val message: TextReference, - override val onConfirmClick: (() -> Unit), - ) : SwapAlertUM() { - override val title: TextReference = resourceReference( - R.string.swapping_alert_title, - ) - override val confirmButtonText: TextReference = - resourceReference(id = R.string.common_ok) - } + fun informationAlert(message: TextReference, onConfirmClick: () -> Unit): DialogMessage = DialogMessage( + title = resourceReference(R.string.swapping_alert_title), + message = message, + firstAction = EventMessageAction( + title = resourceReference(id = R.string.common_ok), + onClick = onConfirmClick, + ), + ) } \ No newline at end of file diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/models/SwapStateHolder.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/models/SwapStateHolder.kt index 47517e2801..02b46b544c 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/models/SwapStateHolder.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/models/SwapStateHolder.kt @@ -7,14 +7,11 @@ import com.tangem.common.ui.bottomsheet.permission.state.GiveTxPermissionState import com.tangem.common.ui.notifications.NotificationUM import com.tangem.common.ui.swapStoriesScreen.SwapStoriesUM import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig -import com.tangem.core.ui.event.StateEvent -import com.tangem.core.ui.event.consumedEvent import com.tangem.core.ui.extensions.TextReference import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.feature.swap.domain.models.ui.PriceImpact import com.tangem.feature.swap.models.states.FeeItemState import com.tangem.feature.swap.models.states.ProviderState -import com.tangem.feature.swap.models.states.events.SwapEvent import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf @@ -24,7 +21,6 @@ internal data class SwapStateHolder( val blockchainId: String, // not the same as networkId, its local id in app val notifications: ImmutableList = persistentListOf(), val isInsufficientFunds: Boolean, - val event: StateEvent = consumedEvent(), val changeCardsButtonState: ChangeCardsButtonState, val providerState: ProviderState, diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/models/states/events/SwapEvent.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/models/states/events/SwapEvent.kt deleted file mode 100644 index a00fed2610..0000000000 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/models/states/events/SwapEvent.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.tangem.feature.swap.models.states.events - -import androidx.compose.runtime.Immutable -import com.tangem.common.ui.alerts.models.AlertUM - -@Immutable -internal sealed class SwapEvent { - data class ShowAlert(val alert: AlertUM) : SwapEvent() -} \ No newline at end of file diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt index 6c955e7c86..ed0a2dcfe8 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt @@ -5,21 +5,17 @@ import androidx.compose.ui.text.input.TextFieldValue import com.tangem.common.ui.account.AccountTitleUM import com.tangem.common.ui.account.CryptoPortfolioIconConverter import com.tangem.common.ui.account.toUM -import com.tangem.common.ui.alerts.models.AlertDemoModeUM import com.tangem.common.ui.bottomsheet.permission.state.* import com.tangem.common.ui.notifications.NotificationUM import com.tangem.common.ui.swapStoriesScreen.SwapStoriesFactory import com.tangem.common.ui.userwallet.ext.walletInterationIcon import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter -import com.tangem.core.ui.event.consumedEvent -import com.tangem.core.ui.event.triggeredEvent import com.tangem.core.ui.extensions.* import com.tangem.core.ui.format.bigdecimal.anyDecimals import com.tangem.core.ui.format.bigdecimal.crypto import com.tangem.core.ui.format.bigdecimal.fiat import com.tangem.core.ui.format.bigdecimal.format -import com.tangem.core.ui.utils.parseBigDecimal import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.models.account.Account import com.tangem.domain.models.currency.CryptoCurrency @@ -29,7 +25,6 @@ import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.isHotWallet import com.tangem.domain.promo.models.StoryContent import com.tangem.domain.transaction.usecase.gasless.IsGaslessFeeSupportedForNetwork -import com.tangem.feature.swap.converters.SwapTransactionErrorStateConverter import com.tangem.feature.swap.converters.TokensDataConverter import com.tangem.feature.swap.converters.TokensDataConverterV2 import com.tangem.feature.swap.domain.models.ExpressDataError @@ -43,12 +38,10 @@ import com.tangem.feature.swap.model.SwapNotificationsFactory import com.tangem.feature.swap.model.SwapProcessDataState import com.tangem.feature.swap.models.* import com.tangem.feature.swap.models.states.* -import com.tangem.feature.swap.models.states.events.SwapEvent import com.tangem.feature.swap.presentation.R import com.tangem.feature.swap.utils.formatToUIRepresentation import com.tangem.utils.Provider import com.tangem.utils.StringsSigns.DASH_SIGN -import com.tangem.utils.StringsSigns.PERCENT import com.tangem.utils.StringsSigns.TILDE_SIGN import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf @@ -972,117 +965,6 @@ internal class StateBuilder( ) } - fun createErrorTransactionAlert( - uiState: SwapStateHolder, - error: SwapTransactionState.Error, - onDismiss: () -> Unit, - onSupportClick: (String) -> Unit, - isReverseSwapPossible: Boolean, - ): SwapStateHolder { - val errorAlert = SwapTransactionErrorStateConverter( - onSupportClick = onSupportClick, - onDismiss = onDismiss, - ).convert(error) - return uiState.copy( - event = errorAlert?.let { - triggeredEvent( - data = SwapEvent.ShowAlert(errorAlert), - onConsume = onDismiss, - ) - } ?: consumedEvent(), - changeCardsButtonState = getChangeCardsButtonState(isReverseSwapPossible), - ) - } - - fun createDemoModeAlert( - uiState: SwapStateHolder, - onDismiss: () -> Unit, - isReverseSwapPossible: Boolean, - ): SwapStateHolder { - return uiState.copy( - event = triggeredEvent( - data = SwapEvent.ShowAlert(AlertDemoModeUM(onDismiss)), - onConsume = onDismiss, - ), - changeCardsButtonState = getChangeCardsButtonState(isReverseSwapPossible), - ) - } - - @Suppress("LongParameterList") - fun createAlert( - uiState: SwapStateHolder, - isPriceImpact: Boolean, - token: String, - provider: SwapProvider, - onDismiss: () -> Unit, - isReverseSwapPossible: Boolean, - ): SwapStateHolder { - val slippage = provider.slippage?.let { "${it.parseBigDecimal(1)}$PERCENT" } - val combinedMessage = buildList { - when (provider.type) { - ExchangeProviderType.CEX -> { - if (slippage != null) { - add( - resourceReference( - id = R.string.swapping_alert_cex_description_with_slippage, - formatArgs = wrappedList(token, slippage), - ), - ) - } else { - add(resourceReference(R.string.swapping_alert_cex_description, wrappedList(token))) - } - } - ExchangeProviderType.DEX, - ExchangeProviderType.DEX_BRIDGE, - -> { - if (isPriceImpact) { - add(resourceReference(R.string.swapping_high_price_impact_description)) - add(stringReference("\n\n")) - } - if (slippage != null) { - add( - resourceReference( - id = R.string.swapping_alert_dex_description_with_slippage, - formatArgs = wrappedList(slippage), - ), - ) - } else { - add(resourceReference(R.string.swapping_alert_dex_description, wrappedList(token))) - } - } - } - } - return uiState.copy( - event = triggeredEvent( - SwapEvent.ShowAlert( - SwapAlertUM.InformationAlert( - message = combinedReference(combinedMessage.toWrappedList()), - onConfirmClick = onDismiss, - ), - ), - onConsume = onDismiss, - ), - changeCardsButtonState = getChangeCardsButtonState(isReverseSwapPossible), - ) - } - - fun addAlert( - uiState: SwapStateHolder, - message: TextReference = resourceReference(R.string.common_unknown_error), - onDismiss: () -> Unit = { clearAlert(uiState) }, - ): SwapStateHolder { - return uiState.copy( - event = triggeredEvent( - SwapEvent.ShowAlert( - SwapAlertUM.GenericError(onDismiss, message), - ), - onConsume = onDismiss, - ), - ) - } - - fun clearAlert(uiState: SwapStateHolder): SwapStateHolder = uiState.copy(event = consumedEvent()) - fun addNotification(uiState: SwapStateHolder, message: TextReference?, onClick: () -> Unit): SwapStateHolder { return uiState.copy( notifications = notificationsFactory.getGeneralErrorStateNotifications( diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/SwapEventEffect.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/SwapEventEffect.kt deleted file mode 100644 index 3a7455b5b0..0000000000 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/SwapEventEffect.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.tangem.feature.swap.ui - -import androidx.compose.runtime.* -import androidx.compose.ui.platform.LocalSoftwareKeyboardController -import com.tangem.common.ui.alerts.models.AlertUM -import com.tangem.core.ui.components.BasicDialog -import com.tangem.core.ui.components.DialogButtonUM -import com.tangem.core.ui.event.EventEffect -import com.tangem.core.ui.event.StateEvent -import com.tangem.core.ui.extensions.resolveReference -import com.tangem.core.ui.extensions.stringResourceSafe -import com.tangem.feature.swap.models.states.events.SwapEvent -import com.tangem.feature.swap.presentation.R - -@Composable -internal fun SwapEventEffect(event: StateEvent) { - var alertConfig by remember { mutableStateOf(value = null) } - - val keyboardController = LocalSoftwareKeyboardController.current - LaunchedEffect(key1 = alertConfig) { - keyboardController?.hide() - } - - alertConfig?.let { - SwapAlert(state = it, onDismiss = { alertConfig = null }) - } - - EventEffect( - event = event, - onTrigger = { value -> - when (value) { - is SwapEvent.ShowAlert -> { - alertConfig = value.alert - } - } - }, - ) -} - -@Composable -internal fun SwapAlert(state: AlertUM, onDismiss: () -> Unit) { - val confirmButton = DialogButtonUM( - title = state.confirmButtonText.resolveReference(), - onClick = { - state.onConfirmClick?.invoke() - onDismiss() - }, - ) - val dismissButton = DialogButtonUM( - title = stringResourceSafe(id = R.string.common_cancel), - onClick = onDismiss, - ) - - BasicDialog( - message = state.message.resolveReference(), - confirmButton = confirmButton, - onDismissDialog = onDismiss, - title = state.title?.resolveReference(), - dismissButton = dismissButton, - ) -} \ No newline at end of file diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt index b4d3c15097..813e71cc11 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt @@ -117,10 +117,6 @@ internal fun SwapScreenContent( textAlign = TextAlign.Start, ) } - - SwapEventEffect( - event = state.event, - ) } } diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/YieldSupplyAlertFactory.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/YieldSupplyAlertFactory.kt index 00958d2ec1..078a18f3e9 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/YieldSupplyAlertFactory.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/YieldSupplyAlertFactory.kt @@ -1,7 +1,6 @@ package com.tangem.features.yield.supply.impl.common -import com.tangem.common.ui.alerts.TransactionErrorAlertConverter -import com.tangem.common.ui.alerts.models.AlertDemoModeUM +import com.tangem.common.ui.alerts.TransactionErrorDialogFactory import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.core.ui.extensions.resourceReference @@ -24,6 +23,7 @@ class YieldSupplyAlertFactory @Inject constructor( private val saveBlockchainErrorUseCase: SaveBlockchainErrorUseCase, private val getWalletMetaInfoUseCase: GetWalletMetaInfoUseCase, private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase, + private val transactionErrorDialogFactory: TransactionErrorDialogFactory, ) { fun getGenericErrorState(onFailedTxEmailClick: () -> Unit, popBack: () -> Unit = {}) { @@ -41,35 +41,17 @@ class YieldSupplyAlertFactory @Inject constructor( } fun getSendTransactionErrorState( - error: SendTransactionError?, + error: SendTransactionError, popBack: () -> Unit, onFailedTxEmailClick: (String) -> Unit, ) { - val transactionErrorAlertConverter = TransactionErrorAlertConverter( + val errorDialog = transactionErrorDialogFactory.create( + error = error, popBackStack = popBack, onFailedTxEmailClick = onFailedTxEmailClick, - ) + ) ?: return - val errorAlert = error?.let { transactionErrorAlertConverter.convert(error) } ?: return - val onConfirmClick = errorAlert.onConfirmClick ?: return - - uiMessageSender.send( - DialogMessage.Companion( - title = errorAlert.title, - message = errorAlert.message, - firstActionBuilder = { - EventMessageAction( - title = errorAlert.confirmButtonText, - onClick = onConfirmClick, - ) - }, - secondActionBuilder = if (errorAlert !is AlertDemoModeUM) { - { cancelAction() } - } else { - null - }, - ), - ) + uiMessageSender.send(errorDialog) } suspend fun onFailedTxEmailClick(userWallet: UserWallet, cryptoCurrency: CryptoCurrency?, errorMessage: String?) {