diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index 39dc0e0..d1aefa3 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -62,7 +62,7 @@ - [x] **UI-01**: Web app served by Python backend — no external hosting required - [x] **UI-02**: Terminal/hacker aesthetic — dark theme, monospace fonts, CRT/scanline vibe; NOT generic SaaS look -- [ ] **UI-03**: All primary operations accessible without mouse (keyboard shortcuts for play/pause/seek/undo) +- [x] **UI-03**: All primary operations accessible without mouse (keyboard shortcuts for play/pause/seek/undo) - [x] **UI-04**: Live preview panel — simulated LED strip visualization in browser canvas, synced to playback ### Infrastructure diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 8a3f057..f1f23ac 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -16,7 +16,7 @@ Decimal phases appear between their surrounding integers in numeric order. - [x] **Phase 2: Audio Engine** - MPV IPC bridge, waveform rendering, playback controls, Windows timer fix (completed 2026-04-06) - [x] **Phase 3: Communication Protocol** - UDP packet spec, DRGB/DNRGB/DRGBW encoders, animation library, software simulator (completed 2026-04-06) - [x] **Phase 4: Timeline Editor** - DAW UI (tracks, drag-place blocks, resize, delete), undo/redo, beat detection, snap-to-beat (completed 2026-04-06) -- [ ] **Phase 5: Live Show Execution** - End-to-end show playback, seek-safe cue scheduling, show save/load, keyboard shortcuts, live preview +- [x] **Phase 5: Live Show Execution** - End-to-end show playback, seek-safe cue scheduling, show save/load, keyboard shortcuts, live preview (completed 2026-04-07) - [ ] **Phase 6: AI Sync** - YouTube loading, AI-assisted show generation, beat calibration UI, structural segmentation - [ ] **Phase 7: Microcontroller Firmware** - MicroPython firmware for ESP32/Pico/RPi, animation command + frame receivers for SK6812 and WS2801 @@ -111,7 +111,7 @@ Plans: Plans: - [x] 05-01-PLAN.md — Cue scheduler: server-side position-driven scheduling, 60ms look-ahead, seek-safe fired_ids reset - [x] 05-02-PLAN.md — Live preview panel + show selector: DOM device strips, preview_update handler, show load into timeline -- [ ] 05-03-PLAN.md — Keyboard shortcuts: Space, arrows, Ctrl+Z/Y/S for mouse-free operation +- [x] 05-03-PLAN.md — Keyboard shortcuts: Space, arrows, Ctrl+Z/Y/S for mouse-free operation **UI hint**: yes ### Phase 6: AI Sync @@ -156,6 +156,6 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 | 2. Audio Engine | 3/3 | Complete | 2026-04-06 | | 3. Communication Protocol | 3/3 | Complete | 2026-04-06 | | 4. Timeline Editor | 4/4 | Complete | 2026-04-06 | -| 5. Live Show Execution | 2/3 | In Progress| | +| 5. Live Show Execution | 3/3 | Complete | 2026-04-07 | | 6. AI Sync | 0/3 | Not started | - | | 7. Microcontroller Firmware | 0/3 | Not started | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index ecb0ef9..55d844a 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -2,15 +2,15 @@ gsd_state_version: 1.0 milestone: v1.0 milestone_name: milestone -status: executing -stopped_at: Completed 05-live-show-execution/05-02-PLAN.md -last_updated: "2026-04-07T10:16:36.725Z" +status: verifying +stopped_at: Completed 05-live-show-execution/05-03-PLAN.md +last_updated: "2026-04-07T10:19:03.026Z" last_activity: 2026-04-07 progress: total_phases: 7 - completed_phases: 4 + completed_phases: 5 total_plans: 17 - completed_plans: 16 + completed_plans: 17 percent: 0 --- @@ -27,7 +27,7 @@ See: .planning/PROJECT.md (updated 2026-04-05) Phase: 05 (live-show-execution) — EXECUTING Plan: 3 of 3 -Status: Ready to execute +Status: Phase complete — ready for verification Last activity: 2026-04-07 Progress: [░░░░░░░░░░] 0% @@ -68,6 +68,7 @@ Progress: [░░░░░░░░░░] 0% | Phase 04-timeline-editor P04 | 4min | 2 tasks | 4 files | | Phase 05-live-show-execution P01 | 152 | 2 tasks | 1 files | | Phase 05-live-show-execution P02 | 20 | 2 tasks | 3 files | +| Phase 05-live-show-execution P03 | 10 | 1 tasks | 1 files | ## Accumulated Context @@ -116,6 +117,9 @@ Recent decisions affecting current work: - [Phase 05-live-show-execution]: active_cue tracks already-fired blocks within duration window so preview stays lit; past-cue threshold 100ms for silent skip without UDP dispatch - [Phase 05-live-show-execution]: Preview panel starts hidden (display:none), revealed to flex on show load — avoids empty panel before first show - [Phase 05-live-show-execution]: Strip color uses raw RGB from cue params, not CSS variables — data-driven per UI-SPEC Color section +- [Phase 05-live-show-execution]: e.preventDefault() called first in every key branch — suppresses browser defaults before app logic +- [Phase 05-live-show-execution]: Space on button elements explicitly skipped — prevents double-toggle with native button click +- [Phase 05-live-show-execution]: Ctrl+S uses GET-then-POST round-trip to save current server show state, not in-memory timeline ### Pending Todos @@ -129,8 +133,8 @@ None yet. ## Session Continuity -Last session: 2026-04-07T10:16:36.718Z -Stopped at: Completed 05-live-show-execution/05-02-PLAN.md +Last session: 2026-04-07T10:19:03.021Z +Stopped at: Completed 05-live-show-execution/05-03-PLAN.md Resume file: None Next action: `/gsd:plan-phase 1` diff --git a/.planning/phases/05-live-show-execution/05-03-SUMMARY.md b/.planning/phases/05-live-show-execution/05-03-SUMMARY.md new file mode 100644 index 0000000..848bbc4 --- /dev/null +++ b/.planning/phases/05-live-show-execution/05-03-SUMMARY.md @@ -0,0 +1,96 @@ +--- +phase: 05-live-show-execution +plan: 03 +subsystem: ui +tags: [keyboard-shortcuts, vanilla-js, undo-redo, audio, websocket] + +# Dependency graph +requires: + - phase: 05-01 + provides: "Cue scheduler backend for play/pause/seek server messages" + - phase: 05-02 + provides: "Preview strips for seek-clear pattern" +provides: + - "wireKeyboard() — all 7 keyboard bindings (Space, ArrowLeft, ArrowRight, Ctrl+Z, Ctrl+Shift+Z, Ctrl+Y, Ctrl+S)" + - "Mouse-free operation of all primary actions per UI-03 requirement" +affects: [] + +# Tech tracking +tech-stack: + added: [] + patterns: + - "Keyboard guard pattern: check activeElement tagName before acting (input/select/textarea bypass)" + - "Space-on-button guard: explicit check for tag === 'button' to prevent double-toggle" + - "Ctrl+S round-trip save: GET current show state → POST to /api/shows (manual trigger)" + - "Arrow seek with strip clear: same clear pattern as mouseup seek from Plan 02" + +key-files: + created: [] + modified: + - lightsync/frontend/app.js + +key-decisions: + - "e.preventDefault() called first in every branch — suppresses Space scroll, Arrow scroll, Ctrl+S browser dialog before any logic" + - "Space explicitly guarded on button elements to avoid double-toggle with button click handler" + - "Ctrl+S uses GET-then-POST round-trip (reads current server state, not just timeline) — consistent with existing save pattern" + +patterns-established: + - "wireKeyboard() placed after wireAudio() in init section — both audio wiring functions called together at startup" + - "Arrow seek clears preview strips inline — same pattern as mouseup seek handler" + +requirements-completed: [UI-03] + +# Metrics +duration: 10min +completed: 2026-04-07 +--- + +# Phase 05 Plan 03: Keyboard Shortcuts Summary + +**wireKeyboard() function wired with all 7 keyboard bindings (Space play/pause, Arrow seek, Ctrl+Z/Y undo/redo, Ctrl+S save) — all primary operations accessible without mouse** + +## Performance + +- **Duration:** ~10 min +- **Completed:** 2026-04-07 +- **Tasks:** 1 +- **Files modified:** 1 + +## Accomplishments + +- Added `wireKeyboard()` function to `lightsync/frontend/app.js` (72 lines inserted) +- Space toggles audio play/pause and sends `{ type: 'play' }` or `{ type: 'pause' }` to server via WebSocket +- ArrowLeft seeks back 5 seconds, ArrowRight seeks forward 5 seconds — both send `{ type: 'seek', position }` to server and clear all preview strips +- Ctrl+Z calls `timeline?.history.undo()` via optional chaining (safe when timeline not yet initialized) +- Ctrl+Shift+Z and Ctrl+Y both call `timeline?.history.redo()` +- Ctrl+S prevents browser Save dialog via `e.preventDefault()`, then fetches current show and POSTs it back to `/api/shows` +- All shortcuts are suppressed when `document.activeElement` is an `input`, `select`, or `textarea` +- Space is additionally suppressed when focused element is a `button` to prevent double-toggle with click handler +- `wireKeyboard()` called at init after `wireAudio()` + +## Task Commits + +1. **Task 1: Add wireKeyboard() function and call it at init** - `3562652` (feat) + +## Files Created/Modified + +- `lightsync/frontend/app.js` — Added wireKeyboard() function (72 lines) and wireKeyboard() init call + +## Decisions Made + +- `e.preventDefault()` is called at the start of every key branch to guarantee browser defaults are suppressed before any application logic runs +- Space on `