Palette: seven roles (accent, good, caution added; highlight renamed alarm); no hard-coded colours left
background, foreground, subdued, accent (emphasis without danger), and the state gradient good → caution → alarm; surface and onFill derived. smart-serow's four-key themes still load (highlight = alarm; the new roles fall back). Material's scheme follows: buttons in accent instead of the alarm colour. Link state, mock banner, signal tiles, raw log, checklist button and marks, camera page all take palette roles. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DDwfd6Ki8UfG4hK6W5YpJz
This commit is contained in:
+30
-17
@@ -169,14 +169,15 @@ class MockBanner extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final p = AppTheme.of(context);
|
||||
return Container(
|
||||
color: Colors.amber.shade700,
|
||||
color: p.caution,
|
||||
padding: const EdgeInsets.symmetric(vertical: 6),
|
||||
child: const Text(
|
||||
child: Text(
|
||||
'MOCK DATA — NOT FROM THE CAR',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
color: p.onFill(p.caution),
|
||||
fontWeight: FontWeight.w900,
|
||||
fontSize: 20,
|
||||
letterSpacing: 2,
|
||||
@@ -200,10 +201,11 @@ class LinkBar extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final b = boundary;
|
||||
final p = AppTheme.of(context);
|
||||
final (color, label) = switch (b.state) {
|
||||
LinkState.up => (Colors.green, 'CONNECTED'),
|
||||
LinkState.connecting => (Colors.orange, 'CONNECTING'),
|
||||
LinkState.down => (Colors.red, 'DOWN'),
|
||||
LinkState.up => (p.good, 'CONNECTED'),
|
||||
LinkState.connecting => (p.caution, 'CONNECTING'),
|
||||
LinkState.down => (p.alarm, 'DOWN'),
|
||||
};
|
||||
// Fixed-width numbers, padded with figure spaces (U+2007, digit-wide): the bar must
|
||||
// not reflow every time a value gains a digit.
|
||||
@@ -230,7 +232,10 @@ class LinkBar extends StatelessWidget {
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
Chip(
|
||||
label: Text(label),
|
||||
label: Text(
|
||||
label,
|
||||
style: TextStyle(color: color, fontWeight: FontWeight.w600),
|
||||
),
|
||||
backgroundColor: color.withValues(alpha: 0.3),
|
||||
),
|
||||
Text(b.url, style: const TextStyle(fontFamily: 'monospace')),
|
||||
@@ -317,7 +322,10 @@ Future<void> orinPowerOptions(BuildContext context, Boundary b) async {
|
||||
label: const Text('Reboot'),
|
||||
),
|
||||
FilledButton.icon(
|
||||
style: FilledButton.styleFrom(backgroundColor: Colors.red.shade700),
|
||||
style: FilledButton.styleFrom(
|
||||
backgroundColor: AppTheme.of(context).alarm,
|
||||
foregroundColor: AppTheme.of(context).onFill(AppTheme.of(context).alarm),
|
||||
),
|
||||
onPressed: () => Navigator.of(context).pop('poweroff'),
|
||||
icon: const Icon(Icons.power_settings_new),
|
||||
label: const Text('Power off'),
|
||||
@@ -403,26 +411,27 @@ class SignalTile extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final p = AppTheme.of(context);
|
||||
if (missing) {
|
||||
return ListTile(
|
||||
title: Text(
|
||||
name,
|
||||
style: const TextStyle(fontFamily: 'monospace', color: Colors.grey),
|
||||
style: TextStyle(fontFamily: 'monospace', color: p.subdued),
|
||||
),
|
||||
subtitle: const Text(
|
||||
subtitle: Text(
|
||||
'MISSING · not in the latest state',
|
||||
style: TextStyle(color: Colors.redAccent),
|
||||
style: TextStyle(color: p.alarm),
|
||||
),
|
||||
trailing: Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
const TextSpan(
|
||||
TextSpan(
|
||||
text: '?',
|
||||
style: TextStyle(fontSize: 34, color: Colors.grey),
|
||||
style: TextStyle(fontSize: 34, color: p.subdued),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' ${envelope['unit'] ?? ''}',
|
||||
style: const TextStyle(fontSize: 16, color: Colors.grey),
|
||||
style: TextStyle(fontSize: 16, color: p.subdued),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -439,12 +448,13 @@ class SignalTile extends StatelessWidget {
|
||||
fontSize: 34,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontFeatures: const [FontFeature.tabularFigures()],
|
||||
color: stale || v == null ? Colors.grey : null,
|
||||
color: stale || v == null ? p.subdued : p.foreground,
|
||||
fontStyle: stale ? FontStyle.italic : null,
|
||||
);
|
||||
return ListTile(
|
||||
title: Text(name, style: const TextStyle(fontFamily: 'monospace')),
|
||||
subtitle: Text(
|
||||
style: stale ? TextStyle(color: p.caution) : null,
|
||||
[
|
||||
if (stale) quality.toUpperCase(),
|
||||
if (v == null) 'no value',
|
||||
@@ -479,11 +489,14 @@ class RawLog extends StatelessWidget {
|
||||
if (b.pending.isNotEmpty || b.acks.isNotEmpty) ...[
|
||||
Text('Commands', style: Theme.of(context).textTheme.titleSmall),
|
||||
for (final p in b.pending)
|
||||
Text('… ${p.cmd} ${p.args['text'] ?? ''} (unacked)'),
|
||||
Text(
|
||||
'… ${p.cmd} ${p.args['text'] ?? ''} (unacked)',
|
||||
style: TextStyle(color: AppTheme.of(context).caution),
|
||||
),
|
||||
for (final a in b.acks)
|
||||
Text(
|
||||
'${a.ok ? '✓' : '✗'} ${a.detail}',
|
||||
style: TextStyle(color: a.ok ? null : Colors.redAccent),
|
||||
style: TextStyle(color: a.ok ? AppTheme.of(context).good : AppTheme.of(context).alarm),
|
||||
),
|
||||
const Divider(),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user