Updated on 2026-08-14
This commit is contained in:
commit
cab30e9431
186 changed files with 3729 additions and 2030 deletions
|
|
@ -0,0 +1,35 @@
|
|||
package com.tangem.feature.wallet.presentation.tokenlist.entity
|
||||
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTokensListState.TokensListItemState
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
/**
|
||||
* Token list UM
|
||||
*
|
||||
* @property items items (search bar, tokens, headers)
|
||||
* @property isBalanceHidden flag that indicates if balance should be hidden
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal data class TokenListUM(
|
||||
val items: ImmutableList<TokensListItemState>,
|
||||
val isBalanceHidden: Boolean,
|
||||
) {
|
||||
|
||||
/** Get search bar if it exists */
|
||||
fun getSearchBar(): TokensListItemState.SearchBar? {
|
||||
return items.firstOrNull() as? TokensListItemState.SearchBar
|
||||
}
|
||||
|
||||
/** Get tokens */
|
||||
fun getTokens(): ImmutableList<TokensListItemState> {
|
||||
if (getSearchBar() == null) return items
|
||||
|
||||
return if (items.size > 1) {
|
||||
items.subList(fromIndex = 1, toIndex = items.size)
|
||||
} else {
|
||||
persistentListOf()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package com.tangem.feature.wallet.presentation.tokenlist.entity
|
||||
|
||||
import com.tangem.core.ui.components.fields.entity.SearchBarUM
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTokensListState.TokensListItemState
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* [TokenListUM] controller
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class TokenListUMController @Inject constructor() {
|
||||
|
||||
val state: StateFlow<TokenListUM> get() = _state
|
||||
|
||||
private val _state: MutableStateFlow<TokenListUM> = MutableStateFlow(
|
||||
value = TokenListUM(
|
||||
items = persistentListOf(createInitialSearchBar()),
|
||||
isBalanceHidden = false,
|
||||
),
|
||||
)
|
||||
|
||||
fun update(transform: (TokenListUM) -> TokenListUM) {
|
||||
Timber.d("Applying non-name transformation")
|
||||
_state.update(transform)
|
||||
}
|
||||
|
||||
fun update(transformer: TokenListUMTransformer) {
|
||||
Timber.d("Applying ${transformer::class.simpleName}")
|
||||
_state.update(transformer::transform)
|
||||
}
|
||||
|
||||
/** Get search bar if it exists */
|
||||
fun getSearchBar(): TokensListItemState.SearchBar? = _state.value.getSearchBar()
|
||||
|
||||
private fun createInitialSearchBar(): TokensListItemState.SearchBar {
|
||||
return TokensListItemState.SearchBar(
|
||||
searchBarUM = SearchBarUM(
|
||||
placeholderText = resourceReference(id = R.string.common_search),
|
||||
query = "",
|
||||
onQueryChange = {},
|
||||
isActive = false,
|
||||
onActiveChange = {},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.tangem.feature.wallet.presentation.tokenlist.entity
|
||||
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
|
||||
/**
|
||||
* Base [TokenListUM] transformer
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal interface TokenListUMTransformer : Transformer<TokenListUM>
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package com.tangem.feature.wallet.presentation.tokenlist.entity.transformer
|
||||
|
||||
import com.tangem.core.ui.components.fields.entity.SearchBarUM
|
||||
import com.tangem.feature.wallet.presentation.tokenlist.entity.TokenListUM
|
||||
import com.tangem.feature.wallet.presentation.tokenlist.entity.TokenListUMTransformer
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
/**
|
||||
* Base [SearchBarUM] transformer
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal abstract class SearchBarUMTransformer : TokenListUMTransformer {
|
||||
|
||||
abstract fun transform(prevState: SearchBarUM): SearchBarUM
|
||||
|
||||
override fun transform(prevState: TokenListUM): TokenListUM {
|
||||
val searchBarItem = prevState.getSearchBar()
|
||||
|
||||
return if (searchBarItem != null) {
|
||||
val updatedSearchBar = searchBarItem.copy(searchBarUM = transform(searchBarItem.searchBarUM))
|
||||
|
||||
prevState.copy(
|
||||
items = persistentListOf(
|
||||
updatedSearchBar,
|
||||
*prevState.getTokens().toTypedArray(),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
prevState
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package com.tangem.feature.wallet.presentation.tokenlist.entity.transformer
|
||||
|
||||
import com.tangem.core.ui.components.fields.entity.SearchBarUM
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
|
||||
internal class UpdateSearchBarActiveStateTransformer(private val isActive: Boolean) : SearchBarUMTransformer() {
|
||||
|
||||
override fun transform(prevState: SearchBarUM): SearchBarUM {
|
||||
val placeholderText = if (isActive) {
|
||||
TextReference.EMPTY
|
||||
} else {
|
||||
resourceReference(id = R.string.common_search)
|
||||
}
|
||||
|
||||
return prevState.copy(placeholderText = placeholderText, isActive = isActive)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.tangem.feature.wallet.presentation.tokenlist.entity.transformer
|
||||
|
||||
import com.tangem.core.ui.components.fields.entity.SearchBarUM
|
||||
|
||||
internal class UpdateSearchBarIntentsTransformer(
|
||||
private val onQueryChange: (String) -> Unit,
|
||||
private val onActiveChange: (Boolean) -> Unit,
|
||||
) : SearchBarUMTransformer() {
|
||||
|
||||
override fun transform(prevState: SearchBarUM): SearchBarUM {
|
||||
return prevState.copy(onQueryChange = onQueryChange, onActiveChange = onActiveChange)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.tangem.feature.wallet.presentation.tokenlist.entity.transformer
|
||||
|
||||
import com.tangem.core.ui.components.fields.entity.SearchBarUM
|
||||
|
||||
internal class UpdateSearchQueryTransformer(private val newQuery: String) : SearchBarUMTransformer() {
|
||||
|
||||
override fun transform(prevState: SearchBarUM): SearchBarUM {
|
||||
return prevState.copy(query = newQuery)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package com.tangem.feature.wallet.presentation.tokenlist.entity.transformer
|
||||
|
||||
import com.tangem.common.ui.tokens.TokenItemStateConverter
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.feature.wallet.presentation.tokenlist.entity.TokenListUM
|
||||
import com.tangem.feature.wallet.presentation.tokenlist.entity.TokenListUMTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTokensListState.TokensListItemState
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
internal class UpdateTokenItemsTransformer(
|
||||
appCurrency: AppCurrency,
|
||||
onItemClick: (CryptoCurrencyStatus) -> Unit,
|
||||
private val statuses: List<CryptoCurrencyStatus>,
|
||||
private val isBalanceHidden: Boolean,
|
||||
) : TokenListUMTransformer {
|
||||
|
||||
private val converter = TokenItemStateConverter(appCurrency = appCurrency, onItemClick = onItemClick)
|
||||
|
||||
override fun transform(prevState: TokenListUM): TokenListUM {
|
||||
val items = converter.convertList(input = statuses).map(TokensListItemState::Token)
|
||||
|
||||
return prevState.copy(
|
||||
items = (listOfNotNull(prevState.getSearchBar()) + items).toImmutableList(),
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,6 @@ import com.tangem.core.analytics.models.AnalyticsParam
|
|||
import com.tangem.domain.analytics.CheckIsWalletToppedUpUseCase
|
||||
import com.tangem.domain.analytics.model.WalletBalanceState
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.model.NetworkGroup
|
||||
import com.tangem.domain.tokens.model.TokenList
|
||||
import com.tangem.domain.tokens.model.TotalFiatBalance
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
|
@ -38,7 +37,7 @@ internal class TokenListAnalyticsSender @Inject constructor(
|
|||
if (displayedUiState == null || displayedUiState.pullToRefreshConfig.isRefreshing) return
|
||||
if (tokenList.totalFiatBalance is TotalFiatBalance.Loading) return
|
||||
|
||||
val currenciesStatuses = getCurrenciesStatuses(tokenList)
|
||||
val currenciesStatuses = tokenList.flattenCurrencies()
|
||||
|
||||
sendBalanceLoadedEventIfNeeded(tokenList.totalFiatBalance, currenciesStatuses)
|
||||
sendToppedUpEventIfNeeded(userWallet, tokenList.totalFiatBalance, currenciesStatuses)
|
||||
|
|
@ -46,12 +45,6 @@ internal class TokenListAnalyticsSender @Inject constructor(
|
|||
sendTokenBalancesIfNeeded(currenciesStatuses)
|
||||
}
|
||||
|
||||
private fun getCurrenciesStatuses(tokenList: TokenList): List<CryptoCurrencyStatus> = when (tokenList) {
|
||||
is TokenList.Empty -> emptyList()
|
||||
is TokenList.GroupedByNetwork -> tokenList.groups.flatMap(NetworkGroup::currencies)
|
||||
is TokenList.Ungrouped -> tokenList.currencies
|
||||
}
|
||||
|
||||
private fun sendBalanceLoadedEventIfNeeded(
|
||||
fiatBalance: TotalFiatBalance,
|
||||
currenciesStatuses: List<CryptoCurrencyStatus>,
|
||||
|
|
|
|||
|
|
@ -7,11 +7,9 @@ import com.tangem.domain.demo.IsDemoCardUseCase
|
|||
import com.tangem.domain.promo.PromoBanner
|
||||
import com.tangem.domain.settings.IsReadyToShowRateAppUseCase
|
||||
import com.tangem.domain.settings.ShouldShowRingPromoUseCase
|
||||
import com.tangem.domain.tokens.GetTokenListUseCase
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.model.NetworkGroup
|
||||
import com.tangem.domain.tokens.model.TokenList
|
||||
import com.tangem.domain.tokens.repository.PromoRepository
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
|
@ -30,7 +28,7 @@ import kotlin.collections.count
|
|||
@Suppress("LongParameterList")
|
||||
@ViewModelScoped
|
||||
internal class GetMultiWalletWarningsFactory @Inject constructor(
|
||||
private val getTokenListUseCase: GetTokenListUseCase,
|
||||
private val tokenListStore: MultiWalletTokenListStore,
|
||||
private val isDemoCardUseCase: IsDemoCardUseCase,
|
||||
private val isReadyToShowRateAppUseCase: IsReadyToShowRateAppUseCase,
|
||||
private val shouldShowRingPromoUseCase: ShouldShowRingPromoUseCase,
|
||||
|
|
@ -44,7 +42,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
|
||||
val promoFlow = flow { emit(promoRepository.getRingPromoBanner()) }
|
||||
return combine(
|
||||
flow = getTokenListUseCase.launch(userWallet.walletId),
|
||||
flow = tokenListStore.getOrThrow(userWallet.walletId),
|
||||
flow2 = isReadyToShowRateAppUseCase(),
|
||||
flow3 = isNeedToBackupUseCase(userWallet.walletId),
|
||||
flow4 = shouldShowRingPromoUseCase(userWalletId = userWallet.walletId),
|
||||
|
|
@ -129,6 +127,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
val currencies = maybeTokenList.getMissingAddressCurrencies()
|
||||
.ifEmpty { return }
|
||||
|
||||
addIf(
|
||||
element = WalletNotification.Informational.MissingAddresses(
|
||||
|
|
@ -144,13 +143,8 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
private fun Lce<TokenListError, TokenList>.getMissingAddressCurrencies(): List<CryptoCurrency> {
|
||||
val tokenList = getOrNull(isPartialContentAccepted = false) ?: return emptyList()
|
||||
|
||||
val currencies = when (tokenList) {
|
||||
is TokenList.GroupedByNetwork -> tokenList.groups.flatMap(NetworkGroup::currencies)
|
||||
is TokenList.Ungrouped -> tokenList.currencies
|
||||
is TokenList.Empty -> emptyList()
|
||||
}
|
||||
|
||||
return currencies
|
||||
return tokenList
|
||||
.flattenCurrencies()
|
||||
.filter { it.value is CryptoCurrencyStatus.MissedDerivation }
|
||||
.map(CryptoCurrencyStatus::currency)
|
||||
}
|
||||
|
|
@ -182,13 +176,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
private fun Lce<TokenListError, TokenList>.hasUnreachableNetworks(): Boolean {
|
||||
val tokenList = getOrNull(isPartialContentAccepted = false) ?: return false
|
||||
|
||||
val currencies = when (tokenList) {
|
||||
is TokenList.GroupedByNetwork -> tokenList.groups.flatMap(NetworkGroup::currencies)
|
||||
is TokenList.Ungrouped -> tokenList.currencies
|
||||
is TokenList.Empty -> emptyList()
|
||||
}
|
||||
|
||||
return currencies.any { it.value is CryptoCurrencyStatus.Unreachable }
|
||||
return tokenList.flattenCurrencies().any { it.value is CryptoCurrencyStatus.Unreachable }
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotification>.addRateTheAppNotification(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.domain
|
||||
|
||||
import com.tangem.domain.core.lce.LceFlow
|
||||
import com.tangem.domain.tokens.GetTokenListUseCase
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
import com.tangem.domain.tokens.model.TokenList
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import dagger.hilt.android.scopes.ViewModelScoped
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.ensureActive
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.shareIn
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import javax.inject.Inject
|
||||
|
||||
@ViewModelScoped
|
||||
internal class MultiWalletTokenListStore @Inject constructor(
|
||||
private val getTokenListUseCase: GetTokenListUseCase,
|
||||
) {
|
||||
|
||||
private val flows: ConcurrentHashMap<UserWalletId, LceFlow<TokenListError, TokenList>> by lazy {
|
||||
ConcurrentHashMap()
|
||||
}
|
||||
|
||||
fun addIfNot(userWalletId: UserWalletId, coroutineScope: CoroutineScope) {
|
||||
if (flows[userWalletId] != null) {
|
||||
Timber.d("Flow with token list for $userWalletId already exists")
|
||||
return
|
||||
}
|
||||
|
||||
coroutineScope.ensureActive()
|
||||
|
||||
flows[userWalletId] = getTokenListUseCase
|
||||
.launch(userWalletId)
|
||||
.shareIn(
|
||||
scope = coroutineScope,
|
||||
started = SharingStarted.WhileSubscribed(),
|
||||
replay = 1,
|
||||
)
|
||||
|
||||
Timber.d("Flow with token list for $userWalletId created")
|
||||
}
|
||||
|
||||
fun getOrThrow(userWalletId: UserWalletId): LceFlow<TokenListError, TokenList> {
|
||||
return requireNotNull(flows[userWalletId]) {
|
||||
"Flow with token list for $userWalletId doesn't exist"
|
||||
}
|
||||
}
|
||||
|
||||
fun remove(userWalletId: UserWalletId) {
|
||||
flows.remove(userWalletId)
|
||||
|
||||
Timber.d("Flow with token list for $userWalletId removed")
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
flows.clear()
|
||||
|
||||
Timber.d("All flows with token list cleared")
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,8 @@ import com.tangem.core.ui.extensions.TextReference
|
|||
import com.tangem.core.ui.extensions.plus
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.common.util.getCardsCount
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
|
@ -97,13 +98,7 @@ internal object WalletAdditionalInfoFactory {
|
|||
WalletAdditionalInfo(hideable = false, content = TextReference.Res(R.string.common_locked))
|
||||
} else {
|
||||
val blockchain = scanResponse.cardTypesResolver.getBlockchain()
|
||||
val amount = currencyAmount?.let {
|
||||
BigDecimalFormatter.formatCryptoAmount(
|
||||
cryptoAmount = it,
|
||||
cryptoCurrency = blockchain.currency,
|
||||
decimals = blockchain.decimals(),
|
||||
)
|
||||
}
|
||||
val amount = currencyAmount?.format { crypto(blockchain.currency, blockchain.decimals()) }
|
||||
|
||||
WalletAdditionalInfo(hideable = true, content = TextReference.Str(value = amount.orEmpty()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package com.tangem.feature.wallet.presentation.wallet.domain
|
|||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.domain.settings.SetWalletWithFundsFoundUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.model.NetworkGroup
|
||||
import com.tangem.domain.tokens.model.TokenList
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -12,15 +11,7 @@ internal class WalletWithFundsChecker @Inject constructor(
|
|||
) {
|
||||
|
||||
suspend fun check(tokenList: TokenList) {
|
||||
val hasNonZeroWallets = when (tokenList) {
|
||||
is TokenList.GroupedByNetwork -> {
|
||||
tokenList.groups
|
||||
.flatMap(NetworkGroup::currencies)
|
||||
.hasNonZeroWallets()
|
||||
}
|
||||
is TokenList.Ungrouped -> tokenList.currencies.hasNonZeroWallets()
|
||||
is TokenList.Empty -> false
|
||||
}
|
||||
val hasNonZeroWallets = tokenList.flattenCurrencies().hasNonZeroWallets()
|
||||
|
||||
if (hasNonZeroWallets) setWalletWithFundsFoundUseCase()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@ package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
|
|||
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.tokens.ApplyTokenListSortingUseCase
|
||||
import com.tangem.domain.tokens.GetTokenListUseCase
|
||||
import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.GetMultiWalletWarningsFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenListStore
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.MultiWalletTokenListSubscriber
|
||||
|
|
@ -23,7 +23,7 @@ internal class MultiWalletContentLoader(
|
|||
private val tokenListAnalyticsSender: TokenListAnalyticsSender,
|
||||
private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender,
|
||||
private val walletWithFundsChecker: WalletWithFundsChecker,
|
||||
private val getTokenListUseCase: GetTokenListUseCase,
|
||||
private val tokenListStore: MultiWalletTokenListStore,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val applyTokenListSortingUseCase: ApplyTokenListSortingUseCase,
|
||||
private val getMultiWalletWarningsFactory: GetMultiWalletWarningsFactory,
|
||||
|
|
@ -38,7 +38,7 @@ internal class MultiWalletContentLoader(
|
|||
clickIntents = clickIntents,
|
||||
tokenListAnalyticsSender = tokenListAnalyticsSender,
|
||||
walletWithFundsChecker = walletWithFundsChecker,
|
||||
getTokenListUseCase = getTokenListUseCase,
|
||||
tokenListStore = tokenListStore,
|
||||
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
|
||||
applyTokenListSortingUseCase = applyTokenListSortingUseCase,
|
||||
runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase,
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@ package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
|
|||
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.tokens.ApplyTokenListSortingUseCase
|
||||
import com.tangem.domain.tokens.GetTokenListUseCase
|
||||
import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.GetMultiWalletWarningsFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenListStore
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntents
|
||||
|
|
@ -21,7 +21,7 @@ internal class MultiWalletContentLoaderFactory @Inject constructor(
|
|||
private val tokenListAnalyticsSender: TokenListAnalyticsSender,
|
||||
private val walletWithFundsChecker: WalletWithFundsChecker,
|
||||
private val getMultiWalletWarningsFactory: GetMultiWalletWarningsFactory,
|
||||
private val getTokenListUseCase: GetTokenListUseCase,
|
||||
private val tokenListStore: MultiWalletTokenListStore,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val applyTokenListSortingUseCase: ApplyTokenListSortingUseCase,
|
||||
private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender,
|
||||
|
|
@ -35,7 +35,7 @@ internal class MultiWalletContentLoaderFactory @Inject constructor(
|
|||
stateHolder = stateHolder,
|
||||
tokenListAnalyticsSender = tokenListAnalyticsSender,
|
||||
walletWithFundsChecker = walletWithFundsChecker,
|
||||
getTokenListUseCase = getTokenListUseCase,
|
||||
tokenListStore = tokenListStore,
|
||||
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
|
||||
getMultiWalletWarningsFactory = getMultiWalletWarningsFactory,
|
||||
walletWarningsAnalyticsSender = walletWarningsAnalyticsSender,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.model
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.core.ui.components.fields.entity.SearchBarUM
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
|
|
@ -43,6 +44,11 @@ internal sealed class WalletTokensListState {
|
|||
|
||||
abstract val id: Any
|
||||
|
||||
data class SearchBar(
|
||||
override val id: Any = "search_bar",
|
||||
val searchBarUM: SearchBarUM,
|
||||
) : TokensListItemState()
|
||||
|
||||
data class NetworkGroupTitle(override val id: Int, val name: TextReference) : TokensListItemState()
|
||||
|
||||
data class Token(val state: TokenItemState) : TokensListItemState() {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
|||
import arrow.core.Either
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.domain.common.util.getCardsCount
|
||||
import com.tangem.domain.visa.model.VisaCurrency
|
||||
|
|
@ -41,11 +43,9 @@ internal class SetBalancesAndLimitsTransformer(
|
|||
}
|
||||
|
||||
private fun getContentBlockState(visaCurrency: VisaCurrency) = BalancesAndLimitsBlockState.Content(
|
||||
availableBalance = BigDecimalFormatter.formatCryptoAmount(
|
||||
visaCurrency.limits.remainingOtp,
|
||||
visaCurrency.symbol,
|
||||
visaCurrency.decimals,
|
||||
),
|
||||
availableBalance = visaCurrency.limits.remainingOtp.format {
|
||||
crypto(visaCurrency.symbol, visaCurrency.decimals)
|
||||
},
|
||||
limitDays = Days.daysBetween(DateTime.now(), visaCurrency.limits.expirationDate).days.inc(),
|
||||
isEnabled = true,
|
||||
onClick = clickIntents::onBalancesAndLimitsClick,
|
||||
|
|
@ -72,11 +72,9 @@ internal class SetBalancesAndLimitsTransformer(
|
|||
imageResId = imageResId,
|
||||
onRenameClick = onRenameClick,
|
||||
onDeleteClick = onDeleteClick,
|
||||
balance = BigDecimalFormatter.formatCryptoAmount(
|
||||
visaCurrency.balances.available,
|
||||
visaCurrency.symbol,
|
||||
visaCurrency.decimals,
|
||||
),
|
||||
balance = visaCurrency.balances.available.format {
|
||||
crypto(visaCurrency.symbol, visaCurrency.decimals)
|
||||
},
|
||||
cardCount = userWallet.getCardsCount(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.transformers.converter
|
||||
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.utils.DateTimeFormatters
|
||||
import com.tangem.domain.visa.model.VisaCurrency
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.BalancesAndLimitsBottomSheetConfig
|
||||
|
|
@ -15,11 +16,7 @@ internal class BalancesAndLimitsBottomSheetConverter(
|
|||
) : Converter<VisaCurrency, BalancesAndLimitsBottomSheetConfig> {
|
||||
|
||||
override fun convert(value: VisaCurrency): BalancesAndLimitsBottomSheetConfig {
|
||||
fun formatAmount(amount: BigDecimal): String = BigDecimalFormatter.formatCryptoAmount(
|
||||
amount,
|
||||
cryptoCurrency = value.symbol,
|
||||
decimals = value.decimals,
|
||||
)
|
||||
fun formatAmount(amount: BigDecimal): String = amount.format { crypto(value.symbol, value.decimals) }
|
||||
|
||||
val otpLimit = value.limits.remainingOtp.let(::formatAmount)
|
||||
val noOtpLimit = value.limits.remainingNoOtp.let(::formatAmount)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import com.tangem.core.ui.components.marketprice.MarketPriceBlockState
|
|||
import com.tangem.core.ui.components.marketprice.PriceChangeState
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeType
|
||||
import com.tangem.core.ui.components.marketprice.utils.PriceChangeConverter
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.format.bigdecimal.percent
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
|
|
@ -57,7 +59,7 @@ internal class SingleWalletMarketPriceConverter(
|
|||
private fun formatPriceChange(status: CryptoCurrencyStatus.Value): String {
|
||||
val priceChange = status.priceChange ?: return BigDecimalFormatter.EMPTY_BALANCE_SIGN
|
||||
|
||||
return BigDecimalFormatter.formatPercent(percent = priceChange, useAbsoluteValue = true)
|
||||
return priceChange.format { percent() }
|
||||
}
|
||||
|
||||
private fun getPriceChangeType(status: CryptoCurrencyStatus.Value): PriceChangeType {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import com.tangem.core.ui.extensions.TextReference
|
|||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.utils.toTimeFormat
|
||||
import com.tangem.domain.txhistory.models.TxHistoryItem
|
||||
import com.tangem.domain.txhistory.models.TxHistoryItem.*
|
||||
|
|
@ -15,7 +17,6 @@ import com.tangem.utils.StringsSigns.MINUS
|
|||
import com.tangem.utils.StringsSigns.PLUS
|
||||
import com.tangem.utils.converter.Converter
|
||||
import com.tangem.utils.toBriefAddressFormat
|
||||
import com.tangem.utils.toFormattedCurrencyString
|
||||
|
||||
internal class TxHistoryItemStateConverter(
|
||||
private val symbol: String,
|
||||
|
|
@ -129,6 +130,6 @@ internal class TxHistoryItemStateConverter(
|
|||
this.amount.isZero() -> ""
|
||||
else -> if (isOutgoing) MINUS else PLUS
|
||||
}
|
||||
return prefix + amount.toFormattedCurrencyString(currency = symbol, decimals = decimals)
|
||||
return prefix + amount.format { crypto(symbol = symbol, decimals = decimals) }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.transformers.converter
|
||||
|
||||
import com.tangem.core.ui.extensions.capitalize
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.core.ui.utils.DateTimeFormatters
|
||||
import com.tangem.domain.visa.model.VisaCurrency
|
||||
|
|
@ -66,11 +68,7 @@ internal class VisaTxDetailsBottomSheetConverter(
|
|||
}
|
||||
|
||||
private fun formatNetworkAmount(amount: BigDecimal): String {
|
||||
return BigDecimalFormatter.formatCryptoAmount(
|
||||
cryptoAmount = amount,
|
||||
cryptoCurrency = visaCurrency.symbol,
|
||||
decimals = visaCurrency.decimals,
|
||||
)
|
||||
return amount.format { crypto(visaCurrency.symbol, visaCurrency.decimals) }
|
||||
}
|
||||
|
||||
private fun formatFiatAmount(amount: BigDecimal, fiatCurrency: Currency): String {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers.convert
|
|||
import com.tangem.core.ui.components.transactions.state.TransactionState
|
||||
import com.tangem.core.ui.extensions.capitalize
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.core.ui.utils.DateTimeFormatters
|
||||
import com.tangem.domain.visa.model.VisaCurrency
|
||||
|
|
@ -25,11 +27,7 @@ internal class VisaTxHistoryItemStateConverter(
|
|||
|
||||
return TransactionState.Content(
|
||||
txHash = value.id,
|
||||
amount = BigDecimalFormatter.formatCryptoAmount(
|
||||
cryptoAmount = value.amount,
|
||||
cryptoCurrency = visaCurrency.symbol,
|
||||
decimals = visaCurrency.decimals,
|
||||
),
|
||||
amount = value.amount.format { crypto(visaCurrency.symbol, visaCurrency.decimals) },
|
||||
// Show tx fiat amount instead of tx time
|
||||
time = BigDecimalFormatter.formatFiatAmount(
|
||||
fiatAmount = value.fiatAmount,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import com.tangem.domain.core.lce.LceFlow
|
|||
import com.tangem.domain.core.utils.getOrElse
|
||||
import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
import com.tangem.domain.tokens.model.NetworkGroup
|
||||
import com.tangem.domain.tokens.model.TokenList
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender
|
||||
|
|
@ -41,11 +40,11 @@ internal abstract class BasicTokenListSubscriber(
|
|||
private val sendAnalyticsJobHolder = JobHolder()
|
||||
private val onTokenListReceivedJobHolder = JobHolder()
|
||||
|
||||
protected abstract fun tokenListFlow(): LceFlow<TokenListError, TokenList>
|
||||
protected abstract fun tokenListFlow(coroutineScope: CoroutineScope): LceFlow<TokenListError, TokenList>
|
||||
|
||||
override fun create(coroutineScope: CoroutineScope): Flow<*> {
|
||||
return combine(
|
||||
flow = tokenListFlow()
|
||||
flow = tokenListFlow(coroutineScope)
|
||||
.onEach { maybeTokenList ->
|
||||
coroutineScope.launch {
|
||||
sendTokenListAnalytics(maybeTokenList)
|
||||
|
|
@ -99,15 +98,14 @@ internal abstract class BasicTokenListSubscriber(
|
|||
private suspend fun startCheck(maybeTokenList: Lce<TokenListError, TokenList>) {
|
||||
// Run Polkadot account health check
|
||||
maybeTokenList.getOrNull()?.let { tokenList ->
|
||||
val cryptoCurrencies = when (tokenList) {
|
||||
is TokenList.GroupedByNetwork -> tokenList.groups.flatMap(NetworkGroup::currencies)
|
||||
is TokenList.Ungrouped -> tokenList.currencies
|
||||
is TokenList.Empty -> emptyList()
|
||||
}
|
||||
|
||||
cryptoCurrencies.forEach {
|
||||
runPolkadotAccountHealthCheckUseCase(userWallet.walletId, it.currency.network)
|
||||
}
|
||||
tokenList
|
||||
.flattenCurrencies()
|
||||
.forEach {
|
||||
runPolkadotAccountHealthCheckUseCase(
|
||||
userWalletId = userWallet.walletId,
|
||||
network = it.currency.network,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
|||
import com.tangem.domain.core.lce.Lce
|
||||
import com.tangem.domain.core.lce.LceFlow
|
||||
import com.tangem.domain.tokens.ApplyTokenListSortingUseCase
|
||||
import com.tangem.domain.tokens.GetTokenListUseCase
|
||||
import com.tangem.domain.tokens.RunPolkadotAccountHealthCheckUseCase
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
|
|
@ -12,14 +11,16 @@ import com.tangem.domain.tokens.model.TokenList
|
|||
import com.tangem.domain.tokens.model.TotalFiatBalance
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenListStore
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntents
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class MultiWalletTokenListSubscriber(
|
||||
private val userWallet: UserWallet,
|
||||
private val getTokenListUseCase: GetTokenListUseCase,
|
||||
private val tokenListStore: MultiWalletTokenListStore,
|
||||
private val applyTokenListSortingUseCase: ApplyTokenListSortingUseCase,
|
||||
stateHolder: WalletStateController,
|
||||
clickIntents: WalletClickIntents,
|
||||
|
|
@ -37,8 +38,10 @@ internal class MultiWalletTokenListSubscriber(
|
|||
runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase,
|
||||
) {
|
||||
|
||||
override fun tokenListFlow(): LceFlow<TokenListError, TokenList> {
|
||||
return getTokenListUseCase.launch(userWallet.walletId)
|
||||
override fun tokenListFlow(coroutineScope: CoroutineScope): LceFlow<TokenListError, TokenList> {
|
||||
tokenListStore.addIfNot(userWallet.walletId, coroutineScope)
|
||||
|
||||
return tokenListStore.getOrThrow(userWallet.walletId)
|
||||
}
|
||||
|
||||
override suspend fun onTokenListReceived(maybeTokenList: Lce<TokenListError, TokenList>) {
|
||||
|
|
@ -67,12 +70,6 @@ internal class MultiWalletTokenListSubscriber(
|
|||
}
|
||||
|
||||
private fun getCurrenciesIds(tokenList: TokenList): List<CryptoCurrency.ID> {
|
||||
return when (tokenList) {
|
||||
is TokenList.GroupedByNetwork -> tokenList.groups.flatMap { group ->
|
||||
group.currencies.map { it.currency.id }
|
||||
}
|
||||
is TokenList.Ungrouped -> tokenList.currencies.map { it.currency.id }
|
||||
is TokenList.Empty -> emptyList()
|
||||
}
|
||||
return tokenList.flattenCurrencies().map { it.currency.id }
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAn
|
|||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntents
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
|
|
@ -34,6 +35,9 @@ internal class SingleWalletWithTokenListSubscriber(
|
|||
runPolkadotAccountHealthCheckUseCase = runPolkadotAccountHealthCheckUseCase,
|
||||
) {
|
||||
|
||||
override fun tokenListFlow(): LceFlow<TokenListError, TokenList> = getNodlTokenListUseCase(userWallet.walletId)
|
||||
.map { it.toLce() }
|
||||
override fun tokenListFlow(coroutineScope: CoroutineScope): LceFlow<TokenListError, TokenList> =
|
||||
getNodlTokenListUseCase(
|
||||
userWallet.walletId,
|
||||
)
|
||||
.map { it.toLce() }
|
||||
}
|
||||
|
|
@ -387,7 +387,6 @@ private inline fun BaseScaffoldWithMarkets(
|
|||
sheetContainerColor = backgroundColor.value,
|
||||
scaffoldState = scaffoldState,
|
||||
sheetPeekHeight = peekHeight,
|
||||
sheetShadowElevation = 8.dp,
|
||||
sheetShape = TangemTheme.shapes.bottomSheetLarge,
|
||||
sheetContent = {
|
||||
// hide bottom sheet when back pressed
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.fields.SearchBar
|
||||
import com.tangem.core.ui.components.token.TokenItem
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
|
@ -36,5 +39,11 @@ internal fun MultiCurrencyContentItem(
|
|||
modifier = modifierWithBackground,
|
||||
)
|
||||
}
|
||||
is TokensListItemState.SearchBar -> {
|
||||
SearchBar(
|
||||
state = state.searchBarUM,
|
||||
modifier = modifierWithBackground.padding(all = 12.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ import com.tangem.feature.wallet.presentation.deeplink.WalletDeepLinksHandler
|
|||
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.SelectedWalletAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenListStore
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletNameMigrationUseCase
|
||||
import com.tangem.feature.wallet.presentation.wallet.loaders.WalletScreenContentLoader
|
||||
|
|
@ -69,6 +70,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
private val shouldAskPermissionUseCase: ShouldAskPermissionUseCase,
|
||||
private val marketsFeatureToggles: MarketsFeatureToggles,
|
||||
private val walletImageResolver: WalletImageResolver,
|
||||
private val tokenListStore: MultiWalletTokenListStore,
|
||||
analyticsEventsHandler: AnalyticsEventHandler,
|
||||
) : ViewModel() {
|
||||
|
||||
|
|
@ -110,6 +112,8 @@ internal class WalletViewModel @Inject constructor(
|
|||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
|
||||
tokenListStore.clear()
|
||||
stateHolder.clear()
|
||||
walletScreenContentLoader.cancelAll()
|
||||
}
|
||||
|
|
@ -280,7 +284,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
stateHolder.update(transformer = RenameWalletTransformer(action.selectedWalletId, action.name))
|
||||
}
|
||||
is WalletsUpdateActionResolver.Action.Unknown -> {
|
||||
Timber.w("Unable to perfom action: $action")
|
||||
Timber.w("Unable to perform action: $action")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -318,6 +322,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
|
||||
private fun reinitializeWallet(action: WalletsUpdateActionResolver.Action.ReinitializeWallet) {
|
||||
walletScreenContentLoader.cancel(action.prevWalletId)
|
||||
tokenListStore.remove(action.prevWalletId)
|
||||
|
||||
walletScreenContentLoader.load(
|
||||
userWallet = action.selectedWallet,
|
||||
|
|
@ -357,6 +362,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
|
||||
private suspend fun deleteWallet(action: WalletsUpdateActionResolver.Action.DeleteWallet) {
|
||||
walletScreenContentLoader.cancel(action.deletedWalletId)
|
||||
tokenListStore.remove(action.deletedWalletId)
|
||||
|
||||
walletScreenContentLoader.load(
|
||||
userWallet = action.selectedWallet,
|
||||
|
|
|
|||
|
|
@ -136,7 +136,9 @@ internal class WalletsUpdateActionResolver @Inject constructor(
|
|||
unlockedWallets = wallets.filterNot(UserWallet::isLocked),
|
||||
)
|
||||
}
|
||||
isSelectedWalletCardsCountChanged(state, selectedWallet) -> Action.UpdateWalletCardCount(selectedWallet)
|
||||
isSelectedWalletCardsCountChanged(state, selectedWallet) -> {
|
||||
Action.UpdateWalletCardCount(selectedWallet)
|
||||
}
|
||||
else -> Action.Unknown
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.tangem.domain.wallets.models.UserWalletId
|
|||
import com.tangem.domain.wallets.usecase.*
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.MainScreen
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenListStore
|
||||
import com.tangem.feature.wallet.presentation.wallet.loaders.WalletScreenContentLoader
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletAlertState
|
||||
|
|
@ -37,6 +38,7 @@ internal interface WalletCardClickIntents {
|
|||
@Suppress("LongParameterList")
|
||||
internal class WalletCardClickIntentsImplementor @Inject constructor(
|
||||
private val stateHolder: WalletStateController,
|
||||
private val tokenListStore: MultiWalletTokenListStore,
|
||||
private val walletEventSender: WalletEventSender,
|
||||
private val walletScreenContentLoader: WalletScreenContentLoader,
|
||||
private val renameWalletUseCase: RenameWalletUseCase,
|
||||
|
|
@ -99,6 +101,7 @@ internal class WalletCardClickIntentsImplementor @Inject constructor(
|
|||
override fun onDeleteAfterConfirmationClick(userWalletId: UserWalletId) {
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
walletScreenContentLoader.cancel(userWalletId)
|
||||
tokenListStore.remove(userWalletId)
|
||||
|
||||
val walletToDelete = getUserWalletUseCase(userWalletId).getOrNull() ?: return@launch
|
||||
val hasUserWallets = deleteWalletUseCase(userWalletId).getOrElse {
|
||||
|
|
@ -117,6 +120,7 @@ internal class WalletCardClickIntentsImplementor @Inject constructor(
|
|||
|
||||
reduxStateHolder.onUserWalletSelected(selectedWallet)
|
||||
} else {
|
||||
tokenListStore.clear()
|
||||
stateHolder.clear()
|
||||
appRouter.replaceAll(AppRoute.Home)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import com.tangem.domain.settings.NeverToShowWalletsScrollPreview
|
|||
import com.tangem.domain.tokens.FetchCardTokenListUseCase
|
||||
import com.tangem.domain.tokens.FetchCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.FetchTokenListUseCase
|
||||
import com.tangem.domain.tokens.FetchTokenListUseCase.RefreshMode
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
|
||||
import com.tangem.domain.wallets.usecase.SelectWalletUseCase
|
||||
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
|
||||
|
|
@ -117,7 +118,7 @@ internal class WalletClickIntents @Inject constructor(
|
|||
val maybeFetchResult = if (userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()) {
|
||||
fetchCardTokenListUseCase(userWalletId = userWallet.walletId, refresh = true)
|
||||
} else {
|
||||
fetchTokenListUseCase(userWalletId = userWallet.walletId, refresh = true)
|
||||
fetchTokenListUseCase(userWalletId = userWallet.walletId, mode = RefreshMode.FULL)
|
||||
}
|
||||
|
||||
maybeFetchResult.onLeft {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import com.tangem.domain.redux.LegacyAction
|
|||
import com.tangem.domain.redux.ReduxStateHolder
|
||||
import com.tangem.domain.settings.*
|
||||
import com.tangem.domain.tokens.FetchTokenListUseCase
|
||||
import com.tangem.domain.tokens.FetchTokenListUseCase.RefreshMode
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.analytics.TokenSwapPromoAnalyticsEvent
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager.Lockable.UnlockType
|
||||
|
|
@ -124,18 +125,20 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
|
|||
analyticsEventHandler.send(Basic.CardWasScanned(AnalyticsParam.ScreensSources.Main))
|
||||
analyticsEventHandler.send(MainScreen.NoticeScanYourCardTapped)
|
||||
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
viewModelScope.launch {
|
||||
val userWallet = getSelectedUserWallet() ?: return@launch
|
||||
|
||||
derivePublicKeysUseCase(
|
||||
userWalletId = userWallet.walletId,
|
||||
currencies = missedAddressCurrencies,
|
||||
).fold(
|
||||
ifLeft = { Timber.e(it, "Failed to derive public keys") },
|
||||
ifRight = {
|
||||
fetchTokenListUseCase(userWallet.walletId, mode = RefreshMode.SKIP_CURRENCIES).onLeft {
|
||||
Timber.e("Unable to refresh token list: $it")
|
||||
}
|
||||
},
|
||||
)
|
||||
.onRight {
|
||||
// Refresh must be set to true to ensure that yield balances are updated
|
||||
fetchTokenListUseCase(userWalletId = userWallet.walletId, refresh = true)
|
||||
}
|
||||
.onLeft { Timber.e("Failed to derive public keys: $it") }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue