Updated on 2026-08-14
This commit is contained in:
parent
dbacd5b2a6
commit
14b3b93cf4
7 changed files with 287 additions and 58 deletions
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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?>(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,
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue