From 5554b1abc7271b2ed417dde90549fc0d5d96c176 Mon Sep 17 00:00:00 2001 From: Jannis Braun <151788261+TheZwiss@users.noreply.github.com> Date: Sun, 22 Mar 2026 21:01:02 +0100 Subject: [PATCH] fix: replace broken 2-char hash with djb2 for keybind code mapping The previous hash (charCodeAt(0)*256 + charCodeAt(1)) only used the first 2 characters of KeyboardEvent.code strings, causing all Key* codes (KeyA, KeyB, ..., KeyZ) to collide to the same numeric value. This made Ctrl+D and Ctrl+M appear as identical bindings (false conflict) and broke keybind matching in the web fallback. djb2 hashes the full string, producing unique values for all codes. --- .../components/modals/settingsPanels/KeybindsPanel.tsx | 7 ++++++- packages/web/src/hooks/useKeybinds.ts | 9 ++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/web/src/components/modals/settingsPanels/KeybindsPanel.tsx b/packages/web/src/components/modals/settingsPanels/KeybindsPanel.tsx index 6492a17a..56837a93 100644 --- a/packages/web/src/components/modals/settingsPanels/KeybindsPanel.tsx +++ b/packages/web/src/components/modals/settingsPanels/KeybindsPanel.tsx @@ -26,7 +26,12 @@ function keyDisplayName(code: string, key: string): string { } function codeToNumeric(code: string): number { - return code.charCodeAt(0) * 256 + (code.charCodeAt(1) || 0); + // djb2 hash — produces unique numeric IDs for all KeyboardEvent.code values + let hash = 5381; + for (let i = 0; i < code.length; i++) { + hash = ((hash << 5) + hash + code.charCodeAt(i)) | 0; + } + return hash >>> 0; // ensure unsigned } // --------------------------------------------------------------------------- diff --git a/packages/web/src/hooks/useKeybinds.ts b/packages/web/src/hooks/useKeybinds.ts index f834802c..2f5a2663 100644 --- a/packages/web/src/hooks/useKeybinds.ts +++ b/packages/web/src/hooks/useKeybinds.ts @@ -83,9 +83,12 @@ function setupWebFallback(keybindsRef: React.MutableRefObject): WebCl const activeActions = new Set(); function browserCodeToUiohook(code: string): number { - // Stable numeric ID from KeyboardEvent.code — consistent within web context - // because the recorder captures using the same mapping - return code.charCodeAt(0) * 256 + (code.charCodeAt(1) || 0); + // djb2 hash — must match codeToNumeric() in KeybindsPanel.tsx + let hash = 5381; + for (let i = 0; i < code.length; i++) { + hash = ((hash << 5) + hash + code.charCodeAt(i)) | 0; + } + return hash >>> 0; } function checkKeybinds(isDown: boolean): void {