Updated on 2026-08-14

This commit is contained in:
Tangem 2023-10-10 12:45:26 +03:00
commit 6ad667d49d
77 changed files with 880 additions and 343 deletions

View file

@ -38,7 +38,7 @@ internal class WalletFragment : ComposeFragment() {
setSystemBarsColor(systemBarsColor)
}
_walletRouter.Initialize(fragmentManager = requireActivity().supportFragmentManager)
_walletRouter.Initialize(onFinish = requireActivity()::finish)
}
companion object {

View file

@ -190,7 +190,13 @@ internal object WalletPreviewData {
)
}
val loadingTokenItemState by lazy { TokenItemState.Loading(id = "Loading#1") }
val loadingTokenItemState by lazy {
TokenItemState.Loading(
id = "Loading#1",
iconState = customTokenIconState.copy(isGrayscale = true),
titleState = TokenItemState.TitleState.Content(text = "Polygon"),
)
}
private const val networksSize = 10
private const val tokensSize = 3

View file

@ -14,7 +14,6 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemTypography
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
import org.burnoutcrew.reorderable.ReorderableLazyListState
@ -73,6 +72,6 @@ private fun NonFiatContentText(@StringRes text: Int) {
color = TangemTheme.colors.text.tertiary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = TangemTypography.body2,
style = TangemTheme.typography.body2,
)
}

View file

@ -11,7 +11,6 @@ import androidx.compose.ui.text.style.TextOverflow
import com.tangem.common.Strings
import com.tangem.core.ui.components.RectangleShimmer
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemTypography
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.common.state.TokenItemState.CryptoAmountState as TokenCryptoAmountState
@ -49,7 +48,7 @@ private fun CryptoAmountText(amount: String, modifier: Modifier = Modifier) {
color = TangemTheme.colors.text.tertiary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = TangemTypography.body2,
style = TangemTheme.typography.body2,
)
}

View file

@ -10,7 +10,6 @@ import androidx.compose.ui.text.style.TextOverflow
import com.tangem.common.Strings
import com.tangem.core.ui.components.RectangleShimmer
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemTypography
import com.tangem.feature.wallet.presentation.common.state.TokenItemState.FiatAmountState as TokenFiatAmountState
@Composable
@ -40,7 +39,7 @@ private fun FiatAmountText(text: String, modifier: Modifier = Modifier) {
color = TangemTheme.colors.text.primary1,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = TangemTypography.body2,
style = TangemTheme.typography.body2,
)
}

View file

@ -15,7 +15,6 @@ import com.tangem.core.ui.components.RectangleShimmer
import com.tangem.core.ui.components.SpacerW4
import com.tangem.core.ui.components.marketprice.PriceChangeType
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemTypography
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
import com.tangem.feature.wallet.presentation.common.state.TokenItemState.PriceChangeState as TokenPriceChangeState
@ -87,7 +86,7 @@ private fun PriceChangeText(type: PriceChangeType?, text: String?) {
},
overflow = TextOverflow.Ellipsis,
maxLines = 1,
style = TangemTypography.body2,
style = TangemTheme.typography.body2,
)
}
}

View file

@ -15,7 +15,6 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import com.tangem.core.ui.components.RectangleShimmer
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemTypography
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.common.state.TokenItemState.TitleState as TokenTitleState
@ -63,7 +62,7 @@ private fun CurrencyNameText(name: String, modifier: Modifier = Modifier) {
color = TangemTheme.colors.text.primary1,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
style = TangemTypography.subtitle2,
style = TangemTheme.typography.subtitle2,
)
}

View file

