diff --git a/apps/flipcash/core-ui/src/main/kotlin/com/flipcash/app/core/ui/NavigationBar.kt b/apps/flipcash/core-ui/src/main/kotlin/com/flipcash/app/core/ui/NavigationBar.kt index bcd059a7cf..2afb423a14 100644 --- a/apps/flipcash/core-ui/src/main/kotlin/com/flipcash/app/core/ui/NavigationBar.kt +++ b/apps/flipcash/core-ui/src/main/kotlin/com/flipcash/app/core/ui/NavigationBar.kt @@ -67,11 +67,11 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEach import androidx.compose.ui.zIndex import com.flipcash.app.core.navigation.NavBarButton +import dev.chrisbanes.haze.HazeInput import dev.chrisbanes.haze.HazeState import dev.chrisbanes.haze.blur.HazeBlurStyle import dev.chrisbanes.haze.blur.HazeColorEffect -import dev.chrisbanes.haze.blur.blurEffect -import dev.chrisbanes.haze.hazeEffect +import dev.chrisbanes.haze.blur.hazeBlur import com.flipcash.app.core.navigation.NavBarConfig import com.flipcash.app.theme.FlipcashThemeWrapper import com.flipcash.core.R @@ -271,22 +271,24 @@ private fun NavigationBarV2( // content the pill just reads as the background (a subtle glass, not a black blob); over the // vibrant cards the high alpha mutes their colour toward that same neutral dark. A faint bright // rim gives the glass edge. Haze can only blur Compose-layer pixels, so on the scanner tab (a - // camera SurfaceView) fall back to the opaque pill. `clip` must precede `hazeEffect` to bound the + // camera SurfaceView) fall back to the opaque pill. `clip` must precede `hazeBlur` to bound the // blur to the pill shape, not its bounding box. // Tint toward a grey lifted off the (near-black) background so the pill reads as a light frosted // glass sitting ABOVE the dark content, not the background tone itself. - val glassTint = lerp(CodeTheme.colors.background, Color.White, 0.18f) - val liquidGlass = HazeBlurStyle( - blurRadius = 32.dp, - backgroundColor = CodeTheme.colors.background, - colorEffect = HazeColorEffect.tint(glassTint.copy(alpha = 0.72f)), - ) + val backdrop = CodeTheme.colors.background + val glassTint = lerp(backdrop, Color.White, 0.18f) + // The HazeBlurStyle builder is not a @Composable scope, so theme reads are hoisted above it. + val liquidGlass = HazeBlurStyle { + blurRadius(32.dp) + backgroundColor(backdrop) + colorEffects(listOf(HazeColorEffect.tint(glassTint.copy(alpha = 0.72f)))) + } // Same clip + rim on every tab; only the fill differs. Haze frosts the content beneath — including // the scanner's live camera, since its PreviewView runs in COMPATIBLE mode (a TextureView drawn in // the Compose layer, not a SurfaceView hole). Fall back to a near-opaque fill of the same // lifted-grey tint only when no HazeState is supplied. val pillFill = if (hazeState != null) { - Modifier.hazeEffect(hazeState) { blurEffect { style = liquidGlass } } + Modifier.hazeBlur(HazeInput.Sources(hazeState), liquidGlass) } else { Modifier.background(glassTint.copy(alpha = 0.9f), CircleShape) } diff --git a/apps/flipcash/features/messenger/src/main/kotlin/com/flipcash/app/messenger/internal/screens/components/ChatBottomBar.kt b/apps/flipcash/features/messenger/src/main/kotlin/com/flipcash/app/messenger/internal/screens/components/ChatBottomBar.kt index 4e22a06a82..eb5cb876f9 100644 --- a/apps/flipcash/features/messenger/src/main/kotlin/com/flipcash/app/messenger/internal/screens/components/ChatBottomBar.kt +++ b/apps/flipcash/features/messenger/src/main/kotlin/com/flipcash/app/messenger/internal/screens/components/ChatBottomBar.kt @@ -44,10 +44,10 @@ import com.getcode.ui.components.chat.TypingIndicator import com.getcode.ui.core.drawWithGradient import com.getcode.ui.core.measured import com.getcode.ui.utils.rememberKeyboardController +import dev.chrisbanes.haze.HazeInput import dev.chrisbanes.haze.HazeState -import dev.chrisbanes.haze.blur.blurEffect +import dev.chrisbanes.haze.blur.hazeBlur import dev.chrisbanes.haze.blur.materials.HazeMaterials -import dev.chrisbanes.haze.hazeEffect @Composable internal fun UserControlBottomBar( @@ -96,9 +96,7 @@ internal fun UserControlBottomBar( if (show) { TypingIndicator( modifier = Modifier - .hazeEffect(hazeState) { - blurEffect { style = material } - }, + .hazeBlur(HazeInput.Sources(hazeState), material), ) } } @@ -177,11 +175,7 @@ internal fun UserControlBottomBar( CodeTheme.colors.divider, CodeTheme.shapes.medium, ) - .hazeEffect(hazeState) { - blurEffect { - style = material - } - }, + .hazeBlur(HazeInput.Sources(hazeState), material), focusRequester = focusRequester, hint = "Message", state = state.chatInputState, diff --git a/apps/flipcash/features/messenger/src/main/kotlin/com/flipcash/app/messenger/internal/screens/components/SendCashButton.kt b/apps/flipcash/features/messenger/src/main/kotlin/com/flipcash/app/messenger/internal/screens/components/SendCashButton.kt index 4ea96d4d11..a37649d85d 100644 --- a/apps/flipcash/features/messenger/src/main/kotlin/com/flipcash/app/messenger/internal/screens/components/SendCashButton.kt +++ b/apps/flipcash/features/messenger/src/main/kotlin/com/flipcash/app/messenger/internal/screens/components/SendCashButton.kt @@ -40,10 +40,10 @@ import com.flipcash.services.models.chat.ChatType import com.flipcash.features.messenger.R import com.getcode.theme.CodeTheme import com.getcode.ui.core.addIf +import dev.chrisbanes.haze.HazeInput import dev.chrisbanes.haze.HazeState import dev.chrisbanes.haze.blur.HazeBlurStyle -import dev.chrisbanes.haze.blur.blurEffect -import dev.chrisbanes.haze.hazeEffect +import dev.chrisbanes.haze.blur.hazeBlur @Composable internal fun RowScope.SendCashButton( @@ -122,7 +122,7 @@ internal fun RowScope.SendCashButton( .clip(shape) // Haze sits under the fill — hidden while the background is opaque white, revealed // naturally as the background eases to transparent when typing begins. - .hazeEffect(hazeState) { blurEffect { style = hazeMaterial } } + .hazeBlur(HazeInput.Sources(hazeState), hazeMaterial) .background(backgroundColor, shape) .border(CodeTheme.dimens.border, borderColor, shape) .clickable(onClick = onClick) diff --git a/apps/flipcash/features/tokens/src/main/kotlin/com/flipcash/app/tokens/internal/components/info/CurrencyInfoContentV2.kt b/apps/flipcash/features/tokens/src/main/kotlin/com/flipcash/app/tokens/internal/components/info/CurrencyInfoContentV2.kt index 2bc03e946d..95b07c93db 100644 --- a/apps/flipcash/features/tokens/src/main/kotlin/com/flipcash/app/tokens/internal/components/info/CurrencyInfoContentV2.kt +++ b/apps/flipcash/features/tokens/src/main/kotlin/com/flipcash/app/tokens/internal/components/info/CurrencyInfoContentV2.kt @@ -70,12 +70,12 @@ import com.getcode.theme.extraSmall import com.getcode.ui.components.text.ExpandableText import com.getcode.ui.core.addIf import com.getcode.ui.theme.CodeCircularProgressIndicator +import dev.chrisbanes.haze.HazeInput import dev.chrisbanes.haze.HazeState -import dev.chrisbanes.haze.hazeEffect -import dev.chrisbanes.haze.hazeSource import dev.chrisbanes.haze.blur.HazeBlurStyle import dev.chrisbanes.haze.blur.HazeColorEffect -import dev.chrisbanes.haze.blur.blurEffect +import dev.chrisbanes.haze.blur.hazeBlur +import dev.chrisbanes.haze.hazeSource import com.getcode.util.format /** @@ -503,18 +503,21 @@ internal fun CurrencyInfoTitlePill( hazeState: HazeState? = null, ) { val shape = CircleShape - val glassTint = lerp(CodeTheme.colors.background, Color.White, 0.18f) + val backdrop = CodeTheme.colors.background + val glassBlurRadius = CodeTheme.dimens.grid.x4 + val glassTint = lerp(backdrop, Color.White, 0.18f) // Real liquid glass over the scrolling content when a HazeState is supplied; falls back to a - // translucent capsule otherwise. `clip` precedes `hazeEffect` so the blur is bounded to the pill. + // translucent capsule otherwise. `clip` precedes `hazeBlur` so the blur is bounded to the pill. val fill = if (hazeState != null) { - val liquidGlass = HazeBlurStyle( - blurRadius = CodeTheme.dimens.grid.x4, - backgroundColor = CodeTheme.colors.background, - colorEffect = HazeColorEffect.tint(glassTint.copy(alpha = 0.72f)), - ) + // The HazeBlurStyle builder is not a @Composable scope, so theme reads are hoisted above it. + val liquidGlass = HazeBlurStyle { + blurRadius(glassBlurRadius) + backgroundColor(backdrop) + colorEffects(listOf(HazeColorEffect.tint(glassTint.copy(alpha = 0.72f)))) + } Modifier .clip(shape) - .hazeEffect(hazeState) { blurEffect { style = liquidGlass } } + .hazeBlur(HazeInput.Sources(hazeState), liquidGlass) .border(CodeTheme.dimens.border, Color.White.copy(alpha = 0.08f), shape) } else { Modifier diff --git a/apps/flipcash/shared/tokens/src/main/kotlin/com/flipcash/app/tokens/ui/CurrencyCreatorUpsellCard.kt b/apps/flipcash/shared/tokens/src/main/kotlin/com/flipcash/app/tokens/ui/CurrencyCreatorUpsellCard.kt index 0259132827..6181a246b8 100644 --- a/apps/flipcash/shared/tokens/src/main/kotlin/com/flipcash/app/tokens/ui/CurrencyCreatorUpsellCard.kt +++ b/apps/flipcash/shared/tokens/src/main/kotlin/com/flipcash/app/tokens/ui/CurrencyCreatorUpsellCard.kt @@ -31,11 +31,11 @@ import com.flipcash.app.theme.FlipcashThemeWrapper import com.flipcash.app.theme.MultiDevicePreview import com.flipcash.shared.tokens.R import com.getcode.theme.CodeTheme +import dev.chrisbanes.haze.HazeInput import dev.chrisbanes.haze.HazeState import dev.chrisbanes.haze.blur.HazeBlurStyle import dev.chrisbanes.haze.blur.HazeColorEffect -import dev.chrisbanes.haze.blur.blurEffect -import dev.chrisbanes.haze.hazeEffect +import dev.chrisbanes.haze.blur.hazeBlur @Composable fun CurrencyCreatorUpsellCard( @@ -48,18 +48,20 @@ fun CurrencyCreatorUpsellCard( // When a HazeState is supplied the card frosts whatever list content scrolls beneath it (iOS // "liquid glass"), matching the v2 navigation pill: a wide blur plus a strong tint toward the // BACKGROUND colour at high alpha, finished with a faint bright rim. `clip` must precede - // `hazeEffect` so the blur is bounded to the rounded card, not its bounding box. Falls back to the + // `hazeBlur` so the blur is bounded to the rounded card, not its bounding box. Falls back to the // opaque surface when no HazeState is supplied (e.g. when the card is itself part of the list). - val glassTint = lerp(CodeTheme.colors.background, Color.White, 0.18f) - val liquidGlass = HazeBlurStyle( - blurRadius = 32.dp, - backgroundColor = CodeTheme.colors.background, - colorEffect = HazeColorEffect.tint(glassTint.copy(alpha = 0.72f)), - ) + val backdrop = CodeTheme.colors.background + val glassTint = lerp(backdrop, Color.White, 0.18f) + // The HazeBlurStyle builder is not a @Composable scope, so theme reads are hoisted above it. + val liquidGlass = HazeBlurStyle { + blurRadius(32.dp) + backgroundColor(backdrop) + colorEffects(listOf(HazeColorEffect.tint(glassTint.copy(alpha = 0.72f)))) + } val glassBackground = if (hazeState != null) { Modifier .clip(shape) - .hazeEffect(hazeState) { blurEffect { style = liquidGlass } } + .hazeBlur(HazeInput.Sources(hazeState), liquidGlass) .border(CodeTheme.dimens.border, Color.White.copy(alpha = 0.08f), shape) } else { Modifier diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0dd454b9ce..5bdb3a7223 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -94,7 +94,7 @@ bugsnag = "6.26.1" bugsnag-gradle-plugin = "1.2.0" rinku = "1.6.0" compose-unstyled = "2.9.0" -haze = "2.0.0-alpha03" +haze = "2.0.0-beta01" phantom-connect-kmp = "2.0.2-1.0.1" vico = "3.2.3" diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/BlurredContent.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/BlurredContent.kt index 65d102c774..cb836707fe 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/BlurredContent.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/BlurredContent.kt @@ -10,9 +10,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import com.getcode.theme.CodeTheme -import dev.chrisbanes.haze.blur.blurEffect +import dev.chrisbanes.haze.HazeInput +import dev.chrisbanes.haze.blur.hazeBlur import dev.chrisbanes.haze.blur.materials.HazeMaterials -import dev.chrisbanes.haze.hazeEffect import dev.chrisbanes.haze.hazeSource import dev.chrisbanes.haze.rememberHazeState @@ -40,12 +40,10 @@ fun BlurredContent( Box( Modifier .matchParentSize() - .hazeEffect(hazeState) { - blurEffect { - this.blurRadius = blurRadius - style = material - } - } + .hazeBlur( + input = HazeInput.Sources(hazeState), + style = material.then { blurRadius(blurRadius) }, + ) ) } } diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/CircularIconButton.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/CircularIconButton.kt index 4109437562..e407244c31 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/CircularIconButton.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/CircularIconButton.kt @@ -17,11 +17,11 @@ import androidx.compose.ui.unit.dp import com.getcode.ui.components.AppBarDefaults.IconSize import androidx.compose.foundation.clickable import com.getcode.theme.CodeTheme +import dev.chrisbanes.haze.HazeInput import dev.chrisbanes.haze.HazeState import dev.chrisbanes.haze.blur.HazeBlurStyle import dev.chrisbanes.haze.blur.HazeColorEffect -import dev.chrisbanes.haze.blur.blurEffect -import dev.chrisbanes.haze.hazeEffect +import dev.chrisbanes.haze.blur.hazeBlur private val ButtonSize: Dp @Composable get() = CodeTheme.dimens.staticGrid.x8 @@ -39,18 +39,21 @@ fun CircularIconButton( content: @Composable (Dp) -> Unit, ) { // When a HazeState is supplied the button frosts whatever content scrolls beneath the app bar - // (iOS "liquid glass"), matching the v2 nav pill; `clip` precedes `hazeEffect` so the blur is + // (iOS "liquid glass"), matching the v2 nav pill; `clip` precedes `hazeBlur` so the blur is // bounded to the circle. Falls back to the flat translucent fill when no HazeState is supplied. val fill = if (hazeState != null) { - val glassTint = lerp(CodeTheme.colors.background, Color.White, 0.18f) - val liquidGlass = HazeBlurStyle( - blurRadius = CodeTheme.dimens.grid.x4, - backgroundColor = CodeTheme.colors.background, - colorEffect = HazeColorEffect.tint(glassTint.copy(alpha = 0.72f)), - ) + val backdrop = CodeTheme.colors.background + val glassBlurRadius = CodeTheme.dimens.grid.x4 + val glassTint = lerp(backdrop, Color.White, 0.18f) + // The HazeBlurStyle builder is not a @Composable scope, so theme reads are hoisted above it. + val liquidGlass = HazeBlurStyle { + blurRadius(glassBlurRadius) + backgroundColor(backdrop) + colorEffects(listOf(HazeColorEffect.tint(glassTint.copy(alpha = 0.72f)))) + } Modifier .clip(CircleShape) - .hazeEffect(hazeState) { blurEffect { style = liquidGlass } } + .hazeBlur(HazeInput.Sources(hazeState), liquidGlass) .border(CodeTheme.dimens.border, Color.White.copy(alpha = 0.08f), CircleShape) } else { Modifier