aboutsummaryrefslogtreecommitdiff
path: root/plugins/base/frontend/src/main/components/utils/hotkey.ts
blob: ae813166c3e7941d71ce16d7f202d25828298c3a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/*
 * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
 */

import {detectOsKind, OsKind} from "./os";

type ModifierKey = {
    name: string
    keyArg: string
}

class ModifierKeys {
    static metaKey: ModifierKey = {name: "Command", keyArg: "Meta"}
    static ctrlKey: ModifierKey = {name: "Ctrl", keyArg: "Control"}
    static altKey: ModifierKey = {name: "Alt", keyArg: "Alt"}
    static shiftKey: ModifierKey = {name: "Shift", keyArg: "Shift"}
}

const setOfKeys = [ModifierKeys.altKey, ModifierKeys.shiftKey, ModifierKeys.ctrlKey, ModifierKeys.metaKey]

export class Hotkey {
    private readonly osKind: OsKind;

    constructor() {
        this.osKind = detectOsKind()
    }

    public getOsAccelKeyName() {
        return this.getOsAccelKey().name
    }

    /**
     * Register a hotkey of combination Accel key (Cmd/Ctrl depending on OS).
     * The method also checks that other modifiers key is not pressed to avoid shortcuts intersection.
     * E.g. don't trigger [Ctrl+K] if [Ctrl + Shift + K] pressed
     */
    public registerHotkeyWithAccel = (event: () => void, letter: string) => {
        const osMetaKey = this.getOsAccelKey()
        document.onkeydown = (keyDownEvent) => {
            const isMetaKeyPressed = keyDownEvent.getModifierState(osMetaKey.keyArg)
            const isOtherModifierKeyPressed = setOfKeys
                .filter(key => key !== osMetaKey)
                .map((otherKeys: ModifierKey) => keyDownEvent.getModifierState(otherKeys.keyArg))
                .some(value => value)

            if (isMetaKeyPressed && !isOtherModifierKeyPressed && keyDownEvent.key === letter) {
                keyDownEvent.preventDefault()
                event()
            }
        };
    }

    private getOsAccelKey(): ModifierKey {
        switch (this.osKind) {
            case OsKind.MACOS:
                return ModifierKeys.metaKey
            default:
                return ModifierKeys.ctrlKey
        }
    }
}