Updated on 2026-08-14

This commit is contained in:
Tangem 2026-03-10 17:14:20 +05:00
parent dbacd5b2a6
commit 14b3b93cf4
7 changed files with 287 additions and 58 deletions

View file

@ -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
}
}

View file

@ -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,

View file

@ -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),
)
}
}

View file

@ -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(),
)
}
}
}

View file

@ -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(