feat(web): global keyboard shortcuts (Space/J/L/M/Arrows//)
test-web / test (push) Failing after 32s

Universal music-player conventions, attached at window level from
+layout.svelte:

  Space, K     play / pause
  ArrowLeft    previous track
  ArrowRight   next track
  J            seek -10s
  L            seek +10s
  ArrowUp      volume +5%
  ArrowDown    volume -5%
  M            mute / unmute (restores prior volume)
  /            focus the global search input

Skipped when focus is in an input / textarea / select /
contenteditable so typing in the search box and rename fields
behaves normally. Modifier-only chords (Ctrl/Cmd/Alt + key)
intentionally pass through to the browser.

New store helper `toggleMute()` captures the last non-zero volume
so M can toggle back without permanently losing the user's level.

shortcuts.svelte.ts is the new module; +layout.svelte wires it
alongside useMediaSession / useEventsDispatcher.

Scribe 529, local task #60.
This commit is contained in:
2026-06-01 11:17:59 -04:00
parent 6e6fbc7856
commit 4362233d7c
4 changed files with 264 additions and 0 deletions
+15
View File
@@ -166,6 +166,21 @@ export function setVolume(v: number): void {
storage.write(VOLUME_KEY, String(clamped));
}
// Last non-zero volume captured so the M shortcut can toggle to silent
// then restore. Set lazily on the first toggle and on any setVolume
// that's non-zero. Default 0.5 keeps unmute usable even if the user
// somehow lands at volume=0 with no prior non-zero value.
let _volumeBeforeMute = 0.5;
export function toggleMute(): void {
if (_volume > 0) {
_volumeBeforeMute = _volume;
setVolume(0);
} else {
setVolume(_volumeBeforeMute > 0 ? _volumeBeforeMute : 0.5);
}
}
export function reportTimeUpdate(sec: number): void {
_position = sec;
}