diff --git a/app/src/main/java/com/tangem/tap/di/domain/AppCurrencyDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/AppCurrencyDomainModule.kt index ab7bc24782..f785627aa1 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/AppCurrencyDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/AppCurrencyDomainModule.kt @@ -1,5 +1,6 @@ package com.tangem.tap.di.domain +import com.tangem.domain.appcurrency.FetchAppCurrenciesUseCase import com.tangem.domain.appcurrency.GetAvailableCurrenciesUseCase import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.SelectAppCurrencyUseCase @@ -8,6 +9,7 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.components.ViewModelComponent +import dagger.hilt.android.scopes.ViewModelScoped @Module @InstallIn(ViewModelComponent::class) @@ -31,4 +33,10 @@ internal object AppCurrencyDomainModule { ): GetAvailableCurrenciesUseCase { return GetAvailableCurrenciesUseCase(appCurrencyRepository) } + + @Provides + @ViewModelScoped + fun provideFetchAppCurrenciesUseCase(appCurrencyRepository: AppCurrencyRepository): FetchAppCurrenciesUseCase { + return FetchAppCurrenciesUseCase(appCurrencyRepository) + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt b/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt index 5725564ef4..dc5b58c12a 100644 --- a/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/main/MainViewModel.kt @@ -5,11 +5,13 @@ import androidx.lifecycle.viewModelScope import com.tangem.core.navigation.AppScreen import com.tangem.core.navigation.NavigationAction import com.tangem.core.navigation.ReduxNavController +import com.tangem.domain.appcurrency.FetchAppCurrenciesUseCase import com.tangem.domain.balancehiding.BalanceHidingSettings import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase import com.tangem.domain.balancehiding.ListenToFlipsUseCase import com.tangem.domain.balancehiding.UpdateBalanceHidingSettingsUseCase import com.tangem.tap.features.main.model.MainScreenState +import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch @@ -20,6 +22,8 @@ internal class MainViewModel @Inject constructor( private val updateBalanceHidingSettingsUseCase: UpdateBalanceHidingSettingsUseCase, private val listenToFlipsUseCase: ListenToFlipsUseCase, private val reduxNavController: ReduxNavController, + private val fetchAppCurrenciesUseCase: FetchAppCurrenciesUseCase, + private val dispatchers: CoroutineDispatcherProvider, getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase, ) : ViewModel(), MainIntents { @@ -33,11 +37,18 @@ internal class MainViewModel @Inject constructor( val state: StateFlow = stateHolder.stateFlow init { + updateAppCurrencies() observeFlips() displayBalancesHidingStatusToast() displayHiddenBalancesModalNotification() } + private fun updateAppCurrencies() { + viewModelScope.launch(dispatchers.main) { + fetchAppCurrenciesUseCase.invoke() + } + } + private fun observeFlips() { listenToFlipsUseCase().launchIn(viewModelScope) } diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/CurrenciesResponse.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/CurrenciesResponse.kt index bab2e292de..c2799b1c2d 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/CurrenciesResponse.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/models/CurrenciesResponse.kt @@ -1,11 +1,15 @@ package com.tangem.datasource.api.tangemTech.models import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass +@JsonClass(generateAdapter = true) data class CurrenciesResponse( @Json(name = "currencies") val currencies: List, + @Json(name = "imageHost") val imageHost: String? = null, ) { + @JsonClass(generateAdapter = true) data class Currency( @Json(name = "id") val id: String, @Json(name = "code") val code: String, // this is an uppercase id @@ -13,5 +17,7 @@ data class CurrenciesResponse( @Json(name = "rateBTC") val rateBTC: String, @Json(name = "unit") val unit: String, // $, €, ₽ @Json(name = "type") val type: String, + val iconSmallUrl: String? = null, + val iconMediumUrl: String? = null, ) } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/appcurrency/implementation/DefaultAvailableAppCurrenciesStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/appcurrency/implementation/DefaultAvailableAppCurrenciesStore.kt index ed9d257ec8..6ee08097c5 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/appcurrency/implementation/DefaultAvailableAppCurrenciesStore.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/appcurrency/implementation/DefaultAvailableAppCurrenciesStore.kt @@ -15,8 +15,20 @@ internal class DefaultAvailableAppCurrenciesStore( } override suspend fun store(response: CurrenciesResponse) { - val currencies = response.currencies.associateBy(CurrenciesResponse.Currency::code) + val currencies = response.currencies + .map { + it.copy( + iconSmallUrl = response.imageHost?.plus(IMAGE_SMALL)?.format(it.id), + iconMediumUrl = response.imageHost?.plus(IMAGE_MEDIUM)?.format(it.id), + ) + } + .associateBy(CurrenciesResponse.Currency::code) dataStore.store(currencies) } + + private companion object { + const val IMAGE_MEDIUM = "medium/%s.png" + const val IMAGE_SMALL = "small/%s.png" + } } \ No newline at end of file diff --git a/data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/DefaultAppCurrencyRepository.kt b/data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/DefaultAppCurrencyRepository.kt index b86e0bb03c..bcc535bed2 100644 --- a/data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/DefaultAppCurrencyRepository.kt +++ b/data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/DefaultAppCurrencyRepository.kt @@ -77,16 +77,18 @@ internal class DefaultAppCurrencyRepository( } } - private suspend fun fetchDefaultAppCurrency() { - fetchAvailableCurrenciesIfExpired() - - changeAppCurrency(DEFAULT_CURRENCY_CODE) + override suspend fun fetchDefaultAppCurrency(isRefresh: Boolean) { + withContext(dispatchers.io) { + fetchAvailableCurrenciesIfExpired(isRefresh) + val appCurrency = appPreferencesStore.getSyncOrNull(PreferencesKeys.SELECTED_APP_CURRENCY_KEY) + changeAppCurrency(appCurrency ?: DEFAULT_CURRENCY_CODE) + } } - private suspend fun fetchAvailableCurrenciesIfExpired() { + private suspend fun fetchAvailableCurrenciesIfExpired(isRefresh: Boolean = false) { cacheRegistry.invokeOnExpire( key = AVAILABLE_CURRENCIES_CACHE_KEY, - skipCache = false, + skipCache = isRefresh, expireIn = Duration.standardMinutes(AVAILABLE_CURRENCIES_CACHE_KEY_EXPIRE_MINUTES), block = { fetchAvailableCurrencies() }, ) diff --git a/data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/utils/AppCurrencyConverter.kt b/data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/utils/AppCurrencyConverter.kt index 6b8a6409e8..8717880e9f 100644 --- a/data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/utils/AppCurrencyConverter.kt +++ b/data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/utils/AppCurrencyConverter.kt @@ -11,6 +11,8 @@ internal class AppCurrencyConverter : Converter = either { + catch( + block = { appCurrencyRepository.fetchDefaultAppCurrency(isRefresh = true) }, + catch = { SelectedAppCurrencyError.DataError(it) }, + ) + } +} \ No newline at end of file diff --git a/domain/app-currency/src/main/kotlin/com/tangem/domain/appcurrency/repository/AppCurrencyRepository.kt b/domain/app-currency/src/main/kotlin/com/tangem/domain/appcurrency/repository/AppCurrencyRepository.kt index 3ba529f8ae..fdde5516e4 100644 --- a/domain/app-currency/src/main/kotlin/com/tangem/domain/appcurrency/repository/AppCurrencyRepository.kt +++ b/domain/app-currency/src/main/kotlin/com/tangem/domain/appcurrency/repository/AppCurrencyRepository.kt @@ -5,9 +5,14 @@ import kotlinx.coroutines.flow.Flow interface AppCurrencyRepository { + /** + * Get Selected App Currency from cache or load from network. + */ fun getSelectedAppCurrency(): Flow suspend fun getAvailableAppCurrencies(): List suspend fun changeAppCurrency(currencyCode: String) + + suspend fun fetchDefaultAppCurrency(isRefresh: Boolean = false) } \ No newline at end of file diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/amount/SendAmountStateConverter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/amount/SendAmountStateConverter.kt index df2a63b153..bbadf98185 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/amount/SendAmountStateConverter.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/amount/SendAmountStateConverter.kt @@ -45,7 +45,7 @@ internal class SendAmountStateConverter( ), SendAmountSegmentedButtonsConfig( title = stringReference(appCurrency.code), - iconState = iconStateConverter.convert(status), + iconUrl = appCurrency.iconSmallUrl, isFiat = true, ), ),