Updated on 2026-08-14

This commit is contained in:
Tangem 2025-10-01 14:18:28 +02:00
parent 8d6992ad24
commit 646fe2d349
13 changed files with 72 additions and 32 deletions

View file

@ -63,6 +63,7 @@ import com.tangem.feature.swap.ui.StateBuilder
import com.tangem.feature.swap.utils.formatToUIRepresentation
import com.tangem.features.swap.SwapComponent
import com.tangem.utils.Provider
import com.tangem.utils.TangemLinks.RESOURCE_TO_LEARN_ABOUT_APPROVING_IN_SWAP
import com.tangem.utils.coroutines.*
import com.tangem.utils.isNullOrZero
import kotlinx.coroutines.NonCancellable
@ -1164,6 +1165,9 @@ internal class SwapModel @Inject constructor(
modelScope.launch { shouldShowStoriesUseCase.neverToShow(StoryContentIds.STORY_FIRST_TIME_SWAP.id) }
swapRouter.openScreen(SwapNavScreen.Main)
},
onOpenLearnMoreAboutApproveClick = {
urlOpener.openUrl(RESOURCE_TO_LEARN_ABOUT_APPROVING_IN_SWAP)
},
)
}

View file

@ -243,6 +243,7 @@ internal class SwapNotificationsFactory(
SwapNotificationUM.Info.PermissionNeeded(
providerName = fromToken.symbol,
fromTokenSymbol = providerName,
onApproveClick = actions.openPermissionBottomSheet,
),
)
}

View file

@ -32,4 +32,5 @@ data class UiActions(
val onSuccess: () -> Unit,
val onLinkClick: (String) -> Unit,
val onReceiveCardWarningClick: () -> Unit,
val onOpenLearnMoreAboutApproveClick: () -> Unit,
)

View file

@ -199,6 +199,7 @@ internal object SwapNotificationUM {
data class PermissionNeeded(
val providerName: String,
val fromTokenSymbol: String,
val onApproveClick: () -> Unit,
) : Info(
title = resourceReference(R.string.express_provider_permission_needed),
subtitle = resourceReference(
@ -206,6 +207,10 @@ internal object SwapNotificationUM {
formatArgs = wrappedList(providerName, fromTokenSymbol),
),
iconResId = R.drawable.ic_locked_24,
buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
text = TextReference.Res(R.string.common_approve),
onClick = onApproveClick,
),
)
}
}

View file

@ -347,6 +347,7 @@ internal class StateBuilder(
providerName = swapProvider.name,
onGivePermissionClick = actions.onGivePermissionClick,
onChangeApproveType = actions.onChangeApproveType,
onOpenLearnMoreAboutApproveClick = actions.onOpenLearnMoreAboutApproveClick,
),
fee = feeState,
swapButton = SwapButton(
@ -411,7 +412,8 @@ internal class StateBuilder(
it is SwapNotificationUM.Error || it is NotificationUM.Error ||
it is SwapNotificationUM.Warning.ExpressError || it is SwapNotificationUM.Warning.ExpressGeneralError ||
it is SwapNotificationUM.Warning.NoAvailableTokensToSwap ||
it is SwapNotificationUM.Warning.NeedReserveToCreateAccount
it is SwapNotificationUM.Warning.NeedReserveToCreateAccount ||
it is SwapNotificationUM.Info.PermissionNeeded
}
}
@ -934,12 +936,14 @@ internal class StateBuilder(
)
}
@Suppress("LongParameterList")
private fun convertPermissionState(
lastPermissionState: GiveTxPermissionState,
permissionDataState: PermissionDataState,
providerName: String,
onGivePermissionClick: () -> Unit,
onChangeApproveType: (ApproveType) -> Unit,
onOpenLearnMoreAboutApproveClick: () -> Unit,
): GiveTxPermissionState {
val approveType = if (lastPermissionState is GiveTxPermissionState.ReadyForRequest) {
lastPermissionState.approveType
@ -977,6 +981,7 @@ internal class StateBuilder(
),
dialogText = resourceReference(R.string.swapping_approve_information_text),
footerText = resourceReference(R.string.swap_give_permission_fee_footer),
onOpenLearnMoreAboutApproveClick = onOpenLearnMoreAboutApproveClick,
)
}
}

View file

@ -78,7 +78,7 @@ internal fun SwapScreenContent(state: SwapStateHolder, modifier: Modifier = Modi
if (state.notifications.isNotEmpty()) SwapNotifications(notifications = state.notifications)
MainButton(state = state, onPermissionWarningClick = state.onShowPermissionBottomSheet)
SpacerHMax()
if (state.tosState != null && state.providerState !is ProviderState.Empty) {
ProviderTos(
@ -87,6 +87,8 @@ internal fun SwapScreenContent(state: SwapStateHolder, modifier: Modifier = Modi
.padding(top = TangemTheme.dimens.spacing16),
)
}
MainButton(state = state)
}
if (state.shouldShowMaxAmount && keyboard is Keyboard.Opened) {
@ -359,34 +361,22 @@ private fun SwapNotifications(notifications: List<NotificationUM>) {
}
@Composable
private fun MainButton(state: SwapStateHolder, onPermissionWarningClick: () -> Unit) {
// order is important
when {
state.isInsufficientFunds -> {
PrimaryButton(
modifier = Modifier.fillMaxWidth(),
text = stringResourceSafe(id = R.string.swapping_insufficient_funds),
enabled = false,
onClick = state.swapButton.onClick,
)
}
state.notifications.any { it is SwapNotificationUM.Info.PermissionNeeded } -> {
PrimaryButton(
modifier = Modifier.fillMaxWidth(),
text = stringResourceSafe(id = R.string.give_permission_title),
enabled = true,
onClick = onPermissionWarningClick,
)
}
else -> {
PrimaryButtonIconEnd(
modifier = Modifier.fillMaxWidth(),
text = stringResourceSafe(id = R.string.swapping_swap_action),
iconResId = state.swapButton.walletInteractionIcon,
enabled = state.swapButton.enabled,
onClick = state.swapButton.onClick,
)
}
private fun MainButton(state: SwapStateHolder) {
if (state.isInsufficientFunds) {
PrimaryButton(
modifier = Modifier.fillMaxWidth(),
text = stringResourceSafe(id = R.string.swapping_insufficient_funds),
enabled = false,
onClick = state.swapButton.onClick,
)
} else {
PrimaryButtonIconEnd(
modifier = Modifier.fillMaxWidth(),
text = stringResourceSafe(id = R.string.swapping_swap_action),
iconResId = state.swapButton.walletInteractionIcon,
enabled = state.swapButton.enabled,
onClick = state.swapButton.onClick,
)
}
}
@ -438,6 +428,7 @@ private val state = SwapStateHolder(
SwapNotificationUM.Info.PermissionNeeded(
providerName = "Provider",
fromTokenSymbol = "POL",
onApproveClick = {},
),
SwapNotificationUM.Warning.NoAvailableTokensToSwap("POLYGON"),
),