Updated on 2026-08-14

This commit is contained in:
Tangem 2024-12-16 11:12:08 +05:00
commit eaf56fc0ae
5 changed files with 71 additions and 36 deletions

View file

@ -74,7 +74,7 @@ internal class OnrampStateFactory(
)
}
private fun getErrorState(errorCode: String? = null): OnrampMainComponentUM {
fun getErrorState(errorCode: String? = null): OnrampMainComponentUM {
val state = currentStateProvider()
val endButton = state.topBarConfig.endButtonUM.copy(enabled = true)
@ -84,6 +84,7 @@ internal class OnrampStateFactory(
buyButtonConfig = state.buyButtonConfig.copy(enabled = false),
amountBlockState = state.amountBlockState.copy(
amountFieldModel = state.amountBlockState.amountFieldModel.copy(isError = true),
secondaryFieldModel = OnrampAmountSecondaryFieldUM.Content(TextReference.EMPTY),
),
providerBlockState = OnrampProviderBlockUM.Empty,
errorNotification = NotificationUM.Warning.OnrampErrorNotification(

View file

@ -4,6 +4,7 @@ import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.utils.parseBigDecimalOrNull
import com.tangem.features.onramp.main.entity.OnrampAmountSecondaryFieldUM
import com.tangem.features.onramp.main.entity.OnrampMainComponentUM
import com.tangem.features.onramp.main.entity.OnrampProviderBlockUM
@ -24,7 +25,7 @@ internal class OnrampAmountFieldChangeConverter(
val amountState = state.amountBlockState
val amountTextField = amountState.amountFieldModel
val fiatDecimal = value.toBigDecimalOrNull() ?: BigDecimal.ZERO
val fiatDecimal = value.parseBigDecimalOrNull() ?: BigDecimal.ZERO
val isDoneActionEnabled = !fiatDecimal.isNullOrZero()
val amountFieldModel = amountState.amountFieldModel.copy(
fiatValue = value,

View file

@ -1,6 +1,7 @@
package com.tangem.features.onramp.main.entity.factory.amount
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.extensions.wrappedList
@ -144,6 +145,23 @@ internal class OnrampAmountStateFactory(
)
}
fun getAmountSecondaryResetState(): OnrampMainComponentUM {
val currentState = currentStateProvider()
if (currentState !is OnrampMainComponentUM.Content) return currentState
val amountState = currentState.amountBlockState
if (amountState.secondaryFieldModel is OnrampAmountSecondaryFieldUM.Content) return currentState
return currentState.copy(
amountBlockState = amountState.copy(
secondaryFieldModel = OnrampAmountSecondaryFieldUM.Content(
amount = TextReference.EMPTY,
),
),
)
}
private fun OnrampQuote.toProviderBlockState(isBestRate: Boolean): OnrampProviderBlockUM {
return OnrampProviderBlockUM.Content(
paymentMethod = paymentMethod,

View file

@ -157,7 +157,11 @@ internal class OnrampMainComponentModel @Inject constructor(
}
private suspend fun updatePairsAndQuotes() {
fetchPairsUseCase.invoke(params.cryptoCurrency).onLeft(::handleOnrampError)
_state.update { amountStateFactory.getAmountSecondaryLoadingState() }
fetchPairsUseCase.invoke(params.cryptoCurrency).fold(
ifLeft = ::handleOnrampError,
ifRight = { _state.update { amountStateFactory.getAmountSecondaryResetState() } },
)
startLoadingQuotes()
}
@ -195,39 +199,7 @@ internal class OnrampMainComponentModel @Inject constructor(
.onEach { maybeQuotes ->
maybeQuotes.fold(
ifLeft = ::handleOnrampError,
ifRight = { quotes ->
quotes.filterIsInstance<OnrampQuote.Error>().forEach { errorState ->
sendOnrampErrorAnalytic(errorState.error)
}
val quote = quotes.firstOrNull() ?: return@onEach
val bestProvider = quote as? OnrampQuote.Data
val isMultipleQuotes = !quotes.isSingleItem()
val isOtherQuotesHasData = quotes
.filter { it.paymentMethod == quote.paymentMethod }
.filterNot { it == bestProvider }
.any { it is OnrampQuote.Data }
val hasBestProvider = isMultipleQuotes && isOtherQuotesHasData
val isBestProvider = quote == bestProvider && hasBestProvider
if (quote is OnrampQuote.Data && lastAmount.value != quote.fromAmount.value) {
lastAmount.value = quote.fromAmount.value
analyticsEventHandler.send(
OnrampAnalyticsEvent.ProviderCalculated(
providerName = quote.provider.info.name,
tokenSymbol = params.cryptoCurrency.symbol,
paymentMethod = quote.paymentMethod.name,
),
)
}
_state.update {
amountStateFactory.getAmountSecondaryUpdatedState(
quote = quote,
isBestRate = isBestProvider,
)
}
},
ifRight = ::handleQuoteResult,
)
}
.launchIn(modelScope)
@ -296,6 +268,46 @@ internal class OnrampMainComponentModel @Inject constructor(
super.onDestroy()
}
private fun handleQuoteResult(quotes: List<OnrampQuote>) {
quotes.filterIsInstance<OnrampQuote.Error>().forEach { errorState ->
sendOnrampErrorAnalytic(errorState.error)
}
val quote = quotes.firstOrNull()
if (quote == null) {
_state.update { stateFactory.getErrorState() }
return
}
val bestProvider = quote as? OnrampQuote.Data
val isMultipleQuotes = !quotes.isSingleItem()
val isOtherQuotesHasData = quotes
.filter { it.paymentMethod == quote.paymentMethod }
.filterNot { it == bestProvider }
.any { it is OnrampQuote.Data }
val hasBestProvider = isMultipleQuotes && isOtherQuotesHasData
val isBestProvider = quote == bestProvider && hasBestProvider
if (quote is OnrampQuote.Data && lastAmount.value != quote.fromAmount.value) {
lastAmount.value = quote.fromAmount.value
analyticsEventHandler.send(
OnrampAnalyticsEvent.ProviderCalculated(
providerName = quote.provider.info.name,
tokenSymbol = params.cryptoCurrency.symbol,
paymentMethod = quote.paymentMethod.name,
),
)
}
_state.update {
amountStateFactory.getAmountSecondaryUpdatedState(
quote = quote,
isBestRate = isBestProvider,
)
}
}
private fun showDemoWarning() {
val alertUM = AlertDemoModeUM(onConfirmClick = {})