Updated on 2026-08-14
This commit is contained in:
commit
484c4138af
7 changed files with 49 additions and 39 deletions
|
|
@ -105,10 +105,10 @@ internal class SwapAmountModel @Inject constructor(
|
|||
private var secondaryMaximumAmountBoundary: EnterAmountBoundary? = null
|
||||
private var secondaryMinimumAmountBoundary: EnterAmountBoundary? = null
|
||||
|
||||
var userCountry: UserCountry = UserCountry.Other(Locale.getDefault().country)
|
||||
private var userCountry: UserCountry = UserCountry.Other(Locale.getDefault().country)
|
||||
val bottomSheetNavigation: SlotNavigation<SwapChooseProviderConfig> = SlotNavigation()
|
||||
|
||||
var showBestRateAnimation: Boolean = false
|
||||
private var showBestRateAnimation: Boolean = false
|
||||
|
||||
val uiState: StateFlow<SwapAmountUM>
|
||||
field = MutableStateFlow(params.amountUM)
|
||||
|
|
@ -134,7 +134,10 @@ internal class SwapAmountModel @Inject constructor(
|
|||
}
|
||||
|
||||
fun onStart() {
|
||||
startLoadingQuotesTask(isSilentReload = false)
|
||||
quoteTaskScheduler.scheduleTask(
|
||||
scope = modelScope,
|
||||
task = loadQuotesTask(),
|
||||
)
|
||||
}
|
||||
|
||||
fun onStop() {
|
||||
|
|
@ -533,18 +536,17 @@ internal class SwapAmountModel @Inject constructor(
|
|||
} as? AmountState.Data
|
||||
|
||||
val fromAmountValue = fromAmount?.amountTextField?.cryptoAmount?.value.orZero()
|
||||
|
||||
if (fromAmount?.amountTextField?.isError == true || fromAmountValue.isNullOrZero()) {
|
||||
val isAmountScreen = params is SwapAmountComponentParams.AmountParams
|
||||
val isAmountError = fromAmount?.amountTextField?.isError == true || fromAmountValue.isNullOrZero()
|
||||
if (isAmountScreen && isAmountError) {
|
||||
uiState.transformerUpdate(SwapQuoteEmptyStateTransformer)
|
||||
return
|
||||
}
|
||||
|
||||
val swapGroups = state.swapCurrencies.getGroupWithDirection(state.swapDirection)
|
||||
|
||||
uiState.transformerUpdate(SwapQuoteLoadingStateTransformer)
|
||||
if (!isSilentReload) { uiState.transformerUpdate(SwapQuoteLoadingStateTransformer) }
|
||||
|
||||
modelScope.launch {
|
||||
val quotes = swapGroups.available.filter {
|
||||
val quotes = state.swapCurrencies.getGroupWithDirection(state.swapDirection).available.filter {
|
||||
it.currencyStatus.currency.id == toCryptoCurrency.id
|
||||
}.flatMap {
|
||||
it.providers
|
||||
|
|
@ -591,7 +593,6 @@ internal class SwapAmountModel @Inject constructor(
|
|||
needApplyFcaRestrictions = userCountry.needApplyFCARestrictions(),
|
||||
),
|
||||
)
|
||||
|
||||
feeSelectorReloadTrigger.triggerUpdate()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,8 +34,10 @@ internal class SwapAmountSetQuotesTransformer(
|
|||
|
||||
val sortedQuotes = quotes.sortedWith(SwapQuotesComparator)
|
||||
val bestQuote = findBestQuote(quotes) ?: SwapQuoteUM.Empty
|
||||
val quotesWithDiff = getQuotesWithDiff(sortedQuotes, bestQuote, isSingleProvider)
|
||||
val selectedQuote = if (isSilentReload && prevState.selectedQuote !is SwapQuoteUM.Loading) {
|
||||
prevState.selectedQuote
|
||||
quotesWithDiff.firstOrNull { it.provider?.providerId == prevState.selectedQuote.provider?.providerId }
|
||||
?: prevState.selectedQuote
|
||||
} else {
|
||||
(bestQuote as? SwapQuoteUM.Content)?.copy(
|
||||
diffPercent = DifferencePercent.Best,
|
||||
|
|
@ -55,7 +57,7 @@ internal class SwapAmountSetQuotesTransformer(
|
|||
if (updatedState !is SwapAmountUM.Content) return prevState
|
||||
|
||||
return updatedState.copy(
|
||||
isPrimaryButtonEnabled = updatedState.isPrimaryButtonEnabled && quotes.isNotEmpty(),
|
||||
isPrimaryButtonEnabled = updatedState.isPrimaryButtonEnabled && quotesWithDiff.isNotEmpty(),
|
||||
swapQuotes = getQuotesWithDiff(sortedQuotes, bestQuote, isSingleProvider),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ internal class SwapAmountValueChangeTransformer(
|
|||
)
|
||||
|
||||
return (updatedState as? SwapAmountUM.Content)?.copy(
|
||||
isPrimaryButtonEnabled = false,
|
||||
selectedQuote = if (updatedState.isPrimaryButtonEnabled) {
|
||||
SwapQuoteUM.Empty
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -16,31 +16,34 @@ internal class SwapAmountValueMaxTransformer(
|
|||
override fun transform(prevState: SwapAmountUM): SwapAmountUM {
|
||||
if (prevState !is SwapAmountUM.Content) return prevState
|
||||
|
||||
return prevState
|
||||
.copy(selectedQuote = SwapQuoteUM.Loading)
|
||||
.updateAmount(
|
||||
onPrimaryAmount = { primaryStatus ->
|
||||
val updatedState = prevState.updateAmount(
|
||||
onPrimaryAmount = { primaryStatus ->
|
||||
copy(
|
||||
amountField = AmountFieldSetMaxAmountTransformer(
|
||||
cryptoCurrencyStatus = primaryStatus,
|
||||
maxAmount = primaryMaximumAmountBoundary,
|
||||
minAmount = primaryMinimumAmountBoundary,
|
||||
).transform(prevState.primaryAmount.amountField),
|
||||
)
|
||||
},
|
||||
onSecondaryAmount = { secondaryStatus ->
|
||||
if (secondaryMaximumAmountBoundary != null) {
|
||||
copy(
|
||||
amountField = AmountFieldSetMaxAmountTransformer(
|
||||
cryptoCurrencyStatus = primaryStatus,
|
||||
maxAmount = primaryMaximumAmountBoundary,
|
||||
minAmount = primaryMinimumAmountBoundary,
|
||||
).transform(prevState.primaryAmount.amountField),
|
||||
cryptoCurrencyStatus = secondaryStatus,
|
||||
maxAmount = secondaryMaximumAmountBoundary,
|
||||
minAmount = secondaryMinimumAmountBoundary,
|
||||
).transform(prevState.secondaryAmount.amountField),
|
||||
)
|
||||
},
|
||||
onSecondaryAmount = { secondaryStatus ->
|
||||
if (secondaryMaximumAmountBoundary != null) {
|
||||
copy(
|
||||
amountField = AmountFieldSetMaxAmountTransformer(
|
||||
cryptoCurrencyStatus = secondaryStatus,
|
||||
maxAmount = secondaryMaximumAmountBoundary,
|
||||
minAmount = secondaryMinimumAmountBoundary,
|
||||
).transform(prevState.secondaryAmount.amountField),
|
||||
)
|
||||
} else {
|
||||
this
|
||||
}
|
||||
},
|
||||
)
|
||||
} else {
|
||||
this
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
return (updatedState as? SwapAmountUM.Content)?.copy(
|
||||
isPrimaryButtonEnabled = false,
|
||||
selectedQuote = SwapQuoteUM.Loading,
|
||||
) ?: updatedState
|
||||
}
|
||||
}
|
||||
|
|
@ -42,7 +42,7 @@ internal class SwapProviderStateConverter(
|
|||
|
||||
val additionalBadge = when {
|
||||
needApplyFCARestrictions && provider.isRestrictedByFCA() -> AdditionalBadge.FCAWarningList
|
||||
isNeedBestRateBadge && isBestRate && !needApplyFCARestrictions -> AdditionalBadge.BestTrade
|
||||
isNeedBestRateBadge && isBestRate -> AdditionalBadge.BestTrade
|
||||
else -> AdditionalBadge.Empty
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -94,13 +94,15 @@ internal class DefaultSendWithSwapComponent @AssistedInject constructor(
|
|||
)
|
||||
activeComponent.updateState(model.uiState.value.destinationUM)
|
||||
}
|
||||
is SendWithSwapConfirmComponent -> if (model.currentRoute.value.isEditMode) {
|
||||
is SendWithSwapConfirmComponent -> {
|
||||
analyticsEventHandler.send(
|
||||
CommonSendAnalyticEvents.ConfirmationScreenOpened(
|
||||
categoryName = model.analyticCategoryName,
|
||||
),
|
||||
)
|
||||
activeComponent.updateState(model.uiState.value)
|
||||
if (model.currentRoute.value.isEditMode) {
|
||||
activeComponent.updateState(model.uiState.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
model.currentRoute.emit(stack.active.configuration)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.features.swap.v2.impl.sendviaswap.analytics
|
|||
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.FEE_TYPE
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.PROVIDER
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.RECEIVE_BLOCKCHAIN
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.RECEIVE_TOKEN
|
||||
|
|
@ -24,7 +25,7 @@ internal sealed class SendWithSwapAnalyticEvents(
|
|||
event = "Send With Swap In Progress Screen Opened",
|
||||
params = mapOf(
|
||||
PROVIDER to providerName,
|
||||
"Commission" to if (feeType is AnalyticsParam.FeeType.Normal) "Market" else "Fast",
|
||||
FEE_TYPE to if (feeType is AnalyticsParam.FeeType.Normal) "Market" else "Fast",
|
||||
SEND_TOKEN to fromToken.symbol,
|
||||
RECEIVE_TOKEN to toToken.symbol,
|
||||
SEND_BLOCKCHAIN to fromToken.network.name,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue