Updated on 2026-08-14
This commit is contained in:
parent
613e07734e
commit
3fc34fac64
103 changed files with 403 additions and 297 deletions
|
|
@ -0,0 +1,21 @@
|
|||
package com.tangem.datasource.di
|
||||
|
||||
import com.tangem.datasource.local.datastore.RuntimeDataStore
|
||||
import com.tangem.datasource.local.network.DefaultNetworksStatusesStore
|
||||
import com.tangem.datasource.local.network.NetworksStatusesStore
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal object NetworksStatusesStoreModule {
|
||||
|
||||
@Provides
|
||||
fun provideNetworksStatusesStore(): NetworksStatusesStore {
|
||||
return DefaultNetworksStatusesStore(
|
||||
dataStore = RuntimeDataStore(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -2,15 +2,10 @@ package com.tangem.datasource.local.cache
|
|||
|
||||
import com.tangem.datasource.local.cache.model.CacheKey
|
||||
import com.tangem.datasource.local.datastore.core.StringKeyDataStore
|
||||
import com.tangem.datasource.local.datastore.core.StringKeyDataStoreDecorator
|
||||
|
||||
internal class DefaultCacheKeysStore(
|
||||
dataStore: StringKeyDataStore<CacheKey>,
|
||||
) : CacheKeysStore, StringKeyDataStoreDecorator<String, CacheKey>(dataStore) {
|
||||
|
||||
override fun provideStringKey(key: String): String {
|
||||
return key
|
||||
}
|
||||
) : CacheKeysStore, StringKeyDataStore<CacheKey> by dataStore {
|
||||
|
||||
override suspend fun store(key: CacheKey) {
|
||||
store(key.id, key)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,10 @@ 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.utils.Trigger
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.map
|
||||
import timber.log.Timber
|
||||
|
||||
@Deprecated("Use shared preferences data store instead")
|
||||
|
|
@ -33,16 +36,16 @@ internal class FileDataStore<Value : Any>(
|
|||
return getInternal(key)
|
||||
}
|
||||
|
||||
override suspend fun getAllSyncOrNull(): List<Value> {
|
||||
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) {
|
||||
override suspend fun store(key: String, value: Value) {
|
||||
try {
|
||||
val json = adapter.toJson(item)
|
||||
val json = adapter.toJson(value)
|
||||
|
||||
fileReader.rewriteFile(json, key)
|
||||
writeTrigger.trigger()
|
||||
|
|
@ -51,8 +54,8 @@ internal class FileDataStore<Value : Any>(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun store(items: Map<String, Value>) {
|
||||
items.forEach { (key, item) ->
|
||||
override suspend fun store(values: Map<String, Value>) {
|
||||
values.forEach { (key, item) ->
|
||||
store(key, item)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,37 +5,45 @@ import kotlinx.coroutines.flow.*
|
|||
|
||||
internal class RuntimeDataStore<Data : Any> : StringKeyDataStore<Data> {
|
||||
|
||||
private val store = MutableStateFlow<HashMap<String, Data>>(hashMapOf())
|
||||
private val store: MutableSharedFlow<HashMap<String, Data>?> = MutableSharedFlow(replay = 1)
|
||||
|
||||
init {
|
||||
store.tryEmit(value = null)
|
||||
}
|
||||
|
||||
override fun get(key: String): Flow<Data> {
|
||||
return store
|
||||
.map { value -> value[key] }
|
||||
.map { value ->
|
||||
value?.get(key)
|
||||
}
|
||||
.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
|
||||
|
||||
value
|
||||
return store.map { value ->
|
||||
value?.values?.toList().orEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun store(items: Map<String, Data>) {
|
||||
store.update { value ->
|
||||
items.forEach { (key, item) ->
|
||||
override suspend fun getSyncOrNull(key: String): Data? {
|
||||
return store.firstOrNull()?.get(key)
|
||||
}
|
||||
|
||||
override suspend fun getAllSyncOrNull(): List<Data>? {
|
||||
return store.firstOrNull()?.values?.toList()
|
||||
}
|
||||
|
||||
override suspend fun store(key: String, value: Data) {
|
||||
updateValue { storedValue ->
|
||||
storedValue[key] = value
|
||||
|
||||
storedValue
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun store(values: Map<String, Data>) {
|
||||
updateValue { value ->
|
||||
values.forEach { (key, item) ->
|
||||
value[key] = item
|
||||
}
|
||||
|
||||
|
|
@ -44,7 +52,7 @@ internal class RuntimeDataStore<Data : Any> : StringKeyDataStore<Data> {
|
|||
}
|
||||
|
||||
override suspend fun remove(key: String) {
|
||||
store.update { value ->
|
||||
updateValue { value ->
|
||||
value.remove(key)
|
||||
|
||||
value
|
||||
|
|
@ -52,6 +60,13 @@ internal class RuntimeDataStore<Data : Any> : StringKeyDataStore<Data> {
|
|||
}
|
||||
|
||||
override suspend fun clear() {
|
||||
store.update { hashMapOf() }
|
||||
store.emit(value = null)
|
||||
}
|
||||
|
||||
private suspend inline fun updateValue(update: (HashMap<String, Data>) -> HashMap<String, Data>) {
|
||||
val storedData = store.firstOrNull() ?: hashMapOf()
|
||||
val updatedData = update(storedData)
|
||||
|
||||
store.emit(updatedData)
|
||||
}
|
||||
}
|
||||
|
|
@ -46,9 +46,9 @@ internal class SharedPreferencesDataStore<Value : Any>(
|
|||
return getAllInternal()
|
||||
}
|
||||
|
||||
override suspend fun store(key: String, item: Value) {
|
||||
override suspend fun store(key: String, value: Value) {
|
||||
try {
|
||||
val json = adapter.toJson(item)
|
||||
val json = adapter.toJson(value)
|
||||
|
||||
sharedPreferences.edit { putString(key, json) }
|
||||
writeTrigger.trigger()
|
||||
|
|
@ -57,8 +57,8 @@ internal class SharedPreferencesDataStore<Value : Any>(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun store(items: Map<String, Value>) {
|
||||
items.forEach { (key, item) ->
|
||||
override suspend fun store(values: Map<String, Value>) {
|
||||
values.forEach { (key, item) ->
|
||||
store(key, item)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ internal interface DataStore<Key : Any, Value : Any> {
|
|||
|
||||
suspend fun getSyncOrNull(key: Key): Value?
|
||||
|
||||
suspend fun getAllSyncOrNull(): List<Value>
|
||||
suspend fun getAllSyncOrNull(): List<Value>?
|
||||
|
||||
suspend fun store(key: Key, item: Value)
|
||||
suspend fun store(key: Key, value: Value)
|
||||
|
||||
suspend fun store(items: Map<Key, Value>)
|
||||
suspend fun store(values: Map<Key, Value>)
|
||||
|
||||
suspend fun remove(key: Key)
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ internal abstract class StringKeyDataStoreDecorator<Key : Any, Value : Any>(
|
|||
return wrappedDataStore.getAll()
|
||||
}
|
||||
|
||||
override suspend fun getAllSyncOrNull(): List<Value> {
|
||||
override suspend fun getAllSyncOrNull(): List<Value>? {
|
||||
return wrappedDataStore.getAllSyncOrNull()
|
||||
}
|
||||
|
||||
|
|
@ -24,13 +24,13 @@ internal abstract class StringKeyDataStoreDecorator<Key : Any, Value : Any>(
|
|||
return wrappedDataStore.getSyncOrNull(provideStringKey(key))
|
||||
}
|
||||
|
||||
override suspend fun store(key: Key, item: Value) {
|
||||
wrappedDataStore.store(provideStringKey(key), item)
|
||||
override suspend fun store(key: Key, value: Value) {
|
||||
wrappedDataStore.store(provideStringKey(key), value)
|
||||
}
|
||||
|
||||
override suspend fun store(items: Map<Key, Value>) {
|
||||
override suspend fun store(values: Map<Key, Value>) {
|
||||
wrappedDataStore.store(
|
||||
items = items.mapKeys { (key, _) -> provideStringKey(key) },
|
||||
values = values.mapKeys { (key, _) -> provideStringKey(key) },
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
package com.tangem.datasource.local.network
|
||||
|
||||
import com.tangem.datasource.local.datastore.core.StringKeyDataStore
|
||||
import com.tangem.datasource.local.datastore.core.StringKeyDataStoreDecorator
|
||||
import com.tangem.domain.tokens.model.NetworkStatus
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.extensions.addOrReplace
|
||||
|
||||
internal class DefaultNetworksStatusesStore(
|
||||
dataStore: StringKeyDataStore<Set<NetworkStatus>>,
|
||||
) : NetworksStatusesStore, StringKeyDataStoreDecorator<UserWalletId, Set<NetworkStatus>>(dataStore) {
|
||||
|
||||
override fun provideStringKey(key: UserWalletId): String {
|
||||
return key.stringValue
|
||||
}
|
||||
|
||||
override suspend fun store(key: UserWalletId, value: NetworkStatus) {
|
||||
val newValues = getSyncOrNull(key)
|
||||
?.addOrReplace(value) { it.network == value.network }
|
||||
?: setOf(value)
|
||||
|
||||
store(key, newValues)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.tangem.datasource.local.network
|
||||
|
||||
import com.tangem.domain.tokens.model.NetworkStatus
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface NetworksStatusesStore {
|
||||
|
||||
fun get(key: UserWalletId): Flow<Set<NetworkStatus>>
|
||||
|
||||
suspend fun getSyncOrNull(key: UserWalletId): Set<NetworkStatus>?
|
||||
|
||||
suspend fun store(key: UserWalletId, value: NetworkStatus)
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ package com.tangem.datasource.local.quote
|
|||
import com.tangem.datasource.api.tangemTech.models.QuotesResponse
|
||||
import com.tangem.datasource.local.datastore.core.StringKeyDataStore
|
||||
import com.tangem.datasource.local.quote.model.StoredQuote
|
||||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.tangem.datasource.local.quote
|
|||
|
||||
import com.tangem.datasource.api.tangemTech.models.QuotesResponse
|
||||
import com.tangem.datasource.local.quote.model.StoredQuote
|
||||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface QuotesStore {
|
||||
|
|
|
|||
|
|
@ -10,5 +10,5 @@ interface UserTokensStore {
|
|||
|
||||
suspend fun getSyncOrNull(key: UserWalletId): UserTokensResponse?
|
||||
|
||||
suspend fun store(key: UserWalletId, item: UserTokensResponse)
|
||||
suspend fun store(key: UserWalletId, value: UserTokensResponse)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue