From 21f488af5c22bae1d2d43725f754d47217dc363d Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Fri, 29 May 2026 11:13:29 -0400 Subject: [PATCH 1/2] refactor(theme): consolidate design system, remove legacy theme --- .../com/flipcash/app/theme/FlipcashPreview.kt | 9 +- .../com/flipcash/app/theme/FlipcashTheme.kt | 8 +- ...esignSystem.kt => FlipcashDesignSystem.kt} | 11 +- .../internal/FlipcashLegacyDesignSystem.kt | 107 ------------------ .../main/kotlin/com/getcode/theme/Color.kt | 9 ++ .../main/kotlin/com/getcode/theme/Theme.kt | 8 +- 6 files changed, 28 insertions(+), 124 deletions(-) rename apps/flipcash/shared/theme/src/main/kotlin/com/flipcash/app/theme/internal/{Flipcash2DesignSystem.kt => FlipcashDesignSystem.kt} (92%) delete mode 100644 apps/flipcash/shared/theme/src/main/kotlin/com/flipcash/app/theme/internal/FlipcashLegacyDesignSystem.kt diff --git a/apps/flipcash/shared/theme/src/main/kotlin/com/flipcash/app/theme/FlipcashPreview.kt b/apps/flipcash/shared/theme/src/main/kotlin/com/flipcash/app/theme/FlipcashPreview.kt index 81d5ce201..849ef0942 100644 --- a/apps/flipcash/shared/theme/src/main/kotlin/com/flipcash/app/theme/FlipcashPreview.kt +++ b/apps/flipcash/shared/theme/src/main/kotlin/com/flipcash/app/theme/FlipcashPreview.kt @@ -9,18 +9,15 @@ import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.tooling.preview.PreviewWrapper import androidx.compose.ui.tooling.preview.PreviewWrapperProvider import com.getcode.animation.LocalSharedTransitionScope import com.flipcash.app.theme.internal.Flipcash2DesignSystem -import com.flipcash.app.theme.internal.FlipcashLegacyDesignSystem import com.getcode.theme.CodeTheme @Deprecated("Use FlipcashThemeWrapper") @Composable fun FlipcashPreview( showBackground: Boolean = false, - useLegacyColors: Boolean = false, content: @Composable () -> Unit ) { val previewContent = @Composable { @@ -39,11 +36,7 @@ fun FlipcashPreview( } } - if (useLegacyColors) { - FlipcashLegacyDesignSystem(previewContent) - } else { - Flipcash2DesignSystem(previewContent) - } + Flipcash2DesignSystem(previewContent) } class FlipcashThemeWrapper: PreviewWrapperProvider { diff --git a/apps/flipcash/shared/theme/src/main/kotlin/com/flipcash/app/theme/FlipcashTheme.kt b/apps/flipcash/shared/theme/src/main/kotlin/com/flipcash/app/theme/FlipcashTheme.kt index f949e811d..a00cc0025 100644 --- a/apps/flipcash/shared/theme/src/main/kotlin/com/flipcash/app/theme/FlipcashTheme.kt +++ b/apps/flipcash/shared/theme/src/main/kotlin/com/flipcash/app/theme/FlipcashTheme.kt @@ -2,16 +2,10 @@ package com.flipcash.app.theme import androidx.compose.runtime.Composable import com.flipcash.app.theme.internal.Flipcash2DesignSystem -import com.flipcash.app.theme.internal.FlipcashLegacyDesignSystem @Composable fun FlipcashTheme( - useLegacyColors: Boolean = false, content: @Composable () -> Unit, ) { - if (useLegacyColors) { - FlipcashLegacyDesignSystem(content) - } else { - Flipcash2DesignSystem(content) - } + Flipcash2DesignSystem(content) } \ No newline at end of file diff --git a/apps/flipcash/shared/theme/src/main/kotlin/com/flipcash/app/theme/internal/Flipcash2DesignSystem.kt b/apps/flipcash/shared/theme/src/main/kotlin/com/flipcash/app/theme/internal/FlipcashDesignSystem.kt similarity index 92% rename from apps/flipcash/shared/theme/src/main/kotlin/com/flipcash/app/theme/internal/Flipcash2DesignSystem.kt rename to apps/flipcash/shared/theme/src/main/kotlin/com/flipcash/app/theme/internal/FlipcashDesignSystem.kt index cbe2a0720..09798c901 100644 --- a/apps/flipcash/shared/theme/src/main/kotlin/com/flipcash/app/theme/internal/Flipcash2DesignSystem.kt +++ b/apps/flipcash/shared/theme/src/main/kotlin/com/flipcash/app/theme/internal/FlipcashDesignSystem.kt @@ -52,6 +52,14 @@ object Flipcash2ColorSpec { borderColor = null, borderWidth = 0f, ) + val contactAvatar = GradientSpec( + background = Color.Black, + colors = listOf( + Color(0xFF414141), + Color(0xFF202020) + ), + stops = listOf(0f, 1f) + ) } private val colors = with(Flipcash2ColorSpec) { @@ -94,7 +102,8 @@ private val colors = with(Flipcash2ColorSpec) { bannerWarning = Warning, bannerSuccess = BannerSuccess, scrim = Black40, - accessKey = accessKey + accessKey = accessKey, + contactAvatar = contactAvatar, ) } @Composable diff --git a/apps/flipcash/shared/theme/src/main/kotlin/com/flipcash/app/theme/internal/FlipcashLegacyDesignSystem.kt b/apps/flipcash/shared/theme/src/main/kotlin/com/flipcash/app/theme/internal/FlipcashLegacyDesignSystem.kt deleted file mode 100644 index 0e8e75abc..000000000 --- a/apps/flipcash/shared/theme/src/main/kotlin/com/flipcash/app/theme/internal/FlipcashLegacyDesignSystem.kt +++ /dev/null @@ -1,107 +0,0 @@ -package com.flipcash.app.theme.internal - -import androidx.compose.runtime.Composable -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.font.FontWeight -import com.getcode.theme.BannerSuccess -import com.getcode.theme.BetaIndicator -import com.getcode.theme.Black40 -import com.getcode.theme.BrandAccent -import com.getcode.theme.BrandDark -import com.getcode.theme.BrandIndicator -import com.getcode.theme.BrandMuted -import com.getcode.theme.BrandOverlay -import com.getcode.theme.ColorScheme -import com.getcode.theme.DesignSystem -import com.getcode.theme.Error -import com.getcode.theme.GradientSpec -import com.getcode.theme.Gray50 -import com.getcode.theme.TextError -import com.getcode.theme.Warning -import com.getcode.theme.White -import com.getcode.theme.White05 -import com.getcode.theme.White08 -import com.getcode.theme.White10 -import com.getcode.theme.White50 -import com.getcode.theme.codeTypography - -object FlipcashColorSpec { - val primary = Color(0xFF001A0C) - val primaryLight = Color(0xFF09550B) - val secondary = Color(115, 129, 121) - val secondaryText = Color.White.copy(alpha = 0.5f) - val cashBill = Color(0xFF06450F) - val trackColor = Color.White.copy(alpha = 0.07f) - val bannerThemed = Color(0xFF1A3125) - val success = Color(0xFF1AC86A) - val successText = Color(0xFF73EAA4) - val surfaceVariant = Color.White.copy(alpha = 0.12f) - val errorSurface = Color(0x4AE75454) - val accessKey = GradientSpec( - background = primary, - colors = listOf( - Color(0xFF001A0C), - Color(0xFF042005), - Color(0xFF0C291A), - Color(0xFF004602), - Color(0xFF004602), - ), - stops = listOf(0f, 0.3f, 0.6f, 1f) - ) -} - -private val colors = with(FlipcashColorSpec) { - ColorScheme( - brand = primary, - brandLight = primaryLight, - brandSubtle = secondary, - brandMuted = BrandMuted, - brandDark = BrandDark, - brandOverlay = BrandOverlay, - brandContainer = primary, - secondary = secondary, - tertiary = BrandAccent, - indicator = BrandIndicator, - action = Gray50, - onAction = White, - background = primary, - onBackground = White, - surface = primary, - surfaceVariant = surfaceVariant, - surfaceError = errorSurface, - onSurface = White, - error = Error, - errorText = TextError, - success = success, - successText = success, - textMain = Color.White, - textSecondary = secondaryText, - textTertiary = White50, - border = White08, - divider = White10, - dividerVariant = White05, - trackColor = trackColor, - toggleUncheckedTrackColor = secondary, - cashBill = cashBill, - cashBillDecorColor = Color.White.copy(0.60f), - betaIndicator = BetaIndicator, - bannerThemed = bannerThemed, - bannerError = Error, - bannerWarning = Warning, - bannerSuccess = BannerSuccess, - scrim = Black40, - accessKey = accessKey, - ) -} - -@Composable -internal fun FlipcashLegacyDesignSystem(content: @Composable () -> Unit) { - DesignSystem( - colorScheme = colors, - // override code type system to make screen title's slightly bigger - typography = codeTypography.copy( - screenTitle = codeTypography.displayExtraSmall.copy(fontWeight = FontWeight.W500) - ), - content = content - ) -} diff --git a/ui/theme/src/main/kotlin/com/getcode/theme/Color.kt b/ui/theme/src/main/kotlin/com/getcode/theme/Color.kt index f6cbcd1a2..323b39e12 100644 --- a/ui/theme/src/main/kotlin/com/getcode/theme/Color.kt +++ b/ui/theme/src/main/kotlin/com/getcode/theme/Color.kt @@ -68,6 +68,15 @@ val CodeAccessKey = GradientSpec( stops = listOf(0f, 0.3f, 0.6f, 1f) ) +val CodeContactAvatar = GradientSpec( + background = Brand, + colors = listOf( + Color(0xFF4A5568), + Color(0xFF6B7A90), + ), + stops = listOf(0f, 1f) +) + data class GradientSpec( val background: Color, val colors: List, diff --git a/ui/theme/src/main/kotlin/com/getcode/theme/Theme.kt b/ui/theme/src/main/kotlin/com/getcode/theme/Theme.kt index 6d3aaf7b7..1325a2b99 100644 --- a/ui/theme/src/main/kotlin/com/getcode/theme/Theme.kt +++ b/ui/theme/src/main/kotlin/com/getcode/theme/Theme.kt @@ -58,6 +58,7 @@ internal val CodeDefaultColorScheme = ColorScheme( bannerSuccess = BannerSuccess, scrim = Black40, accessKey = CodeAccessKey, + contactAvatar = CodeContactAvatar, ) @Composable @@ -148,6 +149,7 @@ class ColorScheme( bannerSuccess: Color, scrim: Color, accessKey: GradientSpec, + contactAvatar: GradientSpec, ) { var brand by mutableStateOf(brand) private set @@ -230,6 +232,8 @@ class ColorScheme( var accessKey by mutableStateOf(accessKey) private set + var contactAvatar by mutableStateOf(contactAvatar) + private set fun update(other: ColorScheme) { @@ -272,6 +276,7 @@ class ColorScheme( bannerSuccess = other.bannerSuccess scrim = other.scrim accessKey = other.accessKey + contactAvatar = other.contactAvatar } fun copy(): ColorScheme = ColorScheme( @@ -314,6 +319,7 @@ class ColorScheme( bannerSuccess = bannerSuccess, scrim = scrim, accessKey = accessKey, + contactAvatar = contactAvatar, ) } @@ -361,7 +367,7 @@ fun inputColors( borderColor: Color = CodeTheme.colors.border, unfocusedBorderColor: Color = borderColor, backgroundColor: Color = White05, - placeholderColor: Color = CodeTheme.colors.textTertiary, + placeholderColor: Color = CodeTheme.colors.textSecondary, cursorColor: Color = Color.White, errorBorderColor: Color = CodeTheme.colors.error, ) = TextFieldDefaults.outlinedTextFieldColors( From 3d50a81d784f2656a3b2b838b046544af8fdb5e5 Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Fri, 29 May 2026 11:15:20 -0400 Subject: [PATCH 2/2] fix(navigation): use qualifiedName strings for FlowHost saved state KClass references aren't serializable and can't survive rememberSaveable across process death. Use qualifiedName strings instead so the seeded-stack comparison works after restoration. --- .../src/main/kotlin/com/getcode/navigation/flow/FlowHost.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/navigation/src/main/kotlin/com/getcode/navigation/flow/FlowHost.kt b/ui/navigation/src/main/kotlin/com/getcode/navigation/flow/FlowHost.kt index afc3dc1f6..e97c0133d 100644 --- a/ui/navigation/src/main/kotlin/com/getcode/navigation/flow/FlowHost.kt +++ b/ui/navigation/src/main/kotlin/com/getcode/navigation/flow/FlowHost.kt @@ -223,12 +223,12 @@ private fun FlowHostImpl( // We track what was seeded and only re-seed if the backstack is still untouched. // Animation is suppressed during re-seed so NavDisplay doesn't slide between // the stale and corrected content. - val seededStack = remember { initialStack.map { it::class } } - val currentInitialClasses = initialStack.map { it::class } + val seededStack = rememberSaveable { initialStack.map { it::class.qualifiedName } } + val currentInitialClasses = initialStack.map { it::class.qualifiedName } val suppressTransition = remember { mutableStateOf(false) } LaunchedEffect(currentInitialClasses) { if (currentInitialClasses == seededStack) return@LaunchedEffect - val backstackClasses = innerBackStack.map { it::class } + val backstackClasses = innerBackStack.map { it::class.qualifiedName } if (backstackClasses != seededStack) return@LaunchedEffect suppressTransition.value = true Snapshot.withMutableSnapshot {