feat(hotkey): HotkeyService wrapping globalShortcut
Task 17 of the slice plan. register() pre-checks globalShortcut.isRegistered to detect collisions with other apps (Failure #1 in spec §6.1) and reports the conflict in the return object so the OllamaBanner-style failure surface in Task 29 can report it. unregisterAll() runs on app quit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
26
src/main/services/HotkeyService.ts
Normal file
26
src/main/services/HotkeyService.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { globalShortcut } from 'electron';
|
||||
|
||||
export interface HotkeyBinding {
|
||||
accelerator: string;
|
||||
onTrigger: () => void;
|
||||
}
|
||||
|
||||
export class HotkeyService {
|
||||
private registered: string[] = [];
|
||||
|
||||
register(binding: HotkeyBinding): { ok: boolean; reason?: string } {
|
||||
const accel = binding.accelerator;
|
||||
if (globalShortcut.isRegistered(accel)) {
|
||||
return { ok: false, reason: `${accel} already registered by another app` };
|
||||
}
|
||||
const ok = globalShortcut.register(accel, binding.onTrigger);
|
||||
if (!ok) return { ok: false, reason: `failed to register ${accel}` };
|
||||
this.registered.push(accel);
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
unregisterAll(): void {
|
||||
for (const a of this.registered) globalShortcut.unregister(a);
|
||||
this.registered = [];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user