From 7b210baca4af5a61b29d5bd60753cf390874c2eb Mon Sep 17 00:00:00 2001 From: nesquena-hermes Date: Tue, 14 Jul 2026 01:20:12 +0000 Subject: [PATCH] fix(#5759): match composer-focus chord on '/' char not physical Slash code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Cmd/Ctrl+/ predicate keyed off e.code==='Slash' + !e.shiftKey, which on QWERTZ layouts (a) stole Ctrl/Cmd+- browser zoom-out (physical Slash there is the minus/zoom key) and (b) missed the real shifted-'/' chord. Match e.key==='/' instead — layout-correct on every keyboard. Tests updated to assert the physical code isn't used and a layout-shifted '/' still matches. Co-authored-by: nesquena-hermes --- static/boot.js | 6 +++++- tests/test_issue5759_composer_focus_shortcut.py | 9 ++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/static/boot.js b/static/boot.js index b6916904..ac5d4fdd 100644 --- a/static/boot.js +++ b/static/boot.js @@ -2321,7 +2321,11 @@ document.addEventListener('keydown',async e=>{ } } // Cmd/Ctrl+/ focuses the message composer without creating a chat. - if((e.metaKey||e.ctrlKey)&&!e.altKey&&!e.shiftKey&&(e.key==='/'||e.code==='Slash')){ + // Match on the '/' CHARACTER (e.key), not the physical key position: on QWERTZ + // layouts the physical Slash key produces Ctrl+- (browser zoom-out) and '/' is + // typed as Shift+7, so matching the physical code both steals zoom and misses + // the real '/' chord. e.key==='/' is layout-correct on every keyboard. + if((e.metaKey||e.ctrlKey)&&!e.altKey&&e.key==='/'){ const t=e.target; const isText=t&&(t.tagName==='INPUT'||t.tagName==='TEXTAREA'||t.isContentEditable); if(isText) return; diff --git a/tests/test_issue5759_composer_focus_shortcut.py b/tests/test_issue5759_composer_focus_shortcut.py index 3ebf6a10..a92f918b 100644 --- a/tests/test_issue5759_composer_focus_shortcut.py +++ b/tests/test_issue5759_composer_focus_shortcut.py @@ -4,7 +4,7 @@ from pathlib import Path BOOT_JS = (Path(__file__).parent.parent / "static" / "boot.js").read_text(encoding="utf-8") -CHORD = "(e.metaKey||e.ctrlKey)&&!e.altKey&&!e.shiftKey&&(e.key==='/'||e.code==='Slash')" +CHORD = "(e.metaKey||e.ctrlKey)&&!e.altKey&&e.key==='/'" CTRL_K = "(e.metaKey||e.ctrlKey)&&e.key==='k'" @@ -34,8 +34,11 @@ def _ctrl_k_branch() -> str: def test_composer_focus_chord_uses_cmd_ctrl_slash_and_stays_before_ctrl_k(): assert CHORD in BOOT_JS - assert "&&e.altKey&&!e.shiftKey&&(e.key==='/'||e.code==='Slash')" not in BOOT_JS - assert "e.code==='Slash'" in BOOT_JS + # Must key off the '/' CHARACTER, never the physical Slash code — on QWERTZ + # the Slash key produces Ctrl+- (browser zoom-out) and '/' is Shift+7. + assert "e.code==='Slash'" not in BOOT_JS + # No shiftKey exclusion — a layout-shifted '/' (e.g. Shift+7) must still match. + assert "!e.shiftKey&&e.key==='/'" not in BOOT_JS assert BOOT_JS.index("(e.metaKey||e.ctrlKey)&&!e.shiftKey&&!e.altKey&&(e.key==='b'||e.key==='B')") < BOOT_JS.index(CHORD) assert BOOT_JS.index(CHORD) < BOOT_JS.index(CTRL_K)