From 7b00754e24a4707cfa093d50ec790598e65c2f94 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 3 Mar 2026 17:39:04 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../NorthernLightsBackground.kt | 25 ++++++++----------- .../tangem/core/ui/components/haze/HazeExt.kt | 10 ++++---- .../core/ui/ds/message/TangemMessageEffect.kt | 17 +++++++++---- .../core/ui/ds/row/header/TangemHeaderRow.kt | 14 +++++------ .../internal/TokenRowPriceChangeContent.kt | 14 ++++++----- .../feed/ui/feed/components/NewsSlider.kt | 2 +- .../page/background/NorthernLightsStory.kt | 3 +++ .../tokenActions/TokenActionsComponent.kt | 3 ++- .../presentation/wallet/ui/WalletScreen2.kt | 18 +++++++------ .../ui/components/common/WalletBalance.kt | 15 ++++++++++- .../ui/components/common/WalletContent.kt | 6 ++--- .../multicurrency/MultiCurrencyContent.kt | 1 + 12 files changed, 77 insertions(+), 51 deletions(-) diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/background/northernlights/NorthernLightsBackground.kt b/core/ui/src/main/java/com/tangem/core/ui/components/background/northernlights/NorthernLightsBackground.kt index a59ce0f0e6..27b3583edc 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/background/northernlights/NorthernLightsBackground.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/background/northernlights/NorthernLightsBackground.kt @@ -4,12 +4,7 @@ package com.tangem.core.ui.components.background.northernlights import android.os.Build import androidx.compose.animation.animateColor -import androidx.compose.animation.core.FastOutSlowInEasing -import androidx.compose.animation.core.RepeatMode -import androidx.compose.animation.core.StartOffset -import androidx.compose.animation.core.infiniteRepeatable -import androidx.compose.animation.core.keyframes -import androidx.compose.animation.core.rememberInfiniteTransition +import androidx.compose.animation.core.* import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize @@ -21,7 +16,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import com.tangem.core.ui.components.background.shaderBackground import com.tangem.core.ui.res.LocalPowerSavingState -import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.shader.NorthernLightsMeshGradientShader /** @@ -29,10 +23,14 @@ import com.tangem.core.ui.shader.NorthernLightsMeshGradientShader * Uses a RuntimeShader on Android 13+ and falls back to a simpler implementation on older versions and in power saving mode. */ @Composable -fun NorthernLightsBackground(modifier: Modifier = Modifier, forceSimpleVersion: Boolean = false) { +fun NorthernLightsBackground( + containerColor: Color, + modifier: Modifier = Modifier, + forceSimpleVersion: Boolean = false, +) { val isPowerSavingMode by LocalPowerSavingState.current.isPowerSavingModeEnabled.collectAsState() if (!forceSimpleVersion && Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && !isPowerSavingMode) { - NorthernLightsBackgroundWithShader(modifier) + NorthernLightsBackgroundWithShader(containerColor, modifier) } else { MovingColorfulBlubsBackground(modifier) } @@ -40,9 +38,8 @@ fun NorthernLightsBackground(modifier: Modifier = Modifier, forceSimpleVersion: @Suppress("LongMethod") @Composable -private fun NorthernLightsBackgroundWithShader(modifier: Modifier = Modifier) { +private fun NorthernLightsBackgroundWithShader(containerColor: Color, modifier: Modifier = Modifier) { val transition = rememberInfiniteTransition(label = "FluidMeshGradientV2") - val backgroundColor = TangemTheme.colors2.surface.level1 // Each track cycles through 4 states (matching the screenshot frames): // deep/dark → saturated+bright → light/pastel → vibrant/vivid → back @@ -128,7 +125,7 @@ private fun NorthernLightsBackgroundWithShader(modifier: Modifier = Modifier) { Color(0xFF1444AA), Color(0xFF4422BB), Color(0xFF331199), - backgroundColor, + containerColor, ), speed = 0.5f, scale = 4f, @@ -139,12 +136,12 @@ private fun NorthernLightsBackgroundWithShader(modifier: Modifier = Modifier) { colorsArray[1] = color2 colorsArray[2] = color3 colorsArray[3] = color4 - colorsArray[4] = backgroundColor + colorsArray[4] = containerColor shader.updateColors(colorsArray) Box( modifier = modifier - .background(backgroundColor) + .background(containerColor) .fillMaxSize() .shaderBackground(shader), ) diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/haze/HazeExt.kt b/core/ui/src/main/java/com/tangem/core/ui/components/haze/HazeExt.kt index d34949ea34..b80af29a35 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/haze/HazeExt.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/haze/HazeExt.kt @@ -32,15 +32,15 @@ internal fun ProvideHaze(content: @Composable () -> Unit) { */ @Composable fun Modifier.hazeEffectTangem( + state: HazeState = LocalHazeState.current, style: HazeStyle = HazeStyle.Unspecified, configure: HazeEffectScope.() -> Unit = {}, ): Modifier { val powerSavingEnabled = LocalPowerSavingState.current.isPowerSavingModeEnabled.collectAsState() - val hazeState = LocalHazeState.current - val isGlobalBlurEnabled = hazeState.blurEnabled && !powerSavingEnabled.value + val isGlobalBlurEnabled = state.blurEnabled && !powerSavingEnabled.value val rootBackground by LocalRootBackgroundColor.current - return hazeEffect(hazeState, style) { + return hazeEffect(state, style) { fallbackTint = HazeTint(rootBackground) if (isGlobalBlurEnabled) { configure() @@ -78,5 +78,5 @@ fun Modifier.hazeForegroundEffectTangem( * Applies a haze source to the [Modifier] using the current global haze state. */ @Composable -fun Modifier.hazeSourceTangem(zIndex: Float = 0f, key: Any? = null) = - this.hazeSource(LocalHazeState.current, zIndex, key) \ No newline at end of file +fun Modifier.hazeSourceTangem(state: HazeState = LocalHazeState.current, zIndex: Float = 0f, key: Any? = null) = + this.hazeSource(state, zIndex, key) \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/ds/message/TangemMessageEffect.kt b/core/ui/src/main/java/com/tangem/core/ui/ds/message/TangemMessageEffect.kt index 96e24e5007..03b00e793a 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/ds/message/TangemMessageEffect.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/ds/message/TangemMessageEffect.kt @@ -106,7 +106,10 @@ enum class TangemMessageEffect(val isAnimatable: Boolean) { Color(0x1AFFFFFF), ) } else { - persistentListOf() + persistentListOf( + Color(0xFFE1E1E1), + Color(0xFFE1E1E1), + ) } } } @@ -192,7 +195,10 @@ enum class TangemMessageEffect(val isAnimatable: Boolean) { Color(0x17E44848), ) None -> if (isInDarkTheme) { - persistentListOf() + persistentListOf( + Color(0x1AFFFFFF), + Color(0x1AFFFFFF), + ) } else { persistentListOf( Color(0x0d000000), @@ -238,9 +244,10 @@ internal fun Modifier.messageEffectBackground( val isInDarkTheme = LocalIsInDarkTheme.current val borderGradientColors = remember { messageEffect.getBorderGradient(isInDarkTheme) } val gradientColors = remember { messageEffect.getColorGradient(isInDarkTheme) } + val gradientTint = remember { messageEffect.getGradientTint(isInDarkTheme) } val angle by rememberAnimationAngle(messageEffect.isAnimatable) - val brush = Brush.sweepGradient(messageEffect.getColorGradient(isInDarkTheme)) + val brush = remember { Brush.sweepGradient(messageEffect.getColorGradient(isInDarkTheme)) } val padding = 1.dp.toPx() return this @@ -254,14 +261,14 @@ internal fun Modifier.messageEffectBackground( border( width = 1.dp, brush = Brush.sweepGradient( - colors = messageEffect.getBorderGradient(isInDarkTheme), + colors = borderGradientColors, center = Offset.Infinite, ), shape = RoundedCornerShape(radius), ) } .hazeForegroundEffectTangem( - style = HazeStyle(tints = messageEffect.getGradientTint(isInDarkTheme)), + style = HazeStyle(tints = gradientTint), isBlurEnabled = true, ) { fallbackTint = HazeTint( diff --git a/core/ui/src/main/java/com/tangem/core/ui/ds/row/header/TangemHeaderRow.kt b/core/ui/src/main/java/com/tangem/core/ui/ds/row/header/TangemHeaderRow.kt index f5af27f6c1..c635dff1a6 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/ds/row/header/TangemHeaderRow.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/ds/row/header/TangemHeaderRow.kt @@ -25,10 +25,7 @@ import com.tangem.core.ui.components.SpacerWMax import com.tangem.core.ui.components.currency.icon.CurrencyIconState import com.tangem.core.ui.ds.image.TangemIcon import com.tangem.core.ui.ds.image.TangemIconUM -import com.tangem.core.ui.extensions.TextReference -import com.tangem.core.ui.extensions.clickableSingle -import com.tangem.core.ui.extensions.resolveAnnotatedReference -import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.extensions.* import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreviewRedesign import com.tangem.core.ui.test.TokenElementsTestTags @@ -40,12 +37,13 @@ import com.tangem.core.ui.test.TokenElementsTestTags * @param modifier Modifier for the composable */ @Composable -fun TangemHeaderRow(headerRowUM: TangemHeaderRowUM, modifier: Modifier = Modifier) { +fun TangemHeaderRow(headerRowUM: TangemHeaderRowUM, modifier: Modifier = Modifier, isBalanceHidden: Boolean = false) { TangemHeaderRow( headTangemIconUM = headerRowUM.startIconUM, footerTangemIconRes = headerRowUM.endIconRes, title = headerRowUM.title, subtitle = headerRowUM.subtitle, + isBalanceHidden = isBalanceHidden, modifier = modifier, ) } @@ -63,6 +61,7 @@ fun TangemHeaderRow(headerRowUM: TangemHeaderRowUM, modifier: Modifier = Modifie @Composable fun TangemHeaderRow( modifier: Modifier = Modifier, + isBalanceHidden: Boolean = false, subtitle: TextReference? = null, onItemClick: (() -> Unit)? = null, @DrawableRes footerTangemIconRes: Int? = null, @@ -92,7 +91,7 @@ fun TangemHeaderRow( ) { val wrappedSubtitle = remember(this) { requireNotNull(subtitle) } Text( - text = wrappedSubtitle.resolveAnnotatedReference(), + text = wrappedSubtitle.orMaskWithStars(isBalanceHidden).resolveAnnotatedReference(), style = TangemTheme.typography2.captionSemibold12, color = TangemTheme.colors2.text.neutral.secondary, maxLines = 1, @@ -131,6 +130,7 @@ fun TangemHeaderRow( fun TangemHeaderRow( title: TextReference, modifier: Modifier = Modifier, + isBalanceHidden: Boolean = false, subtitle: TextReference? = null, headTangemIconUM: TangemIconUM? = null, @DrawableRes footerTangemIconRes: Int? = null, @@ -172,7 +172,7 @@ fun TangemHeaderRow( ) { val wrappedSubtitle = remember(this) { requireNotNull(subtitle) } Text( - text = wrappedSubtitle.resolveAnnotatedReference(), + text = wrappedSubtitle.orMaskWithStars(isBalanceHidden).resolveAnnotatedReference(), style = TangemTheme.typography2.captionSemibold12, color = TangemTheme.colors2.text.neutral.secondary, maxLines = 1, diff --git a/core/ui/src/main/java/com/tangem/core/ui/ds/row/token/internal/TokenRowPriceChangeContent.kt b/core/ui/src/main/java/com/tangem/core/ui/ds/row/token/internal/TokenRowPriceChangeContent.kt index ef635a0a8e..052c994ac7 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/ds/row/token/internal/TokenRowPriceChangeContent.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/ds/row/token/internal/TokenRowPriceChangeContent.kt @@ -24,6 +24,12 @@ internal fun RowScope.TokenRowPriceChangeContent( isFlickering: Boolean, isAvailable: Boolean = true, ) { + val color = when (priceChangeState.type) { + PriceChangeType.UP -> TangemTheme.colors2.graphic.status.accent + PriceChangeType.DOWN -> TangemTheme.colors2.graphic.status.warning + PriceChangeType.NEUTRAL -> TangemTheme.colors2.graphic.neutral.tertiary + } + AnimatedContent( targetState = priceChangeState.type, label = "Update the price change's arrow", @@ -39,11 +45,7 @@ internal fun RowScope.TokenRowPriceChangeContent( }, ), ), - tint = when (animatedType) { - PriceChangeType.UP -> TangemTheme.colors2.graphic.status.accent - PriceChangeType.DOWN -> TangemTheme.colors2.graphic.status.warning - PriceChangeType.NEUTRAL -> TangemTheme.colors2.graphic.neutral.secondary - }, + tint = color, contentDescription = null, modifier = Modifier.size(TangemTheme.dimens2.x3), ) @@ -61,7 +63,7 @@ internal fun RowScope.TokenRowPriceChangeContent( style = TangemTheme.typography2.captionSemibold12.applyBladeBrush( isEnabled = isFlickering, textColor = if (isAvailable) { - TangemTheme.colors2.text.neutral.secondary + color } else { TangemTheme.colors2.text.status.disabled }, diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/NewsSlider.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/NewsSlider.kt index 4e20ea9c2f..1bc690a184 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/NewsSlider.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/feed/components/NewsSlider.kt @@ -34,7 +34,7 @@ internal fun NewsSlider(newsSliderConfig: NewsSliderConfig) { .conditionalCompose( condition = isRedesignEnabled, modifier = { - hazeSourceTangem(-1f) + hazeSourceTangem(zIndex = -1f) }, ) .background(color = background), diff --git a/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/storybook/page/background/NorthernLightsStory.kt b/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/storybook/page/background/NorthernLightsStory.kt index 3f96ca9d74..8f0fd1f280 100644 --- a/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/storybook/page/background/NorthernLightsStory.kt +++ b/features/tester/impl/src/main/java/com/tangem/feature/tester/presentation/storybook/page/background/NorthernLightsStory.kt @@ -1,4 +1,5 @@ @file:Suppress("MagicNumber", "LongMethod") + package com.tangem.feature.tester.presentation.storybook.page.background import androidx.compose.foundation.background @@ -15,6 +16,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.tangem.core.ui.components.background.northernlights.NorthernLightsBackground +import com.tangem.core.ui.res.TangemTheme import com.tangem.feature.tester.presentation.storybook.entity.NorthernLightsStory @Composable @@ -22,6 +24,7 @@ internal fun NorthernLightsStory(state: NorthernLightsStory, modifier: Modifier Box(modifier = modifier.fillMaxSize()) { NorthernLightsBackground( modifier = Modifier.fillMaxSize(), + containerColor = TangemTheme.colors2.surface.level1, forceSimpleVersion = state.variant == NorthernLightsStory.Variant.Simple, ) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/tokenActions/TokenActionsComponent.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/tokenActions/TokenActionsComponent.kt index e994cb9f17..aa0ae8e9d7 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/tokenActions/TokenActionsComponent.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/tokenActions/TokenActionsComponent.kt @@ -13,6 +13,7 @@ import com.tangem.core.ui.decompose.ComposableBottomSheetComponent import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.res.TangemTheme import com.tangem.feature.wallet.presentation.wallet.state.model.TokenActionButtonUM +import com.tangem.feature.wallet.presentation.wallet.ui.components.fastForEach import dagger.assisted.Assisted import dagger.assisted.AssistedInject @@ -36,7 +37,7 @@ internal class TokenActionsComponent @AssistedInject constructor( ), ) { Column { - params.actions.forEach { action -> + params.actions.fastForEach { action -> if (action.isEnabled) { val rowColors = if (action.isWarning) { getWarningRowColors() 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 c2c0b04c1a..119588e9f0 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 @@ -54,10 +54,7 @@ import com.tangem.core.ui.ds.topbar.collapsing.TangemCollapsingTopBar import com.tangem.core.ui.ds.topbar.collapsing.rememberTangemExitUntilCollapsedScrollBehavior import com.tangem.core.ui.event.StateEvent import com.tangem.core.ui.extensions.TextReference -import com.tangem.core.ui.res.LocalMainBottomSheetColor -import com.tangem.core.ui.res.LocalWindowSize -import com.tangem.core.ui.res.TangemTheme -import com.tangem.core.ui.res.TangemThemePreviewRedesign +import com.tangem.core.ui.res.* 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 @@ -181,9 +178,16 @@ private fun WalletContent2( Box( modifier = Modifier .fillMaxSize() - .hazeSourceTangem(-1f), + .hazeSourceTangem(zIndex = -1f), ) { - NorthernLightsBackground(Modifier.matchParentSize()) + NorthernLightsBackground( + containerColor = if (LocalIsInDarkTheme.current) { + TangemTheme.colors2.surface.level1 + } else { + TangemTheme.colors2.surface.level2 + }, + modifier = Modifier.matchParentSize(), + ) WalletPagerIndicator( pagerState = walletsPagerState, @@ -201,7 +205,7 @@ private fun WalletContent2( state.wallets2[state.selectedWalletIndex] } - LaunchedEffect(walletsPagerState.currentPage) { + LaunchedEffect(walletsPagerState.currentPage, currentWallet.walletsBalanceUM) { if (walletsPagerState.currentPage == currentWalletIndex) { walletBalance = (currentWallet.walletsBalanceUM as? WalletBalanceUM.Content)?.balanceInAppBar } 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 87d9cebc62..d5e4a5649a 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 @@ -45,6 +45,7 @@ import com.tangem.feature.wallet.presentation.preview.WalletBalancePreview import com.tangem.feature.wallet.presentation.preview.WalletPreviewData import com.tangem.feature.wallet.presentation.wallet.state.model.WalletBalanceUM import com.tangem.feature.wallet.presentation.wallet.ui.components.fastForEach +import com.tangem.utils.StringsSigns import kotlinx.collections.immutable.ImmutableList private const val MIN_SCALE = 0.75f @@ -135,7 +136,19 @@ private fun Balance(walletBalanceUM: WalletBalanceUM, isBalanceHidden: Boolean, ), ) } - is WalletBalanceUM.Error, + is WalletBalanceUM.Error -> { + Text( + text = StringsSigns.DASH_SIGN, + style = TangemTheme.typography2.titleRegular44, + color = TangemTheme.colors2.text.neutral.primary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + autoSize = TextAutoSize.StepBased( + minFontSize = TangemTheme.typography2.bodySemibold15.fontSize, + maxFontSize = TangemTheme.typography2.titleRegular44.fontSize, + ), + ) + } is WalletBalanceUM.Loading, -> { TextShimmer( diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletContent.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletContent.kt index 066a167e8d..3d542d67a6 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletContent.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletContent.kt @@ -45,16 +45,14 @@ internal fun WalletListContent( overscrollEffect = rememberOverscrollEffect(), ) { notifications( - notifications = currentWallet.notifications.map { it.messageUM } - .toPersistentList(), + notifications = currentWallet.notifications.map { it.messageUM }.toPersistentList(), contentColor = containerColor, modifier = movableItemModifier, ) notificationsCarousel( containerColor = containerColor, modifier = movableItemModifier, - notifications = currentWallet.notifications.map { it.messageUM } - .toPersistentList(), + notifications = currentWallet.notificationsCarousel.map { it.messageUM }.toPersistentList(), ) tangemPay( diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/multicurrency/MultiCurrencyContent.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/multicurrency/MultiCurrencyContent.kt index c3755c12bc..905ba692e0 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/multicurrency/MultiCurrencyContent.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/multicurrency/MultiCurrencyContent.kt @@ -204,6 +204,7 @@ private fun LazyListScope.portfolioItem( ) is TangemHeaderRowUM -> TangemHeaderRow( headerRowUM = tokenRowUM, + isBalanceHidden = isBalanceHidden, modifier = itemModifier, ) }