From 5fa3c4b75751aa334a385210e1d584217ce01957 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 28 Jan 2026 14:15:49 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../com/tangem/core/ui/components/Buttons.kt | 3 +- .../tangem/domain/models/wallet/UserWallet.kt | 4 +- .../tangem/feature/swap/model/SwapModel.kt | 6 ++ .../feature/swap/models/SwapStateHolder.kt | 1 + .../tangem/feature/swap/ui/StateBuilder.kt | 7 +++ .../feature/swap/ui/SwapScreenContent.kt | 55 ++++++++++++------- 6 files changed, 55 insertions(+), 21 deletions(-) diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/Buttons.kt b/core/ui/src/main/java/com/tangem/core/ui/components/Buttons.kt index 9ece5a3579..db823f8ad1 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/Buttons.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/Buttons.kt @@ -14,6 +14,7 @@ import androidx.compose.ui.text.TextStyle import androidx.compose.ui.tooling.preview.Preview import com.tangem.core.ui.R import com.tangem.core.ui.components.buttons.common.* +import com.tangem.core.ui.extensions.stringResourceSafe import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview @@ -291,9 +292,9 @@ fun SelectorButton(text: String, onClick: () -> Unit, modifier: Modifier = Modif @Composable fun HoldToConfirmButton( text: String, - hintText: String, onConfirm: () -> Unit, modifier: Modifier = Modifier, + hintText: String = stringResourceSafe(R.string.common_tap_and_hold_hint), enabled: Boolean = true, isLoading: Boolean = false, ) { diff --git a/domain/models/src/main/kotlin/com/tangem/domain/models/wallet/UserWallet.kt b/domain/models/src/main/kotlin/com/tangem/domain/models/wallet/UserWallet.kt index 8f2b0572ff..5df91b67b1 100644 --- a/domain/models/src/main/kotlin/com/tangem/domain/models/wallet/UserWallet.kt +++ b/domain/models/src/main/kotlin/com/tangem/domain/models/wallet/UserWallet.kt @@ -108,4 +108,6 @@ val UserWallet.isLocked get() = when (this) { is UserWallet.Cold -> isLocked is UserWallet.Hot -> isLocked - } \ No newline at end of file + } + +inline val UserWallet.isHotWallet get() = this is UserWallet.Hot \ No newline at end of file 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 24e0159328..be6829e703 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 @@ -104,6 +104,7 @@ import com.tangem.utils.TangemBlogUrlBuilder.RESOURCE_TO_LEARN_ABOUT_APPROVING_I import com.tangem.utils.coroutines.* import com.tangem.utils.isNullOrZero import kotlinx.coroutines.NonCancellable +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -944,6 +945,10 @@ internal class SwapModel @Inject constructor( if (fee == null && tangemPayInput?.isWithdrawal != true) { makeDefaultAlert(resourceReference(R.string.swapping_fee_estimation_error_text)) + modelScope.launch { + delay(SWAP_IN_PROGRESS_DELAY) + startLoadingQuotesFromLastState() + } return } modelScope.launch(dispatchers.main) { @@ -2237,6 +2242,7 @@ internal class SwapModel @Inject constructor( const val DEBOUNCE_AMOUNT_DELAY = 1000L const val DEBOUNCE_SEARCH_DELAY = 500L const val UPDATE_BALANCE_DELAY_MILLIS = 11000L + const val SWAP_IN_PROGRESS_DELAY = 200L const val CHANGELLY_PROVIDER_ID = "changelly" } } \ 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 f37d7dd2fe..47517e2801 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 @@ -79,6 +79,7 @@ data class SwapButton( @DrawableRes val walletInteractionIcon: Int?, val isEnabled: Boolean, val isInProgress: Boolean = false, + val isHoldToConfirm: Boolean = false, val onClick: () -> Unit, ) 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 a14f64d59f..f43c1f4caa 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 @@ -25,6 +25,7 @@ import com.tangem.domain.models.account.Account import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus 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 @@ -126,6 +127,7 @@ internal class StateBuilder( swapButton = SwapButton( walletInteractionIcon = walletInterationIcon(userWalletProvider()), isEnabled = false, + isHoldToConfirm = userWalletProvider().isHotWallet, onClick = {}, ), onRefresh = {}, @@ -185,6 +187,7 @@ internal class StateBuilder( swapButton = SwapButton( walletInteractionIcon = walletInterationIcon(userWalletProvider()), isEnabled = false, + isHoldToConfirm = userWalletProvider().isHotWallet, onClick = { }, ), changeCardsButtonState = ChangeCardsButtonState.DISABLED, @@ -250,6 +253,7 @@ internal class StateBuilder( swapButton = SwapButton( walletInteractionIcon = walletInterationIcon(userWalletProvider()), isEnabled = false, + isHoldToConfirm = userWalletProvider().isHotWallet, onClick = {}, ), providerState = ProviderState.Loading(), @@ -372,6 +376,7 @@ internal class StateBuilder( swapButton = SwapButton( walletInteractionIcon = walletInterationIcon(userWalletProvider()), isEnabled = getSwapButtonEnabled(notifications), + isHoldToConfirm = userWalletProvider().isHotWallet, onClick = actions.onSwapClick, ), changeCardsButtonState = getChangeCardsButtonState(isReverseSwapPossible), @@ -500,6 +505,7 @@ internal class StateBuilder( swapButton = SwapButton( walletInteractionIcon = walletInterationIcon(userWalletProvider()), isEnabled = false, + isHoldToConfirm = userWalletProvider().isHotWallet, onClick = actions.onSwapClick, ), changeCardsButtonState = getChangeCardsButtonState(isReverseSwapPossible), @@ -597,6 +603,7 @@ internal class StateBuilder( swapButton = SwapButton( walletInteractionIcon = walletInterationIcon(userWalletProvider()), isEnabled = false, + isHoldToConfirm = userWalletProvider().isHotWallet, onClick = { }, ), changeCardsButtonState = getChangeCardsButtonState(isReverseSwapPossible), 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 a1cb85f872..e55c8398bf 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 @@ -370,25 +370,42 @@ private fun SwapNotifications(notifications: List) { @Composable 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 = if (state.swapButton.isInProgress) { - stringResourceSafe(id = R.string.swapping_swap_action_in_progress) - } else { - stringResourceSafe(id = R.string.swapping_swap_action) - }, - iconResId = state.swapButton.walletInteractionIcon, - enabled = state.swapButton.isEnabled, - onClick = state.swapButton.onClick, - ) + when { + state.isInsufficientFunds -> { + PrimaryButton( + modifier = Modifier.fillMaxWidth(), + text = stringResourceSafe(id = R.string.swapping_insufficient_funds), + enabled = false, + onClick = state.swapButton.onClick, + ) + } + + state.swapButton.isHoldToConfirm -> { + HoldToConfirmButton( + modifier = Modifier.fillMaxWidth(), + text = stringResourceSafe( + R.string.common_hold_to, + stringResourceSafe(id = R.string.swapping_swap_action), + ), + enabled = state.swapButton.isEnabled, + onConfirm = state.swapButton.onClick, + isLoading = state.swapButton.isInProgress, + ) + } + + else -> { + PrimaryButtonIconEnd( + modifier = Modifier.fillMaxWidth(), + text = if (state.swapButton.isInProgress) { + stringResourceSafe(id = R.string.swapping_swap_action_in_progress) + } else { + stringResourceSafe(id = R.string.swapping_swap_action) + }, + iconResId = state.swapButton.walletInteractionIcon, + enabled = state.swapButton.isEnabled, + onClick = state.swapButton.onClick, + ) + } } }