From 02d660ec52c1fd69b225d8080d084df25c04ff8d Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 24 Jun 2026 22:34:11 +0000 Subject: [PATCH] Show colour swatches in Custom palette slot when colours are set Previously the Custom slot in the theme grid always showed a dashed circle with a + icon, giving no preview of the current custom palette. Now, once any custom colour has been saved, the slot displays three overlapping circles (primary, secondary, tertiary) so the user can see their palette at a glance. The dashed-circle fallback is kept for fresh installs before any colour is chosen. --- .../ui/screens/settings/SettingsScreen.kt | 91 +++++++++++++++---- .../custom-palette-colour-swatches.json | 6 ++ 2 files changed, 77 insertions(+), 20 deletions(-) create mode 100644 changelog/unreleased/custom-palette-colour-swatches.json diff --git a/app/src/main/java/com/mapgie/goflo/ui/screens/settings/SettingsScreen.kt b/app/src/main/java/com/mapgie/goflo/ui/screens/settings/SettingsScreen.kt index 0e06c12..5ad9f51 100644 --- a/app/src/main/java/com/mapgie/goflo/ui/screens/settings/SettingsScreen.kt +++ b/app/src/main/java/com/mapgie/goflo/ui/screens/settings/SettingsScreen.kt @@ -27,6 +27,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.width import androidx.compose.foundation.ScrollState import androidx.compose.foundation.rememberScrollState @@ -2069,9 +2070,12 @@ private fun CompactThemePicker( ) } else { CustomPaletteSlot( - isSelected = isCustom, - onClick = { onSelect(AppTheme.CUSTOM) }, - modifier = Modifier.weight(1f), + isSelected = isCustom, + primaryArgb = customPrimaryArgb, + secondaryArgb = customSecondaryArgb, + tertiaryArgb = customTertiaryArgb, + onClick = { onSelect(AppTheme.CUSTOM) }, + modifier = Modifier.weight(1f), ) } } @@ -2353,9 +2357,17 @@ private fun PaletteOption( // ── Custom palette slot ─────────────────────────────────────────────────────── @Composable -private fun CustomPaletteSlot(isSelected: Boolean, onClick: () -> Unit, modifier: Modifier = Modifier) { +private fun CustomPaletteSlot( + isSelected: Boolean, + primaryArgb: Int, + secondaryArgb: Int, + tertiaryArgb: Int, + onClick: () -> Unit, + modifier: Modifier = Modifier, +) { val selColor = MaterialTheme.colorScheme.primary val outlineColor = MaterialTheme.colorScheme.onSurfaceVariant + val hasColours = primaryArgb != 0 || secondaryArgb != 0 || tertiaryArgb != 0 Column( modifier = modifier @@ -2366,24 +2378,63 @@ private fun CustomPaletteSlot(isSelected: Boolean, onClick: () -> Unit, modifier verticalArrangement = Arrangement.spacedBy(4.dp) ) { Box(modifier = Modifier.size(44.dp), contentAlignment = Alignment.Center) { - Canvas(modifier = Modifier.size(40.dp)) { - val r = size.width / 2f - val strokePx = if (isSelected) 3.dp.toPx() else 1.5.dp.toPx() - drawCircle( - color = if (isSelected) selColor else outlineColor, - radius = r - strokePx / 2f, - style = Stroke( - width = strokePx, - pathEffect = PathEffect.dashPathEffect(floatArrayOf(10f, 6f), 0f), - ), + if (hasColours) { + // Show 3 overlapping colour circles when custom colours have been set + Row( + modifier = Modifier.size(40.dp), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically, + ) { + listOf(primaryArgb, secondaryArgb, tertiaryArgb).forEachIndexed { i, argb -> + Box( + modifier = Modifier + .size(14.dp) + .offset(x = ((-i) * 3).dp) + .clip(CircleShape) + .background(Color(argb)) + .border( + width = 1.dp, + color = MaterialTheme.colorScheme.outline.copy(alpha = 0.4f), + shape = CircleShape, + ) + ) + } + } + // Selection ring + Canvas(modifier = Modifier.size(40.dp)) { + val r = size.width / 2f + val strokePx = if (isSelected) 3.dp.toPx() else 1.5.dp.toPx() + drawCircle( + color = if (isSelected) selColor else outlineColor, + radius = r - strokePx / 2f, + style = Stroke( + width = strokePx, + pathEffect = if (isSelected) null + else PathEffect.dashPathEffect(floatArrayOf(10f, 6f), 0f), + ), + ) + } + } else { + // No custom colours yet: show dashed circle + add icon + Canvas(modifier = Modifier.size(40.dp)) { + val r = size.width / 2f + val strokePx = if (isSelected) 3.dp.toPx() else 1.5.dp.toPx() + drawCircle( + color = if (isSelected) selColor else outlineColor, + radius = r - strokePx / 2f, + style = Stroke( + width = strokePx, + pathEffect = PathEffect.dashPathEffect(floatArrayOf(10f, 6f), 0f), + ), + ) + } + Icon( + imageVector = Icons.Default.Add, + contentDescription = null, + tint = if (isSelected) selColor else outlineColor, + modifier = Modifier.size(20.dp) ) } - Icon( - imageVector = Icons.Default.Add, - contentDescription = null, - tint = if (isSelected) selColor else outlineColor, - modifier = Modifier.size(20.dp) - ) } Text( text = "Custom", diff --git a/changelog/unreleased/custom-palette-colour-swatches.json b/changelog/unreleased/custom-palette-colour-swatches.json new file mode 100644 index 0000000..e7b1928 --- /dev/null +++ b/changelog/unreleased/custom-palette-colour-swatches.json @@ -0,0 +1,6 @@ +{ + "bump": "patch", + "changed": [ + "Custom palette slot in the theme grid now shows three colour swatches when custom colours have been set, so you can see your current palette at a glance without tapping into it" + ] +}