@ -22,9 +22,11 @@ internal sealed class TokenItemState {
abstract val priceChangeState: PriceChangeState?
/** Loading token state */
data class Loading(override val id: String) : TokenItemState() {
override val iconState: IconState = IconState.Loading
override val titleState: TitleState = TitleState.Loading
data class Loading(
override val id: String,
override val iconState: IconState,
override val titleState: TitleState.Content,
) : TokenItemState() {
override val fiatAmountState: FiatAmountState = FiatAmountState.Loading
override val cryptoAmountState: CryptoAmountState = CryptoAmountState.Loading
override val priceChangeState: PriceChangeState = PriceChangeState.Loading

View file

@ -19,6 +19,8 @@ import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
@ -86,6 +88,7 @@ private fun TokenList(
isBalanceHidden: Boolean,
modifier: Modifier = Modifier,
) {
val hapticFeedback = LocalHapticFeedback.current
Box(modifier = modifier) {
val onDragEnd: (Int, Int) -> Unit = remember {
{ _, _ ->
@ -119,7 +122,10 @@ private fun TokenList(
) { index, item ->
val onDragStart = remember(item) {
{ dndConfig.onItemDragStart(item) }
{
dndConfig.onItemDragStart(item)
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
}
}
DraggableItem(

View file

@ -7,7 +7,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavHostController
@ -21,6 +20,7 @@ import com.tangem.core.navigation.NavigationAction
import com.tangem.core.navigation.ReduxNavController
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.feature.onboarding.navigation.OnboardingRouter
import com.tangem.feature.wallet.presentation.WalletFragment
import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensScreen
import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensViewModel
@ -33,13 +33,13 @@ import kotlin.properties.Delegates
internal class DefaultWalletRouter(private val reduxNavController: ReduxNavController) : InnerWalletRouter {
private var navController: NavHostController by Delegates.notNull()
private var fragmentManager: FragmentManager by Delegates.notNull()
private var onFinish: () -> Unit = {}
override fun getEntryFragment(): Fragment = WalletFragment.create()
@Composable
override fun Initialize(fragmentManager: FragmentManager) {
this.fragmentManager = fragmentManager
override fun Initialize(onFinish: () -> Unit) {
this.onFinish = onFinish
NavHost(
navController = rememberNavController().apply { navController = this },
@ -78,11 +78,11 @@ internal class DefaultWalletRouter(private val reduxNavController: ReduxNavContr
* next element is wallet screen entry.
* If backstack contains only NavGraph entry and wallet screen entry then we close the wallet fragment.
*/
if (navController.backQueue.size == BACKSTACK_ENTRY_COUNT_TO_CLOSE_WALLET_SCREEN) {
if (screen != null) {
if (navController.currentBackStack.value.size == BACKSTACK_ENTRY_COUNT_TO_CLOSE_WALLET_SCREEN) {
if (screen == AppScreen.Home) {
reduxNavController.navigate(action = NavigationAction.PopBackTo(screen))
} else {
fragmentManager.popBackStack()
onFinish.invoke()
}
} else {
navController.popBackStack()
@ -100,18 +100,26 @@ internal class DefaultWalletRouter(private val reduxNavController: ReduxNavContr
}
override fun openOnboardingScreen() {
reduxNavController.navigate(action = NavigationAction.NavigateTo(AppScreen.OnboardingWallet))
reduxNavController.navigate(
action = NavigationAction.NavigateTo(
screen = AppScreen.OnboardingWallet,
bundle = bundleOf(OnboardingRouter.CAN_SKIP_BACKUP to false),
),
)
}
override fun openTxHistoryWebsite(url: String) {
reduxNavController.navigate(action = NavigationAction.OpenUrl(url))
}
override fun openTokenDetails(currency: CryptoCurrency) {
override fun openTokenDetails(userWalletId: UserWalletId, currency: CryptoCurrency) {
reduxNavController.navigate(
action = NavigationAction.NavigateTo(
screen = AppScreen.WalletDetails,
bundle = bundleOf(TokenDetailsRouter.CRYPTO_CURRENCY_KEY to currency),
bundle = bundleOf(
TokenDetailsRouter.USER_WALLET_ID_KEY to userWalletId.stringValue,
TokenDetailsRouter.CRYPTO_CURRENCY_KEY to currency,
),
),
)
}

View file

@ -2,7 +2,6 @@ package com.tangem.feature.wallet.presentation.router
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.fragment.app.FragmentManager
import com.tangem.core.navigation.AppScreen
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.wallets.models.UserWalletId
@ -22,11 +21,11 @@ internal interface InnerWalletRouter : WalletRouter {
/**
* Initialize router
*
* @param fragmentManager fragment manager
* @param onFinish finish activity callback
*/
@Suppress("TopLevelComposableFunctions")
@Composable
fun Initialize(fragmentManager: FragmentManager)
fun Initialize(onFinish: () -> Unit)
/** Pop back stack */
fun popBackStack(screen: AppScreen? = null)
@ -44,7 +43,7 @@ internal interface InnerWalletRouter : WalletRouter {
fun openTxHistoryWebsite(url: String)
/** Open token details screen */
fun openTokenDetails(currency: CryptoCurrency)
fun openTokenDetails(userWalletId: UserWalletId, currency: CryptoCurrency)
/** Open stories screen */
fun openStoriesScreen()

View file

@ -16,6 +16,8 @@ internal sealed interface WalletCardState {
/** Title */
val title: String
val additionalInfo: TextReference?
/** Wallet image resource id */
@get:DrawableRes
val imageResId: Int?
@ -41,10 +43,10 @@ internal sealed interface WalletCardState {
data class Content(
override val id: UserWalletId,
override val title: String,
override val additionalInfo: TextReference,
override val imageResId: Int?,
override val onRenameClick: (UserWalletId, String) -> Unit,
override val onDeleteClick: (UserWalletId) -> Unit,
val additionalInfo: TextReference,
val cardCount: Int?,
val balance: String,
) : WalletCardState
@ -54,18 +56,18 @@ internal sealed interface WalletCardState {
*
* @property id wallet id
* @property title wallet name
* @property additionalInfo wallet additional info
* @property imageResId wallet image resource id
* @property onRenameClick lambda be invoked when Rename button is clicked
* @property onDeleteClick lambda be invoked when Delete button is clicked
* @property additionalInfo wallet additional info
*/
data class LockedContent(
override val id: UserWalletId,
override val title: String,
override val additionalInfo: TextReference,
override val imageResId: Int?,
override val onRenameClick: (UserWalletId, String) -> Unit,
override val onDeleteClick: (UserWalletId) -> Unit,
val additionalInfo: TextReference,
) : WalletCardState
/**
@ -83,7 +85,9 @@ internal sealed interface WalletCardState {
override val imageResId: Int?,
override val onRenameClick: (UserWalletId, String) -> Unit,
override val onDeleteClick: (UserWalletId) -> Unit,
) : WalletCardState
) : WalletCardState {
override val additionalInfo: TextReference = EMPTY_BALANCE_TEXT
}
/**
* Wallet card loading state
@ -97,6 +101,7 @@ internal sealed interface WalletCardState {
data class Loading(
override val id: UserWalletId,
override val title: String,
override val additionalInfo: TextReference? = null,
override val imageResId: Int?,
override val onRenameClick: (UserWalletId, String) -> Unit,
override val onDeleteClick: (UserWalletId) -> Unit,

View file

@ -126,6 +126,7 @@ internal class WalletSkeletonStateConverter(
return WalletCardState.Loading(
id = walletId,
title = name,
additionalInfo = if (isMultiCurrency) WalletAdditionalInfoFactory.resolve(wallet = this) else null,
imageResId = createImageResId(),
onRenameClick = clickIntents::onRenameClick,
onDeleteClick = clickIntents::onDeleteClick,

View file

@ -94,7 +94,7 @@ internal fun WalletCard(state: WalletCardState, isBalanceHidden: Boolean, modifi
)
AdditionalInfo(
text = resolveAdditionalTextByState(state),
text = state.additionalInfo,
modifier = Modifier.constrainAs(additionalTextRef) {
start.linkTo(parent.start)
top.linkTo(balanceRef.bottom)
@ -345,15 +345,6 @@ private fun AdditionalInfo(text: TextReference?, modifier: Modifier = Modifier)
}
}
private fun resolveAdditionalTextByState(state: WalletCardState): TextReference? {
return when (state) {
is WalletCardState.Content -> state.additionalInfo
is WalletCardState.LockedContent -> state.additionalInfo
is WalletCardState.Error -> WalletCardState.EMPTY_BALANCE_TEXT
is WalletCardState.Loading -> null
}
}
@Composable
private fun AdditionalInfoText(text: TextReference) {
Text(
@ -361,7 +352,7 @@ private fun AdditionalInfoText(text: TextReference) {
color = TangemTheme.colors.text.tertiary,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = TangemTheme.typography.caption,
style = TangemTheme.typography.caption2,
)
}

View file

@ -92,7 +92,7 @@ private fun LazyListScope.nonContentItem(modifier: Modifier = Modifier) {
modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing48),
color = TangemTheme.colors.text.tertiary,
textAlign = TextAlign.Center,
style = TangemTheme.typography.caption,
style = TangemTheme.typography.caption2,
)
}
}

View file

@ -16,24 +16,31 @@ internal class CryptoCurrencyStatusToTokenItemConverter(
private val clickIntents: WalletClickIntents,
) : Converter<CryptoCurrencyStatus, TokenItemState> {
private val iconStateConverter = CryptoCurrencyToIconStateConverter()
private val iconStateConverter by lazy(::CryptoCurrencyToIconStateConverter)
override fun convert(value: CryptoCurrencyStatus): TokenItemState {
return when (value.value) {
is CryptoCurrencyStatus.Loading -> TokenItemState.Loading(id = value.currency.id.value)
is CryptoCurrencyStatus.Loading -> value.mapToLoadingState()
is CryptoCurrencyStatus.Loaded,
is CryptoCurrencyStatus.Custom,
is CryptoCurrencyStatus.NoQuote,
is CryptoCurrencyStatus.NoAccount,
-> value.mapToTokenItemState()
is CryptoCurrencyStatus.MissedDerivation -> value.mapToNoAddressTokenItemState()
// TODO: Add other token item states, currently not designed
is CryptoCurrencyStatus.Unreachable,
is CryptoCurrencyStatus.NoAmount,
-> value.mapToUnreachableTokenItemState()
}
}
private fun CryptoCurrencyStatus.mapToLoadingState(): TokenItemState.Loading {
return TokenItemState.Loading(
id = currency.id.value,
iconState = iconStateConverter.convert(value = this),
titleState = TokenItemState.TitleState.Content(text = currency.name),
)
}
private fun CryptoCurrencyStatus.mapToTokenItemState(): TokenItemState.Content {
return TokenItemState.Content(
id = currency.id.value,

View file

@ -25,7 +25,7 @@ internal class FiatBalanceToWalletCardConverter(
}
private fun WalletCardState.toLoadingWalletCardState(): WalletCardState {
return WalletCardState.Loading(id, title, imageResId, onRenameClick, onDeleteClick)
return WalletCardState.Loading(id, title, additionalInfo, imageResId, onRenameClick, onDeleteClick)
}
private fun WalletCardState.toErrorWalletCardState(): WalletCardState {

View file

@ -1,21 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.utils
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletTokensListState
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
internal object LoadingItemsProvider {
fun getLoadingMultiCurrencyTokens(): ImmutableList<WalletTokensListState.TokensListItemState.Token> {
val items = mutableListOf<WalletTokensListState.TokensListItemState.Token>()
repeat(times = 5) {
items.add(
WalletTokensListState.TokensListItemState.Token(
state = TokenItemState.Loading(id = "Loading#$it"),
),
)
}
return items.toImmutableList()
}
}

View file

@ -2,6 +2,7 @@ package com.tangem.feature.wallet.presentation.wallet.viewmodels
import androidx.lifecycle.*
import androidx.paging.cachedIn
import arrow.core.Either
import arrow.core.getOrElse
import com.tangem.blockchain.blockchains.cardano.CardanoUtils
import com.tangem.blockchain.common.Blockchain
@ -39,6 +40,7 @@ import com.tangem.domain.redux.LegacyAction
import com.tangem.domain.redux.ReduxStateHolder
import com.tangem.domain.settings.*
import com.tangem.domain.tokens.*
import com.tangem.domain.tokens.error.TokenListError
import com.tangem.domain.tokens.legacy.TradeCryptoAction
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
@ -48,6 +50,7 @@ import com.tangem.domain.tokens.models.analytics.TokenReceiveAnalyticsEvent
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
import com.tangem.domain.userwallets.UserWalletBuilder
import com.tangem.domain.walletconnect.WalletConnectActions
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.UserWalletId
@ -156,6 +159,7 @@ internal class WalletViewModel @Inject constructor(
private var singleWalletCryptoCurrencyStatus: CryptoCurrencyStatus? = null
private val tokensJobHolder = JobHolder()
private val updateWcJobHolder = JobHolder()
private val marketPriceJobHolder = JobHolder()
private val buttonsJobHolder = JobHolder()
private val notificationsJobHolder = JobHolder()
@ -453,6 +457,7 @@ internal class WalletViewModel @Inject constructor(
* If jobs aren't stopped and wallet is changed then it will update state for the prev wallet.
*/
tokensJobHolder.update(job = null)
updateWcJobHolder.update(job = null)
marketPriceJobHolder.update(job = null)
buttonsJobHolder.update(job = null)
notificationsJobHolder.update(job = null)
@ -719,7 +724,7 @@ internal class WalletViewModel @Inject constructor(
override fun onTokenItemClick(currency: CryptoCurrency) {
analyticsEventsHandler.send(PortfolioEvent.TokenTapped)
router.openTokenDetails(currency = currency)
router.openTokenDetails(getSelectedWallet().walletId, currency)
}
override fun onTokenItemLongClick(cryptoCurrencyStatus: CryptoCurrencyStatus) {
@ -849,6 +854,7 @@ internal class WalletViewModel @Inject constructor(
* If jobs aren't stopped and wallet is changed then it will update state for the prev wallet.
*/
tokensJobHolder.update(job = null)
updateWcJobHolder.update(job = null)
marketPriceJobHolder.update(job = null)
buttonsJobHolder.update(job = null)
notificationsJobHolder.update(job = null)
@ -860,17 +866,22 @@ internal class WalletViewModel @Inject constructor(
wallet.isLocked -> {
uiState = stateFactory.getLockedState()
}
wallet.isMultiCurrency -> getMultiCurrencyContent(index)
wallet.isMultiCurrency -> getMultiCurrencyContent(wallet, index)
!wallet.isMultiCurrency -> getSingleCurrencyContent(index)
}
}
private fun getMultiCurrencyContent(walletIndex: Int) {
private fun getMultiCurrencyContent(wallet: UserWallet, walletIndex: Int) {
val state = requireNotNull(uiState as? WalletMultiCurrencyState) {
"Impossible to get a token list updates if state isn't WalletMultiCurrencyState"
}
getTokenListUseCase(userWalletId = state.walletsListConfig.wallets[walletIndex].id)
val tokenListFlow = getTokenListUseCase(userWalletId = state.walletsListConfig.wallets[walletIndex].id)
.shareIn(viewModelScope, SharingStarted.WhileSubscribed())
initAndSetupWc(tokenListFlow, wallet)
tokenListFlow
.distinctUntilChanged()
.onEach { maybeTokenList ->
uiState = stateFactory.getStateByTokensList(maybeTokenList)
@ -903,6 +914,44 @@ internal class WalletViewModel @Inject constructor(
}
}
private fun initAndSetupWc(tokenListFlow: SharedFlow<Either<TokenListError, TokenList>>, wallet: UserWallet) {
initWalletConnectForWallet(wallet)
tokenListFlow
.filter(::filterLoadedTokenList)
.take(1)
.onEach {
it.onRight {
setupWalletConnectOnWallet(wallet)
}
}
.flowOn(dispatchers.io)
.launchIn(viewModelScope)
.saveIn(updateWcJobHolder)
}
private fun List<CryptoCurrencyStatus>.isAllCurrenciesLoaded(): Boolean {
return !this.any { it.value is CryptoCurrencyStatus.Loading }
}
private fun filterLoadedTokenList(either: Either<TokenListError, TokenList>): Boolean {
return either.fold(
ifRight = { list ->
when (list) {
is TokenList.Ungrouped -> {
list.currencies.isAllCurrenciesLoaded()
}
is TokenList.GroupedByNetwork -> {
list.groups.flatMap { group -> group.currencies }.isAllCurrenciesLoaded()
}
else -> {
false
}
}
},
ifLeft = { false },
)
}
private fun List<CryptoCurrencyStatus>.hasNonZeroWallets(): Boolean {
return any {
val amount = it.value.amount ?: return@any false
@ -912,7 +961,7 @@ internal class WalletViewModel @Inject constructor(
private fun getSingleCurrencyContent(index: Int) {
val wallet = getWallet(index)
getPrimaryCurrencyStatusUpdatesUseCase(userWalletId = wallet.walletId)
getPrimaryCurrencyStatusUpdatesUseCase(wallet.walletId)
.distinctUntilChanged()
.onEach { maybeCryptoCurrencyStatus ->
uiState = stateFactory.getSingleCurrencyLoadedBalanceState(maybeCryptoCurrencyStatus)
@ -925,8 +974,8 @@ internal class WalletViewModel @Inject constructor(
}
updateNotifications(index)
updateButtons(userWalletId = wallet.walletId, currencyStatus = status)
updateTxHistory(status.currency)
updateButtons(wallet.walletId, status)
updateTxHistory(wallet.walletId, status.currency, refresh = false)
}
}
.flowOn(dispatchers.io)
@ -934,9 +983,12 @@ internal class WalletViewModel @Inject constructor(
.saveIn(marketPriceJobHolder)
}
private fun updateTxHistory(currency: CryptoCurrency) {
private fun updateTxHistory(userWalletId: UserWalletId, currency: CryptoCurrency, refresh: Boolean) {
viewModelScope.launch(dispatchers.io) {
val txHistoryItemsCountEither = txHistoryItemsCountUseCase(currency.network)
val txHistoryItemsCountEither = txHistoryItemsCountUseCase(
userWalletId = userWalletId,
network = currency.network,
)
uiState = stateFactory.getLoadingTxHistoryState(
itemsCountEither = txHistoryItemsCountEither,
@ -944,7 +996,11 @@ internal class WalletViewModel @Inject constructor(
txHistoryItemsCountEither.onRight {
uiState = stateFactory.getLoadedTxHistoryState(
txHistoryEither = txHistoryItemsUseCase(currency = currency).map {
txHistoryEither = txHistoryItemsUseCase(
userWalletId = userWalletId,
currency = currency,
refresh = refresh,
).map {
it.cachedIn(viewModelScope)
},
)
@ -1006,6 +1062,10 @@ internal class WalletViewModel @Inject constructor(
uiState = stateFactory.getRefreshedState()
uiState = result.fold(stateFactory::getStateByCurrencyStatusError) { uiState }
singleWalletCryptoCurrencyStatus?.let {
updateTxHistory(wallet.walletId, it.currency, refresh = true)
}
}.saveIn(refreshContentJobHolder)
}
@ -1021,6 +1081,18 @@ internal class WalletViewModel @Inject constructor(
)
}
private fun initWalletConnectForWallet(userWallet: UserWallet) {
reduxStateHolder.dispatch(
WalletConnectActions.New.Initialize(userWallet = userWallet),
)
}
private fun setupWalletConnectOnWallet(userWallet: UserWallet) {
reduxStateHolder.dispatch(
WalletConnectActions.New.SetupUserChains(userWallet = userWallet),
)
}
private fun getWallet(index: Int): UserWallet {
return requireNotNull(
value = wallets.getOrNull(index),
@ -1028,5 +1100,12 @@ internal class WalletViewModel @Inject constructor(
)
}
private fun getSelectedWallet(): UserWallet {
val state = uiState as? WalletState.ContentState
?: error("Unable to get selected user wallet")
return getWallet(state.walletsListConfig.selectedWalletIndex)
}
private fun getCardTypeResolver(index: Int): CardTypesResolver = getWallet(index).scanResponse.cardTypesResolver
}