diff --git a/apps/flipcash/features/scanner/src/main/kotlin/com/flipcash/app/scanner/internal/bills/ScannableContainer.kt b/apps/flipcash/features/scanner/src/main/kotlin/com/flipcash/app/scanner/internal/bills/ScannableContainer.kt index 801b1fd23..901a168e0 100644 --- a/apps/flipcash/features/scanner/src/main/kotlin/com/flipcash/app/scanner/internal/bills/ScannableContainer.kt +++ b/apps/flipcash/features/scanner/src/main/kotlin/com/flipcash/app/scanner/internal/bills/ScannableContainer.kt @@ -44,6 +44,8 @@ import com.flipcash.app.bills.components.cards.LocalTipCardBackdrop import com.flipcash.app.bills.components.cards.LocalTipCardBaseAlpha import com.flipcash.app.bills.components.cards.LocalTipCardColor import com.flipcash.app.bills.components.cards.TipCardOpaqueFallback +import com.flipcash.app.featureflags.FeatureFlag +import com.flipcash.app.featureflags.LocalFeatureFlags import com.flipcash.app.core.android.extensions.launchAppSettings import com.flipcash.app.core.bill.Scannable import com.flipcash.app.core.tipping.LocalTipCoordinator @@ -128,10 +130,15 @@ internal fun ScannableContainer( // The frosted camera backdrop snapshots the feed (a GPU→CPU readback). Gate it to devices that // can absorb that — API 31+ for the blur, and not low-RAM. Everywhere else the card falls back // to an opaque approximation of the frosted tone. - val supportsFrostedTipCard = remember { + val deviceSupportsFrostedTipCard = remember { Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && context.getSystemService(ActivityManager::class.java)?.isLowRamDevice != true } + // Also gated behind a beta flag (off by default); the opaque fallback is used when it's disabled. + val frostedTipCardFlagEnabled by LocalFeatureFlags.current + .observe(FeatureFlag.FrostedTipCard) + .collectAsStateWithLifecycle() + val frostedTipCardEnabled = deviceSupportsFrostedTipCard && frostedTipCardFlagEnabled OnLifecycleEvent { _, event -> if (event == Lifecycle.Event.ON_STOP && !autoStart) { @@ -292,18 +299,19 @@ internal fun ScannableContainer( val isTipCard = updatedBillState.bill is Scannable.TipCard val tipCardBackdrop = rememberCameraTipCardBackdrop( previewView = previewView, - enabled = isTipCard && supportsFrostedTipCard, + enabled = isTipCard && frostedTipCardEnabled, containerOriginInWindow = containerOriginInWindow, ) - // Where the frosted backdrop is unavailable, render the tip card as an opaque approximation - // of the frosted tone instead of a translucent panel over the (stutter-prone) live camera. - val useOpaqueFallback = isTipCard && !supportsFrostedTipCard + // Where the frosted backdrop is unavailable (incapable device or the beta flag is off), + // render the tip card as an opaque approximation of the frosted tone instead of a + // translucent panel over the (stutter-prone) live camera. + val useOpaqueFallback = isTipCard && !frostedTipCardEnabled CompositionLocalProvider( LocalTipCardBackdrop provides tipCardBackdrop, LocalTipCardColor provides if (useOpaqueFallback) TipCardOpaqueFallback else Color.Unspecified, - LocalTipCardBaseAlpha provides if (useOpaqueFallback) 1f else LocalTipCardBaseAlpha.current, + LocalTipCardBaseAlpha provides if (useOpaqueFallback) 1f else 0.45f, ) { AnimatedScannable( modifier = Modifier.fillMaxSize(), diff --git a/apps/flipcash/shared/bills/src/main/kotlin/com/flipcash/app/bills/components/cards/TipCard.kt b/apps/flipcash/shared/bills/src/main/kotlin/com/flipcash/app/bills/components/cards/TipCard.kt index 62bf75c36..2c2fdcfa8 100644 --- a/apps/flipcash/shared/bills/src/main/kotlin/com/flipcash/app/bills/components/cards/TipCard.kt +++ b/apps/flipcash/shared/bills/src/main/kotlin/com/flipcash/app/bills/components/cards/TipCard.kt @@ -55,7 +55,7 @@ val LocalTipCardBackdrop = staticCompositionLocalOf<(@Composable BoxScope.() -> /** Blur radius used for the card's backdrop, tuned to read like the design's 40px background blur. */ -val TipCardBlurRadius: Dp = 24.dp +val TipCardBlurRadius: Dp = 16.dp /** * Base tint color for the card. Defaults to the theme's tip-card color; overridden on the opaque diff --git a/apps/flipcash/shared/featureflags/src/main/kotlin/com/flipcash/app/featureflags/FeatureFlag.kt b/apps/flipcash/shared/featureflags/src/main/kotlin/com/flipcash/app/featureflags/FeatureFlag.kt index 7c0b7226a..2bca1bf91 100644 --- a/apps/flipcash/shared/featureflags/src/main/kotlin/com/flipcash/app/featureflags/FeatureFlag.kt +++ b/apps/flipcash/shared/featureflags/src/main/kotlin/com/flipcash/app/featureflags/FeatureFlag.kt @@ -267,6 +267,16 @@ sealed interface FeatureFlag { override val minTrack: FeatureTrack = FeatureTrack.Production } + @FeatureFlagMarker + data object FrostedTipCard: FeatureFlag { + override val key: String = "frosted_tip_card_enabled" + override val default: Boolean = false + override val launched: Boolean = false + override val visible: Boolean = true + override val persistLogOut: Boolean = false + override val minTrack: FeatureTrack = FeatureTrack.Beta + } + companion object { val entries: List> get() = FeatureFlagEntries.entries @@ -305,6 +315,7 @@ val FeatureFlag<*>.title: String FeatureFlag.AddMoneyUX -> "Add Money UX" FeatureFlag.ShowNetworkState -> "Network Offline Indicator" FeatureFlag.Tipping -> "Tipping" + FeatureFlag.FrostedTipCard -> "Frosted Tip Card" } val FeatureFlag<*>.message: String @@ -334,6 +345,7 @@ val FeatureFlag<*>.message: String FeatureFlag.AddMoneyUX -> "When enabled, the user experience for getting money into the app will be focused around 'Adding Money'" FeatureFlag.ShowNetworkState -> "When enabled, you'll gain the ability to see the network state on the Scanner when offline" FeatureFlag.Tipping -> "When enabled, you'll gain the ability to tip other users and set up your own tip card to receive tips" + FeatureFlag.FrostedTipCard -> "When enabled, the tip card in the scanner renders as frosted glass over a blurred snapshot of the camera instead of a solid card" }