Updated on 2026-08-14

This commit is contained in:
Tangem 2026-03-30 14:20:20 +03:00
parent f26ad91361
commit c0fa00479b
8 changed files with 170 additions and 97 deletions

View file

@ -76,20 +76,17 @@ internal class WalletTokensListUMConverter(
onEmptyClick = { clickIntents.onManageTokensClick(value.mainAccount.accountId) },
)
} else {
val isCollapsable = value.accountStatuses.count {
it is AccountStatus.CryptoPortfolio && it.account.tokensCount > 0
} > 1
val tokenListUM = value.accountStatuses
.filterIsInstance<AccountStatus.CryptoPortfolio>()
.asSequence()
.flatMap { accountStatus ->
if (isAccountsModeEnabled) {
val isCollapsable = accountStatus.tokenList.flattenCurrencies().isNotEmpty()
val isExpanded = expandedAccounts.contains(accountStatus.account.accountId)
sequenceOf(
TokensListItemUM2.Portfolio(
tokenRowUM = accountRowConverter.convert(accountStatus),
isExpanded = isExpanded || !isCollapsable,
isExpanded = isExpanded,
isCollapsable = isCollapsable,
onEmptyClick = { clickIntents.onManageTokensClick(accountStatus.account.accountId) },
tokenList = getTokenListItems(
@ -166,7 +163,7 @@ internal class WalletTokensListUMConverter(
return if (accountList.flattenCurrencies().size > 1 && !selectedWallet.isSingleWalletWithToken()) {
TangemButtonUM(
text = resourceReference(R.string.organize_tokens_title),
isEnabled = accountList.totalFiatBalance is TotalFiatBalance.Loading,
isEnabled = accountList.totalFiatBalance !is TotalFiatBalance.Loading,
size = TangemButtonSize.X9,
shape = TangemButtonShape.Rounded,
type = TangemButtonType.PrimaryInverse,

View file

@ -58,6 +58,7 @@ import com.tangem.core.ui.ds.topbar.collapsing.TangemCollapsingTopBar
import com.tangem.core.ui.ds.topbar.collapsing.rememberTangemExitUntilCollapsedScrollBehavior
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.res.*
import com.tangem.core.ui.utils.TangemSharedTransitionLayout
import com.tangem.feature.wallet.presentation.common.preview.WalletScreenPreviewData
import com.tangem.feature.wallet.presentation.wallet.state.model.NOT_INITIALIZED_WALLET_INDEX
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletBalanceUM
@ -95,12 +96,28 @@ internal fun WalletScreen2(
pageCount = { state.wallets2.size },
)
val listStates = rememberSaveable(saver = lazyListStateMapSaver(walletsPagerState.pageCount)) {
mutableMapOf<Int, LazyListState>().apply {
repeat(walletsPagerState.pageCount) { index -> put(index, LazyListState()) }
}
}
val isTopOverscrollEnabled by remember {
derivedStateOf {
val listState = listStates[walletsPagerState.currentPage] ?: return@derivedStateOf false
listState.layoutInfo.totalItemsCount > 0 &&
!listState.canScrollBackward && !listState.canScrollForward ||
listState.canScrollBackward && !listState.canScrollForward
}
}
val partialCollapsedHeight = 64.dp + statusBarHeight
val balanceBlockHeight = 320.dp + partialCollapsedHeight
val behavior = rememberTangemExitUntilCollapsedScrollBehavior(
expandedHeight = balanceBlockHeight,
partialCollapsedHeight = partialCollapsedHeight,
snapAnimationSpec = spring(stiffness = Spring.StiffnessMedium),
isTopOverscrollEnabled = isTopOverscrollEnabled,
)
val coroutineScope = rememberCoroutineScope()
@ -113,6 +130,7 @@ internal fun WalletScreen2(
bottomSheetContent = bottomSheetContent,
bottomSheetHeaderHeightProvider = bottomSheetHeaderHeightProvider,
onBottomSheetStateChange = onBottomSheetStateChange,
listStates = listStates,
)
WalletEventEffect(
@ -135,6 +153,7 @@ private fun WalletContent2(
walletsPagerState: PagerState,
tangemPayComponent: TangemPayMainBlockComponent,
behavior: TangemCollapsingAppBarBehavior,
listStates: Map<Int, LazyListState>,
bottomSheetHeaderHeightProvider: () -> Dp,
onBottomSheetStateChange: (BottomSheetState) -> Unit,
bottomSheetContent: @Composable (() -> Unit),
@ -174,12 +193,6 @@ private fun WalletContent2(
}
}
val listStates = rememberSaveable(saver = lazyListStateMapSaver(walletsPagerState.pageCount)) {
mutableMapOf<Int, LazyListState>().apply {
repeat(walletsPagerState.pageCount) { index -> put(index, LazyListState()) }
}
}
val canPagerScroll by remember { derivedStateOf { behavior.state.heightOffset == 0f } }
val pullToRefreshState = rememberPullToRefreshState()
@ -220,7 +233,8 @@ private fun WalletContent2(
LaunchedEffect(walletsPagerState.currentPage, currentWallet.walletsBalanceUM) {
if (walletsPagerState.currentPage == currentWalletIndex) {
walletBalance = (currentWallet.walletsBalanceUM as? WalletBalanceUM.Content)?.balanceInAppBar
walletBalance =
(currentWallet.walletsBalanceUM as? WalletBalanceUM.Content)?.balanceInAppBar
}
}
LaunchedEffect(walletsPagerState.currentPage, currentWallet.pullToRefreshConfig) {
@ -240,39 +254,45 @@ private fun WalletContent2(
val pageSlideAlpha by rememberPageAlpha(walletsPagerState, currentWalletIndex)
TangemPullToRefreshSlidingContainer(
state = pullToRefreshState,
config = currentWallet.pullToRefreshConfig,
modifier = Modifier.alpha(pageSlideAlpha),
indicatorOffset = with(LocalDensity.current) {
behavior.state.partialHeightLimit.toDp()
},
TangemSharedTransitionLayout(
modifier = Modifier
.fillMaxSize()
.alpha(pageSlideAlpha),
) {
TangemCollapsingTopBar(
state = behavior.state,
collapsingPart = {
WalletBalance(
behavior = behavior,
walletBalanceUM = currentWallet.walletsBalanceUM,
buttons = currentWallet.buttons,
isBalanceHidden = state.isHidingMode,
)
TangemPullToRefreshSlidingContainer(
state = pullToRefreshState,
config = currentWallet.pullToRefreshConfig,
indicatorOffset = with(LocalDensity.current) {
behavior.state.partialHeightLimit.toDp()
},
body = {
WalletListContent(
currentWallet = currentWallet,
listState = listState,
isBalanceHidden = state.isHidingMode,
tangemPayComponent = tangemPayComponent,
contentPadding = contentPadding,
modifier = Modifier
.fillMaxSize()
.nestedScroll(behavior.nestedScrollConnection),
)
},
)
) {
TangemCollapsingTopBar(
state = behavior.state,
collapsingPart = {
WalletBalance(
behavior = behavior,
walletBalanceUM = currentWallet.walletsBalanceUM,
buttons = currentWallet.buttons,
isBalanceHidden = state.isHidingMode,
)
},
body = {
WalletListContent(
currentWallet = currentWallet,
listState = listState,
isBalanceHidden = state.isHidingMode,
contentPadding = contentPadding,
tangemPayComponent = tangemPayComponent,
modifier = Modifier
.fillMaxSize()
.nestedScroll(behavior.nestedScrollConnection),
)
},
)
}
val peekHeight = bottomSheetHeaderHeightProvider() + handComposableComponentHeight + bottomBarHeight
val peekHeight =
bottomSheetHeaderHeightProvider() + handComposableComponentHeight + bottomBarHeight
MarketsHint(
modifier = Modifier
.align(Alignment.BottomCenter)

View file

@ -15,7 +15,6 @@ import com.tangem.common.ui.notifications.notificationsCarousel
import com.tangem.core.ui.components.transactions.state.TxHistoryState
import com.tangem.core.ui.components.transactions.txHistoryItems
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.utils.TangemSharedTransitionLayout
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
import com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency.tokensListItems
@ -40,41 +39,40 @@ internal fun WalletListContent(
val movableItemModifier = Modifier.padding(horizontal = TangemTheme.dimens2.x3)
val itemModifier = movableItemModifier.padding(top = TangemTheme.dimens2.x3)
TangemSharedTransitionLayout(modifier) {
LazyColumn(
state = listState,
contentPadding = contentPadding,
horizontalAlignment = Alignment.CenterHorizontally,
overscrollEffect = rememberOverscrollEffect(),
) {
notifications(
notifications = currentWallet.notifications.map { it.messageUM }.toPersistentList(),
contentColor = containerColor,
modifier = movableItemModifier,
)
notificationsCarousel(
containerColor = containerColor,
modifier = movableItemModifier,
notifications = currentWallet.notificationsCarousel.map { it.messageUM }.toPersistentList(),
)
LazyColumn(
modifier = modifier,
state = listState,
contentPadding = contentPadding,
horizontalAlignment = Alignment.CenterHorizontally,
overscrollEffect = rememberOverscrollEffect(),
) {
notifications(
notifications = currentWallet.notifications.map { it.messageUM }.toPersistentList(),
contentColor = containerColor,
modifier = movableItemModifier,
)
notificationsCarousel(
containerColor = containerColor,
modifier = movableItemModifier,
notifications = currentWallet.notificationsCarousel.map { it.messageUM }.toPersistentList(),
)
tangemPay(
tangemPayComponent = tangemPayComponent,
tangemPayUM = currentWallet.tangemPayMainUM,
isBalanceHidden = isBalanceHidden,
modifier = itemModifier,
)
tangemPay(
tangemPayComponent = tangemPayComponent,
tangemPayUM = currentWallet.tangemPayMainUM,
isBalanceHidden = isBalanceHidden,
modifier = itemModifier,
)
tokensListItems2(
walletTokensListUM = currentWallet.tokensListUM,
modifier = movableItemModifier,
isBalanceHidden = isBalanceHidden,
)
tokensListItems2(
walletTokensListUM = currentWallet.tokensListUM,
modifier = movableItemModifier,
isBalanceHidden = isBalanceHidden,
)
nftCollections2(state = currentWallet, itemModifier = itemModifier)
nftCollections2(state = currentWallet, itemModifier = itemModifier)
organizeTokens2(state = currentWallet, itemModifier = itemModifier)
}
organizeTokens2(state = currentWallet, itemModifier = itemModifier)
}
}