Updated on 2026-08-14
This commit is contained in:
commit
cdd662f90b
11 changed files with 171 additions and 114 deletions
|
|
@ -140,9 +140,10 @@ internal object OnrampDomainModule {
|
|||
@Singleton
|
||||
fun provideGetOnrampPaymentMethodsUseCase(
|
||||
onrampRepository: OnrampRepository,
|
||||
settingsRepository: SettingsRepository,
|
||||
onrampErrorResolver: OnrampErrorResolver,
|
||||
): GetOnrampPaymentMethodsUseCase {
|
||||
return GetOnrampPaymentMethodsUseCase(onrampRepository, onrampErrorResolver)
|
||||
return GetOnrampPaymentMethodsUseCase(onrampRepository, settingsRepository, onrampErrorResolver)
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
|
|||
|
|
@ -343,9 +343,7 @@ internal class DefaultOnrampRepository(
|
|||
|
||||
override suspend fun getAvailablePaymentMethods(): Set<OnrampPaymentMethod> {
|
||||
val quotes = requireNotNull(quotesStore.getSyncOrNull(QUOTES_KEY)) { "Quotes must not be null" }
|
||||
return quotes
|
||||
.filterIsInstance<OnrampQuote.Data>()
|
||||
.mapTo(hashSetOf(), OnrampQuote.Data::paymentMethod)
|
||||
return quotes.mapTo(hashSetOf(), OnrampQuote::paymentMethod)
|
||||
}
|
||||
|
||||
override suspend fun saveSelectedPaymentMethod(paymentMethod: OnrampPaymentMethod) {
|
||||
|
|
|
|||
|
|
@ -5,14 +5,22 @@ import com.tangem.domain.onramp.model.OnrampPaymentMethod
|
|||
import com.tangem.domain.onramp.model.error.OnrampError
|
||||
import com.tangem.domain.onramp.repositories.OnrampErrorResolver
|
||||
import com.tangem.domain.onramp.repositories.OnrampRepository
|
||||
import com.tangem.domain.settings.repositories.SettingsRepository
|
||||
|
||||
class GetOnrampPaymentMethodsUseCase(
|
||||
private val repository: OnrampRepository,
|
||||
private val settingsRepository: SettingsRepository,
|
||||
private val errorResolver: OnrampErrorResolver,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(): Either<OnrampError, Set<OnrampPaymentMethod>> {
|
||||
return Either.catch { repository.getAvailablePaymentMethods() }
|
||||
.mapLeft(errorResolver::resolve)
|
||||
return Either.catch {
|
||||
val isGooglePayAvailable = settingsRepository.isGooglePayAvailability()
|
||||
|
||||
repository.getAvailablePaymentMethods()
|
||||
.toList()
|
||||
.sortedBy { it.type.getPriority(isGooglePayAvailable) }
|
||||
.toSet()
|
||||
}.mapLeft(errorResolver::resolve)
|
||||
}
|
||||
}
|
||||
|
|
@ -31,34 +31,23 @@ class GetOnrampProviderWithQuoteUseCase(
|
|||
private fun List<OnrampQuote>.quoteWithProvider(
|
||||
provider: OnrampProvider,
|
||||
selectedPaymentMethod: OnrampPaymentMethod,
|
||||
): OnrampProviderWithQuote? {
|
||||
val quoteData = this.filterIsInstance<OnrampQuote.Data>()
|
||||
val matchedPaymentMethodQuote = quoteData.firstOrNull { it.paymentMethod == selectedPaymentMethod }
|
||||
val paymentMethodNotSupported = quoteData.filterNot { it.paymentMethod == selectedPaymentMethod }
|
||||
val amountError =
|
||||
filterIsInstance<OnrampQuote.Error>().firstOrNull { it.paymentMethod == selectedPaymentMethod }
|
||||
return when {
|
||||
matchedPaymentMethodQuote != null -> {
|
||||
OnrampProviderWithQuote.Data(
|
||||
provider = matchedPaymentMethodQuote.provider,
|
||||
paymentMethod = matchedPaymentMethodQuote.paymentMethod,
|
||||
toAmount = matchedPaymentMethodQuote.toAmount,
|
||||
fromAmount = matchedPaymentMethodQuote.fromAmount,
|
||||
)
|
||||
}
|
||||
paymentMethodNotSupported.isNotEmpty() -> {
|
||||
Unavailable.NotSupportedPaymentMethod(
|
||||
provider = provider,
|
||||
availablePaymentMethods = paymentMethodNotSupported.map(OnrampQuote.Data::paymentMethod),
|
||||
)
|
||||
}
|
||||
amountError != null -> {
|
||||
Unavailable.Error(
|
||||
amountError.provider,
|
||||
amountError,
|
||||
)
|
||||
}
|
||||
else -> null
|
||||
): OnrampProviderWithQuote {
|
||||
val matchedQuote = firstOrNull { it.paymentMethod == selectedPaymentMethod }
|
||||
return when (matchedQuote) {
|
||||
is OnrampQuote.Data -> OnrampProviderWithQuote.Data(
|
||||
provider = matchedQuote.provider,
|
||||
paymentMethod = matchedQuote.paymentMethod,
|
||||
toAmount = matchedQuote.toAmount,
|
||||
fromAmount = matchedQuote.fromAmount,
|
||||
)
|
||||
is OnrampQuote.Error -> Unavailable.Error(
|
||||
provider = matchedQuote.provider,
|
||||
quoteError = matchedQuote,
|
||||
)
|
||||
null -> Unavailable.NotSupportedPaymentMethod(
|
||||
provider = provider,
|
||||
availablePaymentMethods = provider.paymentMethods,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -38,6 +38,7 @@ import com.tangem.utils.Provider
|
|||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.coroutines.PeriodicTask
|
||||
import com.tangem.utils.coroutines.SingleTaskScheduler
|
||||
import com.tangem.utils.extensions.isSingleItem
|
||||
import com.tangem.utils.isNullOrZero
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -196,8 +197,17 @@ internal class OnrampMainComponentModel @Inject constructor(
|
|||
quotes.filterIsInstance<OnrampQuote.Error>().forEach { errorState ->
|
||||
sendOnrampErrorAnalytic(errorState.error)
|
||||
}
|
||||
val isNoQuotes = quotes.none { it is OnrampQuote.Data }
|
||||
val quote = quotes.firstOrNull() ?: return@onEach
|
||||
|
||||
val bestProvider = quote as? OnrampQuote.Data
|
||||
val isMultipleQuotes = !quotes.isSingleItem()
|
||||
val isOtherQuotesHasData = quotes
|
||||
.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(
|
||||
|
|
@ -208,7 +218,12 @@ internal class OnrampMainComponentModel @Inject constructor(
|
|||
),
|
||||
)
|
||||
}
|
||||
_state.update { amountStateFactory.getAmountSecondaryUpdatedState(quote, isNoQuotes) }
|
||||
_state.update {
|
||||
amountStateFactory.getAmountSecondaryUpdatedState(
|
||||
quote = quote,
|
||||
isBestRate = isBestProvider,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.features.onramp.providers.entity
|
||||
|
||||
import com.tangem.features.onramp.paymentmethod.entity.PaymentMethodUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
|
|
@ -9,6 +10,6 @@ internal sealed interface ProviderListBottomSheetConfig {
|
|||
@Serializable
|
||||
data class PaymentMethods(
|
||||
val selectedMethodId: String,
|
||||
val paymentMethodsUM: List<PaymentMethodUM>,
|
||||
val paymentMethodsUM: ImmutableList<PaymentMethodUM>,
|
||||
) : ProviderListBottomSheetConfig
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@ internal sealed interface ProviderListItemUM {
|
|||
val imageUrl: String,
|
||||
val rate: String,
|
||||
val isBestRate: Boolean,
|
||||
val diffRate: TextReference,
|
||||
val diffRate: TextReference?,
|
||||
val isSelected: Boolean,
|
||||
val onClick: () -> Unit,
|
||||
) : ProviderListItemUM
|
||||
|
|
|
|||
|
|
@ -1,8 +1,16 @@
|
|||
package com.tangem.features.onramp.providers.entity
|
||||
|
||||
import com.tangem.domain.onramp.model.OnrampPaymentMethod
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
internal data class ProviderListUM(
|
||||
val paymentMethod: ProviderListPaymentMethodUM,
|
||||
internal data class SelectPaymentAndProviderUM(
|
||||
val paymentMethods: ImmutableList<OnrampPaymentMethod>,
|
||||
val selectedPaymentMethod: SelectProviderUM,
|
||||
val isPaymentMethodClickEnabled: Boolean,
|
||||
val onPaymentMethodClick: () -> Unit,
|
||||
)
|
||||
|
||||
internal data class SelectProviderUM(
|
||||
val paymentMethod: OnrampPaymentMethod,
|
||||
val providers: ImmutableList<ProviderListItemUM>,
|
||||
)
|
||||
|
|
@ -28,8 +28,11 @@ import com.tangem.features.onramp.providers.entity.*
|
|||
import com.tangem.features.onramp.utils.sendOnrampErrorEvent
|
||||
import com.tangem.utils.StringsSigns.MINUS
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.extensions.isSingleItem
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
|
@ -41,24 +44,41 @@ import javax.inject.Inject
|
|||
internal class SelectProviderModel @Inject constructor(
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val getSelectedPaymentMethodsUseCase: GetOnrampPaymentMethodsUseCase,
|
||||
private val getOnrampPaymentMethodsUseCase: GetOnrampPaymentMethodsUseCase,
|
||||
private val getOnrampSelectedPaymentMethodUseCase: GetOnrampSelectedPaymentMethodUseCase,
|
||||
private val getOnrampProviderWithQuoteUseCase: GetOnrampProviderWithQuoteUseCase,
|
||||
private val saveSelectedPaymentMethod: OnrampSaveSelectedPaymentMethod,
|
||||
paramsContainer: ParamsContainer,
|
||||
) : Model() {
|
||||
|
||||
val state: StateFlow<ProviderListUM> get() = _state.asStateFlow()
|
||||
val state: StateFlow<SelectPaymentAndProviderUM> get() = _state.asStateFlow()
|
||||
val bottomSheetNavigation: SlotNavigation<ProviderListBottomSheetConfig> = SlotNavigation()
|
||||
private val params: SelectProviderComponent.Params = paramsContainer.require()
|
||||
private val _state = MutableStateFlow(getInitialState())
|
||||
|
||||
init {
|
||||
analyticsEventHandler.send(OnrampAnalyticsEvent.ProvidersScreenOpened)
|
||||
getPaymentMethods()
|
||||
getProviders(params.selectedPaymentMethod)
|
||||
subscribeToPaymentMethodUpdates()
|
||||
}
|
||||
|
||||
private fun getPaymentMethods() {
|
||||
modelScope.launch {
|
||||
val methods = getOnrampPaymentMethodsUseCase().fold(
|
||||
ifLeft = { error ->
|
||||
sendOnrampErrorEvent(error)
|
||||
emptySet()
|
||||
},
|
||||
ifRight = { it },
|
||||
)
|
||||
_state.value = state.value.copy(
|
||||
paymentMethods = methods.toPersistentList(),
|
||||
isPaymentMethodClickEnabled = methods.isNotEmpty(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun subscribeToPaymentMethodUpdates() {
|
||||
getOnrampSelectedPaymentMethodUseCase.invoke()
|
||||
.onEach { maybePaymentMethod ->
|
||||
|
|
@ -74,11 +94,11 @@ internal class SelectProviderModel @Inject constructor(
|
|||
modelScope.launch {
|
||||
getOnrampProviderWithQuoteUseCase.invoke(paymentMethod)
|
||||
.onRight { quotes ->
|
||||
val hasQuotesData = quotes.any { it is OnrampProviderWithQuote.Data }
|
||||
_state.update { state ->
|
||||
state.copy(
|
||||
paymentMethod = state.paymentMethod.copy(enabled = hasQuotesData),
|
||||
providers = quotes.toProvidersListItems(),
|
||||
selectedPaymentMethod = state.selectedPaymentMethod.copy(
|
||||
providers = quotes.toProvidersListItems(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -89,58 +109,47 @@ internal class SelectProviderModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun getInitialState(): ProviderListUM {
|
||||
return ProviderListUM(
|
||||
paymentMethod = ProviderListPaymentMethodUM(
|
||||
id = params.selectedPaymentMethod.id,
|
||||
name = params.selectedPaymentMethod.name,
|
||||
imageUrl = params.selectedPaymentMethod.imageUrl,
|
||||
enabled = false,
|
||||
onClick = ::openPaymentMethods,
|
||||
private fun getInitialState(): SelectPaymentAndProviderUM {
|
||||
return SelectPaymentAndProviderUM(
|
||||
paymentMethods = persistentListOf(params.selectedPaymentMethod),
|
||||
isPaymentMethodClickEnabled = false,
|
||||
onPaymentMethodClick = ::openPaymentMethods,
|
||||
selectedPaymentMethod = SelectProviderUM(
|
||||
paymentMethod = params.selectedPaymentMethod,
|
||||
providers = emptyList<ProviderListItemUM>().toImmutableList(),
|
||||
),
|
||||
providers = emptyList<ProviderListItemUM>().toImmutableList(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun openPaymentMethods() {
|
||||
analyticsEventHandler.send(OnrampAnalyticsEvent.PaymentMethodsScreenOpened)
|
||||
modelScope.launch {
|
||||
val methods = getSelectedPaymentMethodsUseCase().fold(
|
||||
ifLeft = { error ->
|
||||
sendOnrampErrorEvent(error)
|
||||
emptySet()
|
||||
},
|
||||
ifRight = { it },
|
||||
)
|
||||
bottomSheetNavigation.activate(
|
||||
ProviderListBottomSheetConfig.PaymentMethods(
|
||||
selectedMethodId = _state.value.paymentMethod.id,
|
||||
paymentMethodsUM = methods.toPaymentUMList(),
|
||||
),
|
||||
)
|
||||
}
|
||||
bottomSheetNavigation.activate(
|
||||
ProviderListBottomSheetConfig.PaymentMethods(
|
||||
selectedMethodId = state.value.selectedPaymentMethod.paymentMethod.id,
|
||||
paymentMethodsUM = state.value.paymentMethods.toPaymentUMList(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun Set<OnrampPaymentMethod>.toPaymentUMList(): List<PaymentMethodUM> = map { method ->
|
||||
private fun ImmutableList<OnrampPaymentMethod>.toPaymentUMList(): ImmutableList<PaymentMethodUM> = map { method ->
|
||||
PaymentMethodUM(
|
||||
id = method.id,
|
||||
imageUrl = method.imageUrl,
|
||||
name = method.name,
|
||||
onSelect = { onPaymentMethodSelected(method) },
|
||||
)
|
||||
}
|
||||
}.toPersistentList()
|
||||
|
||||
private fun onPaymentMethodSelected(paymentMethod: OnrampPaymentMethod) {
|
||||
analyticsEventHandler.send(OnrampAnalyticsEvent.OnPaymentMethodChosen(paymentMethod = paymentMethod.name))
|
||||
modelScope.launch {
|
||||
saveSelectedPaymentMethod.invoke(paymentMethod)
|
||||
_state.update { state ->
|
||||
val paymentMethodUM = state.paymentMethod.copy(
|
||||
id = paymentMethod.id,
|
||||
name = paymentMethod.name,
|
||||
imageUrl = paymentMethod.imageUrl,
|
||||
state.copy(
|
||||
selectedPaymentMethod = state.selectedPaymentMethod.copy(
|
||||
paymentMethod = paymentMethod,
|
||||
),
|
||||
)
|
||||
state.copy(paymentMethod = paymentMethodUM)
|
||||
}
|
||||
bottomSheetNavigation.dismiss()
|
||||
}
|
||||
|
|
@ -151,7 +160,11 @@ internal class SelectProviderModel @Inject constructor(
|
|||
val sorted = sortByRate()
|
||||
|
||||
val bestProvider = sorted.firstOrNull() as? OnrampProviderWithQuote.Data
|
||||
return sorted.mapIndexed { index, quote ->
|
||||
val isMultipleQuotes = !sorted.isSingleItem()
|
||||
val isOtherQuotesHasData = sorted.filterNot { it == bestProvider }.any { it is OnrampProviderWithQuote.Data }
|
||||
val hasBestProvider = isMultipleQuotes && isOtherQuotesHasData
|
||||
|
||||
return sorted.map { quote ->
|
||||
when (quote) {
|
||||
is OnrampProviderWithQuote.Data -> {
|
||||
val rate = quote.toAmount.value.format {
|
||||
|
|
@ -162,14 +175,16 @@ internal class SelectProviderModel @Inject constructor(
|
|||
}
|
||||
val isSelectedProvider = quote.provider.id == params.selectedProviderId
|
||||
val isSelectedPayment = quote.paymentMethod.id == params.selectedPaymentMethod.id
|
||||
val isBestProvider = quote == bestProvider && hasBestProvider
|
||||
ProviderListItemUM.Available(
|
||||
providerId = quote.provider.id,
|
||||
imageUrl = quote.provider.info.imageLarge,
|
||||
name = quote.provider.info.name,
|
||||
rate = rate,
|
||||
isSelected = isSelectedProvider && isSelectedPayment,
|
||||
isBestRate = quote == bestProvider,
|
||||
diffRate = stringReference("$MINUS${rateDiff.format { percent() }}"),
|
||||
isBestRate = isBestProvider,
|
||||
diffRate = stringReference("$MINUS${rateDiff.format { percent() }}")
|
||||
.takeIf { hasBestProvider },
|
||||
onClick = {
|
||||
onProviderSelected(
|
||||
result = SelectProviderResult.ProviderWithQuote(
|
||||
|
|
@ -178,7 +193,7 @@ internal class SelectProviderModel @Inject constructor(
|
|||
fromAmount = quote.fromAmount,
|
||||
toAmount = quote.toAmount,
|
||||
),
|
||||
isBestRate = bestProvider == quote,
|
||||
isBestRate = isBestProvider,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
|
@ -237,7 +252,7 @@ internal class SelectProviderModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun sendOnrampErrorEvent(error: OnrampError) {
|
||||
val selectedProvider = state.value.providers.firstOrNull {
|
||||
val selectedProvider = state.value.selectedPaymentMethod.providers.firstOrNull {
|
||||
it.providerId == params.selectedProviderId
|
||||
}
|
||||
analyticsEventHandler.sendOnrampErrorEvent(
|
||||
|
|
|
|||
|
|
@ -2,21 +2,26 @@ package com.tangem.features.onramp.providers.model.previewData
|
|||
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.domain.onramp.model.OnrampPaymentMethod
|
||||
import com.tangem.domain.onramp.model.PaymentMethodType
|
||||
import com.tangem.features.onramp.providers.entity.ProviderListItemUM
|
||||
import com.tangem.features.onramp.providers.entity.ProviderListPaymentMethodUM
|
||||
import com.tangem.features.onramp.providers.entity.ProviderListUM
|
||||
import com.tangem.features.onramp.providers.entity.SelectPaymentAndProviderUM
|
||||
import com.tangem.features.onramp.providers.entity.SelectProviderUM
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
internal object SelectProviderPreviewData {
|
||||
|
||||
val state = ProviderListUM(
|
||||
paymentMethod = ProviderListPaymentMethodUM(
|
||||
private val paymentMethods = persistentListOf(
|
||||
OnrampPaymentMethod(
|
||||
id = "card",
|
||||
name = "Card",
|
||||
imageUrl = "https://s3.eu-central-1.amazonaws.com/tangem.api/express/PaymentMethods/visa-mc.png",
|
||||
onClick = {},
|
||||
enabled = false,
|
||||
type = PaymentMethodType.CARD,
|
||||
),
|
||||
)
|
||||
|
||||
private val providerListUM = SelectProviderUM(
|
||||
paymentMethod = paymentMethods.first(),
|
||||
providers = persistentListOf(
|
||||
ProviderListItemUM.Available(
|
||||
providerId = "mercuryo",
|
||||
|
|
@ -46,4 +51,11 @@ internal object SelectProviderPreviewData {
|
|||
),
|
||||
),
|
||||
)
|
||||
|
||||
val state = SelectPaymentAndProviderUM(
|
||||
paymentMethods = paymentMethods,
|
||||
selectedPaymentMethod = providerListUM,
|
||||
isPaymentMethodClickEnabled = false,
|
||||
onPaymentMethodClick = {},
|
||||
)
|
||||
}
|
||||
|
|
@ -32,11 +32,11 @@ import com.tangem.core.ui.extensions.resolveReference
|
|||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.domain.onramp.model.OnrampPaymentMethod
|
||||
import com.tangem.features.onramp.impl.R
|
||||
import com.tangem.features.onramp.paymentmethod.ui.PaymentMethodIcon
|
||||
import com.tangem.features.onramp.providers.entity.ProviderListItemUM
|
||||
import com.tangem.features.onramp.providers.entity.ProviderListPaymentMethodUM
|
||||
import com.tangem.features.onramp.providers.entity.ProviderListUM
|
||||
import com.tangem.features.onramp.providers.entity.SelectPaymentAndProviderUM
|
||||
import com.tangem.features.onramp.providers.model.previewData.SelectProviderPreviewData
|
||||
import com.tangem.features.onramp.utils.selectedBorder
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ internal fun SelectProviderBottomSheet(config: TangemBottomSheetConfig, content:
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun SelectProviderBottomSheetContent(state: ProviderListUM, modifier: Modifier = Modifier) {
|
||||
internal fun SelectProviderBottomSheetContent(state: SelectPaymentAndProviderUM, modifier: Modifier = Modifier) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.background(TangemTheme.colors.background.primary)
|
||||
|
|
@ -65,16 +65,23 @@ internal fun SelectProviderBottomSheetContent(state: ProviderListUM, modifier: M
|
|||
)
|
||||
PaymentMethodBlock(
|
||||
modifier = Modifier.padding(top = TangemTheme.dimens.spacing20, bottom = TangemTheme.dimens.spacing16),
|
||||
state = state.paymentMethod,
|
||||
state = state.selectedPaymentMethod.paymentMethod,
|
||||
isClickEnabled = state.isPaymentMethodClickEnabled,
|
||||
onPaymentMethodClick = state.onPaymentMethodClick,
|
||||
)
|
||||
state.providers.fastForEach { provider ->
|
||||
state.selectedPaymentMethod.providers.fastForEach { provider ->
|
||||
key(provider.providerId) { ProviderItem(state = provider) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PaymentMethodBlock(state: ProviderListPaymentMethodUM, modifier: Modifier = Modifier) {
|
||||
private fun PaymentMethodBlock(
|
||||
state: OnrampPaymentMethod,
|
||||
isClickEnabled: Boolean,
|
||||
onPaymentMethodClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.clip(RoundedCornerShape(TangemTheme.dimens.radius16))
|
||||
|
|
@ -83,7 +90,7 @@ private fun PaymentMethodBlock(state: ProviderListPaymentMethodUM, modifier: Mod
|
|||
color = TangemTheme.colors.stroke.secondary,
|
||||
shape = RoundedCornerShape(TangemTheme.dimens.radius16),
|
||||
)
|
||||
.clickable(enabled = state.enabled, onClick = state.onClick)
|
||||
.clickable(enabled = isClickEnabled, onClick = onPaymentMethodClick)
|
||||
.padding(all = TangemTheme.dimens.spacing12),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
|
||||
|
|
@ -177,23 +184,26 @@ private fun AvailableProviderItem(state: ProviderListItemUM.Available, modifier:
|
|||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
if (state.isBestRate) {
|
||||
Text(
|
||||
text = stringResource(R.string.express_provider_best_rate),
|
||||
style = TangemTheme.typography.caption1,
|
||||
color = TangemTheme.colors.text.constantWhite,
|
||||
modifier = Modifier
|
||||
.clip(RoundedCornerShape(4.dp))
|
||||
.background(TangemTheme.colors.icon.accent)
|
||||
.padding(vertical = 1.dp, horizontal = 6.dp),
|
||||
)
|
||||
} else {
|
||||
Text(
|
||||
text = state.diffRate.resolveReference(),
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.warning,
|
||||
modifier = Modifier.padding(vertical = 1.dp),
|
||||
)
|
||||
when {
|
||||
state.isBestRate -> {
|
||||
Text(
|
||||
text = stringResource(R.string.express_provider_best_rate),
|
||||
style = TangemTheme.typography.caption1,
|
||||
color = TangemTheme.colors.text.constantWhite,
|
||||
modifier = Modifier
|
||||
.clip(RoundedCornerShape(4.dp))
|
||||
.background(TangemTheme.colors.icon.accent)
|
||||
.padding(vertical = 1.dp, horizontal = 6.dp),
|
||||
)
|
||||
}
|
||||
state.diffRate != null -> {
|
||||
Text(
|
||||
text = state.diffRate.resolveReference(),
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.warning,
|
||||
modifier = Modifier.padding(vertical = 1.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -247,7 +257,7 @@ private fun UnavailableProviderItem(
|
|||
@Composable
|
||||
private fun SelectProviderBottomSheetContent_Preview(
|
||||
@PreviewParameter(SelectProviderBottomSheetContentPreviewProvider::class)
|
||||
data: ProviderListUM,
|
||||
data: SelectPaymentAndProviderUM,
|
||||
) {
|
||||
TangemThemePreview {
|
||||
SelectProviderBottomSheetContent(data)
|
||||
|
|
@ -255,8 +265,8 @@ private fun SelectProviderBottomSheetContent_Preview(
|
|||
}
|
||||
|
||||
private class SelectProviderBottomSheetContentPreviewProvider :
|
||||
PreviewParameterProvider<ProviderListUM> {
|
||||
override val values: Sequence<ProviderListUM>
|
||||
PreviewParameterProvider<SelectPaymentAndProviderUM> {
|
||||
override val values: Sequence<SelectPaymentAndProviderUM>
|
||||
get() = sequenceOf(
|
||||
SelectProviderPreviewData.state,
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue