polyv-live-cli
Version:
CLI tool for managing PolyV live streaming services.
193 lines • 6.33 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.KeyboardHandler = void 0;
class KeyboardHandler {
constructor() {
this.shortcuts = new Map();
this.keySequences = new Map();
this.currentSequence = [];
this.SEQUENCE_TIMEOUT_MS = 1000;
}
static normalizeKeyEvent(rawKey, rawCh) {
if (!rawKey) {
return {
key: '',
shift: false,
ctrl: false,
alt: false,
meta: false,
ch: rawCh || '',
};
}
return {
key: rawKey.name || rawKey.key || '',
shift: !!rawKey.shift,
ctrl: !!rawKey.ctrl,
alt: !!rawKey.meta || !!rawKey.alt,
meta: !!rawKey.meta,
full: rawKey.full || '',
ch: rawCh || rawKey.ch || '',
};
}
static buildShortcutKey(event) {
const parts = [];
if (event.ctrl)
parts.push('ctrl');
if (event.alt)
parts.push('alt');
if (event.shift)
parts.push('shift');
if (event.meta)
parts.push('meta');
if (event.key) {
parts.push(event.key.toLowerCase());
}
return parts.join('+');
}
static parseShortcutKey(shortcut) {
const parts = shortcut.toLowerCase().split('+');
const key = parts[parts.length - 1] || '';
return {
ctrl: parts.includes('ctrl') || parts.includes('c'),
alt: parts.includes('alt') || parts.includes('a'),
shift: parts.includes('shift') || parts.includes('s'),
meta: parts.includes('meta') || parts.includes('m'),
key,
};
}
static matchesShortcut(event, shortcut) {
const expected = KeyboardHandler.parseShortcutKey(shortcut);
const actual = KeyboardHandler.buildShortcutKey(event);
const expectedKey = KeyboardHandler.buildShortcutKey({
key: expected.key,
ctrl: expected.ctrl,
alt: expected.alt,
shift: expected.shift,
meta: expected.meta,
});
return actual === expectedKey;
}
registerShortcut(config) {
const key = config.key.toLowerCase();
this.shortcuts.set(key, config);
}
unregisterShortcut(key) {
this.shortcuts.delete(key.toLowerCase());
}
findMatchingShortcut(event) {
for (const [key, config] of this.shortcuts) {
if (KeyboardHandler.matchesShortcut(event, key)) {
return config;
}
}
return this.checkSequenceMatch(event);
}
registerKeySequence(sequence, action) {
const key = sequence.join(' ');
this.keySequences.set(key, sequence);
this.registerShortcut({
key,
description: `Key sequence: ${sequence.join(' ')}`,
action,
global: true,
});
}
checkSequenceMatch(event) {
const eventKey = event.key.toLowerCase();
this.currentSequence.push(eventKey);
if (this.sequenceTimeout) {
clearTimeout(this.sequenceTimeout);
}
this.sequenceTimeout = setTimeout(() => {
this.currentSequence = [];
}, this.SEQUENCE_TIMEOUT_MS);
const currentSequenceKey = this.currentSequence.join(' ');
for (const [sequenceKey, _sequence] of this.keySequences) {
if (sequenceKey === currentSequenceKey) {
this.currentSequence = [];
if (this.sequenceTimeout) {
clearTimeout(this.sequenceTimeout);
}
return this.shortcuts.get(sequenceKey);
}
else if (sequenceKey.startsWith(currentSequenceKey + ' ')) {
return undefined;
}
}
this.currentSequence = [];
if (this.sequenceTimeout) {
clearTimeout(this.sequenceTimeout);
}
return undefined;
}
static isNavigationKey(key) {
const navigationKeys = [
'up', 'down', 'left', 'right',
'home', 'end', 'pageup', 'pagedown',
'tab', 'enter', 'escape', 'space',
];
return navigationKeys.includes(key.toLowerCase());
}
static isFunctionKey(key) {
return /^f\d+$/.test(key.toLowerCase());
}
static isPrintableKey(event) {
if (KeyboardHandler.isFunctionKey(event.key) ||
KeyboardHandler.isNavigationKey(event.key) ||
event.ctrl || event.alt || event.meta) {
return false;
}
return event.ch !== undefined && event.ch.length === 1;
}
static getKeyDescription(event) {
const parts = [];
if (event.ctrl)
parts.push('Ctrl');
if (event.alt)
parts.push('Alt');
if (event.shift)
parts.push('Shift');
if (event.meta)
parts.push('Meta');
let keyName = event.key;
if (keyName) {
keyName = keyName.charAt(0).toUpperCase() + keyName.slice(1);
const keyMappings = {
'Escape': 'Esc',
'Enter': '↵',
'Tab': '⇥',
'Space': '␣',
'Up': '↑',
'Down': '↓',
'Left': '←',
'Right': '→',
'Pageup': 'PgUp',
'Pagedown': 'PgDn',
};
keyName = keyMappings[keyName] || keyName;
}
parts.push(keyName);
return parts.join('+');
}
getShortcuts() {
return Array.from(this.shortcuts.values());
}
getShortcutsByContext(context) {
return Array.from(this.shortcuts.values())
.filter(shortcut => shortcut.context === context || shortcut.global);
}
clear() {
this.shortcuts.clear();
this.keySequences.clear();
this.currentSequence = [];
if (this.sequenceTimeout) {
clearTimeout(this.sequenceTimeout);
this.sequenceTimeout = undefined;
}
}
destroy() {
this.clear();
}
}
exports.KeyboardHandler = KeyboardHandler;
//# sourceMappingURL=keyboard-handler.js.map