template/packages/system/src/hotkey/command.ts
2026-10-22 22:25:59 +08:00

124 lines
3.4 KiB
TypeScript

import { logger } from '@motajs/common';
import { KeyCode } from './keyCodes';
import { HotkeyEmitMode, IHotkeyCommand, IHotkeyCommandInit } from './type';
/**
* 判断按键是否为辅助按键,即 Ctrl / Shift / Alt / Meta 之一
* @param key 按键码
*/
export function isAuxiliaryKey(key: KeyCode): boolean {
return (
key === KeyCode.Ctrl ||
key === KeyCode.Shift ||
key === KeyCode.Alt ||
key === KeyCode.Meta
);
}
export class HotkeyCommand implements IHotkeyCommand {
readonly priority: number;
readonly block: boolean;
mode: HotkeyEmitMode;
interval: number;
timeout: number;
dt: number;
length: number;
/** 按键组合列表,长度与 {@link length} 保持一致 */
private keys: KeyCode[][] = [];
constructor(
readonly command: string,
init: IHotkeyCommandInit
) {
this.command = command;
this.priority = init.priority;
this.block = init.block ?? false;
this.mode = init.mode ?? HotkeyEmitMode.KeyUp;
this.timeout = init.timeout ?? 0;
this.interval = init.interval ?? 0;
this.dt = init.dt ?? 0;
this.length = 0;
this.setKeys(init.defaults.length);
init.defaults.forEach((keys, index) =>
this.setKeyCombination(index, keys)
);
}
setKeys(count: number): void {
if (!Number.isInteger(count)) {
logger.warn(207, 'float');
return;
}
if (count <= 0) {
logger.warn(207, 'negative integer');
return;
}
if (count > this.keys.length) {
while (count > this.keys.length) {
this.keys.push([]);
}
} else if (count < this.keys.length) {
while (count < this.keys.length) {
this.keys.pop();
}
}
this.length = this.keys.length;
}
setKeyCombination(index: number, keys: KeyCode[]): void {
if (!Number.isInteger(index)) {
logger.warn(206, 'float');
return;
}
if (index < 0) {
logger.warn(206, 'negetive integer');
return;
}
if (index >= this.keys.length) {
logger.warn(206, 'integer but exceeds combination count');
return;
}
this.keys[index] = keys.slice();
if (this.mode === HotkeyEmitMode.KeyUp) {
const regular = keys.filter(v => !isAuxiliaryKey(v));
if (regular.length >= 2) {
logger.warn(203, this.command);
}
}
}
getKeyCombination(index: number): readonly KeyCode[] {
return this.keys[index]?.slice() ?? [];
}
*iterateKeyCombinations(): Iterable<
[index: number, key: readonly KeyCode[]]
> {
for (let i = 0; i < this.keys.length; i++) {
yield [i, this.keys[i].slice()];
}
}
keyUp(timeout: number = 0): void {
this.mode = HotkeyEmitMode.KeyUp;
this.timeout = timeout;
}
once(timeout: number = 0): void {
this.mode = HotkeyEmitMode.Once;
this.timeout = timeout;
}
continuous(
interval: number = 0,
dt: number = 0,
timeout: number = 0
): void {
this.mode = HotkeyEmitMode.Continuous;
this.interval = interval;
this.dt = dt;
this.timeout = timeout;
}
}