Updated on 2026-08-14
This commit is contained in:
parent
d42cb2a79e
commit
00c5775f03
7 changed files with 70 additions and 29 deletions
|
|
@ -28,6 +28,7 @@ import com.arkivanov.decompose.value.Value
|
|||
import com.arkivanov.essenty.backhandler.BackHandler
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.core.ui.UiDependencies
|
||||
import com.tangem.core.ui.components.haze.ProvideHaze
|
||||
import com.tangem.core.ui.components.snackbar.TangemSnackbarHost
|
||||
import com.tangem.core.ui.components.snackbar.TangemTopSnackbarHost
|
||||
import com.tangem.core.ui.message.EventMessageEffect
|
||||
|
|
@ -72,8 +73,10 @@ internal fun RootContent(
|
|||
when (val instance = child.instance) {
|
||||
is RoutingComponent.Child.Initial -> Unit
|
||||
is RoutingComponent.Child.ComposableComponent -> {
|
||||
ProvideHaze {
|
||||
instance.component.Content(Modifier.fillMaxSize())
|
||||
}
|
||||
}
|
||||
is RoutingComponent.Child.LegacyIntent -> {
|
||||
// TODO: Remove and use it's own router: [REDACTED_JIRA]
|
||||
LaunchedEffect(instance) {
|
||||
|
|
|
|||
|
|
@ -4,10 +4,12 @@ import androidx.compose.animation.core.CubicBezierEasing
|
|||
import androidx.compose.animation.core.FiniteAnimationSpec
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.CompositingStrategy
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.layout.layout
|
||||
import com.arkivanov.decompose.extensions.compose.stack.animation.*
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import kotlin.math.abs
|
||||
|
||||
object RoutingTransitionAnimationFactory {
|
||||
|
||||
|
|
@ -18,8 +20,10 @@ object RoutingTransitionAnimationFactory {
|
|||
is AppRoute.Home,
|
||||
-> fade(tween(400)).plus(scale(tween(400)))
|
||||
is AppRoute.Wallet,
|
||||
-> slideAndFade(directions = setOf(Direction.ENTER_BACK, Direction.EXIT_BACK))
|
||||
.plus(
|
||||
-> slideAndFade(
|
||||
slideDirections = setOf(Direction.ENTER_BACK, Direction.EXIT_BACK),
|
||||
fadeDirections = emptySet(),
|
||||
).plus(
|
||||
scaleWithDirection(
|
||||
directions = setOf(Direction.ENTER_FRONT, Direction.EXIT_FRONT),
|
||||
animationSpec = tween(400),
|
||||
|
|
@ -52,28 +56,64 @@ object RoutingTransitionAnimationFactory {
|
|||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param slideDirections directions in which the horizontal slide is applied.
|
||||
* `null` (default) means slide in all directions.
|
||||
* @param fadeDirections directions in which the alpha fade is applied.
|
||||
* `null` (default) means fade in all directions. Pass `emptySet()` to disable the fade
|
||||
* entirely — useful for screens that own a `hazeEffect` (e.g. WalletTopBar's progressive
|
||||
* blur), where wrapping the screen in an animated `graphicsLayer { alpha = ... }` causes
|
||||
* a visible blink over the blurred region.
|
||||
*/
|
||||
@Suppress("MagicNumber")
|
||||
private fun slideAndFade(directions: Set<Direction>? = null): StackAnimator {
|
||||
private fun slideAndFade(
|
||||
slideDirections: Set<Direction>? = null,
|
||||
fadeDirections: Set<Direction>? = null,
|
||||
): StackAnimator {
|
||||
val easing = CubicBezierEasing(a = 0.55f, b = 0.0f, c = 0.0f, d = 1f)
|
||||
|
||||
return stackAnimator(
|
||||
val slide = stackAnimator(
|
||||
animationSpec = tween(durationMillis = 400, easing = easing),
|
||||
) { factor, direction, content ->
|
||||
content(
|
||||
if (directions == null || directions.contains(direction)) {
|
||||
if (slideDirections == null || slideDirections.contains(direction)) {
|
||||
Modifier.offsetXFactor(factor)
|
||||
} else {
|
||||
Modifier
|
||||
},
|
||||
)
|
||||
}.plus(
|
||||
fade(
|
||||
}
|
||||
|
||||
val fade = directionalFade(
|
||||
animationSpec = tween(
|
||||
delayMillis = 50,
|
||||
durationMillis = 300,
|
||||
easing = easing,
|
||||
),
|
||||
),
|
||||
directions = fadeDirections,
|
||||
)
|
||||
|
||||
return slide.plus(fade)
|
||||
}
|
||||
|
||||
/**
|
||||
* Like `decompose.fade(...)` but only applies the alpha `graphicsLayer` when `direction`
|
||||
* is in [directions]. `null` directions = always fade (matches stock `fade()` behavior).
|
||||
* `emptySet()` directions = never fade (modifier passes through untouched).
|
||||
*/
|
||||
private fun directionalFade(
|
||||
animationSpec: FiniteAnimationSpec<Float>,
|
||||
directions: Set<Direction>?,
|
||||
): StackAnimator = stackAnimator(animationSpec) { factor, direction, content ->
|
||||
content(
|
||||
if (directions == null || directions.contains(direction)) {
|
||||
Modifier.graphicsLayer {
|
||||
alpha = 1f - abs(factor)
|
||||
compositingStrategy = CompositingStrategy.Offscreen
|
||||
}
|
||||
} else {
|
||||
Modifier
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
|||
|
||||
@OptIn(ExperimentalHazeMaterialsApi::class)
|
||||
@Composable
|
||||
internal fun ProvideHaze(content: @Composable () -> Unit) {
|
||||
fun ProvideHaze(content: @Composable () -> Unit) {
|
||||
val hazeState = rememberHazeState()
|
||||
CompositionLocalProvider(
|
||||
LocalHazeState provides hazeState,
|
||||
|
|
@ -47,7 +47,7 @@ fun isHazeBlurEffectivelyEnabled(state: HazeState = LocalHazeState.current): Boo
|
|||
@Composable
|
||||
fun Modifier.hazeEffectTangem(
|
||||
state: HazeState = LocalHazeState.current,
|
||||
style: HazeStyle = HazeStyle.Unspecified,
|
||||
style: HazeStyle = CupertinoMaterials.ultraThin(),
|
||||
configure: HazeEffectScope.() -> Unit = {},
|
||||
): Modifier {
|
||||
val isGlobalBlurEnabled = isHazeBlurEffectivelyEnabled(state)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
|||
* @param modifier Modifier to be applied to the button.
|
||||
*/
|
||||
@Composable
|
||||
fun SecondaryTangemButton(buttonUM: TangemButtonUM, modifier: Modifier = Modifier) {
|
||||
fun SecondaryTangemButton(buttonUM: TangemButtonUM, modifier: Modifier = Modifier, withHazeEffect: Boolean = true) {
|
||||
SecondaryTangemButton(
|
||||
onClick = buttonUM.onClick,
|
||||
modifier = modifier,
|
||||
|
|
@ -40,6 +40,7 @@ fun SecondaryTangemButton(buttonUM: TangemButtonUM, modifier: Modifier = Modifie
|
|||
size = buttonUM.size,
|
||||
shape = buttonUM.shape,
|
||||
onLongClick = buttonUM.onLongClick,
|
||||
withHazeEffect = withHazeEffect,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -70,6 +71,7 @@ fun SecondaryTangemButton(
|
|||
size: TangemButtonSize = TangemButtonSize.X15,
|
||||
shape: TangemButtonShape = TangemButtonShape.Default,
|
||||
onLongClick: (() -> Unit)? = null,
|
||||
withHazeEffect: Boolean = true,
|
||||
) {
|
||||
val backgroundModifier = if (isEnabled) {
|
||||
Modifier.background(TangemTheme.colors2.button.backgroundSecondary)
|
||||
|
|
@ -86,7 +88,7 @@ fun SecondaryTangemButton(
|
|||
onClick = onClick,
|
||||
modifier = modifier
|
||||
.clip(shape.toShape(size))
|
||||
.hazeEffectTangem()
|
||||
.then(if (withHazeEffect) Modifier.hazeEffectTangem() else Modifier)
|
||||
.then(backgroundModifier),
|
||||
text = text,
|
||||
contentColor = contentColor,
|
||||
|
|
|
|||
|
|
@ -2,14 +2,11 @@
|
|||
|
||||
package com.tangem.core.ui.res
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.text.selection.LocalTextSelectionColors
|
||||
import androidx.compose.foundation.text.selection.TextSelectionColors
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.tangem.core.ui.components.haze.ProvideHaze
|
||||
import com.tangem.core.ui.components.haze.hazeSourceTangem
|
||||
import com.tangem.core.ui.res.generated.TangemDimens3
|
||||
import com.tangem.core.ui.res.generated.TangemTypography3
|
||||
import com.tangem.core.ui.res.generated.darkColors3
|
||||
|
|
@ -55,14 +52,12 @@ fun TangemThemeRedesign(content: @Composable () -> Unit) {
|
|||
LocalTextSelectionColors provides TangemTextSelectionColors2,
|
||||
) {
|
||||
ProvideHaze {
|
||||
Box(Modifier.hazeSourceTangem(zIndex = 1f)) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val TangemTextSelectionColors2: TextSelectionColors
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ internal fun TokenMarketBlock(tokenMarketBlockUM: TokenMarketBlockUM, modifier:
|
|||
tangemIconUM = TangemIconUM.Icon(iconRes = CoreR.drawable.ic_arrow_expand_24),
|
||||
shape = TangemButtonShape.Rounded,
|
||||
size = TangemButtonSize.X10,
|
||||
withHazeEffect = false,
|
||||
modifier = Modifier
|
||||
.layoutId(TangemRowLayoutId.TAIL)
|
||||
.padding(start = TangemTheme.dimens2.x10),
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ markdown = "0.7.2"
|
|||
markdownComposeView = "0.5.4"
|
||||
usedesk = "4.4.0"
|
||||
sumsub = "1.38.0"
|
||||
haze = "1.7.1"
|
||||
haze = "1.7.2"
|
||||
kotlinpoet = "1.18.1"
|
||||
customerio = "4.6.3"
|
||||
surveysparrow = "1.2.9"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue