Updated on 2026-08-14

This commit is contained in:
Tangem 2026-03-12 11:50:24 +03:00
parent 6588ff4fbc
commit ea180bc503
3 changed files with 70 additions and 58 deletions

View file

@ -15,6 +15,7 @@ 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
@ -37,39 +38,40 @@ internal fun WalletListContent(
val movableItemModifier = Modifier.padding(horizontal = TangemTheme.dimens2.x3)
val itemModifier = movableItemModifier.padding(top = TangemTheme.dimens2.x3)
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(),
)
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(),
)
tangemPay(
walletUM = currentWallet,
isBalanceHiding = isBalanceHidden,
modifier = itemModifier,
)
tangemPay(
walletUM = currentWallet,
isBalanceHiding = 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)
}
}
}

View file

@ -2,6 +2,9 @@ package com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrenc
import androidx.compose.animation.*
import androidx.compose.animation.core.FastOutLinearInEasing
import androidx.compose.animation.core.LinearOutSlowInEasing
import androidx.compose.animation.core.animateIntAsState
import androidx.compose.animation.core.snap
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
@ -26,7 +29,6 @@ import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.test.MainScreenTestTags
import com.tangem.core.ui.utils.lazyListItemPosition
import kotlinx.collections.immutable.ImmutableList
import kotlinx.coroutines.delay
internal fun LazyListScope.portfolioContentItems(
items: ImmutableList<TokensListItemUM.Portfolio>,
@ -155,18 +157,17 @@ private fun LazyListScope.portfolioItem(
key = "account-${portfolio.id}",
contentType = "account-content",
) {
var lastIndexProxy by remember { mutableIntStateOf(lastIndex) }
// When collapsing the portfolio, we delay updating lastIndexProxy to allow
// shrinking animation to complete before changing the shape.
LaunchedEffect(lastIndex) {
if (lastIndex != 0) {
lastIndexProxy = lastIndex
return@LaunchedEffect
}
delay(timeMillis = minOf(50 * tokens.size, 250).toLong())
lastIndexProxy = 0
}
// Snap immediately on expand; on collapse, hold until all child items finish
// their shrink animation, then snap to fully-rounded shape.
val effectiveLastIndex by animateIntAsState(
targetValue = lastIndex,
animationSpec = if (lastIndex != 0) {
snap()
} else {
snap(delayMillis = minOf(50 * tokens.lastIndex, 250) + 150)
},
label = "lastIndex",
)
PortfolioListItem(
state = portfolio,
@ -176,7 +177,7 @@ private fun LazyListScope.portfolioItem(
.roundedShapeItemDecoration(
currentIndex = 0,
radius = TangemTheme.dimens.radius14,
lastIndex = lastIndexProxy,
lastIndex = effectiveLastIndex,
backgroundColor = TangemTheme.colors.background.primary,
),
)
@ -199,18 +200,14 @@ internal fun SlideInItemVisibility(
AnimatedVisibility(
modifier = modifier,
visible = visible,
enter = fadeIn(
tween(100, delayMillis = delayEnter),
) + expandVertically(
tween(100, delayMillis = delayEnter, easing = FastOutLinearInEasing),
enter = expandVertically(
tween(200, delayMillis = delayEnter, easing = LinearOutSlowInEasing),
expandFrom = Alignment.Top,
),
exit = fadeOut(
tween(100, delayMillis = delayExit),
) + shrinkVertically(
tween(100, delayMillis = delayExit, easing = FastOutLinearInEasing),
) + fadeIn(tween(200, delayMillis = delayEnter, easing = LinearOutSlowInEasing)),
exit = shrinkVertically(
tween(150, delayMillis = delayExit, easing = FastOutLinearInEasing),
shrinkTowards = Alignment.Top,
),
) + fadeOut(tween(150, delayMillis = delayExit, easing = FastOutLinearInEasing)),
) {
content()
}

View file

@ -3,6 +3,8 @@ package com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrenc
import androidx.compose.animation.*
import androidx.compose.animation.SharedTransitionScope.ResizeMode.Companion.scaleToBounds
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.animateIntAsState
import androidx.compose.animation.core.snap
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@ -214,6 +216,7 @@ private fun LazyListScope.portfolioItem(
)
}
@Suppress("MagicNumber")
private fun LazyListScope.accountItem(
listItem: TokensListItemUM2.Portfolio,
modifier: Modifier,
@ -225,6 +228,18 @@ private fun LazyListScope.accountItem(
key = listItem.tokenRowUM.id,
contentType = listItem.tokenRowUM::class.java,
) {
// Snap immediately on expand; on collapse, hold the current value until all
// child items finish their shrink animation, then snap to fully-rounded shape.
val effectiveLastIndex by animateIntAsState(
targetValue = if (listItem.isExpanded) lastIndex else 0,
animationSpec = if (listItem.isExpanded) {
snap()
} else {
snap(delayMillis = minOf(50 * maxOf(listItem.tokenList.lastIndex, 0), 250) + 150)
},
label = "lastIndex",
)
val portfolioModifier = modifier
.padding(top = if (index != 0) TangemTheme.dimens2.x2 else TangemTheme.dimens2.x3)
.testTag(MainScreenTestTags.TOKEN_LIST_ITEM)
@ -233,7 +248,7 @@ private fun LazyListScope.accountItem(
currentIndex = 0,
radius = 18.dp,
addDefaultPadding = false,
lastIndex = if (listItem.isExpanded) lastIndex else 0,
lastIndex = effectiveLastIndex,
backgroundColor = TangemTheme.colors2.surface.level3,
)
if (listItem.isCollapsable) {
@ -288,10 +303,9 @@ internal fun PortfolioRowItem(
isBalanceHidden: Boolean,
modifier: Modifier = Modifier,
) {
// TangemSharedTransitionLayout {
ProvideSharedTransitionScope(modifier) {
val iconSharedContentState = rememberSharedContentState(key = "icon")
val titleSharedContentState = rememberSharedContentState(key = "title")
val iconSharedContentState = rememberSharedContentState(key = "icon_${item.tokenRowUM.id}")
val titleSharedContentState = rememberSharedContentState(key = "title_${item.tokenRowUM.id}")
val boundsTransform = BoundsTransform { _, _ -> tween(250) }
AnimatedContent(
@ -382,7 +396,6 @@ internal fun PortfolioRowItem(
)
}
}
// }
}
}