v3 M1b: runtime per-provider theming (firmware) + accent push (daemon)

The watch recolors to the active provider's brand, live, and it's cheap to add
more providers later.

Firmware:
- theme.h: expose THEME_ACCENT_HEX; ui.cpp: COL_ACCENT becomes a runtime
  lv_color_t backed by a shared style (s_accent_style). Static accent widgets
  (launcher tile icons, usage status line, session tokens) attach the shared
  style, so ui_set_theme() recolors them instantly via lv_obj_report_style_change
  — no widget tracking, no recreation.
- ui_set_theme(pv, accent_rgb): swaps the accent + a small logo table keyed by
  provider id (fallback to the Claude mark until a provider ships a logo). Change-
  guarded, so the ~3s payload cadence doesn't churn.
- main.cpp: parse "pv" (id) + "ac" (0xRRGGBB) from the payload and apply.
- Adding a provider needs zero firmware color edits (accent is data-driven) and
  at most one logo-table row.

Daemon: push "ac" = active provider's brand accent alongside "pv".

Test fix: test_providers used asyncio.run(), which closed the suite's shared
event loop and broke every later get_event_loop() test (Py3.13) — mirror the
repo's _run() helper instead.

Verified on the 2.06: forcing an OpenAI-green theme recolored the live launcher
icons (report_style_change path). 216 builds clean; daemon suite 94 passed.
This commit is contained in:
wenil
2026-07-10 00:40:24 +03:00
parent 6e3f8e9084
commit 83bd2bed43
7 changed files with 83 additions and 7 deletions
+7
View File
@@ -166,6 +166,13 @@ static bool parse_json(const char* json, UsageData* out) {
int maxk = dim["maxk"] | 6500;
ui_dimmer_set_snapshot(on, bri, ct, mink, maxk);
}
// v3: provider theme — "pv" (id) selects the logo, "ac" (0xRRGGBB) the brand
// accent. Stamped on every usage payload; ui_set_theme is change-guarded so
// it only repaints on an actual provider switch.
const char* pv = doc["pv"] | (const char*)nullptr;
uint32_t ac = doc["ac"] | 0u;
if (pv != nullptr || ac != 0u) ui_set_theme(pv, ac);
return true;
}