update
This commit is contained in:
parent
da535c5de2
commit
c86abe5ff7
@ -1,24 +1,21 @@
|
||||
import { HotkeyDefinitionType, specialKeys } from './HotkeyDefinitionType';
|
||||
import { HotkeyListener } from './HotkeyListener';
|
||||
import { JsonHelper, ObjectHelper } from '@ainias42/js-helper';
|
||||
import { JsonHelper, ObjectHelper, Override } from '@ainias42/js-helper';
|
||||
import { HotkeyEntry } from './HotkeyEntry';
|
||||
import { SubKeyType } from './SubKeyType';
|
||||
import { HotkeyPressedMap } from './HotkeyPressedMap';
|
||||
import { HotkeyConfigWithOptionals } from './HotkeyConfigWithOptionals';
|
||||
|
||||
export class HotkeyManager<HotkeyConfig extends Record<string, HotkeyEntry<string>>> {
|
||||
export class HotKeyManager<HotkeyConfig extends Record<string, HotkeyEntry<string>>> {
|
||||
private keyPressedMap = new Map<string, boolean>();
|
||||
private hotkeys: HotkeyConfig;
|
||||
private hotkeysPressedMap: HotkeyPressedMap<HotkeyConfig>;
|
||||
private hotKeys: HotkeyConfig;
|
||||
private hotKeysPressedMap: HotkeyPressedMap<HotkeyConfig>;
|
||||
private enabled = true;
|
||||
private ignoreFormElements = true;
|
||||
private readonly ignoreFormElements: boolean = true;
|
||||
|
||||
constructor(hotkeys: HotkeyConfigWithOptionals<HotkeyConfig>, ignoreFormElements?: boolean) {
|
||||
this.hotkeys = ObjectHelper.entries(hotkeys).reduce((acc, [key, value]) => {
|
||||
acc[key] = { subKeys: {}, callbacks: [], ...value } as unknown as HotkeyConfig[typeof key];
|
||||
return acc;
|
||||
}, {} as HotkeyConfig);
|
||||
this.hotkeysPressedMap = this.generateHotkeyPressedMap();
|
||||
this.hotKeys = {} as HotkeyConfig;
|
||||
this.addHotKeys(hotkeys);
|
||||
|
||||
if (ignoreFormElements !== undefined) {
|
||||
this.ignoreFormElements = ignoreFormElements;
|
||||
@ -29,7 +26,8 @@ export class HotkeyManager<HotkeyConfig extends Record<string, HotkeyEntry<strin
|
||||
return (
|
||||
element instanceof HTMLInputElement ||
|
||||
element instanceof HTMLSelectElement ||
|
||||
element instanceof HTMLTextAreaElement
|
||||
element instanceof HTMLTextAreaElement ||
|
||||
(element instanceof HTMLElement && element.contentEditable === 'true')
|
||||
);
|
||||
}
|
||||
|
||||
@ -38,7 +36,7 @@ export class HotkeyManager<HotkeyConfig extends Record<string, HotkeyEntry<strin
|
||||
}
|
||||
|
||||
private static checkAffections(keyDefinitions: HotkeyDefinitionType[], key: string): boolean {
|
||||
return keyDefinitions.some((keyDefinition) => HotkeyManager.checkAffection(keyDefinition, key));
|
||||
return keyDefinitions.some((keyDefinition) => HotKeyManager.checkAffection(keyDefinition, key));
|
||||
}
|
||||
|
||||
private static checkAffection(keyDefinition: HotkeyDefinitionType, key: string): boolean {
|
||||
@ -48,11 +46,28 @@ export class HotkeyManager<HotkeyConfig extends Record<string, HotkeyEntry<strin
|
||||
);
|
||||
}
|
||||
|
||||
addHotKeys<NewHotkeyConfig extends Record<string, HotkeyEntry<string>>>(
|
||||
hotkeys: HotkeyConfigWithOptionals<NewHotkeyConfig>,
|
||||
) {
|
||||
type NewConfig = Override<HotkeyConfig, NewHotkeyConfig>;
|
||||
|
||||
this.hotKeys = {
|
||||
...this.hotKeys,
|
||||
...ObjectHelper.entries(hotkeys).reduce((acc, [key, value]) => {
|
||||
acc[key] = { subKeys: {}, callbacks: [], ...value } as unknown as NewConfig[typeof key];
|
||||
return acc;
|
||||
}, {} as NewConfig),
|
||||
};
|
||||
this.hotKeysPressedMap = this.generateHotkeyPressedMap();
|
||||
|
||||
return this as unknown as HotKeyManager<NewConfig>;
|
||||
}
|
||||
|
||||
addListener<HotkeyName extends keyof HotkeyConfig>(
|
||||
hotkeyName: HotkeyName,
|
||||
callback: HotkeyListener<SubKeyType<HotkeyConfig, HotkeyName>>,
|
||||
) {
|
||||
const { callbacks } = this.hotkeys[hotkeyName];
|
||||
const { callbacks } = this.hotKeys[hotkeyName];
|
||||
callbacks.push(callback);
|
||||
return () => {
|
||||
const index = callbacks.indexOf(callback);
|
||||
@ -71,15 +86,15 @@ export class HotkeyManager<HotkeyConfig extends Record<string, HotkeyEntry<strin
|
||||
}
|
||||
|
||||
addHotKeyDefinition(hotkey: keyof HotkeyConfig, definition: HotkeyDefinitionType) {
|
||||
this.hotkeys[hotkey].keys.push(definition);
|
||||
this.hotKeys[hotkey].keys.push(definition);
|
||||
}
|
||||
|
||||
removeHotkeyDefinition(hotkey: keyof HotkeyConfig, definition: HotkeyDefinitionType) {
|
||||
this.hotkeys[hotkey].keys = this.hotkeys[hotkey].keys.filter((key) => !HotkeyManager.isEqual(key, definition));
|
||||
removeHotKeyDefinition(hotkey: keyof HotkeyConfig, definition: HotkeyDefinitionType) {
|
||||
this.hotKeys[hotkey].keys = this.hotKeys[hotkey].keys.filter((key) => !HotKeyManager.isEqual(key, definition));
|
||||
}
|
||||
|
||||
setHotkeyDefinitions(hotkey: keyof HotkeyConfig, definitions: HotkeyDefinitionType[]) {
|
||||
this.hotkeys[hotkey].keys = definitions;
|
||||
setHotKeyDefinitions(hotkey: keyof HotkeyConfig, definitions: HotkeyDefinitionType[]) {
|
||||
this.hotKeys[hotkey].keys = definitions;
|
||||
}
|
||||
|
||||
addSubKeyDefinition<HotkeyName extends keyof HotkeyConfig>(
|
||||
@ -87,7 +102,7 @@ export class HotkeyManager<HotkeyConfig extends Record<string, HotkeyEntry<strin
|
||||
subKey: SubKeyType<HotkeyConfig, HotkeyName>,
|
||||
definition: HotkeyDefinitionType,
|
||||
) {
|
||||
this.hotkeys[hotkey].subKeys[subKey as string].push(definition);
|
||||
this.hotKeys[hotkey].subKeys[subKey as string].push(definition);
|
||||
}
|
||||
|
||||
removeSubKeyDefinition<HotkeyName extends keyof HotkeyConfig>(
|
||||
@ -95,8 +110,8 @@ export class HotkeyManager<HotkeyConfig extends Record<string, HotkeyEntry<strin
|
||||
subKey: SubKeyType<HotkeyConfig, HotkeyName>,
|
||||
definition: HotkeyDefinitionType,
|
||||
) {
|
||||
const { subKeys } = this.hotkeys[hotkey];
|
||||
subKeys[subKey as string] = subKeys[subKey as string].filter((key) => !HotkeyManager.isEqual(key, definition));
|
||||
const { subKeys } = this.hotKeys[hotkey];
|
||||
subKeys[subKey as string] = subKeys[subKey as string].filter((key) => !HotKeyManager.isEqual(key, definition));
|
||||
}
|
||||
|
||||
setSubKeyDefinitions<HotkeyName extends keyof HotkeyConfig>(
|
||||
@ -104,16 +119,16 @@ export class HotkeyManager<HotkeyConfig extends Record<string, HotkeyEntry<strin
|
||||
subKey: SubKeyType<HotkeyConfig, HotkeyName>,
|
||||
definitions: HotkeyDefinitionType[],
|
||||
) {
|
||||
this.hotkeys[hotkey].subKeys[subKey as string] = definitions;
|
||||
this.hotKeys[hotkey].subKeys[subKey as string] = definitions;
|
||||
}
|
||||
|
||||
getConfig() {
|
||||
return this.hotkeys;
|
||||
return this.hotKeys;
|
||||
}
|
||||
|
||||
addKeyListeners() {
|
||||
window.addEventListener('keydown', (e) => {
|
||||
if (this.ignoreFormElements && HotkeyManager.isFormElement(e.target)) {
|
||||
if (this.ignoreFormElements && HotKeyManager.isFormElement(e.target)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -134,16 +149,16 @@ export class HotkeyManager<HotkeyConfig extends Record<string, HotkeyEntry<strin
|
||||
});
|
||||
}
|
||||
|
||||
getHotkeysPressedMap() {
|
||||
return this.hotkeysPressedMap;
|
||||
getHotKeysPressedMap() {
|
||||
return this.hotKeysPressedMap;
|
||||
}
|
||||
|
||||
isHotkeyPressed(hotkey: keyof HotkeyConfig) {
|
||||
return this.hotkeysPressedMap[hotkey].isPressed;
|
||||
isHotKeyPressed(hotkey: keyof HotkeyConfig) {
|
||||
return this.hotKeysPressedMap[hotkey].isPressed;
|
||||
}
|
||||
|
||||
isSubKeyPressed<Hotkey extends keyof HotkeyConfig>(hotkey: Hotkey, subkey: SubKeyType<HotkeyConfig, Hotkey>) {
|
||||
return this.hotkeysPressedMap[hotkey].isPressed && this.hotkeysPressedMap[hotkey].subKeys[subkey];
|
||||
return this.hotKeysPressedMap[hotkey].isPressed && this.hotKeysPressedMap[hotkey].subKeys[subkey];
|
||||
}
|
||||
|
||||
private checkHotkeyDefinitions(keyDefinitions: HotkeyDefinitionType[]): boolean {
|
||||
@ -165,7 +180,7 @@ export class HotkeyManager<HotkeyConfig extends Record<string, HotkeyEntry<strin
|
||||
}
|
||||
|
||||
private generateHotkeyPressedMap() {
|
||||
return ObjectHelper.entries(this.hotkeys).reduce((acc, [key, value]) => {
|
||||
return ObjectHelper.entries(this.hotKeys).reduce((acc, [key, value]) => {
|
||||
const isPressed = this.checkHotkeyDefinitions(value.keys);
|
||||
acc[key] = {
|
||||
isPressed,
|
||||
@ -183,8 +198,8 @@ export class HotkeyManager<HotkeyConfig extends Record<string, HotkeyEntry<strin
|
||||
}
|
||||
|
||||
private triggerListenerFor(key: keyof HotkeyConfig, event: KeyboardEvent) {
|
||||
const pressedEntry = this.hotkeysPressedMap[key];
|
||||
this.hotkeys[key].callbacks.forEach((callback) =>
|
||||
const pressedEntry = this.hotKeysPressedMap[key];
|
||||
this.hotKeys[key].callbacks.forEach((callback) =>
|
||||
callback({ event, subKeys: pressedEntry.subKeys, isPressed: pressedEntry.isPressed }),
|
||||
);
|
||||
}
|
||||
@ -192,9 +207,9 @@ export class HotkeyManager<HotkeyConfig extends Record<string, HotkeyEntry<strin
|
||||
private checkHotkeys(event: KeyboardEvent) {
|
||||
const hotkeysToTrigger: (keyof HotkeyConfig)[] = [];
|
||||
|
||||
const oldMap = this.hotkeysPressedMap;
|
||||
this.hotkeysPressedMap = this.generateHotkeyPressedMap();
|
||||
const hotkeysToCheckAffection = ObjectHelper.entries(this.hotkeysPressedMap).filter(([key, value]) => {
|
||||
const oldMap = this.hotKeysPressedMap;
|
||||
this.hotKeysPressedMap = this.generateHotkeyPressedMap();
|
||||
const hotkeysToCheckAffection = ObjectHelper.entries(this.hotKeysPressedMap).filter(([key, value]) => {
|
||||
const oldValue = oldMap[key];
|
||||
if (
|
||||
oldValue.isPressed !== value.isPressed ||
|
||||
@ -209,12 +224,12 @@ export class HotkeyManager<HotkeyConfig extends Record<string, HotkeyEntry<strin
|
||||
// Check for repeated pressed. Nothing changed, but key is pressed again
|
||||
const eventKey = event.key.toLowerCase();
|
||||
hotkeysToCheckAffection.forEach(([key]) => {
|
||||
const keyDefinition = this.hotkeys[key];
|
||||
if (HotkeyManager.checkAffections(keyDefinition.keys, eventKey)) {
|
||||
const keyDefinition = this.hotKeys[key];
|
||||
if (HotKeyManager.checkAffections(keyDefinition.keys, eventKey)) {
|
||||
hotkeysToTrigger.push(key);
|
||||
} else {
|
||||
ObjectHelper.values(keyDefinition.subKeys).forEach((subKeyDefinitions) => {
|
||||
if (HotkeyManager.checkAffections(subKeyDefinitions, eventKey)) {
|
||||
if (HotKeyManager.checkAffections(subKeyDefinitions, eventKey)) {
|
||||
hotkeysToTrigger.push(key);
|
||||
}
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user