Updated on 2026-08-14
This commit is contained in:
parent
2a0e8f78a6
commit
7aa44c4da7
17 changed files with 364 additions and 61 deletions
|
|
@ -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),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.tangem.datasource.local.appcurrency
|
||||
|
||||
import com.tangem.datasource.api.tangemTech.models.CurrenciesResponse
|
||||
|
||||
interface AvailableAppCurrenciesStore {
|
||||
|
||||
suspend fun getAllSyncOrNull(): List<CurrenciesResponse.Currency>?
|
||||
|
||||
suspend fun getSyncOrNull(key: String): CurrenciesResponse.Currency?
|
||||
|
||||
suspend fun store(response: CurrenciesResponse)
|
||||
}
|
||||
|
|
@ -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<CurrenciesResponse.Currency>,
|
||||
) : AvailableAppCurrenciesStore,
|
||||
StringKeyDataStoreDecorator<String, CurrenciesResponse.Currency>(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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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<CurrenciesResponse.Currency>,
|
||||
) : SelectedAppCurrencyStore, KeylessDataStoreDecorator<CurrenciesResponse.Currency>(dataStore)
|
||||
|
|
@ -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<Value : Any>(
|
||||
private val fileReader: FileReader,
|
||||
private val adapter: JsonAdapter<Value>,
|
||||
) : StringKeyDataStore<Value> {
|
||||
|
||||
private val writeTrigger = MutableSharedFlow<WriteTrigger>(
|
||||
replay = 1,
|
||||
onBufferOverflow = BufferOverflow.DROP_OLDEST,
|
||||
)
|
||||
private val writeTrigger = Trigger()
|
||||
|
||||
override fun get(key: String): Flow<Value> {
|
||||
return writeTrigger
|
||||
.onEmpty { emit(WriteTrigger) }
|
||||
.map { getInternal(key) }
|
||||
.filterNotNull()
|
||||
.distinctUntilChanged()
|
||||
}
|
||||
|
||||
override fun getAll(): Flow<List<Value>> {
|
||||
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<Value> {
|
||||
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<Value : Any>(
|
|||
|
||||
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? {
|
||||
|
|
|
|||
|
|
@ -13,10 +13,18 @@ internal class RuntimeDataStore<Data : Any> : StringKeyDataStore<Data> {
|
|||
.filterNotNull()
|
||||
}
|
||||
|
||||
override fun getAll(): Flow<List<Data>> {
|
||||
return store.map { value -> value.values.toList() }
|
||||
}
|
||||
|
||||
override suspend fun getSyncOrNull(key: String): Data? {
|
||||
return store.value[key]
|
||||
}
|
||||
|
||||
override suspend fun getAllSyncOrNull(): List<Data> {
|
||||
return store.value.values.toList()
|
||||
}
|
||||
|
||||
override suspend fun store(key: String, item: Data) {
|
||||
store.update { value ->
|
||||
value[key] = item
|
||||
|
|
|
|||
|
|
@ -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<Value : Any>(
|
||||
|
|
@ -16,32 +19,39 @@ internal class SharedPreferencesDataStore<Value : Any>(
|
|||
private val adapter: JsonAdapter<Value>,
|
||||
) : StringKeyDataStore<Value> {
|
||||
|
||||
private val sharedPreferences by lazy {
|
||||
private val sharedPreferences: SharedPreferences by lazy {
|
||||
context.getSharedPreferences(preferencesName, MODE_PRIVATE)
|
||||
}
|
||||
|
||||
private val writeTrigger = MutableSharedFlow<WriteTrigger>(
|
||||
replay = 1,
|
||||
onBufferOverflow = BufferOverflow.DROP_OLDEST,
|
||||
)
|
||||
private val writeTrigger = Trigger()
|
||||
|
||||
override fun get(key: String): Flow<Value> {
|
||||
return writeTrigger
|
||||
.onEmpty { emit(WriteTrigger) }
|
||||
.map { getInternal(key) }
|
||||
.filterNotNull()
|
||||
.distinctUntilChanged()
|
||||
}
|
||||
|
||||
override fun getAll(): Flow<List<Value>> {
|
||||
return writeTrigger
|
||||
.map { getAllInternal() }
|
||||
.distinctUntilChanged()
|
||||
}
|
||||
|
||||
override suspend fun getSyncOrNull(key: String): Value? {
|
||||
return getInternal(key)
|
||||
}
|
||||
|
||||
override suspend fun getAllSyncOrNull(): List<Value> {
|
||||
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<Value : Any>(
|
|||
}
|
||||
|
||||
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<Value : Any>(
|
|||
null
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAllInternal(): List<Value> {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,8 +6,12 @@ internal interface DataStore<Key : Any, Value : Any> {
|
|||
|
||||
fun get(key: Key): Flow<Value>
|
||||
|
||||
fun getAll(): Flow<List<Value>>
|
||||
|
||||
suspend fun getSyncOrNull(key: Key): Value?
|
||||
|
||||
suspend fun getAllSyncOrNull(): List<Value>
|
||||
|
||||
suspend fun store(key: Key, item: Value)
|
||||
|
||||
suspend fun store(items: Map<Key, Value>)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
package com.tangem.datasource.local.datastore.core
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
internal abstract class KeylessDataStoreDecorator<Value : Any>(
|
||||
wrappedDataStore: StringKeyDataStore<Value>,
|
||||
) : StringKeyDataStoreDecorator<Unit, Value>(wrappedDataStore) {
|
||||
|
||||
override fun provideStringKey(key: Unit): String {
|
||||
return STRING_KEY
|
||||
}
|
||||
|
||||
fun get(): Flow<Value> {
|
||||
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"
|
||||
}
|
||||
}
|
||||
|
|
@ -3,34 +3,42 @@ package com.tangem.datasource.local.datastore.core
|
|||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
internal abstract class StringKeyDataStoreDecorator<Key : Any, Value : Any>(
|
||||
private val dataStore: StringKeyDataStore<Value>,
|
||||
private val wrappedDataStore: StringKeyDataStore<Value>,
|
||||
) : DataStore<Key, Value> {
|
||||
|
||||
abstract fun provideStringKey(key: Key): String
|
||||
|
||||
override fun get(key: Key): Flow<Value> {
|
||||
return dataStore.get(provideStringKey(key))
|
||||
return wrappedDataStore.get(provideStringKey(key))
|
||||
}
|
||||
|
||||
override fun getAll(): Flow<List<Value>> {
|
||||
return wrappedDataStore.getAll()
|
||||
}
|
||||
|
||||
override suspend fun getAllSyncOrNull(): List<Value> {
|
||||
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<Key, Value>) {
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
package com.tangem.datasource.local.datastore.model
|
||||
|
||||
internal typealias WriteTrigger = Unit
|
||||
|
|
@ -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<Boolean> = MutableStateFlow(value = false),
|
||||
) : Flow<Unit> {
|
||||
|
||||
/**
|
||||
* 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<Unit>): Nothing {
|
||||
triggerFlow.collect { collector.emit(Unit) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers an emission.
|
||||
*/
|
||||
fun trigger() {
|
||||
triggerFlow.value = !triggerFlow.value
|
||||
}
|
||||
}
|
||||
|
|
@ -30,4 +30,5 @@ dependencies {
|
|||
/** Other */
|
||||
implementation(deps.kotlin.coroutines)
|
||||
implementation(deps.timber)
|
||||
implementation(deps.jodatime)
|
||||
}
|
||||
|
|
@ -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<AppCurrency> {
|
||||
return selectedAppCurrencyStore.get()
|
||||
.onEmpty { fetchDefaultAppCurrency() }
|
||||
.map(appCurrencyConverter::convert)
|
||||
.flowOn(dispatchers.io)
|
||||
}
|
||||
|
||||
override suspend fun getAvailableAppCurrencies(): List<AppCurrency> {
|
||||
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"
|
||||
}
|
||||
}
|
||||
|
|
@ -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<AppCurrency> {
|
||||
return flowOf(mockAppCurrencies.first())
|
||||
}
|
||||
|
||||
override suspend fun getAvailableAppCurrencies(): List<AppCurrency> {
|
||||
return mockAppCurrencies
|
||||
}
|
||||
|
||||
override suspend fun changeAppCurrency(currencyCode: String) {
|
||||
/* no-op */
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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<CurrenciesResponse.Currency, AppCurrency> {
|
||||
|
||||
override fun convert(value: CurrenciesResponse.Currency): AppCurrency {
|
||||
return AppCurrency(
|
||||
code = value.code,
|
||||
name = value.name,
|
||||
symbol = value.unit,
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue