Add whiteboard undo and redo shortcuts
Whiteboard history actions currently require the toolbar. Add Ctrl+Z for Undo and Ctrl+Y or Ctrl+Shift+Z for Redo on Windows/Linux, and Cmd+Z/Cmd+Shift+Z on macOS while focus is in the canvas or drawing toolbar, preserving text-field undo. Printable ASCII characters follow the selected keyboard layout, so punctuation does not trigger a shortcut based on its physical key. Only a single non-ASCII character can fall back to the physical key code; named keys and empty values are ignored.
Make the canvas reachable with Tab and focus it without scrolling after an accepted drawing start. After Undo, Redo or Clear, preserve focus on a usable toolbar control and move it to the canvas only if the previously focused control becomes disabled or focus was on the page body. Keyboard and button edits share the existing applyBoardEdit() path and editing restrictions. Document the shortcuts in the existing README row under "Whiteboard interviews".
Acceptance criteria from #352
- AC1: One history action per distinct press; browser tests cover strokes, erasers, undoable Clear and discarded redo branches.
- AC2: Tab access, visible focus, no-scroll focus restoration, usable buttons and platform-specific shortcut hints are covered. Tests cover repeated Enter activation of Undo and Redo, focus recovery when a button becomes disabled, and unchanged scroll positions. The drawing-start case captures scroll positions before pointer-down.
- AC3: Tests reject edits before start, while paused, during behavioral rounds, after ending and during unfinished strokes; no edit is queued.
- AC4: Text-field undo remains usable; tests cover outside focus, composition, repeats, extra modifiers and previously handled events, including non-Latin fallback events. Printable ASCII punctuation, named keys, empty values and ASCII control characters do not trigger unintended board edits.
- AC5: Empty history and ignored events add no operation; the default is prevented only for successful actions. The handler adds no warning.
- AC6: Keyboard and button actions share
applyBoardEdit(); tests verify repainting and serialized replay operations with local sinks. After drawing uploads settle, Undo and Redo must each produce a new completed upload whose JPEG content, byte length and stroke metadata match the current board.
Validation
Automated test environment: Ubuntu 26.04 LTS under WSL2, using Linux Chromium through Playwright 1.64.1, Node.js 22.22.3, Rust stable 1.99.1 and OpenJDK 21. Non-Latin key events and macOS shortcut combinations are simulated in Linux Chromium.
- The original Ctrl and Cmd shortcut cases failed before implementation and pass with this change. The non-Latin layout cases failed before the key-code fallback was added. The toolbar-focus and printable-key regression cases also failed before their respective corrections and pass afterward. The Ctrl+Shift+Z synchronization case failed before the additional Redo binding was implemented and passes afterward.
- All seventeen whiteboard shortcut cases pass, including printable-key matching, non-Latin fallback, toolbar focus retention and drawing-start scrolling. Removing drawing-start
preventScrollfails the scroll assertion; using physical codes unconditionally fails the Latin-precedence assertions. - Synchronization checks independently verify drawing, Undo and Redo uploads and replay operations. Removing the edit-triggered publish scheduling fails the Undo upload wait; reusing an earlier JPEG fails the Undo image comparison.
- Both Windows/Linux Redo bindings are listed in the tooltip,
aria-keyshortcutsand README. Guard tests exercise available Undo and Redo history, including Ctrl+Shift+Z, rather than relying on empty history to reject an event. - Focused whiteboard shortcut, whiteboard model and Run shortcut suites: 59 passed, no failures or skips.
CI=true ./scripts/test.shpassed after integration with upstream3198a99: exit 0; 1,883 Rust tests passed, all 1,385 browser tests passed with no skips, and 49 hook checks passed.- cargo-audit passed with one allowed yanked-version warning for tokio 1.54.0. actionlint, Ruff, ShellCheck and the complete formatter chain, including commentflow and shfmt, passed.
- Manual check: basic Ctrl+Z/Ctrl+Y operations behaved as expected during a live interview in Google Chrome 155.0.8059.85 on Windows 11. Toolbar focus retention and recovery also passed manual browser testing on Windows. I also confirmed that Ctrl+Shift+Z performs Redo in a manual browser check.
- Coverage gaps: 23 Rust tests remain ignored by default. Native macOS behavior and full end-to-end live-service and recording validation remain untested.
Closes #352