feat/keyboard-shortcuts #3
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/keyboard-shortcuts"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Escape was handled locally in seven modules, each unaware of the others, and most toggles had no Escape at all — the DSL inspector, group select, the preset sidebar, notation edit/create and the rehearsal chooser could only be left via their own button. New js/system/keyboardShortcuts.js owns global key handling. Modules register dismissible layers with a tier; one press backs out of exactly the innermost active layer, so nested states unwind instead of collapsing at once: overlay fullscreen cue video popup rehearsal mark chooser substate DSL path-pick, preset click-to-place, group wrap panel selection group selection, audio-object and annotation selection panel DSL editor sidebar, preset sidebar, live console mode group select, DSL inspector, draw/erase/select, annotation edit, audio-object edit, notation create/edit Deliberately not on the stack: freeze animations, mic analysis, and marker/playhead visibility. Escape dismisses things that capture input or cover the score, never a setting you switched on — escaping a freeze mid-edit would undo the reason you froze. The listener runs at window capture but only consumes the event when one of its layers is active; otherwise Escape falls through untouched to the handlers that own it (inline dialogs, the live console's cue browser, stopwatch fullscreen). It also defers whenever focus is in a text field, so Escape still cancels an inline edit, and ignores modifier chords. Equal-priority layers go in registration order. Supporting changes: - dslInspector: the exit paths its toggle buttons were inlining are now named functions (_cancelPick, _exitInspector, _closePresetPanel, _exitGroupMode) so button and Escape share one path; the module exports getDslEscapeLayers() rather than its private state. Cancelling a preset placement also clears the 'click in the score to place…' status, which used to linger. - video.js registers the fullscreen overlay as a layer instead of its own window listener, so it outranks the rest rather than racing it. - oscillaLive exports isLiveConsoleOpen/hideLiveConsole. - drawing.js and interactionSurface.js lose their Escape branches — the central handler supersedes them — with pointers left behind. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>Reviving a design that was already here and switched off: the H/F/T/R block UIBindings carried commented out, an exported toggleKeybindingsPopup with nothing behind it, and a #keybindings-popup stub whose whole body read <!-- left unchanged -->. The docs already promised shortcuts that did not exist. Keys now dispatch in three stages: 1. Escape unwinds one layer of the Escape stack 2. Contexts an active tool gets first refusal on a key 3. Global map whatever no context claimed Stage 2 is what makes bare letters safe. drawing's handleDrawingKeydown already returned handled/not-handled, so it registers as a context and keeps D/E/V/S while a drawing mode runs, while the same letters fall through to the global map otherwise. So D enters draw mode, D inside eraser returns to draw (context), D inside draw exits (global) — one binding, not a collision. Tools D draw · A annotations · O audio objects · N notation edit I DSL editor · G group select · P presets · L live console Session M drop marker · Shift+M marker visibility · R rehearsal marks View F fullscreen · Shift+F freeze anims · T splash · H this list Left on the mouse deliberately: reset animations (destructive), audio analysis (fires a mic permission prompt), waveform labels (rare). A stray keypress on those costs more than the reach saves. Bare letters fire during performance, so the authoring tools (I G P N) carry authoring:true and are ignored while window.transportControlsDisabled is set — locked performer clients keep the session keys and lose the score-editing ones. H renders #keybindings-popup from the keymap itself, including the keys other modules still dispatch, so the help cannot drift from the bindings. The module header lists those outliers (transport seek/speed, the Ctrl chords, Alt+Shift preset panels) with the reason they stay put: they own state machines, not keymap concerns. Also: - dslInspector exports toggleDslInspector/togglePresetPanel/ toggleGroupMode/toggleAnimFreeze so button and key share one path. - _closePanel is null-safe: it is now reachable from `i` before the panel has ever been built, which a button click could never do. - docs: notation.md no longer claims there is no shortcut; audioObject and dev-dsl-inspector name the actual keys. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>