Updated on 2026-08-14
This commit is contained in:
parent
7a7204c6c4
commit
0a1a59d421
6 changed files with 105 additions and 38 deletions
|
|
@ -16,6 +16,7 @@ import com.tangem.domain.core.lce.Lce
|
|||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.TotalFiatBalance
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.quote.PriceChange
|
||||
import com.tangem.utils.converter.Converter
|
||||
import com.tangem.utils.extensions.isZero
|
||||
|
|
@ -49,7 +50,7 @@ class AccountCryptoPortfolioItemStateConverter(
|
|||
)
|
||||
}
|
||||
return TokenItemState.Content(
|
||||
id = account.accountId.value,
|
||||
id = account.accountId.toItemId(),
|
||||
iconState = AccountIconItemStateConverter.convert(this),
|
||||
titleState = TokenItemState.TitleState.Content(
|
||||
text = accountName.toUM().value,
|
||||
|
|
@ -75,7 +76,7 @@ class AccountCryptoPortfolioItemStateConverter(
|
|||
|
||||
private fun Account.CryptoPortfolio.mapToLoadingState(): TokenItemState.Content {
|
||||
return TokenItemState.Content(
|
||||
id = account.accountId.value,
|
||||
id = account.accountId.toItemId(),
|
||||
iconState = AccountIconItemStateConverter.convert(account),
|
||||
titleState = TokenItemState.TitleState.Content(
|
||||
text = accountName.toUM().value,
|
||||
|
|
@ -97,7 +98,7 @@ class AccountCryptoPortfolioItemStateConverter(
|
|||
|
||||
private fun Account.CryptoPortfolio.mapToUnreachableState(): TokenItemState.Unreachable {
|
||||
return TokenItemState.Unreachable(
|
||||
id = account.accountId.value,
|
||||
id = account.accountId.toItemId(),
|
||||
iconState = AccountIconItemStateConverter.convert(account),
|
||||
titleState = TokenItemState.TitleState.Content(
|
||||
text = accountName.toUM().value,
|
||||
|
|
@ -119,6 +120,8 @@ class AccountCryptoPortfolioItemStateConverter(
|
|||
)
|
||||
}
|
||||
|
||||
private fun AccountId.toItemId() = this.userWalletId.stringValue + this.value
|
||||
|
||||
private fun BigDecimal.getPriceChangeType(): PriceChangeType = PriceChangeConverter.fromBigDecimal(value = this)
|
||||
|
||||
private fun StatusSource.isFlickering(): Boolean = this == StatusSource.CACHE
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.tangem.core.decompose.di.ModelScoped
|
|||
import com.tangem.domain.account.models.AccountList
|
||||
import com.tangem.domain.account.producer.SingleAccountListProducer
|
||||
import com.tangem.domain.account.supplier.SingleAccountListSupplier
|
||||
import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
|
@ -13,13 +14,20 @@ import javax.inject.Inject
|
|||
@ModelScoped
|
||||
internal class ExpandedAccountsHolder @Inject constructor(
|
||||
private val singleAccountListSupplier: SingleAccountListSupplier,
|
||||
private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase,
|
||||
) {
|
||||
|
||||
private val expandedAccounts = MutableStateFlow<Map<UserWalletId, Set<AccountId>>>(mapOf())
|
||||
|
||||
fun expandedAccounts(userWallet: UserWallet): Flow<Set<AccountId>> = channelFlow {
|
||||
walletAccounts(userWallet)
|
||||
.onEach { accountList ->
|
||||
combine(
|
||||
flow = walletAccounts(userWallet),
|
||||
flow2 = isAccountsModeEnabledUseCase.invoke(),
|
||||
transform = { accountList, isAccountsMode ->
|
||||
if (!isAccountsMode) {
|
||||
expandedAccounts.update { emptyMap() }
|
||||
return@combine
|
||||
}
|
||||
val isSingleAccount = accountList.accounts.size == 1
|
||||
val defaultExpanded = when {
|
||||
isSingleAccount -> setOf(accountList.mainAccount.accountId)
|
||||
|
|
@ -31,7 +39,8 @@ internal class ExpandedAccountsHolder @Inject constructor(
|
|||
if (isSingleAccount) expandedSet = defaultExpanded
|
||||
map.plus(userWallet.walletId to expandedSet)
|
||||
}
|
||||
}.launchIn(this)
|
||||
},
|
||||
).launchIn(this)
|
||||
|
||||
expandedAccounts
|
||||
.mapNotNull { map -> map[userWallet.walletId] }
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import androidx.compose.foundation.lazy.LazyListState
|
|||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.snapshots.SnapshotStateMap
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.drawBehind
|
||||
|
|
@ -55,6 +56,7 @@ import com.tangem.core.ui.components.rememberIsKeyboardVisible
|
|||
import com.tangem.core.ui.components.sheetscaffold.*
|
||||
import com.tangem.core.ui.components.snackbar.CopiedTextSnackbar
|
||||
import com.tangem.core.ui.components.snackbar.TangemSnackbar
|
||||
import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM
|
||||
import com.tangem.core.ui.components.transactions.state.TxHistoryState
|
||||
import com.tangem.core.ui.event.StateEvent
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
|
|
@ -76,6 +78,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.holder.TxHistor
|
|||
import com.tangem.feature.wallet.presentation.wallet.ui.components.TokenActionsBottomSheet
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.WalletsList
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.common.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.fastForEach
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency.nftCollections
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency.organizeTokensButton
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.marketPriceBlock
|
||||
|
|
@ -143,7 +146,7 @@ private fun WalletContent(
|
|||
*/
|
||||
val selectedWalletIndex by remember(state.selectedWalletIndex) { mutableIntStateOf(state.selectedWalletIndex) }
|
||||
val selectedWallet = state.wallets.getOrElse(selectedWalletIndex) { state.wallets[state.selectedWalletIndex] }
|
||||
val selectedWalletChanged = rememberChangedOnce(selectedWalletIndex)
|
||||
val (expandedState, collapsedState) = getExpandPortfolioStates(selectedWallet)
|
||||
|
||||
val listState = rememberLazyListState()
|
||||
|
||||
|
|
@ -241,10 +244,16 @@ private fun WalletContent(
|
|||
|
||||
contentItems(
|
||||
state = selectedWallet,
|
||||
selectedWalletChanged = selectedWalletChanged,
|
||||
txHistoryItems = txHistoryItems,
|
||||
isBalanceHidden = state.isHidingMode,
|
||||
modifier = movableItemModifier,
|
||||
portfolioVisibleState = {
|
||||
findPortfolioVisibleState(
|
||||
portfolio = it,
|
||||
expandedState = expandedState,
|
||||
collapsedState = collapsedState,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
nftCollections(state = selectedWallet, itemModifier = itemModifier)
|
||||
|
|
@ -292,12 +301,59 @@ private fun WalletContent(
|
|||
)
|
||||
}
|
||||
|
||||
private fun findPortfolioVisibleState(
|
||||
portfolio: TokensListItemUM.Portfolio,
|
||||
expandedState: SnapshotStateMap<String, MutableTransitionState<Boolean>>,
|
||||
collapsedState: SnapshotStateMap<String, MutableTransitionState<Boolean>>,
|
||||
): MutableTransitionState<Boolean> {
|
||||
val portfolioKey = portfolio.id
|
||||
|
||||
fun forceVisible() = MutableTransitionState(true).apply { targetState = true }
|
||||
val shouldExpand = portfolio.isExpanded
|
||||
return if (shouldExpand) {
|
||||
collapsedState[portfolioKey] ?: forceVisible()
|
||||
} else {
|
||||
expandedState[portfolioKey] ?: forceVisible()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun rememberChangedOnce(selectedWalletIndex: Int): Boolean {
|
||||
var prev by remember { mutableIntStateOf(selectedWalletIndex) }
|
||||
val changed = prev != selectedWalletIndex
|
||||
SideEffect { prev = selectedWalletIndex }
|
||||
return changed
|
||||
private fun getExpandPortfolioStates(
|
||||
state: WalletState,
|
||||
): Pair<
|
||||
SnapshotStateMap<String, MutableTransitionState<Boolean>>,
|
||||
SnapshotStateMap<String, MutableTransitionState<Boolean>>,
|
||||
> {
|
||||
val expandedTransitionState =
|
||||
remember { mutableStateMapOf<String, MutableTransitionState<Boolean>>() }
|
||||
val collapsedTransitionState =
|
||||
remember { mutableStateMapOf<String, MutableTransitionState<Boolean>>() }
|
||||
|
||||
val portfolioContent = state is WalletState.MultiCurrency.Content &&
|
||||
state.tokensListState is WalletTokensListState.ContentState.PortfolioContent
|
||||
if (!portfolioContent) {
|
||||
return expandedTransitionState to collapsedTransitionState
|
||||
}
|
||||
|
||||
state.tokensListState.items.fastForEach { portfolio ->
|
||||
val portfolioKey = portfolio.id
|
||||
val shouldExpand = portfolio.isExpanded
|
||||
|
||||
fun toggleVisible() = MutableTransitionState(false).apply { targetState = true }
|
||||
fun forceVisible() = MutableTransitionState(true).apply { targetState = true }
|
||||
|
||||
val isFirstCall = collapsedTransitionState[portfolioKey] == null ||
|
||||
expandedTransitionState[portfolioKey] == null
|
||||
when {
|
||||
isFirstCall -> {
|
||||
collapsedTransitionState[portfolioKey] = forceVisible()
|
||||
expandedTransitionState[portfolioKey] = forceVisible()
|
||||
}
|
||||
shouldExpand -> expandedTransitionState[portfolioKey] = toggleVisible()
|
||||
else -> collapsedTransitionState[portfolioKey] = toggleVisible()
|
||||
}
|
||||
}
|
||||
return expandedTransitionState to collapsedTransitionState
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList", "LongMethod", "CyclomaticComplexMethod")
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.ui.components.common
|
||||
|
||||
import androidx.compose.animation.core.MutableTransitionState
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.paging.compose.LazyPagingItems
|
||||
import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM
|
||||
import com.tangem.core.ui.components.transactions.state.TxHistoryState
|
||||
import com.tangem.core.ui.components.transactions.txHistoryItems
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
|
|
@ -22,11 +24,11 @@ internal fun LazyListScope.contentItems(
|
|||
txHistoryItems: LazyPagingItems<TxHistoryState.TxHistoryItemState>?,
|
||||
isBalanceHidden: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
selectedWalletChanged: Boolean,
|
||||
portfolioVisibleState: (portfolio: TokensListItemUM.Portfolio) -> MutableTransitionState<Boolean>,
|
||||
) {
|
||||
when (state) {
|
||||
is WalletState.MultiCurrency -> {
|
||||
tokensListItems(state.tokensListState, modifier, isBalanceHidden, selectedWalletChanged)
|
||||
tokensListItems(state.tokensListState, modifier, isBalanceHidden, portfolioVisibleState)
|
||||
}
|
||||
is WalletState.SingleCurrency -> {
|
||||
txHistoryItems(state.txHistoryState, txHistoryItems, isBalanceHidden, modifier)
|
||||
|
|
|
|||
|
|
@ -8,9 +8,7 @@ import androidx.compose.foundation.layout.padding
|
|||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalInspectionMode
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
|
@ -27,7 +25,7 @@ internal fun LazyListScope.portfolioContentItems(
|
|||
items: ImmutableList<TokensListItemUM.Portfolio>,
|
||||
modifier: Modifier = Modifier,
|
||||
isBalanceHidden: Boolean,
|
||||
selectedWalletChanged: Boolean,
|
||||
portfolioVisibleState: (portfolio: TokensListItemUM.Portfolio) -> MutableTransitionState<Boolean>,
|
||||
) {
|
||||
items.forEachIndexed { index, item ->
|
||||
portfolioTokensList(
|
||||
|
|
@ -35,7 +33,7 @@ internal fun LazyListScope.portfolioContentItems(
|
|||
modifier = modifier,
|
||||
portfolioIndex = index,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
selectedWalletChanged = selectedWalletChanged,
|
||||
portfolioVisibleState = portfolioVisibleState,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -45,7 +43,7 @@ internal fun LazyListScope.portfolioTokensList(
|
|||
modifier: Modifier,
|
||||
portfolioIndex: Int,
|
||||
isBalanceHidden: Boolean,
|
||||
selectedWalletChanged: Boolean,
|
||||
portfolioVisibleState: (portfolio: TokensListItemUM.Portfolio) -> MutableTransitionState<Boolean>,
|
||||
) {
|
||||
val tokens = portfolio.tokens
|
||||
val isExpanded = portfolio.isExpanded
|
||||
|
|
@ -55,7 +53,7 @@ internal fun LazyListScope.portfolioTokensList(
|
|||
modifier = modifier,
|
||||
portfolioIndex = portfolioIndex,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
selectedWalletChanged = selectedWalletChanged,
|
||||
portfolioVisibleState = portfolioVisibleState,
|
||||
)
|
||||
if (!isExpanded) return
|
||||
if (tokens.isEmpty()) {
|
||||
|
|
@ -63,17 +61,22 @@ internal fun LazyListScope.portfolioTokensList(
|
|||
key = "$NON_CONTENT_TOKENS_LIST_KEY account-${portfolio.id}",
|
||||
contentType = "$NON_CONTENT_TOKENS_LIST_KEY account-${portfolio.id}",
|
||||
) {
|
||||
NonContentItemContent(
|
||||
modifier = Modifier
|
||||
val appear = portfolioVisibleState(portfolio)
|
||||
SlideInItemVisibility(
|
||||
modifier = modifier
|
||||
.animateItem()
|
||||
.roundedShapeItemDecoration(
|
||||
radius = TangemTheme.dimens.radius14,
|
||||
currentIndex = 1,
|
||||
lastIndex = 1,
|
||||
backgroundColor = TangemTheme.colors.background.primary,
|
||||
)
|
||||
.padding(vertical = TangemTheme.dimens.spacing28),
|
||||
)
|
||||
),
|
||||
visibleState = appear,
|
||||
) {
|
||||
NonContentItemContent(
|
||||
modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing28),
|
||||
)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
@ -84,10 +87,7 @@ internal fun LazyListScope.portfolioTokensList(
|
|||
itemContent = { tokenIndex, token ->
|
||||
val indexWithHeader = tokenIndex.inc()
|
||||
val lastIndex = tokens.lastIndex.inc()
|
||||
val isPreview = LocalInspectionMode.current
|
||||
val appear = remember {
|
||||
MutableTransitionState(selectedWalletChanged || isPreview).apply { targetState = true }
|
||||
}
|
||||
val appear = portfolioVisibleState(portfolio)
|
||||
SlideInItemVisibility(
|
||||
modifier = modifier
|
||||
.testModifier(indexWithHeader)
|
||||
|
|
@ -116,7 +116,7 @@ private fun LazyListScope.portfolioItem(
|
|||
modifier: Modifier,
|
||||
portfolioIndex: Int,
|
||||
isBalanceHidden: Boolean,
|
||||
selectedWalletChanged: Boolean,
|
||||
portfolioVisibleState: (portfolio: TokensListItemUM.Portfolio) -> MutableTransitionState<Boolean>,
|
||||
) {
|
||||
val tokens = portfolio.tokens
|
||||
val isExpanded = portfolio.isExpanded
|
||||
|
|
@ -140,11 +140,7 @@ private fun LazyListScope.portfolioItem(
|
|||
lastIndex = lastIndex,
|
||||
backgroundColor = TangemTheme.colors.background.primary,
|
||||
)
|
||||
val isPreview = LocalInspectionMode.current
|
||||
val appear = remember {
|
||||
MutableTransitionState(selectedWalletChanged || isPreview || tokens.isEmpty())
|
||||
.apply { targetState = true }
|
||||
}
|
||||
val appear = portfolioVisibleState(portfolio)
|
||||
if (isExpanded) {
|
||||
SlideInItemVisibility(
|
||||
modifier = anchorModifier,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency
|
||||
|
||||
import androidx.compose.animation.core.MutableTransitionState
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
|
|
@ -40,14 +41,14 @@ internal fun LazyListScope.tokensListItems(
|
|||
state: WalletTokensListState,
|
||||
modifier: Modifier = Modifier,
|
||||
isBalanceHidden: Boolean,
|
||||
selectedWalletChanged: Boolean,
|
||||
portfolioVisibleState: (portfolio: TokensListItemUM.Portfolio) -> MutableTransitionState<Boolean>,
|
||||
) {
|
||||
when (state) {
|
||||
is WalletTokensListState.ContentState.PortfolioContent -> portfolioContentItems(
|
||||
items = state.items,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
modifier = modifier,
|
||||
selectedWalletChanged = selectedWalletChanged,
|
||||
portfolioVisibleState = portfolioVisibleState,
|
||||
)
|
||||
is WalletTokensListState.ContentState.Content,
|
||||
is WalletTokensListState.ContentState.Loading,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue