From 92ffa4f7c2e9ec879af1c9d143800f882ba560d7 Mon Sep 17 00:00:00 2001 From: patrick Date: Tue, 11 Aug 2026 23:12:00 -0400 Subject: [PATCH] fix: forward app shortcuts pressed inside the book MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Key events do not cross document boundaries, so shortcuts bound on the window never fired while the book had focus and the browser default won instead — ctrl+B opened bookmarks rather than the chapter sidebar. Replay them on the window, cancelling the original only if a handler claimed it so ctrl+C still copies. --- .../lib/components/reader/foliate-view.svelte | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/frontend/src/lib/components/reader/foliate-view.svelte b/frontend/src/lib/components/reader/foliate-view.svelte index ef122d8..e247fce 100644 --- a/frontend/src/lib/components/reader/foliate-view.svelte +++ b/frontend/src/lib/components/reader/foliate-view.svelte @@ -104,7 +104,46 @@ doc.addEventListener('keydown', onKeydown); } + /** + * Replays a shortcut pressed inside the book on the host window. + * + * Key events do not cross document boundaries, so a shortcut pressed while + * the book has focus never reaches the app's handlers — which are bound on + * the window, as the sidebar's ctrl+B is — and the browser's own default runs + * instead. That is why ctrl+B opened bookmarks in the book but toggled the + * chapter sidebar everywhere else. + * + * The original is only cancelled if an app handler actually claimed the + * replay, so combinations the app does not use — ctrl+C above all — keep + * their normal browser behaviour. + */ + function forwardShortcut(event: KeyboardEvent) { + const source = (event.target as Node | null)?.ownerDocument; + // isTrusted rules out the replay itself, which would otherwise recurse. + if (!event.isTrusted || !source || source === document) return; + + const claimed = !window.dispatchEvent( + new KeyboardEvent('keydown', { + key: event.key, + code: event.code, + ctrlKey: event.ctrlKey, + metaKey: event.metaKey, + shiftKey: event.shiftKey, + altKey: event.altKey, + bubbles: true, + cancelable: true + }) + ); + + if (claimed) event.preventDefault(); + } + function onKeydown(event: KeyboardEvent) { + if (event.ctrlKey || event.metaKey || event.altKey) { + forwardShortcut(event); + return; + } + switch (event.key) { case 'ArrowLeft': case 'PageUp':