Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KeyboardShortcut class #268

Open
hudson-newey opened this issue Jan 15, 2025 · 0 comments
Open

KeyboardShortcut class #268

hudson-newey opened this issue Jan 15, 2025 · 0 comments
Labels

Comments

@hudson-newey
Copy link
Member

hudson-newey commented Jan 15, 2025

At the moment we have a KeyboardShortcut interface that we use to store keyboard shortcut information.

This interface allows us to create shortcuts like

const trueShortcut = {
	description: "Add a 'true' decision for 'cow'",
	keys: [shiftSymbol, "q", "o"]
} satisfies KeyboardShortcut;

However, this format is not really useful for keyboard event listeners which would need to listen for the "Q" keys being held down. Notice that "Q" is capitalized in the event listener because it requires shift.

This means that a lot of the time, our event listeners do not use this KeyboardShortcut interface e.g. the ClassificationComponent because it's easier to just use the raw key.

I think that not using the KeyboardShortcut interface is a smell that the interface is not expressive enough.

Therefore, I propose that the KeyboardShortcut interface should handle recognizing its own keyboard events. This would mean that all keyboard shortcut matching would be done in one place and not spread out over the entire client.


Having a single place for shortcut event matching would also make it easier to change the behavior of shortcuts and add functionality in the future.

E.g. Supporting keyboard patterns would be trivial with a KeyboardShortcut class (example of extending keyboard shortcuts; this is not something that I actually want to support)

const trueShortcut = new KeyboardShortcut({
	description: "make a true decision",
	keys: [[CtrlSymbol, "K"], ["O"]],
});

In this example it would be verbally described as

"Hold ctrl and press 'K', lift up ctrl + 'K', then press 'O' to 'make a true decision'"

An Example of what the class might look like

export class KeyboardShortcut {
    public constructor(public keys: ShortcutKey[], public description?: string, public hasMouse = false)

    // probably not a static field. Maybe a service, but just for illustrative purposes
    private static previousKeys: string[] = [];

    public isShortcut(event: KeyboardEvent) {
        const requiresShift = keys.some((key) => key === shiftSymbol);
        const hasRequiredModifiers = requiredShift && event.shift;

        const previousCombinations = KeyboardShortcut.previousKeys.slice(this.keys.length);
        return previousCombinations.all((key, i) => key === this.keys[i]);
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant