Updated on 2026-08-14

This commit is contained in:
Tangem 2026-01-28 14:15:49 +03:00
parent bba00924d4
commit 5fa3c4b757
6 changed files with 55 additions and 21 deletions

View file

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

View file

@ -108,4 +108,6 @@ val UserWallet.isLocked
get() = when (this) {
is UserWallet.Cold -> isLocked
is UserWallet.Hot -> isLocked
}
}
inline val UserWallet.isHotWallet get() = this is UserWallet.Hot

View file

@ -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"
}
}

View file

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

View file

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

View file

@ -370,25 +370,42 @@ private fun SwapNotifications(notifications: List<NotificationUM>) {
@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,
)
}
}
}