From 7aa44c4da7039a20ef2c207eed6c94440a6e9223 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 15 Aug 2023 14:08:30 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../datasource/di/AppCurrencyDataModule.kt | 31 +++++- .../AvailableAppCurrenciesStore.kt | 12 ++ .../DefaultAvailableAppCurrenciesStore.kt | 22 ++++ .../DefaultSelectedAppCurrencyStore.kt | 10 ++ .../local/datastore/FileDataStore.kt | 33 ++++-- .../local/datastore/RuntimeDataStore.kt | 8 ++ .../datastore/SharedPreferencesDataStore.kt | 49 +++++--- .../local/datastore/core/DataStore.kt | 4 + .../core/KeylessDataStoreDecorator.kt | 28 +++++ .../core/StringKeyDataStoreDecorator.kt | 22 ++-- .../local/datastore/model/WriteTrigger.kt | 3 - .../local/datastore/utils/Trigger.kt | 35 ++++++ data/app-currency/build.gradle.kts | 1 + .../DefaultAppCurrencyRepository.kt | 105 ++++++++++++++++++ .../appcurrency/MockAppCurrencyRepository.kt | 23 ---- .../appcurrency/di/AppCurrencyDataModule.kt | 23 +++- .../appcurrency/utils/AppCurrencyConverter.kt | 16 +++ 17 files changed, 364 insertions(+), 61 deletions(-) create mode 100644 core/datasource/src/main/java/com/tangem/datasource/local/appcurrency/AvailableAppCurrenciesStore.kt create mode 100644 core/datasource/src/main/java/com/tangem/datasource/local/appcurrency/implementation/DefaultAvailableAppCurrenciesStore.kt create mode 100644 core/datasource/src/main/java/com/tangem/datasource/local/appcurrency/implementation/DefaultSelectedAppCurrencyStore.kt create mode 100644 core/datasource/src/main/java/com/tangem/datasource/local/datastore/core/KeylessDataStoreDecorator.kt delete mode 100644 core/datasource/src/main/java/com/tangem/datasource/local/datastore/model/WriteTrigger.kt create mode 100644 core/datasource/src/main/java/com/tangem/datasource/local/datastore/utils/Trigger.kt create mode 100644 data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/DefaultAppCurrencyRepository.kt delete mode 100644 data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/MockAppCurrencyRepository.kt create mode 100644 data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/utils/AppCurrencyConverter.kt diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/AppCurrencyDataModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/AppCurrencyDataModule.kt index 724634e0a3..b6d8832f86 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/di/AppCurrencyDataModule.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/di/AppCurrencyDataModule.kt @@ -1,10 +1,18 @@ package com.tangem.datasource.di -import com.tangem.datasource.local.appcurrency.MockSelectedAppCurrencyStore +import android.content.Context +import com.squareup.moshi.Moshi +import com.tangem.datasource.api.tangemTech.models.CurrenciesResponse +import com.tangem.datasource.local.appcurrency.AvailableAppCurrenciesStore import com.tangem.datasource.local.appcurrency.SelectedAppCurrencyStore +import com.tangem.datasource.local.appcurrency.implementation.DefaultAvailableAppCurrenciesStore +import com.tangem.datasource.local.appcurrency.implementation.DefaultSelectedAppCurrencyStore +import com.tangem.datasource.local.datastore.RuntimeDataStore +import com.tangem.datasource.local.datastore.SharedPreferencesDataStore import dagger.Module import dagger.Provides import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import javax.inject.Singleton @@ -14,7 +22,24 @@ internal object AppCurrencyDataModule { @Provides @Singleton - fun provideSelectedAppCurrencyStore(): SelectedAppCurrencyStore { - return MockSelectedAppCurrencyStore() + fun provideAvailableAppCurrenciesStore(): AvailableAppCurrenciesStore { + return DefaultAvailableAppCurrenciesStore( + dataStore = RuntimeDataStore(), + ) + } + + @Provides + @Singleton + fun provideSelectedAppCurrencyStore( + @ApplicationContext context: Context, + @NetworkMoshi moshi: Moshi, + ): SelectedAppCurrencyStore { + return DefaultSelectedAppCurrencyStore( + dataStore = SharedPreferencesDataStore( + preferencesName = "selected_app_currency", + context = context, + adapter = moshi.adapter(CurrenciesResponse.Currency::class.java), + ), + ) } } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/appcurrency/AvailableAppCurrenciesStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/appcurrency/AvailableAppCurrenciesStore.kt new file mode 100644 index 0000000000..be9b7281cf --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/local/appcurrency/AvailableAppCurrenciesStore.kt @@ -0,0 +1,12 @@ +package com.tangem.datasource.local.appcurrency + +import com.tangem.datasource.api.tangemTech.models.CurrenciesResponse + +interface AvailableAppCurrenciesStore { + + suspend fun getAllSyncOrNull(): List? + + suspend fun getSyncOrNull(key: String): CurrenciesResponse.Currency? + + suspend fun store(response: CurrenciesResponse) +} \ 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 new file mode 100644 index 0000000000..ed9d257ec8 --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/local/appcurrency/implementation/DefaultAvailableAppCurrenciesStore.kt @@ -0,0 +1,22 @@ +package com.tangem.datasource.local.appcurrency.implementation + +import com.tangem.datasource.api.tangemTech.models.CurrenciesResponse +import com.tangem.datasource.local.appcurrency.AvailableAppCurrenciesStore +import com.tangem.datasource.local.datastore.core.StringKeyDataStore +import com.tangem.datasource.local.datastore.core.StringKeyDataStoreDecorator + +internal class DefaultAvailableAppCurrenciesStore( + private val dataStore: StringKeyDataStore, +) : AvailableAppCurrenciesStore, + StringKeyDataStoreDecorator(dataStore) { + + override fun provideStringKey(key: String): String { + return key + } + + override suspend fun store(response: CurrenciesResponse) { + val currencies = response.currencies.associateBy(CurrenciesResponse.Currency::code) + + dataStore.store(currencies) + } +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/appcurrency/implementation/DefaultSelectedAppCurrencyStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/appcurrency/implementation/DefaultSelectedAppCurrencyStore.kt new file mode 100644 index 0000000000..c79bf3045b --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/local/appcurrency/implementation/DefaultSelectedAppCurrencyStore.kt @@ -0,0 +1,10 @@ +package com.tangem.datasource.local.appcurrency.implementation + +import com.tangem.datasource.api.tangemTech.models.CurrenciesResponse +import com.tangem.datasource.local.appcurrency.SelectedAppCurrencyStore +import com.tangem.datasource.local.datastore.core.KeylessDataStoreDecorator +import com.tangem.datasource.local.datastore.core.StringKeyDataStore + +internal class DefaultSelectedAppCurrencyStore( + dataStore: StringKeyDataStore, +) : SelectedAppCurrencyStore, KeylessDataStoreDecorator(dataStore) \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/datastore/FileDataStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/datastore/FileDataStore.kt index c69c6d5c64..cc65a7ff21 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/datastore/FileDataStore.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/datastore/FileDataStore.kt @@ -3,38 +3,49 @@ package com.tangem.datasource.local.datastore import com.squareup.moshi.JsonAdapter import com.tangem.datasource.files.FileReader import com.tangem.datasource.local.datastore.core.StringKeyDataStore -import com.tangem.datasource.local.datastore.model.WriteTrigger -import kotlinx.coroutines.channels.BufferOverflow +import com.tangem.datasource.local.datastore.utils.Trigger import kotlinx.coroutines.flow.* import timber.log.Timber +@Deprecated("Use shared preferences data store instead") internal class FileDataStore( private val fileReader: FileReader, private val adapter: JsonAdapter, ) : StringKeyDataStore { - private val writeTrigger = MutableSharedFlow( - replay = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST, - ) + private val writeTrigger = Trigger() override fun get(key: String): Flow { return writeTrigger - .onEmpty { emit(WriteTrigger) } .map { getInternal(key) } .filterNotNull() + .distinctUntilChanged() + } + + override fun getAll(): Flow> { + val e = NotImplementedError("`getAll()` function not implemented for `FileDataStore`") + Timber.e(e) + + throw e } override suspend fun getSyncOrNull(key: String): Value? { return getInternal(key) } + override suspend fun getAllSyncOrNull(): List { + val e = NotImplementedError("`getAllSyncOrNull()` function not implemented for `FileDataStore`") + Timber.e(e) + + throw e + } + override suspend fun store(key: String, item: Value) { try { val json = adapter.toJson(item) fileReader.rewriteFile(json, key) - writeTrigger.tryEmit(WriteTrigger) + writeTrigger.trigger() } catch (e: Throwable) { Timber.e(e, "Unable to write file: $key") } @@ -48,10 +59,14 @@ internal class FileDataStore( override suspend fun remove(key: String) { fileReader.removeFile(key) + writeTrigger.trigger() } override suspend fun clear() { - // TODO: Implement if needed + val e = NotImplementedError("`clear()` function not implemented for `FileDataStore`") + Timber.e(e) + + throw e } private fun getInternal(fileName: String): Value? { diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/datastore/RuntimeDataStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/datastore/RuntimeDataStore.kt index d1c4eff1eb..2d4149648f 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/datastore/RuntimeDataStore.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/datastore/RuntimeDataStore.kt @@ -13,10 +13,18 @@ internal class RuntimeDataStore : StringKeyDataStore { .filterNotNull() } + override fun getAll(): Flow> { + return store.map { value -> value.values.toList() } + } + override suspend fun getSyncOrNull(key: String): Data? { return store.value[key] } + override suspend fun getAllSyncOrNull(): List { + return store.value.values.toList() + } + override suspend fun store(key: String, item: Data) { store.update { value -> value[key] = item diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/datastore/SharedPreferencesDataStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/datastore/SharedPreferencesDataStore.kt index e8952a5a82..cd2ed5c463 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/datastore/SharedPreferencesDataStore.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/datastore/SharedPreferencesDataStore.kt @@ -2,12 +2,15 @@ package com.tangem.datasource.local.datastore import android.content.Context import android.content.Context.MODE_PRIVATE +import android.content.SharedPreferences import androidx.core.content.edit import com.squareup.moshi.JsonAdapter import com.tangem.datasource.local.datastore.core.StringKeyDataStore -import com.tangem.datasource.local.datastore.model.WriteTrigger -import kotlinx.coroutines.channels.BufferOverflow -import kotlinx.coroutines.flow.* +import com.tangem.datasource.local.datastore.utils.Trigger +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.filterNotNull +import kotlinx.coroutines.flow.map import timber.log.Timber internal class SharedPreferencesDataStore( @@ -16,32 +19,39 @@ internal class SharedPreferencesDataStore( private val adapter: JsonAdapter, ) : StringKeyDataStore { - private val sharedPreferences by lazy { + private val sharedPreferences: SharedPreferences by lazy { context.getSharedPreferences(preferencesName, MODE_PRIVATE) } - private val writeTrigger = MutableSharedFlow( - replay = 1, - onBufferOverflow = BufferOverflow.DROP_OLDEST, - ) + private val writeTrigger = Trigger() override fun get(key: String): Flow { return writeTrigger - .onEmpty { emit(WriteTrigger) } .map { getInternal(key) } .filterNotNull() + .distinctUntilChanged() + } + + override fun getAll(): Flow> { + return writeTrigger + .map { getAllInternal() } + .distinctUntilChanged() } override suspend fun getSyncOrNull(key: String): Value? { return getInternal(key) } + override suspend fun getAllSyncOrNull(): List { + return getAllInternal() + } + override suspend fun store(key: String, item: Value) { try { val json = adapter.toJson(item) sharedPreferences.edit { putString(key, json) } - writeTrigger.emit(WriteTrigger) + writeTrigger.trigger() } catch (e: Throwable) { Timber.e(e, "Unable to edit preferences: $key") } @@ -54,13 +64,13 @@ internal class SharedPreferencesDataStore( } override suspend fun remove(key: String) { - sharedPreferences.edit { - remove(key) - } + sharedPreferences.edit { remove(key) } + writeTrigger.trigger() } override suspend fun clear() { sharedPreferences.edit { clear() } + writeTrigger.trigger() } private fun getInternal(key: String): Value? { @@ -73,4 +83,17 @@ internal class SharedPreferencesDataStore( null } } + + private fun getAllInternal(): List { + return sharedPreferences.all.mapNotNull { (key, value) -> + try { + val json = value as? String ?: return@mapNotNull null + + adapter.fromJson(json) + } catch (e: Throwable) { + Timber.e(e, "Unable to convert value from JSON: $key") + null + } + } + } } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/datastore/core/DataStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/datastore/core/DataStore.kt index 7374c56980..4ac5668e44 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/datastore/core/DataStore.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/datastore/core/DataStore.kt @@ -6,8 +6,12 @@ internal interface DataStore { fun get(key: Key): Flow + fun getAll(): Flow> + suspend fun getSyncOrNull(key: Key): Value? + suspend fun getAllSyncOrNull(): List + suspend fun store(key: Key, item: Value) suspend fun store(items: Map) diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/datastore/core/KeylessDataStoreDecorator.kt b/core/datasource/src/main/java/com/tangem/datasource/local/datastore/core/KeylessDataStoreDecorator.kt new file mode 100644 index 0000000000..3d567967cf --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/local/datastore/core/KeylessDataStoreDecorator.kt @@ -0,0 +1,28 @@ +package com.tangem.datasource.local.datastore.core + +import kotlinx.coroutines.flow.Flow + +internal abstract class KeylessDataStoreDecorator( + wrappedDataStore: StringKeyDataStore, +) : StringKeyDataStoreDecorator(wrappedDataStore) { + + override fun provideStringKey(key: Unit): String { + return STRING_KEY + } + + fun get(): Flow { + return get(Unit) + } + + suspend fun getSyncOrNull(): Value? { + return getSyncOrNull(Unit) + } + + suspend fun store(item: Value) { + store(Unit, item) + } + + private companion object { + const val STRING_KEY = "key" + } +} \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/datastore/core/StringKeyDataStoreDecorator.kt b/core/datasource/src/main/java/com/tangem/datasource/local/datastore/core/StringKeyDataStoreDecorator.kt index 92daa1a731..e6afee1d93 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/datastore/core/StringKeyDataStoreDecorator.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/datastore/core/StringKeyDataStoreDecorator.kt @@ -3,34 +3,42 @@ package com.tangem.datasource.local.datastore.core import kotlinx.coroutines.flow.Flow internal abstract class StringKeyDataStoreDecorator( - private val dataStore: StringKeyDataStore, + private val wrappedDataStore: StringKeyDataStore, ) : DataStore { abstract fun provideStringKey(key: Key): String override fun get(key: Key): Flow { - return dataStore.get(provideStringKey(key)) + return wrappedDataStore.get(provideStringKey(key)) + } + + override fun getAll(): Flow> { + return wrappedDataStore.getAll() + } + + override suspend fun getAllSyncOrNull(): List { + return wrappedDataStore.getAllSyncOrNull() } override suspend fun getSyncOrNull(key: Key): Value? { - return dataStore.getSyncOrNull(provideStringKey(key)) + return wrappedDataStore.getSyncOrNull(provideStringKey(key)) } override suspend fun store(key: Key, item: Value) { - dataStore.store(provideStringKey(key), item) + wrappedDataStore.store(provideStringKey(key), item) } override suspend fun store(items: Map) { - dataStore.store( + wrappedDataStore.store( items = items.mapKeys { (key, _) -> provideStringKey(key) }, ) } override suspend fun remove(key: Key) { - dataStore.remove(provideStringKey(key)) + wrappedDataStore.remove(provideStringKey(key)) } override suspend fun clear() { - dataStore.clear() + wrappedDataStore.clear() } } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/datastore/model/WriteTrigger.kt b/core/datasource/src/main/java/com/tangem/datasource/local/datastore/model/WriteTrigger.kt deleted file mode 100644 index aaab7f83df..0000000000 --- a/core/datasource/src/main/java/com/tangem/datasource/local/datastore/model/WriteTrigger.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.tangem.datasource.local.datastore.model - -internal typealias WriteTrigger = Unit \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/datastore/utils/Trigger.kt b/core/datasource/src/main/java/com/tangem/datasource/local/datastore/utils/Trigger.kt new file mode 100644 index 0000000000..d343129a6f --- /dev/null +++ b/core/datasource/src/main/java/com/tangem/datasource/local/datastore/utils/Trigger.kt @@ -0,0 +1,35 @@ +package com.tangem.datasource.local.datastore.utils + +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.FlowCollector +import kotlinx.coroutines.flow.MutableStateFlow + +/** + * Represents a trigger mechanism to emit values on-demand. + * + * This class provides a mechanism to trigger emissions via the [trigger] method. + * + * @property triggerFlow The internal flow that gets toggled to trigger emissions. + */ +internal class Trigger( + private val triggerFlow: MutableStateFlow = MutableStateFlow(value = false), +) : Flow { + + /** + * Collects values emitted by this flow. + * + * Overrides the default collection mechanism to emit a [Unit] value whenever [triggerFlow] changes. + * + * @param collector The collector responsible for handling emitted values. + */ + override suspend fun collect(collector: FlowCollector): Nothing { + triggerFlow.collect { collector.emit(Unit) } + } + + /** + * Triggers an emission. + */ + fun trigger() { + triggerFlow.value = !triggerFlow.value + } +} \ No newline at end of file diff --git a/data/app-currency/build.gradle.kts b/data/app-currency/build.gradle.kts index 7020b7c452..69613e2e85 100644 --- a/data/app-currency/build.gradle.kts +++ b/data/app-currency/build.gradle.kts @@ -30,4 +30,5 @@ dependencies { /** Other */ implementation(deps.kotlin.coroutines) implementation(deps.timber) + implementation(deps.jodatime) } \ 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 new file mode 100644 index 0000000000..8a780ba151 --- /dev/null +++ b/data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/DefaultAppCurrencyRepository.kt @@ -0,0 +1,105 @@ +package com.tangem.data.appcurrency + +import com.tangem.data.appcurrency.utils.AppCurrencyConverter +import com.tangem.data.common.cache.CacheRegistry +import com.tangem.datasource.api.tangemTech.TangemTechApi +import com.tangem.datasource.api.tangemTech.models.CurrenciesResponse +import com.tangem.datasource.local.appcurrency.AvailableAppCurrenciesStore +import com.tangem.datasource.local.appcurrency.SelectedAppCurrencyStore +import com.tangem.domain.appcurrency.model.AppCurrency +import com.tangem.domain.appcurrency.repository.AppCurrencyRepository +import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEmpty +import kotlinx.coroutines.withContext +import org.joda.time.Duration +import timber.log.Timber + +internal class DefaultAppCurrencyRepository( + private val tangemTechApi: TangemTechApi, + private val availableAppCurrenciesStore: AvailableAppCurrenciesStore, + private val selectedAppCurrencyStore: SelectedAppCurrencyStore, + private val cacheRegistry: CacheRegistry, + private val dispatchers: CoroutineDispatcherProvider, +) : AppCurrencyRepository { + + private val appCurrencyConverter = AppCurrencyConverter() + + override fun getSelectedAppCurrency(): Flow { + return selectedAppCurrencyStore.get() + .onEmpty { fetchDefaultAppCurrency() } + .map(appCurrencyConverter::convert) + .flowOn(dispatchers.io) + } + + override suspend fun getAvailableAppCurrencies(): List { + return withContext(dispatchers.io) { + fetchAvailableCurrenciesIfExpired() + + val currencies = availableAppCurrenciesStore.getAllSyncOrNull() + ?.map(appCurrencyConverter::convert) + + requireNotNull(currencies) { + "No available currencies stored" + } + } + } + + override suspend fun changeAppCurrency(currencyCode: String) { + withContext(dispatchers.io) { + val currency = requireNotNull(availableAppCurrenciesStore.getSyncOrNull(currencyCode)) { + "Unable to find app currency with provided code: $currencyCode" + } + + selectedAppCurrencyStore.store(currency) + } + } + + private suspend fun fetchDefaultAppCurrency() { + fetchAvailableCurrenciesIfExpired() + + changeAppCurrency(DEFAULT_CURRENCY_CODE) + } + + private suspend fun fetchAvailableCurrenciesIfExpired() { + cacheRegistry.invokeOnExpire( + key = AVAILABLE_CURRENCIES_CACHE_KEY, + skipCache = false, + expireIn = Duration.standardMinutes(AVAILABLE_CURRENCIES_CACHE_KEY_EXPIRE_MINUTES), + block = { fetchAvailableCurrencies() }, + ) + } + + private suspend fun fetchAvailableCurrencies() { + try { + val response = tangemTechApi.getCurrencyList() + + availableAppCurrenciesStore.store(response) + } catch (e: Throwable) { + Timber.e(e, "Unable to fetch available currencies") + + availableAppCurrenciesStore.store(getDefaultCurrenciesResponse()) + } + } + + private fun getDefaultCurrenciesResponse(): CurrenciesResponse = CurrenciesResponse( + currencies = listOf( + CurrenciesResponse.Currency( + id = DEFAULT_CURRENCY_CODE.lowercase(), + code = DEFAULT_CURRENCY_CODE, + name = "US Dollar", + unit = "$", + type = "fiat", + rateBTC = "", + ), + ), + ) + + private companion object { + const val AVAILABLE_CURRENCIES_CACHE_KEY = "available_currencies" + const val AVAILABLE_CURRENCIES_CACHE_KEY_EXPIRE_MINUTES = 15L + const val DEFAULT_CURRENCY_CODE = "USD" + } +} \ No newline at end of file diff --git a/data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/MockAppCurrencyRepository.kt b/data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/MockAppCurrencyRepository.kt deleted file mode 100644 index e3e518afdc..0000000000 --- a/data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/MockAppCurrencyRepository.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.tangem.data.appcurrency - -import com.tangem.domain.appcurrency.model.AppCurrency -import com.tangem.domain.appcurrency.repository.AppCurrencyRepository -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flowOf - -internal class MockAppCurrencyRepository : AppCurrencyRepository { - - private val mockAppCurrencies = listOf(AppCurrency(code = "USD", name = "US Dollar", symbol = "$")) - - override fun getSelectedAppCurrency(): Flow { - return flowOf(mockAppCurrencies.first()) - } - - override suspend fun getAvailableAppCurrencies(): List { - return mockAppCurrencies - } - - override suspend fun changeAppCurrency(currencyCode: String) { - /* no-op */ - } -} \ No newline at end of file diff --git a/data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/di/AppCurrencyDataModule.kt b/data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/di/AppCurrencyDataModule.kt index d7f7ebb36c..cd80c7c52b 100644 --- a/data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/di/AppCurrencyDataModule.kt +++ b/data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/di/AppCurrencyDataModule.kt @@ -1,7 +1,12 @@ package com.tangem.data.appcurrency.di -import com.tangem.data.appcurrency.MockAppCurrencyRepository +import com.tangem.data.appcurrency.DefaultAppCurrencyRepository +import com.tangem.data.common.cache.CacheRegistry +import com.tangem.datasource.api.tangemTech.TangemTechApi +import com.tangem.datasource.local.appcurrency.AvailableAppCurrenciesStore +import com.tangem.datasource.local.appcurrency.SelectedAppCurrencyStore import com.tangem.domain.appcurrency.repository.AppCurrencyRepository +import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -14,7 +19,19 @@ internal object AppCurrencyDataModule { @Provides @Singleton - fun provideAppCurrencyRepository(): AppCurrencyRepository { - return MockAppCurrencyRepository() + fun provideAppCurrencyRepository( + tangemTechApi: TangemTechApi, + availableAppCurrenciesStore: AvailableAppCurrenciesStore, + selectedAppCurrencyStore: SelectedAppCurrencyStore, + cacheRegistry: CacheRegistry, + dispatchers: CoroutineDispatcherProvider, + ): AppCurrencyRepository { + return DefaultAppCurrencyRepository( + tangemTechApi, + availableAppCurrenciesStore, + selectedAppCurrencyStore, + cacheRegistry, + dispatchers, + ) } } \ No newline at end of file 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 new file mode 100644 index 0000000000..6b8a6409e8 --- /dev/null +++ b/data/app-currency/src/main/kotlin/com/tangem/data/appcurrency/utils/AppCurrencyConverter.kt @@ -0,0 +1,16 @@ +package com.tangem.data.appcurrency.utils + +import com.tangem.datasource.api.tangemTech.models.CurrenciesResponse +import com.tangem.domain.appcurrency.model.AppCurrency +import com.tangem.utils.converter.Converter + +internal class AppCurrencyConverter : Converter { + + override fun convert(value: CurrenciesResponse.Currency): AppCurrency { + return AppCurrency( + code = value.code, + name = value.name, + symbol = value.unit, + ) + } +} \ No newline at end of file