@@ -153,14 +153,17 @@ private fun MainScreen(state: WatchState, accent: Color) {
153153 )
154154 Spacer (Modifier .width(3 .dp))
155155 }
156+ val useAccent = state.accentKey != " default"
156157 Text (
157158 text = " %.0f" .format(WatchUnits .speed(state.speedKmh, state.imperialUnits)),
158159 fontSize = speedFontSp,
159160 fontWeight = FontWeight .Bold ,
160- // The gauge band already encodes the safety zones via
161- // green/yellow/red. The speed glyph follows the user's
162- // accent so the watch identity matches their phone.
163- color = accent
161+ // Default accent → tier coloring (green/yellow/orange/red)
162+ // so the watch matches the phone dashboard's "rainbow"
163+ // mode. Any other accent → wear that accent so the
164+ // watch identity stays consistent with the phone's pick.
165+ color = if (useAccent) accent
166+ else speedTierColor(state.speedKmh, maxSpeed)
164167 )
165168 if (state.showSpeedUnit) {
166169 Spacer (Modifier .width(3 .dp))
@@ -227,6 +230,8 @@ private fun MainScreen(state: WatchState, accent: Color) {
227230 phonePercent = state.phoneBatteryPercent.takeIf { state.showPhoneBattery },
228231 watchPercent = watchPercent.takeIf { state.showWatchBattery },
229232 showWheelChip = state.showWheelBattery,
233+ accent = accent,
234+ useAccentTint = state.accentKey != " default" ,
230235 fontSize = batteryFontSp,
231236 iconSize = batteryIconDp,
232237 spacing = batterySpacingDp
@@ -280,6 +285,8 @@ private fun BatteryRow(
280285 phonePercent : Int? ,
281286 watchPercent : Int? ,
282287 showWheelChip : Boolean ,
288+ accent : Color ,
289+ useAccentTint : Boolean ,
283290 fontSize : TextUnit ,
284291 iconSize : Dp ,
285292 spacing : Dp
@@ -292,10 +299,10 @@ private fun BatteryRow(
292299 // an em-dash so the row layout stays put rather than collapsing the
293300 // moment a wheel drops out.
294301 if (showWheelChip) {
295- BatteryChip (Icons .Filled .ElectricScooter , wheelPercent, fontSize, iconSize)
302+ BatteryChip (Icons .Filled .ElectricScooter , wheelPercent, accent, useAccentTint, fontSize, iconSize)
296303 }
297- phonePercent?.let { BatteryChip (Icons .Filled .PhoneAndroid , it, fontSize, iconSize) }
298- watchPercent?.let { BatteryChip (Icons .Filled .Watch , it, fontSize, iconSize) }
304+ phonePercent?.let { BatteryChip (Icons .Filled .PhoneAndroid , it, accent, useAccentTint, fontSize, iconSize) }
305+ watchPercent?.let { BatteryChip (Icons .Filled .Watch , it, accent, useAccentTint, fontSize, iconSize) }
299306 }
300307}
301308
@@ -307,8 +314,22 @@ private fun pwmTierColor(percent: Float): Color = when {
307314}
308315
309316@Composable
310- private fun BatteryChip (icon : ImageVector , percent : Int? , fontSize : TextUnit , iconSize : Dp ) {
311- val tint = if (percent != null ) batteryTint(percent) else Color (0xFF606060 )
317+ private fun BatteryChip (
318+ icon : ImageVector ,
319+ percent : Int? ,
320+ accent : Color ,
321+ useAccentTint : Boolean ,
322+ fontSize : TextUnit ,
323+ iconSize : Dp
324+ ) {
325+ // Default accent → tier coloring (green / amber / red) so the rider
326+ // gets a glanceable sense of remaining range. Any other accent →
327+ // the chip wears the accent so the watch identity stays consistent.
328+ val tint = when {
329+ percent == null -> Color (0xFF606060 )
330+ useAccentTint -> accent
331+ else -> batteryTint(percent)
332+ }
312333 Row (verticalAlignment = Alignment .CenterVertically ) {
313334 Icon (
314335 imageVector = icon,
@@ -336,47 +357,49 @@ private fun batteryTint(percent: Int): Color = when {
336357@Composable
337358private fun ActionRow (state : WatchState , accent : Color , buttonSize : Dp , iconSize : Dp ) {
338359 val context = LocalContext .current
339- val enabled = state.connected
340- // Use the same dim grey as the phone dashboard's grayed action tiles so
341- // disconnected reads identically across surfaces.
360+ val live = state.connected
361+ // Custom dim palette for the disconnected state — the Wear Button's own
362+ // `enabled = false` styling fades the whole button to ~12% alpha which
363+ // makes the icon nearly invisible. Keeping the button "enabled" with our
364+ // own muted colors and guarding the onClick keeps it visually present
365+ // while still being non-interactive.
342366 val disabledBg = Color (0xFF1A1A1A )
343367 val disabledFg = Color (0xFF555555 )
344368 Row (horizontalArrangement = Arrangement .spacedBy(10 .dp)) {
345369 if (state.hasHorn) {
346370 Button (
347371 onClick = {
348- if (enabled ) WatchStateRepository .sendControl(context, WatchControl .HORN )
372+ if (live ) WatchStateRepository .sendControl(context, WatchControl .HORN )
349373 },
350- enabled = enabled,
351374 colors = ButtonDefaults .primaryButtonColors(
352- backgroundColor = if (enabled ) accent else disabledBg,
353- contentColor = if (enabled ) Color .Black else disabledFg
375+ backgroundColor = if (live ) accent else disabledBg,
376+ contentColor = if (live ) Color .Black else disabledFg
354377 ),
355378 modifier = Modifier .size(buttonSize)
356379 ) {
357380 Icon (
358381 imageVector = Icons .Filled .Campaign ,
359382 contentDescription = stringResource(R .string.watch_horn),
383+ tint = if (live) Color .Black else disabledFg,
360384 modifier = Modifier .size(iconSize)
361385 )
362386 }
363387 }
364388 if (state.hasLight) {
365389 Button (
366390 onClick = {
367- if (! enabled ) return @Button
391+ if (! live ) return @Button
368392 val intent = if (state.lightOn) WatchControl .LIGHT_OFF else WatchControl .LIGHT_ON
369393 WatchStateRepository .sendControl(context, intent)
370394 },
371- enabled = enabled,
372395 colors = ButtonDefaults .secondaryButtonColors(
373396 backgroundColor = when {
374- ! enabled -> disabledBg
397+ ! live -> disabledBg
375398 state.lightOn -> accent.copy(alpha = 0.30f )
376399 else -> Color (0xFF2A2A2A )
377400 },
378401 contentColor = when {
379- ! enabled -> disabledFg
402+ ! live -> disabledFg
380403 state.lightOn -> accent
381404 else -> Color (0xFFB0B0B0 )
382405 }
@@ -387,7 +410,7 @@ private fun ActionRow(state: WatchState, accent: Color, buttonSize: Dp, iconSize
387410 imageVector = Icons .Filled .FlashlightOn ,
388411 contentDescription = stringResource(R .string.watch_light),
389412 tint = when {
390- ! enabled -> disabledFg
413+ ! live -> disabledFg
391414 state.lightOn -> Color (0xFFFFC107 )
392415 else -> Color (0xFF606060 )
393416 },
@@ -448,18 +471,26 @@ private fun DetailsScreen(state: WatchState, accent: Color) {
448471 fontWeight = FontWeight .SemiBold
449472 )
450473 }
474+ // Same accent rule as the dial: default accent → white speed
475+ // so the row aligns with the rest of the value column; any
476+ // custom accent → wear that accent.
477+ val useAccent = state.accentKey != " default"
451478 Text (
452479 text = " %.0f %s" .format(speedDisplay, speedUnit),
453480 fontSize = speedSp,
454481 fontWeight = FontWeight .Bold ,
455- color = accent
482+ color = if (useAccent) accent else Color . White
456483 )
457484 Spacer (Modifier .height(4 .dp))
458485 val live = state.connected
459- // Accent-tint live values so the page reads as a continuation of
460- // the dashboard's accent identity. Disconnected dashes stay grey
461- // so the rider can tell at a glance that the row isn't live.
462- val valueColor = if (live) accent else Color (0xFF606060 )
486+ // Live values: white when default accent (matches phone dashboard's
487+ // value column) or the accent color when the user picked one.
488+ // Disconnected dashes stay muted grey.
489+ val valueColor = when {
490+ ! live -> Color (0xFF606060 )
491+ useAccent -> accent
492+ else -> Color .White
493+ }
463494 DetailRow (R .string.watch_voltage_label, if (live) " %.1f V" .format(state.voltage) else DASH , labelSp, valueSp, labelWidth, valueWidth, valueColor)
464495 DetailRow (R .string.watch_current_label, if (live) " %.1f A" .format(state.current) else DASH , labelSp, valueSp, labelWidth, valueWidth, valueColor)
465496 DetailRow (R .string.watch_power_label, if (live) " %.0f W" .format(powerW) else DASH , labelSp, valueSp, labelWidth, valueWidth, valueColor)
0 commit comments