@@ -58,6 +58,9 @@ import com.eried.eucplanet.wear.bridge.WatchControl
5858import com.eried.eucplanet.wear.bridge.WatchState
5959import com.eried.eucplanet.wear.bridge.WatchStateRepository
6060
61+ /* * Em-dash placeholder used when a metric isn't live. Matches the phone dashboard. */
62+ private const val DASH = " —"
63+
6164/* *
6265 * Two-page horizontal pager: page 0 is the dashboard (gauge + horn/light);
6366 * page 1 is the detail strip (voltage / current / PWM / temp / trip / torque).
@@ -108,13 +111,17 @@ private fun MainScreen(state: WatchState, accent: Color) {
108111 val centerOffsetY = - (sw * 0.06f ).coerceIn(18f , 28f ).dp
109112 val watchPercent = rememberWatchBatteryPercent()
110113
111- // Full-bleed dial as the background frame.
114+ // Full-bleed dial as the background frame. Color-band visibility and
115+ // its orange/red thresholds follow the phone's Display settings so the
116+ // two surfaces always agree.
112117 SpeedGauge (
113118 speed = state.speedKmh,
114119 maxSpeed = maxSpeed,
115120 imperial = state.imperialUnits,
116121 accent = accent,
117- showColorBand = true ,
122+ showColorBand = state.showGaugeBand,
123+ orangeThresholdPct = state.gaugeOrangeThresholdPct,
124+ redThresholdPct = state.gaugeRedThresholdPct,
118125 fullBleed = true ,
119126 drawSpeedText = false ,
120127 modifier = Modifier .fillMaxSize()
@@ -150,7 +157,11 @@ private fun MainScreen(state: WatchState, accent: Color) {
150157 text = " %.0f" .format(WatchUnits .speed(state.speedKmh, state.imperialUnits)),
151158 fontSize = speedFontSp,
152159 fontWeight = FontWeight .Bold ,
153- color = speedTierColor(state.speedKmh, maxSpeed)
160+ // Disconnected: use the accent color so the dashboard
161+ // matches the gauge's safe-band tint instead of the
162+ // green-tier "0" that reads as if the wheel were idle.
163+ color = if (state.connected) speedTierColor(state.speedKmh, maxSpeed)
164+ else accent
154165 )
155166 if (state.showSpeedUnit) {
156167 Spacer (Modifier .width(3 .dp))
@@ -183,11 +194,20 @@ private fun MainScreen(state: WatchState, accent: Color) {
183194 }
184195 if (showBar && showPwmNumber) Spacer (Modifier .width(6 .dp))
185196 if (showPwmNumber) {
197+ // When the bar is alongside, the "%" is enough — the
198+ // bar itself is the visual context. Text-only mode
199+ // gets a full "Load (PWM): N%" label since there's no
200+ // bar to clue the rider in.
201+ val pwmText = when {
202+ ! state.connected -> if (showBar) DASH else " Load (PWM): $DASH "
203+ showBar -> " %.0f%%" .format(state.pwmPercent)
204+ else -> " Load (PWM): %.0f%%" .format(state.pwmPercent)
205+ }
186206 Text (
187- text = " %.0f%% " .format(state.pwmPercent) ,
207+ text = pwmText ,
188208 fontSize = pwmNumberSp,
189209 fontWeight = FontWeight .Medium ,
190- color = pwmTierColor(state.pwmPercent)
210+ color = if (state.connected) pwmTierColor(state.pwmPercent) else Color ( 0xFF606060 )
191211 )
192212 }
193213 }
@@ -204,9 +224,10 @@ private fun MainScreen(state: WatchState, accent: Color) {
204224 verticalArrangement = Arrangement .spacedBy((sw * 0.018f ).coerceIn(5f , 9f ).dp)
205225 ) {
206226 BatteryRow (
207- wheelPercent = state.batteryPercent.takeIf { state.showWheelBattery },
227+ wheelPercent = state.batteryPercent.takeIf { state.showWheelBattery && state.connected },
208228 phonePercent = state.phoneBatteryPercent.takeIf { state.showPhoneBattery },
209229 watchPercent = watchPercent.takeIf { state.showWatchBattery },
230+ showWheelChip = state.showWheelBattery,
210231 fontSize = batteryFontSp,
211232 iconSize = batteryIconDp,
212233 spacing = batterySpacingDp
@@ -259,6 +280,7 @@ private fun BatteryRow(
259280 wheelPercent : Int? ,
260281 phonePercent : Int? ,
261282 watchPercent : Int? ,
283+ showWheelChip : Boolean ,
262284 fontSize : TextUnit ,
263285 iconSize : Dp ,
264286 spacing : Dp
@@ -267,9 +289,14 @@ private fun BatteryRow(
267289 horizontalArrangement = Arrangement .spacedBy(spacing),
268290 verticalAlignment = Alignment .CenterVertically
269291 ) {
270- if (wheelPercent != null ) BatteryChip (Icons .Filled .ElectricScooter , wheelPercent, fontSize, iconSize)
271- if (phonePercent != null ) BatteryChip (Icons .Filled .PhoneAndroid , phonePercent, fontSize, iconSize)
272- if (watchPercent != null ) BatteryChip (Icons .Filled .Watch , watchPercent, fontSize, iconSize)
292+ // Wheel chip is visible when the user enabled it; disconnected shows
293+ // an em-dash so the row layout stays put rather than collapsing the
294+ // moment a wheel drops out.
295+ if (showWheelChip) {
296+ BatteryChip (Icons .Filled .ElectricScooter , wheelPercent, fontSize, iconSize)
297+ }
298+ phonePercent?.let { BatteryChip (Icons .Filled .PhoneAndroid , it, fontSize, iconSize) }
299+ watchPercent?.let { BatteryChip (Icons .Filled .Watch , it, fontSize, iconSize) }
273300 }
274301}
275302
@@ -281,8 +308,8 @@ private fun pwmTierColor(percent: Float): Color = when {
281308}
282309
283310@Composable
284- private fun BatteryChip (icon : ImageVector , percent : Int , fontSize : TextUnit , iconSize : Dp ) {
285- val tint = batteryTint(percent)
311+ private fun BatteryChip (icon : ImageVector , percent : Int? , fontSize : TextUnit , iconSize : Dp ) {
312+ val tint = if (percent != null ) batteryTint(percent) else Color ( 0xFF606060 )
286313 Row (verticalAlignment = Alignment .CenterVertically ) {
287314 Icon (
288315 imageVector = icon,
@@ -292,7 +319,7 @@ private fun BatteryChip(icon: ImageVector, percent: Int, fontSize: TextUnit, ico
292319 )
293320 Spacer (Modifier .width(2 .dp))
294321 Text (
295- text = " $ percent" ,
322+ text = percent?.toString() ? : DASH ,
296323 fontSize = fontSize,
297324 color = tint,
298325 fontWeight = FontWeight .Medium
@@ -429,13 +456,14 @@ private fun DetailsScreen(state: WatchState, accent: Color) {
429456 color = Color .White
430457 )
431458 Spacer (Modifier .height(4 .dp))
432- DetailRow (R .string.watch_voltage_label, " %.1f V" .format(state.voltage), labelSp, valueSp, labelWidth, valueWidth)
433- DetailRow (R .string.watch_current_label, " %.1f A" .format(state.current), labelSp, valueSp, labelWidth, valueWidth)
434- DetailRow (R .string.watch_power_label, " %.0f W" .format(powerW), labelSp, valueSp, labelWidth, valueWidth)
435- DetailRow (R .string.watch_pwm_label, " %.0f %%" .format(state.pwmPercent), labelSp, valueSp, labelWidth, valueWidth)
436- DetailRow (R .string.watch_temp_label, " %.0f %s" .format(tempDisplay, tempUnit), labelSp, valueSp, labelWidth, valueWidth)
437- DetailRow (R .string.watch_torque_label, " %.1f" .format(state.torque), labelSp, valueSp, labelWidth, valueWidth)
438- DetailRow (R .string.watch_trip_label, " %.2f %s" .format(tripDisplay, distUnit), labelSp, valueSp, labelWidth, valueWidth)
459+ val live = state.connected
460+ DetailRow (R .string.watch_voltage_label, if (live) " %.1f V" .format(state.voltage) else DASH , labelSp, valueSp, labelWidth, valueWidth)
461+ DetailRow (R .string.watch_current_label, if (live) " %.1f A" .format(state.current) else DASH , labelSp, valueSp, labelWidth, valueWidth)
462+ DetailRow (R .string.watch_power_label, if (live) " %.0f W" .format(powerW) else DASH , labelSp, valueSp, labelWidth, valueWidth)
463+ DetailRow (R .string.watch_pwm_label, if (live) " %.0f %%" .format(state.pwmPercent) else DASH , labelSp, valueSp, labelWidth, valueWidth)
464+ DetailRow (R .string.watch_temp_label, if (live) " %.0f %s" .format(tempDisplay, tempUnit) else DASH , labelSp, valueSp, labelWidth, valueWidth)
465+ DetailRow (R .string.watch_torque_label, if (live) " %.1f" .format(state.torque) else DASH , labelSp, valueSp, labelWidth, valueWidth)
466+ DetailRow (R .string.watch_trip_label, if (live) " %.2f %s" .format(tripDisplay, distUnit) else DASH , labelSp, valueSp, labelWidth, valueWidth)
439467 }
440468 }
441469}
0 commit comments