One-liner: Added Cmd/Ctrl+A (select all) and Escape (clear selection) to the VSIL Editor, both pushing undoable snapshots. Also fixed a latent r214 bug where onSelectAll/onLayerUp/onLayerDown read from layersRef.current (never updated) — replaced with selection.layers (singleton, kept in sync by LayersPanel).
By the numbers:
shortcuts.ts, selection.ts, VSILEditor.tsx), 2 files newmain-BYn0C_p6.js (804 kB, 145 kB gz) + main-E2xBBPNt.css (59 kB, 10 kB gz)Why it matters: After r215 + r216, the editor has rich multi-select + multi-transform — but only mouse-driven. The user wants keyboard parity. Cmd+A and Esc are the universal "select all" / "deselect" gestures, expected in every modern editor.
Key implementation choices:
useShortcuts interface with onSelectAll + onClearSelection (optional). VSILEditor wires them in. No new event listeners — the existing keydown listener on the editor div handles them.selectAll(allLayerIds) reads from selection.layers (singleton, written by LayersPanel on every render via setCurrentLayers). This replaced the dead layersRef.current that r214 left behind. This is the same pattern that powers undo/redo/zoom/tool — r217 just applies it to the multi-select API.selectAll early-returns if the new set matches the current set. clearSelection early-returns if already empty. This prevents spam-clicking Cmd+A from polluting the undo stack.activeAssetId, activeRegionId, selectedRegionIds, layers, zoom, tool — same as every other snap in r214+. This means undo correctly rolls back the entire editor state, not just the selection.The bug it fixed:
// r214 (broken):
const layersRef = useRef<LayerEntry[]>([]); // ← never assigned
onSelectAll: () => {
const arr = layersRef.current; // ← always []
selectionRef.current.selectAll(arr.map(l => l.id)); // ← no-op
}
// r217 (fixed):
onSelectAll: () => {
const arr = selection.layers; // ← from singleton, kept in sync
selectionRef.current.selectAll(arr.map(l => l.id));
}
This same bug also affected r214's onLayerUp / onLayerDown (the [ and ] shortcuts) — those remain broken in this commit (out of scope for r217). The fix is the same: read from selection.layers instead. R218 or r217.1 candidate.
What r217 does NOT do:
Status: SHIPPED LOCALLY on feat/id9-r217-keyboard from main @ cc5a51d. Ready to push + merge.
Production deploy: BLOCKED — VPS SSH not available from sandbox. Build is ready, operator needs to deploy from their side or provide SSH key. Bulletin b1866 covers this.
Next:
feat/id9-r217-keyboard