Updated on 2026-08-14

This commit is contained in:
Tangem 2024-12-12 18:32:39 +05:00
commit d4bafed03c
7 changed files with 73 additions and 41 deletions

View file

@ -83,9 +83,7 @@ internal class DefaultOnrampRepository(
private val onrampErrorAdapter = moshi.adapter(ExpressErrorResponse::class.java)
private val onrampErrorConverter = OnrampErrorConverter(onrampErrorAdapter)
override suspend fun getCurrencies(): Flow<List<OnrampCurrency>> = withContext(dispatchers.io) {
currenciesStore.get(CURRENCIES_KEY)
}
override fun getCurrencies(): Flow<List<OnrampCurrency>> = currenciesStore.get(CURRENCIES_KEY)
override suspend fun fetchCurrencies() = withContext(dispatchers.io) {
if (!currenciesStore.getSyncOrNull(CURRENCIES_KEY).isNullOrEmpty()) return@withContext
@ -97,9 +95,7 @@ internal class DefaultOnrampRepository(
currenciesStore.store(CURRENCIES_KEY, result)
}
override suspend fun getCountries(): Flow<List<OnrampCountry>> = withContext(dispatchers.io) {
countriesStore.get(COUNTRIES_KEY)
}
override fun getCountries(): Flow<List<OnrampCountry>> = countriesStore.get(COUNTRIES_KEY)
override suspend fun getCountriesSync(): List<OnrampCountry>? {
return countriesStore.getSyncOrNull(COUNTRIES_KEY)

View file

@ -13,7 +13,7 @@ class GetOnrampCurrenciesUseCase(
private val errorResolver: OnrampErrorResolver,
) {
suspend operator fun invoke(): EitherFlow<OnrampError, OnrampCurrencies> {
operator fun invoke(): EitherFlow<OnrampError, OnrampCurrencies> {
return onrampRepository.getCurrencies().map { currenciesList ->
Either.catch {
val (populars, others) = currenciesList.toSet()

View file

@ -10,8 +10,8 @@ import kotlinx.coroutines.flow.Flow
@Suppress("TooManyFunctions")
interface OnrampRepository {
// api
suspend fun getCurrencies(): Flow<List<OnrampCurrency>>
suspend fun getCountries(): Flow<List<OnrampCountry>>
fun getCurrencies(): Flow<List<OnrampCurrency>>
fun getCountries(): Flow<List<OnrampCountry>>
suspend fun getCountriesSync(): List<OnrampCountry>?
suspend fun getCountryByIp(): OnrampCountry
suspend fun getStatus(txId: String): OnrampStatus

View file

@ -0,0 +1,15 @@
package com.tangem.features.onramp.selectcountry.entity.transformer
import com.tangem.features.onramp.selectcountry.entity.CountryListUM
import com.tangem.utils.transformer.Transformer
internal class UpdateCountryItemsErrorTransformer(
private val onRetry: () -> Unit,
) : Transformer<CountryListUM> {
override fun transform(prevState: CountryListUM): CountryListUM {
return CountryListUM.Error(
searchBarUM = prevState.searchBarUM,
onRetry = onRetry,
)
}
}

View file

@ -17,6 +17,7 @@ import com.tangem.features.onramp.selectcountry.SelectCountryComponent
import com.tangem.features.onramp.selectcountry.entity.CountryItemState
import com.tangem.features.onramp.selectcountry.entity.CountryListUM
import com.tangem.features.onramp.selectcountry.entity.CountryListUMController
import com.tangem.features.onramp.selectcountry.entity.transformer.UpdateCountryItemsErrorTransformer
import com.tangem.features.onramp.selectcountry.entity.transformer.UpdateCountryItemsLoadingTransformer
import com.tangem.features.onramp.selectcountry.entity.transformer.UpdateCountryItemsTransformer
import com.tangem.features.onramp.utils.InputManager
@ -26,8 +27,10 @@ import com.tangem.features.onramp.utils.sendOnrampErrorEvent
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import javax.inject.Inject
@ -44,13 +47,12 @@ internal class OnrampSelectCountryModel @Inject constructor(
paramsContainer: ParamsContainer,
) : Model() {
val state: StateFlow<CountryListUM> get() = countryListUMController.state
val state: StateFlow<CountryListUM> get() = controller.state
private val params: SelectCountryComponent.Params = paramsContainer.require()
private val countryListUMController = CountryListUMController(
private val controller = CountryListUMController(
searchBarUM = createSearchBarUM(),
loadingItems = loadingItems,
)
private val refreshTrigger = MutableSharedFlow<Unit>()
init {
analyticsEventHandler.send(OnrampAnalyticsEvent.SelectResidenceOpened)
@ -58,20 +60,13 @@ internal class OnrampSelectCountryModel @Inject constructor(
modelScope.launch { subscribeOnUpdateState() }
}
private fun updateCountriesList() {
modelScope.launch {
fetchOnrampCountriesUseCase()
}
}
fun dismiss() {
params.onDismiss()
}
@OptIn(ExperimentalCoroutinesApi::class)
private suspend fun subscribeOnUpdateState() {
combine(
flow = refreshTrigger.onStart { emit(Unit) }.flatMapLatest { getOnrampCountriesUseCase() },
flow = getOnrampCountriesUseCase(),
flow2 = getOnrampCountryUseCase(),
flow3 = searchManager.query,
) { maybeCountries, maybeCountry, query ->
@ -89,7 +84,7 @@ internal class OnrampSelectCountryModel @Inject constructor(
onCountryClick = ::saveCountry,
)
}
.onEach(countryListUMController::update)
.onEach(controller::update)
.launchIn(modelScope)
}
@ -102,23 +97,31 @@ internal class OnrampSelectCountryModel @Inject constructor(
}
private fun onRetry() {
modelScope.launch { refreshTrigger.emit(Unit) }
countryListUMController.update(UpdateCountryItemsLoadingTransformer(loadingItems))
controller.update(UpdateCountryItemsLoadingTransformer(loadingItems))
updateCountriesList()
}
private fun updateCountriesList() {
modelScope.launch {
fetchOnrampCountriesUseCase().onLeft {
controller.update(UpdateCountryItemsErrorTransformer(onRetry = ::onRetry))
}
}
}
private fun onSearchQueryChange(newQuery: String) {
val searchBarUM = countryListUMController.state.value.searchBarUM
val searchBarUM = controller.state.value.searchBarUM
if (searchBarUM.query == newQuery) return
modelScope.launch {
countryListUMController.update(transformer = UpdateSearchQueryTransformer(newQuery))
controller.update(transformer = UpdateSearchQueryTransformer(newQuery))
searchManager.update(newQuery)
}
}
private fun onSearchBarActiveChange(isActive: Boolean) {
countryListUMController.update(
controller.update(
transformer = UpdateSearchBarActiveStateTransformer(
isActive = isActive,
placeHolder = resourceReference(id = R.string.common_search),
@ -137,7 +140,7 @@ internal class OnrampSelectCountryModel @Inject constructor(
}
private companion object {
private const val LOADING_ITEMS_COUNT = 5
const val LOADING_ITEMS_COUNT = 5
val loadingItems: ImmutableList<CountryItemState.Loading> = MutableList(LOADING_ITEMS_COUNT) {
CountryItemState.Loading("Loading #$it")
}.toImmutableList()

View file

@ -0,0 +1,15 @@
package com.tangem.features.onramp.selectcurrency.entity.transformer
import com.tangem.features.onramp.selectcurrency.entity.CurrenciesListUM
import com.tangem.utils.transformer.Transformer
internal class UpdateCurrencyItemsErrorTransformer(
private val onRetry: () -> Unit,
) : Transformer<CurrenciesListUM> {
override fun transform(prevState: CurrenciesListUM): CurrenciesListUM {
return CurrenciesListUM.Error(
searchBarUM = prevState.searchBarUM,
onRetry = onRetry,
)
}
}

View file

@ -18,6 +18,7 @@ import com.tangem.features.onramp.selectcurrency.entity.CurrenciesListUM
import com.tangem.features.onramp.selectcurrency.entity.CurrenciesSection
import com.tangem.features.onramp.selectcurrency.entity.CurrencyItemState
import com.tangem.features.onramp.selectcurrency.entity.CurrencyListController
import com.tangem.features.onramp.selectcurrency.entity.transformer.UpdateCurrencyItemsErrorTransformer
import com.tangem.features.onramp.selectcurrency.entity.transformer.UpdateCurrencyItemsLoadingTransformer
import com.tangem.features.onramp.selectcurrency.entity.transformer.UpdateCurrencyItemsTransformer
import com.tangem.features.onramp.utils.InputManager
@ -27,8 +28,10 @@ import com.tangem.features.onramp.utils.sendOnrampErrorEvent
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import javax.inject.Inject
@ -51,23 +54,15 @@ internal class OnrampSelectCurrencyModel @Inject constructor(
currencySearchBarUM = createSearchBarUM(),
loadingSections = loadingSections,
)
private val refreshTrigger = MutableSharedFlow<Unit>()
init {
updateCurrenciesList()
subscribeOnUpdateState()
}
private fun updateCurrenciesList() {
modelScope.launch {
fetchOnrampCurrenciesUseCase()
}
}
@OptIn(ExperimentalCoroutinesApi::class)
private fun subscribeOnUpdateState() {
combine(
flow = refreshTrigger.onStart { emit(Unit) }.flatMapLatest { getOnrampCurrenciesUseCase() },
flow = getOnrampCurrenciesUseCase(),
flow2 = searchManager.query,
) { maybeCurrencies, query ->
maybeCurrencies.onLeft {
@ -97,8 +92,16 @@ internal class OnrampSelectCurrencyModel @Inject constructor(
}
private fun onRetry() {
modelScope.launch { refreshTrigger.emit(Unit) }
controller.update(UpdateCurrencyItemsLoadingTransformer(loadingSections))
updateCurrenciesList()
}
private fun updateCurrenciesList() {
modelScope.launch {
fetchOnrampCurrenciesUseCase().onLeft {
controller.update(UpdateCurrencyItemsErrorTransformer(onRetry = ::onRetry))
}
}
}
private fun onSearchQueryChange(newQuery: String) {