Skip to content

v2.12.0 — Mobile-ready · installable PWA · pytest + CI

Choose a tag to compare

@gfargo gfargo released this 17 May 12:53
· 25 commits to main since this release
cb3317d

v2.12.0 — Mobile-ready · installable PWA · pytest + CI

A polish-and-foundation release. The web UI now feels native on phones (and installs like one), and the codebase finally has a real test suite + CI to keep regressions out.

Two big themes:

📱 Mobile audit + PWA installability

The web UI got rewritten for phones from the ground up — not "shrunk to fit," properly redesigned for touch and small viewports.

  • Every component touched: BLACKOUT button, the 7-tab row, modals, scene/group/cue/chase builders, chat composer, tool panels — all reworked for portrait phones.
  • Touch targets ≥ 44px everywhere per Apple HIG. No more thumb-fumbling on dense control rows.
  • 16px form inputs to prevent iOS Safari from auto-zooming on focus.
  • Safe-area insets respected (notch / home indicator).
  • Tabs row scrolls horizontally when 7 tabs don't fit — no more wrapping.
  • Full-screen modals on phones, stacked layouts for cue/chase builders.
  • Edge-to-edge chat composer with proper keyboard handling.

PWA installability lands too:

  • /manifest.json with proper icons, theme color, display: standalone.
  • /icon.svg served from the control server (no asset pipeline required).
  • /sw.js service worker registered on load.
  • Apple-specific meta tags (apple-mobile-web-app-capable, status bar style, etc.) so iOS "Add to Home Screen" gives a chromeless app.
  • Android Chrome shows the install prompt automatically.

Open http://lights.local:9999 on your phone → Add to Home Screen → it launches like a native app.

✅ Test suite + GitHub Actions CI

After 11 minor releases of "ship and hope," the project finally has automated guardrails.

~180 pytest tests covering pure-function helpers across the v2.3 → v2.11 buildout:

  • test_time_parser.py — cue list timestamp parsing ("0:32.500", "32s", "1:23:45", int ms)
  • test_cct.py — Tanner Helland CCT-to-RGB + WWA proportional blend
  • test_strobe.py — strobe rate → DMX 0..255 mapping, off forms, clamping
  • test_palette.py_normalize_palette_value across all six accepted shapes
  • test_cue_normalizer.py — scene / chase / action cue shape normalization
  • test_misc_helpers.py — direction + run-order enums, fixture ID coercion, _parse_level (0-255 / "75%" / "+30")

Sub-second full suite. Tests the contract, not the implementation.

GitHub Actions CI runs three jobs in parallel on every push + PR:

  1. python — pytest matrix on Python 3.11 + 3.12, plus ast.parse syntax check on both app.py and mcp-server/server.py.
  2. js — extracts the inline <script> from templates/index.html and runs node --check on it (would have caught the duplicate </style> we hit during the mobile rewrite).
  3. html — verifies balanced open/close tags for div, script, style, button, select in the template.

What's NOT covered (yet): Flask routes, the persistent WebSocket loop, AI provider calls, XML workspace mutations, cue list playback engine. All deliberate — integration-test territory for later if they become regression hotspots. See control-server/tests/README.md for the full breakdown and how to add new tests.

Upgrade

./scripts/lightsctl.sh update

Then ./scripts/lightsctl.sh restart and open the web UI on your phone — it should feel like a different app.

What's next

With mobile + PWA + CI in place, the foundation work is done. Next up: integration tests for the Flask layer, more chase patterns, and the visual cue list timeline view.