Updated on 2026-08-14

This commit is contained in:
Tangem 2026-02-25 16:39:35 +03:00
commit bfd903b43c
595 changed files with 12755 additions and 19837 deletions

View file

@ -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<SwapTransactionState.Error, AlertUM?> {
override fun convert(value: SwapTransactionState.Error): AlertUM? {
private val transactionErrorDialogFactory: TransactionErrorDialogFactory = TransactionErrorDialogFactory(),
) : Converter<SwapTransactionState.Error, DialogMessage?> {
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) },
)
}

View file

@ -24,12 +24,22 @@ import com.tangem.core.analytics.models.event.SwapAnalyticsEvent
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.R
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
@ -162,6 +172,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<SwapComponent.Params>()
@ -342,7 +353,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
@ -360,7 +372,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
@ -1027,7 +1040,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()
@ -1053,7 +1066,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(
@ -1097,21 +1110,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)
@ -1120,7 +1123,7 @@ internal class SwapModel @Inject constructor(
}.onFailure { error ->
Timber.e(error)
startLoadingQuotesFromLastState()
makeDefaultAlert()
showAlert()
}
}
}
@ -1212,7 +1215,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
}
@ -1242,29 +1245,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()
}
}
}
@ -1654,12 +1647,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")
@ -1779,14 +1854,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 = {
@ -2092,31 +2160,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

View file

@ -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,
),
)
}

View file

@ -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<NotificationUM> = persistentListOf(),
val isInsufficientFunds: Boolean,
val event: StateEvent<SwapEvent> = consumedEvent(),
val changeCardsButtonState: ChangeCardsButtonState,
val providerState: ProviderState,

View file

@ -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()
}

View file

@ -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(

View file

@ -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<SwapEvent>) {
var alertConfig by remember { mutableStateOf<AlertUM?>(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,
)
}

View file

@ -117,10 +117,6 @@ internal fun SwapScreenContent(
textAlign = TextAlign.Start,
)
}
SwapEventEffect(
event = state.event,
)
}
}