From 14b3b93cf4684b9074b766269a7aecf73c1935fe Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 10 Mar 2026 17:14:20 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../TangemPullToRefreshContainer.kt | 147 +++++++++++++++++- ...BalanceExitUntilCollapsedScrollBehavior.kt | 38 +++-- .../model/intents/WalletClickIntents.kt | 28 ++-- .../presentation/wallet/ui/WalletScreen2.kt | 23 ++- .../ui/components/common/WalletBalance.kt | 5 +- .../components/common/WalletPagerIndicator.kt | 64 +++++--- .../ui/components/common/WalletTopBar.kt | 40 ++++- 7 files changed, 287 insertions(+), 58 deletions(-) diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/containers/pullToRefresh/TangemPullToRefreshContainer.kt b/core/ui/src/main/java/com/tangem/core/ui/components/containers/pullToRefresh/TangemPullToRefreshContainer.kt index 19e1491cf4..13b1a4e914 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/containers/pullToRefresh/TangemPullToRefreshContainer.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/containers/pullToRefresh/TangemPullToRefreshContainer.kt @@ -1,20 +1,32 @@ package com.tangem.core.ui.components.containers.pullToRefresh import android.content.res.Configuration +import androidx.compose.animation.core.animateDpAsState +import androidx.compose.animation.core.tween import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.* +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults.Indicator +import androidx.compose.material3.pulltorefresh.PullToRefreshState import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.core.ui.res.TangemThemePreviewRedesign +import kotlin.math.ln +/** + * A composable function that provides a pull-to-refresh container using Material3's PullToRefreshBox. + */ @OptIn(ExperimentalMaterial3Api::class) @Composable fun TangemPullToRefreshContainer( @@ -45,6 +57,114 @@ fun TangemPullToRefreshContainer( } } +/** + * A composable function that provides a pull-to-refresh container that slides the content down + * to reveal a progress indicator, then slides it back up when refreshing completes. + * + * The indicator appears during the pull gesture (driven by drag distance) and remains visible + * while refreshing is in progress. + * + * @param config Pull-to-refresh configuration (isRefreshing, onRefresh). + * @param modifier Modifier applied to the outer container. + * @param indicatorOffset Additional offset for the indicator block position. + * @param content The content to display. + */ +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun TangemPullToRefreshSlidingContainer( + config: PullToRefreshConfig, + modifier: Modifier = Modifier, + state: PullToRefreshState = rememberPullToRefreshState(), + indicatorOffset: Dp = 0.dp, + content: @Composable BoxScope.() -> Unit, +) { + val indicatorSize = 24.dp + val contentOffset = getPullToRefreshIndicatorOffset( + pullToRefreshConfig = config, + pullToRefreshState = state, + ) + PullToRefreshBox( + isRefreshing = config.isRefreshing, + onRefresh = { + config.onRefresh(PullToRefreshConfig.ShowRefreshState()) + }, + state = state, + modifier = modifier, + indicator = {}, + ) { + Box(modifier = Modifier.fillMaxSize()) { + // Content slides down + Box( + modifier = Modifier + .fillMaxSize() + .offset(y = contentOffset), + ) { + content() + } + // Indicator block slides in from above + Box( + contentAlignment = Alignment.Center, + modifier = Modifier + .fillMaxWidth() + .height(contentOffset) + .offset(y = indicatorOffset), + ) { + if (contentOffset > 0.dp) { + if (config.isRefreshing) { + // Indeterminate spinner while refreshing + CircularProgressIndicator( + modifier = Modifier.size(indicatorSize), + color = TangemTheme.colors2.graphic.neutral.primary, + strokeWidth = 2.dp, + ) + } else { + // Determinate arc driven by pull fraction + CircularProgressIndicator( + progress = { state.distanceFraction.coerceAtLeast(0f).coerceIn(0f, 1f) }, + modifier = Modifier.size(indicatorSize), + color = TangemTheme.colors2.graphic.neutral.primary, + trackColor = Color.Transparent, + strokeWidth = 2.dp, + ) + } + } + } + } + } +} + +/** + * Calculates the vertical offset for the pull-to-refresh indicator + * based on the current pull state and refreshing status. + */ +@Composable +fun getPullToRefreshIndicatorOffset( + pullToRefreshConfig: PullToRefreshConfig?, + pullToRefreshState: PullToRefreshState, +): Dp { + val indicatorBlockHeight = 56.dp + val maxOverscroll = 24.dp + + val refreshingOffset by animateDpAsState( + targetValue = if (pullToRefreshConfig?.isRefreshing == true) indicatorBlockHeight else 0.dp, + animationSpec = tween(durationMillis = 300), + label = "SlidingContentOffset", + ) + + // Drag-driven offset with overscroll: linear up to indicatorBlockHeight, + // then dampened logarithmic curve beyond for a rubber-band effect + val fraction = pullToRefreshState.distanceFraction.coerceAtLeast(0f) + val dragOffset = if (fraction <= 1f) { + indicatorBlockHeight * fraction + } else { + val overscrollFraction = ln(1f + (fraction - 1f)) / ln(2f) // dampened curve + indicatorBlockHeight + maxOverscroll * overscrollFraction.coerceAtMost(1f) + } + + // Use the larger of the two so the transition from drag → refreshing is seamless + return maxOf(dragOffset, refreshingOffset) +} + // region Preview @Preview(showBackground = true, widthDp = 360, heightDp = 720) @Preview(showBackground = true, widthDp = 360, heightDp = 720, uiMode = Configuration.UI_MODE_NIGHT_YES) @@ -55,10 +175,31 @@ private fun TangemPullToRefreshContainer_Preview() { config = PullToRefreshConfig(isRefreshing = true, {}), ) { Box( - modifier = Modifier.fillMaxSize() + modifier = Modifier + .fillMaxSize() .background(TangemTheme.colors.background.secondary), ) } } } +// endregion + +// region Preview +@Preview(showBackground = true, widthDp = 360, heightDp = 720) +@Preview(showBackground = true, widthDp = 360, heightDp = 720, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun TangemPullToRefreshSlidingContainer_Preview() { + TangemThemePreviewRedesign { + TangemPullToRefreshSlidingContainer( + config = PullToRefreshConfig(isRefreshing = true, {}), + indicatorOffset = 56.dp, + ) { + Box( + modifier = Modifier + .fillMaxSize() + .background(TangemTheme.colors2.surface.level1), + ) + } + } +} // endregion \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/ds/topbar/collapsing/WalletBalanceExitUntilCollapsedScrollBehavior.kt b/core/ui/src/main/java/com/tangem/core/ui/ds/topbar/collapsing/WalletBalanceExitUntilCollapsedScrollBehavior.kt index c3e18a6df6..166348b94b 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/ds/topbar/collapsing/WalletBalanceExitUntilCollapsedScrollBehavior.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/ds/topbar/collapsing/WalletBalanceExitUntilCollapsedScrollBehavior.kt @@ -2,15 +2,17 @@ package com.tangem.core.ui.ds.topbar.collapsing import androidx.compose.animation.core.* import androidx.compose.animation.rememberSplineBasedDecay +import androidx.compose.foundation.gestures.FlingBehavior import androidx.compose.foundation.gestures.Orientation -import androidx.compose.foundation.gestures.draggable -import androidx.compose.foundation.gestures.rememberDraggableState +import androidx.compose.foundation.gestures.ScrollScope +import androidx.compose.foundation.gestures.scrollable import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.input.nestedscroll.NestedScrollConnection import androidx.compose.ui.input.nestedscroll.NestedScrollSource +import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Velocity import androidx.compose.ui.unit.dp @@ -121,20 +123,24 @@ private fun exitUntilCollapsedScrollBehavior( @Composable fun Modifier.snapToExitUntilCollapsed(behavior: TangemCollapsingAppBarBehavior): Modifier { - return draggable( - orientation = Orientation.Vertical, - state = rememberDraggableState { delta -> - behavior.state.heightOffset += delta - }, - onDragStopped = { velocity -> - settleAppBar( - state = behavior.state, - velocity = velocity, - flingAnimationSpec = behavior.flingAnimationSpec, - snapAnimationSpec = behavior.snapAnimationSpec, - ) - }, - ) + return nestedScroll(behavior.nestedScrollConnection) + .scrollable( + orientation = Orientation.Vertical, + state = behavior.state, + flingBehavior = remember(behavior) { + object : FlingBehavior { + override suspend fun ScrollScope.performFling(initialVelocity: Float): Float { + val consumed = settleAppBar( + state = behavior.state, + velocity = initialVelocity, + flingAnimationSpec = behavior.flingAnimationSpec, + snapAnimationSpec = behavior.snapAnimationSpec, + ) + return initialVelocity - consumed.y + } + } + }, + ) } /** diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletClickIntents.kt index 8f03d6ae84..47c3f6be8a 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletClickIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletClickIntents.kt @@ -1,6 +1,7 @@ package com.tangem.feature.wallet.child.wallet.model.intents import com.tangem.core.decompose.di.ModelScoped +import com.tangem.core.ui.DesignFeatureToggles import com.tangem.domain.exchange.RampStateManager import com.tangem.domain.models.wallet.isLocked import com.tangem.domain.onramp.FetchHotCryptoUseCase @@ -15,6 +16,7 @@ import com.tangem.feature.wallet.presentation.wallet.domain.unwrap 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.WalletState +import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetRefreshStateTransformer import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.async @@ -41,6 +43,7 @@ internal class WalletClickIntents @Inject constructor( private val onrampStatusFactory: OnrampStatusFactory, private val tangemPayIntents: TangemPayClickIntentsImplementor, private val yieldSupplyApyUpdateUseCase: YieldSupplyApyUpdateUseCase, + private val designFeatureToggles: DesignFeatureToggles, ) : BaseWalletClickIntents(), WalletCardClickIntents by walletCardClickIntentsImplementor, WalletWarningsClickIntents by warningsClickIntentsImplementer, @@ -86,17 +89,24 @@ internal class WalletClickIntents @Inject constructor( } fun onRefreshSwipe(showRefreshState: Boolean) { - when (stateController.getSelectedWallet()) { - is WalletState.MultiCurrency.Content -> { - refreshMultiCurrencyContent(showRefreshState) + if (designFeatureToggles.isRedesignEnabled) { + when (stateController.getSelectedWalletUM()) { + is WalletUM.Content -> refreshMultiCurrencyContent(showRefreshState) + is WalletUM.Locked -> Unit } - is WalletState.SingleCurrency.Content, - -> { - refreshSingleCurrencyContent(showRefreshState) + } else { + when (stateController.getSelectedWallet()) { + is WalletState.MultiCurrency.Content -> { + refreshMultiCurrencyContent(showRefreshState) + } + is WalletState.SingleCurrency.Content, + -> { + refreshSingleCurrencyContent(showRefreshState) + } + is WalletState.MultiCurrency.Locked, + is WalletState.SingleCurrency.Locked, + -> Unit } - is WalletState.MultiCurrency.Locked, - is WalletState.SingleCurrency.Locked, - -> Unit } } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen2.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen2.kt index 6e0ea2edc8..83c59d731f 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen2.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen2.kt @@ -19,6 +19,7 @@ import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Text +import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment @@ -42,6 +43,7 @@ import com.tangem.core.ui.components.atoms.Hand import com.tangem.core.ui.components.atoms.handComposableComponentHeight import com.tangem.core.ui.components.background.northernlights.NorthernLightsBackground import com.tangem.core.ui.components.bottomsheets.state.BottomSheetState +import com.tangem.core.ui.components.containers.pullToRefresh.TangemPullToRefreshSlidingContainer import com.tangem.core.ui.components.haze.hazeSourceTangem import com.tangem.core.ui.components.rememberIsKeyboardVisible import com.tangem.core.ui.components.sheetscaffold.* @@ -130,6 +132,11 @@ private fun WalletContent2( val bottomBarHeight = with(density) { WindowInsets.systemBars.getBottom(this).toDp() } var walletBalance by remember { mutableStateOf(TextReference.EMPTY) } + var pullToRefreshConfig by remember { + mutableStateOf( + state.wallets2.getOrNull(state.selectedWalletIndex)?.pullToRefreshConfig, + ) + } BaseScaffoldWithMarkets( state = state, @@ -164,6 +171,8 @@ private fun WalletContent2( val canPagerScroll by remember { derivedStateOf { behavior.state.heightOffset == 0f } } + val pullToRefreshState = rememberPullToRefreshState() + Box( modifier = Modifier .fillMaxSize() @@ -180,6 +189,8 @@ private fun WalletContent2( WalletPagerIndicator( pagerState = walletsPagerState, + pullToRefreshState = pullToRefreshState, + pullToRefreshConfig = pullToRefreshConfig, behavior = behavior, ) @@ -199,6 +210,11 @@ private fun WalletContent2( walletBalance = (currentWallet.walletsBalanceUM as? WalletBalanceUM.Content)?.balanceInAppBar } } + LaunchedEffect(walletsPagerState.currentPage, currentWallet.pullToRefreshConfig) { + if (walletsPagerState.currentPage == currentWalletIndex) { + pullToRefreshConfig = currentWallet.pullToRefreshConfig + } + } val isShowMarketsHint by remember { derivedStateOf { @@ -211,8 +227,13 @@ private fun WalletContent2( val pageSlideAlpha by rememberPageAlpha(walletsPagerState, currentWalletIndex) - Box( + TangemPullToRefreshSlidingContainer( + state = pullToRefreshState, + config = currentWallet.pullToRefreshConfig, modifier = Modifier.alpha(pageSlideAlpha), + indicatorOffset = with(LocalDensity.current) { + behavior.state.partialHeightLimit.toDp() + }, ) { TangemCollapsingTopBar( state = behavior.state, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletBalance.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletBalance.kt index 0d4a5903ce..dd23a5debb 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletBalance.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletBalance.kt @@ -6,6 +6,7 @@ import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.togetherWith +import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.text.TextAutoSize import androidx.compose.material3.Text @@ -75,7 +76,7 @@ internal fun WalletBalance( horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier .fillMaxWidth() - .height(200.dp), + .padding(vertical = 58.dp), ) { Balance( walletBalanceUM = walletBalanceUM, @@ -147,7 +148,6 @@ private fun Balance(walletBalanceUM: WalletBalanceUM, isBalanceHidden: Boolean, text = "123456", style = TangemTheme.typography2.titleRegular44, radius = TangemTheme.dimens2.x25, - textSizeHeight = true, ) } } @@ -194,6 +194,7 @@ private fun WalletBalance_Preview(@PreviewParameter(WalletBalancePreviewProvider behavior = rememberTangemExitUntilCollapsedScrollBehavior(), buttons = WalletPreviewData.actionButtons, isBalanceHidden = false, + modifier = Modifier.background(TangemTheme.colors2.surface.level1), ) } } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletPagerIndicator.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletPagerIndicator.kt index d047533bb3..de6770b7e9 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletPagerIndicator.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletPagerIndicator.kt @@ -1,49 +1,71 @@ package com.tangem.feature.wallet.presentation.wallet.ui.components.common +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.pager.PagerState +import androidx.compose.material3.pulltorefresh.PullToRefreshState import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.scale import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.unit.dp +import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig +import com.tangem.core.ui.components.containers.pullToRefresh.getPullToRefreshIndicatorOffset import com.tangem.core.ui.ds.TangemPagerIndicator import com.tangem.core.ui.ds.topbar.collapsing.TangemCollapsingAppBarBehavior private const val MIN_SCALE = 0.75f private const val MAX_SCALE = 1f +private const val WALLET_INDICATOR_OFFSET = 0.63f @Composable -internal fun WalletPagerIndicator(pagerState: PagerState, behavior: TangemCollapsingAppBarBehavior) { +internal fun WalletPagerIndicator( + pagerState: PagerState, + behavior: TangemCollapsingAppBarBehavior, + pullToRefreshConfig: PullToRefreshConfig?, + pullToRefreshState: PullToRefreshState, +) { val collapsedFraction = behavior.state.collapsedFraction val alpha = MAX_SCALE - collapsedFraction val scale = alpha.coerceIn(MIN_SCALE, MAX_SCALE) + val height = with(LocalDensity.current) { + behavior.state.heightOffsetLimit.toDp().unaryMinus() + } - Box( - modifier = Modifier - .graphicsLayer { - scaleY = scale - translationY = behavior.state.heightOffset - } - .fillMaxWidth() - .height( - with(LocalDensity.current) { - behavior.state.heightOffsetLimit.toDp().unaryMinus() - }, - ) - .alpha(alpha), + val contentOffset = getPullToRefreshIndicatorOffset( + pullToRefreshConfig = pullToRefreshConfig, + pullToRefreshState = pullToRefreshState, + ) + val padding = height * WALLET_INDICATOR_OFFSET + + AnimatedVisibility( + visible = pagerState.pageCount > 1, + enter = fadeIn(), + exit = fadeOut(), ) { - TangemPagerIndicator( - pagerState = pagerState, + Box( modifier = Modifier - .padding(top = 248.dp) - .scale(scaleY = 1f, scaleX = scale) - .fillMaxWidth(), - ) + .graphicsLayer { + scaleY = scale + translationY = behavior.state.heightOffset + contentOffset.toPx() + } + .fillMaxWidth() + .height(height) + .alpha(alpha), + ) { + TangemPagerIndicator( + pagerState = pagerState, + modifier = Modifier + .padding(top = padding) + .scale(scaleY = 1f, scaleX = scale) + .fillMaxWidth(), + ) + } } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletTopBar.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletTopBar.kt index 7dd4faf316..520a13c331 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletTopBar.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletTopBar.kt @@ -1,17 +1,24 @@ package com.tangem.feature.wallet.presentation.wallet.ui.components.common import android.content.res.Configuration +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.lerp import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import com.tangem.core.ui.components.haze.hazeEffectTangem import com.tangem.core.ui.ds.topbar.TangemTopBar +import com.tangem.core.ui.ds.topbar.TangemTopBarActionContent import com.tangem.core.ui.ds.topbar.TangemTopBarActionUM import com.tangem.core.ui.ds.topbar.collapsing.TangemCollapsingAppBarBehavior import com.tangem.core.ui.ds.topbar.collapsing.rememberTangemExitUntilCollapsedScrollBehavior @@ -55,11 +62,32 @@ internal fun WalletTopBar( TangemTopBar( title = wrappedBalance, - startAction = TangemTopBarActionUM( - iconRes = R.drawable.ic_tangem_24, - isActionable = false, - ), - endActions = topBarConfig.endActions, + startContent = { + TangemTopBarActionContent( + TangemTopBarActionUM( + iconRes = R.drawable.ic_tangem_24, + isActionable = false, + ), + ) + }, + endContent = { + Row( + horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens2.x5), + modifier = Modifier + .clip(CircleShape) + .background( + lerp( + start = Color.Transparent, + stop = TangemTheme.colors2.button.backgroundSecondary, + fraction = behavior.state.collapsedFraction, + ), + ), + ) { + topBarConfig.endActions.forEach { action -> + TangemTopBarActionContent(action) + } + } + }, modifier = Modifier .statusBarsPadding() .testTag(MainScreenTestTags.TOP_BAR), @@ -134,7 +162,7 @@ private fun WalletTopBar_WithQrButton_Preview() { topBarConfig = WalletTopBarConfig( endActions = persistentListOf( TangemTopBarActionUM( - iconRes = com.tangem.core.ui.R.drawable.ic_qrcode_scaner_24, + iconRes = R.drawable.ic_qrcode_scaner_24, onClick = {}, ), TangemTopBarActionUM(