Updated on 2026-08-14
This commit is contained in:
parent
15fb5b3954
commit
ff1ac5d0e7
6 changed files with 79 additions and 37 deletions
|
|
@ -87,7 +87,7 @@ internal class AddCustomTokenViewModel @Inject constructor(
|
|||
currentCryptoCurrencies = getSelectedWalletSyncUseCase().fold(
|
||||
ifLeft = { emptyList() },
|
||||
ifRight = { selectedWallet ->
|
||||
getCurrenciesUseCase(selectedWallet.walletId).fold(
|
||||
getCurrenciesUseCase.getSync(selectedWallet.walletId).fold(
|
||||
ifLeft = { emptyList() },
|
||||
ifRight = { it },
|
||||
)
|
||||
|
|
|
|||
|
|
@ -49,7 +49,11 @@ internal class TokensListMigration(
|
|||
is Either.Right -> {
|
||||
currentUserWallet = selectedWalletEither.value
|
||||
|
||||
when (val currenciesEither = getCurrenciesUseCase(userWalletId = selectedWalletEither.value.walletId)) {
|
||||
when (
|
||||
val currenciesEither = getCurrenciesUseCase.getSync(
|
||||
userWalletId = selectedWalletEither.value.walletId,
|
||||
)
|
||||
) {
|
||||
is Either.Left -> {
|
||||
Timber.e(currenciesEither.value.toString())
|
||||
TokensListCryptoCurrencies(coins = emptyList(), tokens = emptyList())
|
||||
|
|
|
|||
|
|
@ -1,16 +1,27 @@
|
|||
package com.tangem.domain.tokens
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.left
|
||||
import arrow.core.raise.catch
|
||||
import arrow.core.raise.either
|
||||
import arrow.core.right
|
||||
import com.tangem.domain.tokens.error.GetCurrenciesError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
class GetCryptoCurrenciesUseCase(private val currenciesRepository: CurrenciesRepository) {
|
||||
|
||||
suspend operator fun invoke(
|
||||
operator fun invoke(userWalletId: UserWalletId): Flow<Either<GetCurrenciesError, List<CryptoCurrency>>> {
|
||||
return currenciesRepository.getMultiCurrencyWalletCurrenciesUpdates(userWalletId)
|
||||
.map<List<CryptoCurrency>, Either<GetCurrenciesError, List<CryptoCurrency>>> { it.right() }
|
||||
.catch { emit(GetCurrenciesError.DataError(it).left()) }
|
||||
}
|
||||
|
||||
suspend fun getSync(
|
||||
userWalletId: UserWalletId,
|
||||
refresh: Boolean = false,
|
||||
): Either<GetCurrenciesError, List<CryptoCurrency>> {
|
||||
|
|
|
|||
|
|
@ -424,7 +424,7 @@ internal class AddCustomTokenViewModel @Inject constructor(
|
|||
selectedWallet: UserWallet,
|
||||
cryptoCurrency: CryptoCurrency,
|
||||
): Boolean {
|
||||
val currenciesList = getCurrenciesUseCase(selectedWallet.walletId).getOrElse { emptyList() }
|
||||
val currenciesList = getCurrenciesUseCase.getSync(selectedWallet.walletId).getOrElse { emptyList() }
|
||||
return when (cryptoCurrency) {
|
||||
is CryptoCurrency.Coin -> {
|
||||
currenciesList.any {
|
||||
|
|
|
|||
|
|
@ -33,11 +33,15 @@ import com.tangem.utils.Provider
|
|||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.coroutines.Debouncer
|
||||
import com.tangem.utils.coroutines.Debouncer.Companion.DEFAULT_WAIT_TIME_MS
|
||||
import com.tangem.utils.coroutines.JobHolder
|
||||
import com.tangem.utils.coroutines.saveIn
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.plus
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.util.Collections
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
import javax.inject.Inject
|
||||
import kotlin.collections.set
|
||||
import kotlin.properties.Delegates
|
||||
|
|
@ -62,8 +66,6 @@ internal class ManageTokensViewModel @Inject constructor(
|
|||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
) : ViewModel(), ManageTokensClickIntents, ManageTokensUiEvents {
|
||||
|
||||
private val debouncer = Debouncer()
|
||||
|
||||
private val stateFactory = ManageTokensStateFactory(
|
||||
currentStateProvider = Provider { uiState },
|
||||
clickIntents = this,
|
||||
|
|
@ -73,11 +75,17 @@ internal class ManageTokensViewModel @Inject constructor(
|
|||
var uiState: ManageTokensState by mutableStateOf(stateFactory.getInitialState(flowOf(PagingData.from(emptyList()))))
|
||||
private set
|
||||
|
||||
private var allAddedCurrencies: MutableList<CryptoCurrency> = mutableListOf()
|
||||
private val currenciesListJobHolder: JobHolder = JobHolder()
|
||||
|
||||
private var wallets: List<UserWallet> by Delegates.notNull()
|
||||
private val debouncer = Debouncer()
|
||||
|
||||
private var addedCurrenciesByWallet: MutableMap<UserWallet, MutableList<CryptoCurrency>> = mutableMapOf()
|
||||
private var allAddedCurrencies: MutableList<CryptoCurrency> = Collections.synchronizedList(
|
||||
mutableListOf<CryptoCurrency>(),
|
||||
)
|
||||
|
||||
private var wallets: CopyOnWriteArrayList<UserWallet> by Delegates.notNull()
|
||||
|
||||
private var addedCurrenciesByWallet: MutableMap<UserWallet, MutableList<CryptoCurrency>> = ConcurrentHashMap()
|
||||
|
||||
private var selectedWallet: UserWallet? = null
|
||||
|
||||
|
|
@ -114,34 +122,53 @@ internal class ManageTokensViewModel @Inject constructor(
|
|||
getWalletsUseCase()
|
||||
.distinctUntilChanged()
|
||||
.collectLatest { userWallets ->
|
||||
wallets = userWallets.filter { it.isMultiCurrency && !it.isLocked }
|
||||
wallets.map { wallet ->
|
||||
val currencies = getCurrenciesUseCase(wallet.walletId).fold(
|
||||
ifLeft = { emptyList() },
|
||||
ifRight = { it },
|
||||
)
|
||||
allAddedCurrencies += currencies
|
||||
addedCurrenciesByWallet[wallet] = currencies.toMutableList()
|
||||
}
|
||||
withContext(dispatchers.main) {
|
||||
uiState = uiState.copy(tokens = getInitialTokensList())
|
||||
}
|
||||
selectedWallet = getSelectedWalletSyncUseCase().fold(
|
||||
ifLeft = { null },
|
||||
ifRight = { if (!it.isMultiCurrency || it.isLocked) null else it },
|
||||
)
|
||||
if (selectedWallet == null && wallets.isNotEmpty()) {
|
||||
selectWalletUseCase(wallets.first().walletId)
|
||||
selectedWallet = wallets.first()
|
||||
}
|
||||
updateDerivationNotificationState()
|
||||
withContext(dispatchers.main) {
|
||||
uiState = stateFactory.updateChooseWalletState(wallets, userWallets, selectedWallet)
|
||||
}
|
||||
launch {
|
||||
subscribeToCurrencies(userWallets)
|
||||
}.saveIn(currenciesListJobHolder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun subscribeToCurrencies(userWallets: List<UserWallet>) {
|
||||
wallets = CopyOnWriteArrayList(userWallets.filter { it.isMultiCurrency && !it.isLocked })
|
||||
|
||||
combine(wallets.map { getCurrenciesUseCase.invoke(it.walletId).distinctUntilChanged() }) {
|
||||
allAddedCurrencies.clear()
|
||||
addedCurrenciesByWallet.clear()
|
||||
|
||||
val walletsWithCurrencies = wallets.zip(
|
||||
it.map { currencyList ->
|
||||
currencyList.getOrElse {
|
||||
Timber.e("Couldn't retrieve currency list")
|
||||
emptyList()
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
allAddedCurrencies = walletsWithCurrencies.flatMap { it.second }.toMutableList()
|
||||
|
||||
walletsWithCurrencies.forEach { (wallet, currencies) ->
|
||||
addedCurrenciesByWallet[wallet] = currencies.toMutableList()
|
||||
}
|
||||
|
||||
withContext(dispatchers.main) {
|
||||
uiState = uiState.copy(tokens = getInitialTokensList())
|
||||
}
|
||||
selectedWallet = getSelectedWalletSyncUseCase().fold(
|
||||
ifLeft = { null },
|
||||
ifRight = { if (!it.isMultiCurrency || it.isLocked) null else it },
|
||||
)
|
||||
if (selectedWallet == null && wallets.isNotEmpty()) {
|
||||
selectWalletUseCase(wallets.first().walletId)
|
||||
selectedWallet = wallets.first()
|
||||
}
|
||||
updateDerivationNotificationState()
|
||||
withContext(dispatchers.main) {
|
||||
uiState = stateFactory.updateChooseWalletState(wallets, userWallets, selectedWallet)
|
||||
}
|
||||
}.collect()
|
||||
}
|
||||
|
||||
private fun getInitialTokensList(searchText: String = ""): Flow<PagingData<TokenItemState>> {
|
||||
return getGlobalTokenListUseCase(searchText = searchText).map {
|
||||
it.map { token -> tokenConverter.convert(token) }
|
||||
|
|
|
|||
|
|
@ -324,7 +324,7 @@ internal class SendViewModel @Inject constructor(
|
|||
.filterNot { it.walletId == userWalletId || it.isLocked }
|
||||
.map { wallet ->
|
||||
async(dispatchers.io) {
|
||||
getCryptoCurrenciesUseCase(wallet.walletId)
|
||||
getCryptoCurrenciesUseCase.getSync(wallet.walletId)
|
||||
.fold(
|
||||
ifRight = { currencyItem ->
|
||||
val walletCurrency = currencyItem.firstOrNull {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue