Receiver management improvements for the admin Receivers tab:
- Per-receiver health: server now tracks each connection's state
(connecting/connected/down), message count, and last-message time, exposed
via new GET /api/admin/receiver-status and POST /api/admin/test-receivers.
- Receivers tab redesign: live "Active Receivers" panel with colored
indicators (green=receiving, yellow=connected/no data, red=unreachable),
a clear select -> SAVE & APPLY -> auto-test flow, and selectable scan
results with a "USE SELECTED RECEIVERS" action.
- Network scan interface selector: scan a chosen interface/subnet instead of
every local subnet. Oversized subnets (>/20, e.g. a docker /16) are disabled
in the UI and rejected server-side, eliminating slow/hanging scans.
Critical fix — server crash on receiver restart:
- Receiver connection tasks were awaited inside main()'s top-level
asyncio.gather. Restarting receivers cancels those tasks, and the resulting
CancelledError propagated into the gather and killed the whole server
process (every action after a restart then failed). Receiver tasks now run
as independent background tasks; restart cancels and awaits them with
return_exceptions=True so cancellation can never tear down the server.
Also cache-bust admin.css/admin.js/pixel-editor.js (?v=) so updated assets
load without a manual hard-refresh, and surface a clear message instead of a
silent "Loading…" when the status endpoint is unavailable.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Build a dependency-free Canvas2D pixel editor integrated into the admin
Sprites tab. Each sprite card gains an EDIT button that opens a full-screen
editor for the sprite at its native 500x333 resolution.
Tools: pencil (1-8px brush, Bresenham interpolation), eraser, color picker
(palette + native input + pick-from-canvas), fill bucket (flood fill), pan.
Features: cursor-centered zoom, space-drag pan, undo/redo (snapshot per
stroke), pixel grid overlay, transparency checkerboard, load existing sprite,
and keyboard shortcuts (B/E/I/F, Space, +/-/0, Ctrl+Z/Y, G, Esc).
Export reuses the existing POST /api/admin/sprites/{type} upload endpoint via
srcCanvas.toBlob, so no server changes are required.
Closes#5
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>