fix: always enable web fallback keybind listeners alongside Electron IPC

When the Electron main process can't start uiohook (macOS Accessibility
denied, Linux missing input group), the IPC path silently produces no
events. Previously this left zero keybind listeners active. Now the web
capture-phase fallback is always set up as a safety net, ensuring
keybinds work in-app even when the OS-level hook fails.
This commit is contained in:
Jannis Braun
2026-03-22 22:31:59 +01:00
parent e5bf5f71ab
commit 623928812d
+15 -10
View File
@@ -198,31 +198,36 @@ export function useKeybinds(): void {
} }
}, [keybinds, currentVoiceChannelId]); }, [keybinds, currentVoiceChannelId]);
// --- Keybind listeners (Electron IPC or web capture-phase fallback) --- // --- Electron IPC bridge (global shortcuts via uiohook in main process) ---
useEffect(() => { useEffect(() => {
if (keybinds.length === 0) return; if (keybinds.length === 0) return;
if (!isElectron()) return;
// Try Electron IPC bridge first (requires rebuilt desktop app with keybind support)
if (isElectron()) {
const api = window.backspace; const api = window.backspace;
if (api?.syncKeybinds && api?.onKeybindAction) { if (!api?.syncKeybinds || !api?.onKeybindAction) return;
// Desktop app has keybind support — use OS-level global shortcuts
// Sync keybind config to main process — it registers OS-level hooks
api.syncKeybinds(keybinds.map((kb) => ({ api.syncKeybinds(keybinds.map((kb) => ({
actionId: kb.actionId, actionId: kb.actionId,
keys: kb.keys, keys: kb.keys,
mouseButton: kb.mouseButton, mouseButton: kb.mouseButton,
}))); })));
// Listen for matched actions from main process
const cleanup = api.onKeybindAction((action) => { const cleanup = api.onKeybindAction((action) => {
dispatchKeybindAction(action.actionId, action.pressed); dispatchKeybindAction(action.actionId, action.pressed);
}); });
return cleanup; return cleanup;
} }, [keybinds]);
// Desktop app lacks keybind APIs (old build) — fall through to web fallback
}
// Web fallback: capture-phase listeners (works when tab/window is focused) // --- Web fallback: always active as safety net ---
// On web: this is the only keybind path (works when tab is focused).
// On Electron: this provides in-app keybinds even if the OS-level hook
// fails to start (e.g. macOS Accessibility permission denied). When the
// global hook IS working, both fire but dispatchKeybindAction is
// idempotent for toggles (no-op if not in voice / already handled).
useEffect(() => {
if (keybinds.length === 0) return;
const cleanup = setupWebFallback(keybindsRef); const cleanup = setupWebFallback(keybindsRef);
return cleanup ?? undefined; return cleanup ?? undefined;
}, [keybinds]); }, [keybinds]);