From 295c4b0664d5c2bb790d0d3f050f43c9367b73c2 Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Thu, 22 Oct 2026 08:15:06 -0400 Subject: [PATCH] =?UTF-8?q?feat(audio-player):=20keyboard=20shortcuts=20?= =?UTF-8?q?=E2=80=94=20declarative=20keymap,=20dialog,=20media=20keys=20(p?= =?UTF-8?q?lan=20=C2=A72)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Space/Enter (body-focus only), H/L + arrows skip, J/K + PgDn/PgUp chapter steps, B bookmark capture (note box auto-focuses, Enter saves even when blank, Shift+Enter inserts a newline, Esc cancels), Alt+arrows / Alt+H/L speed steps, up/down volume with a brief OSD, M mute, [ ] skip-duration cycle, ? shortcut dialog, Esc closes the top-most surface (help → capture → note edit → drawers → dropdowns). audio-keys.ts is the ONE declarative table: resolveShortcut() drives the document keydown dispatcher and visibleKeymap() renders the templ dialog (x-for over the exposed keymap — templ cannot import TS). Hardware media keys ride the existing MediaSession handlers; the Media* keydown codes resolve through the same table to the SAME methods, so both layers stay one behavior. Guards mirror the ebook reader: typing in any INPUT/TEXTAREA/contentEditable never triggers shortcuts (bookmark notes included), a focused button keeps Space/Enter for itself, and the focused scrubber keeps its arrows (its own @change seeks — a native arrow nudge moves 0.08s, not a 10s skip). SKIP_SECONDS consolidates to one const beside SPEEDS (the templ skip dropdown now iterates skipChoices; [ ] cycles via cycleSkip()) — the same one-source pattern as the §5 speed-list consolidation. Unit: audio-keys.test.ts (resolution, Alt disambiguation, media keys, keymap integrity and conflict-freedom, dialog visibility) and cycleSkip tests. Live: 39 Playwright checks on the KJV folder book covering every binding, the guards, dialog and OSD; probe user created and deleted. --- templates/audio_reader.templ | 54 +++++++- templates/audio_reader_templ.go | 10 +- web/src/audio-keys.test.ts | 91 +++++++++++++ web/src/audio-keys.ts | 229 ++++++++++++++++++++++++++++++++ web/src/audio.test.ts | 20 ++- web/src/audio.ts | 187 +++++++++++++++++++++++--- 6 files changed, 569 insertions(+), 22 deletions(-) create mode 100644 web/src/audio-keys.test.ts create mode 100644 web/src/audio-keys.ts diff --git a/templates/audio_reader.templ b/templates/audio_reader.templ index f5aaef04..7ea9e76b 100644 --- a/templates/audio_reader.templ +++ b/templates/audio_reader.templ @@ -75,6 +75,19 @@ templ AudioReader(user User, metadata ReaderMetadata) { + @@ -219,7 +232,7 @@ templ AudioReader(user User, metadata ReaderMetadata) { class="absolute bottom-full mb-2 left-1/2 -translate-x-1/2 rounded-xl shadow-lg p-1.5 flex flex-col min-w-[7.5rem]" style="background-color: var(--bg-secondary); border: 1px solid var(--border); z-index: 30;" > -