@flighthq/shortcut 0.3.0-next.906.07cea63 → 0.3.1-next.209.43ef1bc
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/contract.d.ts +2 -0
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +2 -0
- package/dist/contract.js.map +1 -1
- package/dist/enableShortcutGuards.d.ts +3 -0
- package/dist/enableShortcutGuards.d.ts.map +1 -0
- package/dist/enableShortcutGuards.js +32 -0
- package/dist/enableShortcutGuards.js.map +1 -0
- package/dist/explainGlobalShortcutRegistration.d.ts +3 -0
- package/dist/explainGlobalShortcutRegistration.d.ts.map +1 -0
- package/dist/explainGlobalShortcutRegistration.js +35 -0
- package/dist/explainGlobalShortcutRegistration.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/shortcut.d.ts +7 -3
- package/dist/shortcut.d.ts.map +1 -1
- package/dist/shortcut.js +146 -34
- package/dist/shortcut.js.map +1 -1
- package/package.json +6 -3
- package/src/enableShortcutGuards.test.ts +122 -0
- package/src/explainGlobalShortcutRegistration.test.ts +93 -0
- package/src/shortcut.test.ts +247 -0
package/dist/contract.d.ts
CHANGED
package/dist/contract.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,qCAAqC,CAAC;AACpD,cAAc,YAAY,CAAC"}
|
package/dist/contract.js
CHANGED
package/dist/contract.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,qCAAqC,CAAC;AACpD,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enableShortcutGuards.d.ts","sourceRoot":"","sources":["../src/enableShortcutGuards.ts"],"names":[],"mappings":"AAOA,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAQD,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { logOnce } from '@flighthq/log/contract';
|
|
2
|
+
import { LogLevel } from '@flighthq/types/contract';
|
|
3
|
+
import { setShortcutDropGuard } from './shortcut';
|
|
4
|
+
// Uninstalls the guard installed by enableShortcutGuards.
|
|
5
|
+
export function disableShortcutGuards() {
|
|
6
|
+
setShortcutDropGuard(null);
|
|
7
|
+
}
|
|
8
|
+
// Installs the caller-facing shortcut guard (opt-in, dev-only). Every global-shortcut command answers
|
|
9
|
+
// a bad call with the same `false` a legitimate miss returns, so the two footguns this package has are
|
|
10
|
+
// both silent: an accelerator string the parser rejects, and a whole application wired up against the
|
|
11
|
+
// default web backend, which has no OS registry to act on. The guard warns once per cause through
|
|
12
|
+
// @flighthq/log. Not importing this module costs production nothing — the message text and the
|
|
13
|
+
// @flighthq/log dependency live only here, and the command path sees a null slot. Idempotent.
|
|
14
|
+
export function enableShortcutGuards() {
|
|
15
|
+
setShortcutDropGuard(warnOnShortcutDrop);
|
|
16
|
+
}
|
|
17
|
+
function warnOnShortcutDrop(drop) {
|
|
18
|
+
if (drop.reason === 'no-native-backend') {
|
|
19
|
+
logOnce('shortcut:no-native-backend', LogLevel.Warn, {
|
|
20
|
+
message: `${drop.operation}: no native shortcut backend is installed, so the default web backend handled this call — a browser cannot register OS-level global hotkeys. Call setShortcutBackend(...) from a native host (Electron/Tauri), and gate the feature on hasNativeShortcutBackend().`,
|
|
21
|
+
}, 'shortcut');
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const parseError = drop.parseError;
|
|
25
|
+
const detail = parseError === null
|
|
26
|
+
? 'it did not parse'
|
|
27
|
+
: `${parseError.reason}${parseError.token === '' ? '' : ` at '${parseError.token}'`}`;
|
|
28
|
+
logOnce('shortcut:unparseable-accelerator', LogLevel.Warn, {
|
|
29
|
+
message: `${drop.operation}('${drop.accelerator}'): the accelerator was dropped because ${detail}. Check the spelling against parseAcceleratorDetailed, or explainGlobalShortcutRegistration for the whole picture.`,
|
|
30
|
+
}, 'shortcut');
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=enableShortcutGuards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enableShortcutGuards.js","sourceRoot":"","sources":["../src/enableShortcutGuards.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEjD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAElD,0DAA0D;AAC1D,MAAM,UAAU,qBAAqB;IACnC,oBAAoB,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AAED,sGAAsG;AACtG,uGAAuG;AACvG,sGAAsG;AACtG,kGAAkG;AAClG,+FAA+F;AAC/F,8FAA8F;AAC9F,MAAM,UAAU,oBAAoB;IAClC,oBAAoB,CAAC,kBAAkB,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,kBAAkB,CAAC,IAA4B;IACtD,IAAI,IAAI,CAAC,MAAM,KAAK,mBAAmB,EAAE,CAAC;QACxC,OAAO,CACL,4BAA4B,EAC5B,QAAQ,CAAC,IAAI,EACb;YACE,OAAO,EAAE,GAAG,IAAI,CAAC,SAAS,oQAAoQ;SAC/R,EACD,UAAU,CACX,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;IACnC,MAAM,MAAM,GACV,UAAU,KAAK,IAAI;QACjB,CAAC,CAAC,kBAAkB;QACpB,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM,GAAG,UAAU,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC;IAC1F,OAAO,CACL,kCAAkC,EAClC,QAAQ,CAAC,IAAI,EACb;QACE,OAAO,EAAE,GAAG,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,WAAW,2CAA2C,MAAM,oHAAoH;KACrN,EACD,UAAU,CACX,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explainGlobalShortcutRegistration.d.ts","sourceRoot":"","sources":["../src/explainGlobalShortcutRegistration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA6B,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAiBrG,wBAAgB,iCAAiC,CAAC,WAAW,EAAE,MAAM,GAAG,yBAAyB,CAgBhG"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createParsedAccelerator, hasNativeShortcutBackend, isGlobalShortcutRegistered, parseAcceleratorDetailed, } from './shortcut';
|
|
2
|
+
// Recomputes why registerGlobalShortcut(`accelerator`, …) would or would not take, and returns it as
|
|
3
|
+
// plain data. Pure: it re-runs the parser and reads the active backend's registry, mutates nothing,
|
|
4
|
+
// registers nothing, never throws on malformed input, and retains no reference to the backend. Import
|
|
5
|
+
// it to debug a hotkey that silently never fires; it sheds from production when unimported.
|
|
6
|
+
//
|
|
7
|
+
// This is the pull half of the diagnostics convention, and it duplicates the register path's drop
|
|
8
|
+
// conditions by design — the maintenance seam is that a new gate on registerGlobalShortcut must gain
|
|
9
|
+
// a matching check here or this query silently goes stale.
|
|
10
|
+
export function explainGlobalShortcutRegistration(accelerator) {
|
|
11
|
+
const parsed = parseAcceleratorDetailed(accelerator, createParsedAccelerator());
|
|
12
|
+
const failed = 'reason' in parsed;
|
|
13
|
+
const parseError = failed ? parsed : null;
|
|
14
|
+
const normalized = failed ? null : _joinNormalized(parsed.modifiers, parsed.key);
|
|
15
|
+
const hasBackend = hasNativeShortcutBackend();
|
|
16
|
+
const registered = normalized !== null && isGlobalShortcutRegistered(normalized);
|
|
17
|
+
let reason;
|
|
18
|
+
if (failed)
|
|
19
|
+
reason = 'unparseable';
|
|
20
|
+
else if (!hasBackend)
|
|
21
|
+
reason = 'no-native-backend';
|
|
22
|
+
else if (registered)
|
|
23
|
+
reason = 'already-registered';
|
|
24
|
+
else
|
|
25
|
+
reason = 'ok';
|
|
26
|
+
return { accelerator, hasNativeBackend: hasBackend, normalized, parseError, registered, reason };
|
|
27
|
+
}
|
|
28
|
+
// Rebuilds the canonical string from an already-parsed chord. Local rather than a call back into
|
|
29
|
+
// normalizeAccelerator so the explanation costs one parse, not two.
|
|
30
|
+
function _joinNormalized(modifiers, key) {
|
|
31
|
+
if (modifiers.length === 0)
|
|
32
|
+
return key;
|
|
33
|
+
return [...modifiers, key].join('+');
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=explainGlobalShortcutRegistration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explainGlobalShortcutRegistration.js","sourceRoot":"","sources":["../src/explainGlobalShortcutRegistration.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,0BAA0B,EAC1B,wBAAwB,GACzB,MAAM,YAAY,CAAC;AAEpB,qGAAqG;AACrG,oGAAoG;AACpG,sGAAsG;AACtG,4FAA4F;AAC5F,EAAE;AACF,kGAAkG;AAClG,qGAAqG;AACrG,2DAA2D;AAC3D,MAAM,UAAU,iCAAiC,CAAC,WAAmB;IACnE,MAAM,MAAM,GAAG,wBAAwB,CAAC,WAAW,EAAE,uBAAuB,EAAE,CAAC,CAAC;IAChF,MAAM,MAAM,GAAG,QAAQ,IAAI,MAAM,CAAC;IAClC,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1C,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IAEjF,MAAM,UAAU,GAAG,wBAAwB,EAAE,CAAC;IAC9C,MAAM,UAAU,GAAG,UAAU,KAAK,IAAI,IAAI,0BAA0B,CAAC,UAAU,CAAC,CAAC;IAEjF,IAAI,MAAiC,CAAC;IACtC,IAAI,MAAM;QAAE,MAAM,GAAG,aAAa,CAAC;SAC9B,IAAI,CAAC,UAAU;QAAE,MAAM,GAAG,mBAAmB,CAAC;SAC9C,IAAI,UAAU;QAAE,MAAM,GAAG,oBAAoB,CAAC;;QAC9C,MAAM,GAAG,IAAI,CAAC;IAEnB,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;AACnG,CAAC;AAED,iGAAiG;AACjG,oEAAoE;AACpE,SAAS,eAAe,CAAC,SAA4B,EAAE,GAAW;IAChE,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IACvC,OAAO,CAAC,GAAG,SAAS,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACvC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { createParsedAccelerator, disableGlobalShortcut, enableGlobalShortcut, enableGlobalShortcutSignals, equalsAccelerator, formatAcceleratorForDisplay, getAcceleratorKey, getAcceleratorKeyLabel, getAcceleratorModifierLabel, getAcceleratorModifiers, getRegisteredGlobalShortcuts, hasGlobalShortcutConflict, isAcceleratorValid, isGlobalShortcutRegistered, normalizeAccelerator, parseAccelerator, parseAcceleratorDetailed, registerGlobalShortcut, resolveCommandOrControlModifier, resumeAllGlobalShortcuts, suspendAllGlobalShortcuts, unregisterAllGlobalShortcuts, unregisterGlobalShortcut, } from './contract';
|
|
1
|
+
export { createParsedAccelerator, disableGlobalShortcut, disableShortcutGuards, disposeGlobalShortcutSignals, enableGlobalShortcut, enableGlobalShortcutSignals, enableShortcutGuards, equalsAccelerator, explainGlobalShortcutRegistration, findAcceleratorConflict, formatAcceleratorForDisplay, getAcceleratorKey, getAcceleratorKeyLabel, getAcceleratorModifierLabel, getAcceleratorModifiers, getRegisteredGlobalShortcuts, hasGlobalShortcutConflict, hasNativeShortcutBackend, isAcceleratorValid, isGlobalShortcutRegistered, normalizeAccelerator, parseAccelerator, parseAcceleratorDetailed, registerGlobalShortcut, resolveCommandOrControlModifier, resumeAllGlobalShortcuts, suspendAllGlobalShortcuts, unregisterAllGlobalShortcuts, unregisterGlobalShortcut, } from './contract';
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,oBAAoB,EACpB,2BAA2B,EAC3B,iBAAiB,EACjB,2BAA2B,EAC3B,iBAAiB,EACjB,sBAAsB,EACtB,2BAA2B,EAC3B,uBAAuB,EACvB,4BAA4B,EAC5B,yBAAyB,EACzB,kBAAkB,EAClB,0BAA0B,EAC1B,oBAAoB,EACpB,gBAAgB,EAChB,wBAAwB,EACxB,sBAAsB,EACtB,+BAA+B,EAC/B,wBAAwB,EACxB,yBAAyB,EACzB,4BAA4B,EAC5B,wBAAwB,GACzB,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,qBAAqB,EACrB,4BAA4B,EAC5B,oBAAoB,EACpB,2BAA2B,EAC3B,oBAAoB,EACpB,iBAAiB,EACjB,iCAAiC,EACjC,uBAAuB,EACvB,2BAA2B,EAC3B,iBAAiB,EACjB,sBAAsB,EACtB,2BAA2B,EAC3B,uBAAuB,EACvB,4BAA4B,EAC5B,yBAAyB,EACzB,wBAAwB,EACxB,kBAAkB,EAClB,0BAA0B,EAC1B,oBAAoB,EACpB,gBAAgB,EAChB,wBAAwB,EACxB,sBAAsB,EACtB,+BAA+B,EAC/B,wBAAwB,EACxB,yBAAyB,EACzB,4BAA4B,EAC5B,wBAAwB,GACzB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { createParsedAccelerator, disableGlobalShortcut, enableGlobalShortcut, enableGlobalShortcutSignals, equalsAccelerator, formatAcceleratorForDisplay, getAcceleratorKey, getAcceleratorKeyLabel, getAcceleratorModifierLabel, getAcceleratorModifiers, getRegisteredGlobalShortcuts, hasGlobalShortcutConflict, isAcceleratorValid, isGlobalShortcutRegistered, normalizeAccelerator, parseAccelerator, parseAcceleratorDetailed, registerGlobalShortcut, resolveCommandOrControlModifier, resumeAllGlobalShortcuts, suspendAllGlobalShortcuts, unregisterAllGlobalShortcuts, unregisterGlobalShortcut, } from './contract';
|
|
1
|
+
export { createParsedAccelerator, disableGlobalShortcut, disableShortcutGuards, disposeGlobalShortcutSignals, enableGlobalShortcut, enableGlobalShortcutSignals, enableShortcutGuards, equalsAccelerator, explainGlobalShortcutRegistration, findAcceleratorConflict, formatAcceleratorForDisplay, getAcceleratorKey, getAcceleratorKeyLabel, getAcceleratorModifierLabel, getAcceleratorModifiers, getRegisteredGlobalShortcuts, hasGlobalShortcutConflict, hasNativeShortcutBackend, isAcceleratorValid, isGlobalShortcutRegistered, normalizeAccelerator, parseAccelerator, parseAcceleratorDetailed, registerGlobalShortcut, resolveCommandOrControlModifier, resumeAllGlobalShortcuts, suspendAllGlobalShortcuts, unregisterAllGlobalShortcuts, unregisterGlobalShortcut, } from './contract';
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,oBAAoB,EACpB,2BAA2B,EAC3B,iBAAiB,EACjB,2BAA2B,EAC3B,iBAAiB,EACjB,sBAAsB,EACtB,2BAA2B,EAC3B,uBAAuB,EACvB,4BAA4B,EAC5B,yBAAyB,EACzB,kBAAkB,EAClB,0BAA0B,EAC1B,oBAAoB,EACpB,gBAAgB,EAChB,wBAAwB,EACxB,sBAAsB,EACtB,+BAA+B,EAC/B,wBAAwB,EACxB,yBAAyB,EACzB,4BAA4B,EAC5B,wBAAwB,GACzB,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,qBAAqB,EACrB,4BAA4B,EAC5B,oBAAoB,EACpB,2BAA2B,EAC3B,oBAAoB,EACpB,iBAAiB,EACjB,iCAAiC,EACjC,uBAAuB,EACvB,2BAA2B,EAC3B,iBAAiB,EACjB,sBAAsB,EACtB,2BAA2B,EAC3B,uBAAuB,EACvB,4BAA4B,EAC5B,yBAAyB,EACzB,wBAAwB,EACxB,kBAAkB,EAClB,0BAA0B,EAC1B,oBAAoB,EACpB,gBAAgB,EAChB,wBAAwB,EACxB,sBAAsB,EACtB,+BAA+B,EAC/B,wBAAwB,EACxB,yBAAyB,EACzB,4BAA4B,EAC5B,wBAAwB,GACzB,MAAM,YAAY,CAAC"}
|
package/dist/shortcut.d.ts
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
|
-
import type { Accelerator, AcceleratorParseError, ParsedAccelerator, ShortcutBackend, ShortcutEvent, ShortcutModifier, ShortcutSignals } from '@flighthq/types/contract';
|
|
1
|
+
import type { Accelerator, AcceleratorParseError, ParsedAccelerator, ShortcutBackend, ShortcutDropGuard, ShortcutEvent, ShortcutKeyName, ShortcutModifier, ShortcutSignals } from '@flighthq/types/contract';
|
|
2
2
|
export declare function createParsedAccelerator(): ParsedAccelerator;
|
|
3
3
|
export declare function createWebShortcutBackend(): ShortcutBackend;
|
|
4
4
|
export declare function disableGlobalShortcut(accelerator: string): boolean;
|
|
5
|
+
export declare function disposeGlobalShortcutSignals(): void;
|
|
5
6
|
export declare function enableGlobalShortcut(accelerator: string): boolean;
|
|
6
7
|
export declare function enableGlobalShortcutSignals(): ShortcutSignals;
|
|
7
8
|
export declare function equalsAccelerator(a: string, b: string): boolean;
|
|
9
|
+
export declare function findAcceleratorConflict(accelerator: string, candidates: readonly string[]): string | null;
|
|
8
10
|
export declare function formatAcceleratorForDisplay(accelerator: string, platform?: string): string;
|
|
9
|
-
export declare function getAcceleratorKey(accelerator: string):
|
|
10
|
-
export declare function getAcceleratorKeyLabel(key:
|
|
11
|
+
export declare function getAcceleratorKey(accelerator: string): ShortcutKeyName | null;
|
|
12
|
+
export declare function getAcceleratorKeyLabel(key: ShortcutKeyName): string;
|
|
11
13
|
export declare function getAcceleratorModifierLabel(modifier: ShortcutModifier, platform?: string): string;
|
|
12
14
|
export declare function getAcceleratorModifiers(accelerator: string, out: ShortcutModifier[]): readonly ShortcutModifier[] | null;
|
|
13
15
|
export declare function getRegisteredGlobalShortcuts(): readonly Accelerator[];
|
|
14
16
|
export declare function getShortcutBackend(): ShortcutBackend;
|
|
15
17
|
export declare function hasGlobalShortcutConflict(accelerator: string): boolean;
|
|
18
|
+
export declare function hasNativeShortcutBackend(): boolean;
|
|
16
19
|
export declare function isAcceleratorValid(input: string): boolean;
|
|
17
20
|
export declare function isGlobalShortcutRegistered(accelerator: string): boolean;
|
|
18
21
|
export declare function normalizeAccelerator(input: string): Accelerator | null;
|
|
@@ -22,6 +25,7 @@ export declare function registerGlobalShortcut(accelerator: string, handler: (ev
|
|
|
22
25
|
export declare function resolveCommandOrControlModifier(platform?: string): Exclude<ShortcutModifier, 'CommandOrControl'>;
|
|
23
26
|
export declare function resumeAllGlobalShortcuts(): void;
|
|
24
27
|
export declare function setShortcutBackend(backend: ShortcutBackend | null): void;
|
|
28
|
+
export declare function setShortcutDropGuard(guard: ShortcutDropGuard | null): void;
|
|
25
29
|
export declare function suspendAllGlobalShortcuts(): void;
|
|
26
30
|
export declare function unregisterAllGlobalShortcuts(): void;
|
|
27
31
|
export declare function unregisterGlobalShortcut(accelerator: string): boolean;
|
package/dist/shortcut.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shortcut.d.ts","sourceRoot":"","sources":["../src/shortcut.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,qBAAqB,EACrB,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,gBAAgB,
|
|
1
|
+
{"version":3,"file":"shortcut.d.ts","sourceRoot":"","sources":["../src/shortcut.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,qBAAqB,EACrB,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,gBAAgB,EAEhB,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAGlC,wBAAgB,uBAAuB,IAAI,iBAAiB,CAE3D;AAKD,wBAAgB,wBAAwB,IAAI,eAAe,CAwB1D;AAID,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAIlE;AAMD,wBAAgB,4BAA4B,IAAI,IAAI,CAInD;AAGD,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAIjE;AAMD,wBAAgB,2BAA2B,IAAI,eAAe,CAI7D;AAID,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAK/D;AASD,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAOzG;AAOD,wBAAgB,2BAA2B,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAW1F;AAGD,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAG7E;AAID,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAEnE;AAKD,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,gBAAgB,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAGjG;AAID,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,gBAAgB,EAAE,GACtB,SAAS,gBAAgB,EAAE,GAAG,IAAI,CAMpC;AAMD,wBAAgB,4BAA4B,IAAI,SAAS,WAAW,EAAE,CAQrE;AAMD,wBAAgB,kBAAkB,IAAI,eAAe,CAIpD;AAID,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAItE;AAKD,wBAAgB,wBAAwB,IAAI,OAAO,CAElD;AAKD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEzD;AAID,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAIvE;AAKD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAItE;AAKD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,iBAAiB,GAAG,iBAAiB,GAAG,IAAI,CAIhG;AAKD,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,iBAAiB,GACrB,iBAAiB,GAAG,qBAAqB,CAI3C;AAKD,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,aAAa,CAAC,KAAK,IAAI,GAChD,OAAO,CAQT;AAKD,wBAAgB,+BAA+B,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,kBAAkB,CAAC,CAEhH;AAGD,wBAAgB,wBAAwB,IAAI,IAAI,CAG/C;AAGD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,GAAG,IAAI,CAExE;AAKD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,GAAG,IAAI,CAE1E;AAID,wBAAgB,yBAAyB,IAAI,IAAI,CAGhD;AAGD,wBAAgB,4BAA4B,IAAI,IAAI,CAGnD;AAID,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAIrE"}
|
package/dist/shortcut.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createSignal, emitSignal } from '@flighthq/signals/contract';
|
|
1
|
+
import { clearSignal, createSignal, emitSignal } from '@flighthq/signals/contract';
|
|
2
2
|
// Allocates a zeroed ParsedAccelerator for use as an `out` argument to parseAccelerator.
|
|
3
3
|
export function createParsedAccelerator() {
|
|
4
4
|
return { key: '', modifiers: [] };
|
|
@@ -34,14 +34,24 @@ export function createWebShortcutBackend() {
|
|
|
34
34
|
// Disables a registered global shortcut without unregistering it; the handler is preserved and
|
|
35
35
|
// can be re-enabled later. Returns false when not registered or unsupported.
|
|
36
36
|
export function disableGlobalShortcut(accelerator) {
|
|
37
|
-
const normalized =
|
|
37
|
+
const normalized = _normalizeForCommand(accelerator, 'disableGlobalShortcut');
|
|
38
38
|
if (normalized === null)
|
|
39
39
|
return false;
|
|
40
40
|
return getShortcutBackend().setEnabled(normalized, false);
|
|
41
41
|
}
|
|
42
|
+
// Releases the global shortcut signal group armed by enableGlobalShortcutSignals: disconnects every
|
|
43
|
+
// onTrigger listener and drops the group so it becomes eligible for collection. A later
|
|
44
|
+
// enableGlobalShortcutSignals arms a fresh group — the identity is not preserved across a dispose.
|
|
45
|
+
// Registered shortcuts are untouched; their directly-registered handlers keep firing.
|
|
46
|
+
export function disposeGlobalShortcutSignals() {
|
|
47
|
+
if (_signals === null)
|
|
48
|
+
return;
|
|
49
|
+
clearSignal(_signals.onTrigger);
|
|
50
|
+
_signals = null;
|
|
51
|
+
}
|
|
42
52
|
// Re-enables a previously disabled global shortcut. Returns false when not registered or unsupported.
|
|
43
53
|
export function enableGlobalShortcut(accelerator) {
|
|
44
|
-
const normalized =
|
|
54
|
+
const normalized = _normalizeForCommand(accelerator, 'enableGlobalShortcut');
|
|
45
55
|
if (normalized === null)
|
|
46
56
|
return false;
|
|
47
57
|
return getShortcutBackend().setEnabled(normalized, true);
|
|
@@ -65,6 +75,23 @@ export function equalsAccelerator(a, b) {
|
|
|
65
75
|
return false;
|
|
66
76
|
return na === nb;
|
|
67
77
|
}
|
|
78
|
+
// Returns the first accelerator in `candidates` that names the same chord as `accelerator`, or null
|
|
79
|
+
// when none does. The conflict probe for a key-binding UI: it answers "is this chord already spoken
|
|
80
|
+
// for in *my* binding list", which is the question a settings screen asks before it lets a user
|
|
81
|
+
// commit a rebind — hasGlobalShortcutConflict only sees chords already registered with the OS, so it
|
|
82
|
+
// cannot see a pending list, another profile's bindings, or a chord the app reserves for itself.
|
|
83
|
+
// Comparison is by normalized form, so any accepted spelling on either side matches. Unparseable
|
|
84
|
+
// candidates never match, and an unparseable `accelerator` returns null.
|
|
85
|
+
export function findAcceleratorConflict(accelerator, candidates) {
|
|
86
|
+
const normalized = normalizeAccelerator(accelerator);
|
|
87
|
+
if (normalized === null)
|
|
88
|
+
return null;
|
|
89
|
+
for (const candidate of candidates) {
|
|
90
|
+
if (normalizeAccelerator(candidate) === normalized)
|
|
91
|
+
return candidate;
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
68
95
|
// Formats an accelerator string for human-readable display per the current OS:
|
|
69
96
|
// macOS: ⌘⇧K (symbols, no separator)
|
|
70
97
|
// Windows/Linux: Ctrl+Shift+K (text labels, '+' separator)
|
|
@@ -126,10 +153,15 @@ export function getRegisteredGlobalShortcuts() {
|
|
|
126
153
|
return result;
|
|
127
154
|
}
|
|
128
155
|
// The active shortcut backend, or a lazily-created web default. There is always a backend.
|
|
156
|
+
// The default is cached in its own slot rather than assigned into the installed-backend slot, so
|
|
157
|
+
// "a host installed a backend" stays distinguishable from "we fell back" for the whole process —
|
|
158
|
+
// folding the two together would make hasNativeShortcutBackend read true after the first command.
|
|
129
159
|
export function getShortcutBackend() {
|
|
130
|
-
if (_backend
|
|
131
|
-
_backend
|
|
132
|
-
|
|
160
|
+
if (_backend !== null)
|
|
161
|
+
return _backend;
|
|
162
|
+
if (_webBackend === null)
|
|
163
|
+
_webBackend = createWebShortcutBackend();
|
|
164
|
+
return _webBackend;
|
|
133
165
|
}
|
|
134
166
|
// True when the (normalized) chord is already registered. A conflict probe over isGlobalShortcutRegistered.
|
|
135
167
|
// Returns false when `accelerator` is unparseable.
|
|
@@ -139,6 +171,12 @@ export function hasGlobalShortcutConflict(accelerator) {
|
|
|
139
171
|
return false;
|
|
140
172
|
return isGlobalShortcutRegistered(normalized);
|
|
141
173
|
}
|
|
174
|
+
// True when a native host backend is installed. False means the default web backend is active, whose
|
|
175
|
+
// registry is a sentinel — no chord can register, and every command is a no-op. The capability probe
|
|
176
|
+
// an application uses to decide whether to offer a global-hotkey settings screen at all.
|
|
177
|
+
export function hasNativeShortcutBackend() {
|
|
178
|
+
return _backend !== null;
|
|
179
|
+
}
|
|
142
180
|
// True when `input` is a parseable accelerator (valid modifiers + recognized key).
|
|
143
181
|
// Callers can use this to distinguish a malformed accelerator from an unsupported one before
|
|
144
182
|
// attempting to register.
|
|
@@ -169,9 +207,7 @@ export function parseAccelerator(input, out) {
|
|
|
169
207
|
const result = _parse(input);
|
|
170
208
|
if (result === null)
|
|
171
209
|
return null;
|
|
172
|
-
|
|
173
|
-
out.modifiers = result.modifiers.slice();
|
|
174
|
-
return out;
|
|
210
|
+
return _copyParsed(result, out);
|
|
175
211
|
}
|
|
176
212
|
// Like parseAccelerator but returns an AcceleratorParseError describing why parsing failed instead
|
|
177
213
|
// of null. The common path (parse + ignore error) should use parseAccelerator; this is for
|
|
@@ -180,15 +216,13 @@ export function parseAcceleratorDetailed(input, out) {
|
|
|
180
216
|
const result = _parseDetailed(input);
|
|
181
217
|
if ('reason' in result)
|
|
182
218
|
return result;
|
|
183
|
-
|
|
184
|
-
out.modifiers = result.modifiers.slice();
|
|
185
|
-
return out;
|
|
219
|
+
return _copyParsed(result, out);
|
|
186
220
|
}
|
|
187
221
|
// Registers a global hotkey. Returns false when the host lacks global-hotkey support (e.g. web).
|
|
188
222
|
// Input is normalized before registration so any accepted spelling maps to the same registry slot.
|
|
189
223
|
// When enableGlobalShortcutSignals() has been called, the onTrigger signal fires after the handler.
|
|
190
224
|
export function registerGlobalShortcut(accelerator, handler) {
|
|
191
|
-
const normalized =
|
|
225
|
+
const normalized = _normalizeForCommand(accelerator, 'registerGlobalShortcut');
|
|
192
226
|
if (normalized === null)
|
|
193
227
|
return false;
|
|
194
228
|
const wrappedHandler = (event) => {
|
|
@@ -206,31 +240,47 @@ export function resolveCommandOrControlModifier(platform) {
|
|
|
206
240
|
}
|
|
207
241
|
// Resumes all global shortcuts after suspendAllGlobalShortcuts(). No-op on unsupported hosts.
|
|
208
242
|
export function resumeAllGlobalShortcuts() {
|
|
243
|
+
_reportNoNativeBackend('resumeAllGlobalShortcuts', '');
|
|
209
244
|
getShortcutBackend().setAllEnabled(true);
|
|
210
245
|
}
|
|
211
246
|
// Installs a native host shortcut backend; pass null to fall back to the web default.
|
|
212
247
|
export function setShortcutBackend(backend) {
|
|
213
248
|
_backend = backend;
|
|
214
249
|
}
|
|
250
|
+
// Installs the drop guard consulted whenever a global-shortcut command returns its sentinel for a
|
|
251
|
+
// knowable caller error; null uninstalls it. This is the diagnostics seam, not the caller-facing
|
|
252
|
+
// entry point — use enableShortcutGuards, which installs the @flighthq/log reporter through here.
|
|
253
|
+
export function setShortcutDropGuard(guard) {
|
|
254
|
+
_dropGuard = guard;
|
|
255
|
+
}
|
|
215
256
|
// Temporarily silences all registered global shortcuts without unregistering them — useful when a
|
|
216
257
|
// modal or text field has focus. Resume with resumeAllGlobalShortcuts(). No-op on unsupported hosts.
|
|
217
258
|
export function suspendAllGlobalShortcuts() {
|
|
259
|
+
_reportNoNativeBackend('suspendAllGlobalShortcuts', '');
|
|
218
260
|
getShortcutBackend().setAllEnabled(false);
|
|
219
261
|
}
|
|
220
262
|
// Unregisters every global hotkey. No-op when the host lacks global-hotkey support.
|
|
221
263
|
export function unregisterAllGlobalShortcuts() {
|
|
264
|
+
_reportNoNativeBackend('unregisterAllGlobalShortcuts', '');
|
|
222
265
|
getShortcutBackend().unregisterAll();
|
|
223
266
|
}
|
|
224
267
|
// Unregisters a global hotkey. Returns false when not registered or unsupported (e.g. web).
|
|
225
268
|
// Input is normalized before the lookup.
|
|
226
269
|
export function unregisterGlobalShortcut(accelerator) {
|
|
227
|
-
const normalized =
|
|
270
|
+
const normalized = _normalizeForCommand(accelerator, 'unregisterGlobalShortcut');
|
|
228
271
|
if (normalized === null)
|
|
229
272
|
return false;
|
|
230
273
|
return getShortcutBackend().unregister(normalized);
|
|
231
274
|
}
|
|
275
|
+
// The backend a native host installed, and separately the web default getShortcutBackend falls back
|
|
276
|
+
// to. Keeping them apart is what lets hasNativeShortcutBackend answer honestly.
|
|
232
277
|
let _backend = null;
|
|
278
|
+
let _webBackend = null;
|
|
233
279
|
let _signals = null;
|
|
280
|
+
// Diagnostics seam: enableShortcutGuards (separately imported, so its message text and its
|
|
281
|
+
// @flighthq/log dependency shake out of a production bundle) fills this, and the command functions
|
|
282
|
+
// reach it through the null check. Not enabling guards costs one comparison per command.
|
|
283
|
+
let _dropGuard = null;
|
|
234
284
|
const _emptyList = [];
|
|
235
285
|
// Canonical modifier order used in normalized form: Control < Alt < Shift < Meta < Super < CommandOrControl.
|
|
236
286
|
// CommandOrControl carries its own ordinal (last) so any chord — including one mixing Control and
|
|
@@ -250,7 +300,9 @@ const _modifierAliases = new Map([
|
|
|
250
300
|
['super', 'Super'],
|
|
251
301
|
['win', 'Super'],
|
|
252
302
|
]);
|
|
253
|
-
// Alias map: lowercase alias → canonical ShortcutKeyName
|
|
303
|
+
// Alias map: lowercase alias → canonical ShortcutKeyName. Typing the values as ShortcutKeyName makes
|
|
304
|
+
// the header the checker: a misspelled canonical name here is a compile error rather than an
|
|
305
|
+
// accelerator that normalizes to a chord no backend recognizes.
|
|
254
306
|
const _keyAliases = new Map([
|
|
255
307
|
// Letters (uppercase canonical form)
|
|
256
308
|
['a', 'A'],
|
|
@@ -345,7 +397,13 @@ const _keyAliases = new Map([
|
|
|
345
397
|
['spacebar', 'Space'],
|
|
346
398
|
[' ', 'Space'],
|
|
347
399
|
['tab', 'Tab'],
|
|
348
|
-
// Numpad
|
|
400
|
+
// Numpad. The num*/num-operator short forms are the spellings Electron's accelerator syntax
|
|
401
|
+
// documents, so a chord copied from an Electron app parses unchanged.
|
|
402
|
+
['numadd', 'NumpadAdd'],
|
|
403
|
+
['numdec', 'NumpadDecimal'],
|
|
404
|
+
['numdiv', 'NumpadDivide'],
|
|
405
|
+
['nummult', 'NumpadMultiply'],
|
|
406
|
+
['numsub', 'NumpadSubtract'],
|
|
349
407
|
['num0', 'Numpad0'],
|
|
350
408
|
['num1', 'Numpad1'],
|
|
351
409
|
['num2', 'Numpad2'],
|
|
@@ -372,8 +430,12 @@ const _keyAliases = new Map([
|
|
|
372
430
|
['numpadenter', 'NumpadEnter'],
|
|
373
431
|
['numpadmultiply', 'NumpadMultiply'],
|
|
374
432
|
['numpadsubtract', 'NumpadSubtract'],
|
|
375
|
-
// Punctuation / symbols
|
|
433
|
+
// Punctuation / symbols. Both symbol characters that double as chord separators are here: the
|
|
434
|
+
// tokenizer hands a trailing '+' or '-' through as a key token rather than eating it, so
|
|
435
|
+
// 'CommandOrControl++' and 'CommandOrControl+-' — the conventional zoom pair — resolve like any
|
|
436
|
+
// other key.
|
|
376
437
|
["'", 'Quote'],
|
|
438
|
+
['+', 'Plus'],
|
|
377
439
|
[',', 'Comma'],
|
|
378
440
|
['-', 'Minus'],
|
|
379
441
|
['.', 'Period'],
|
|
@@ -396,7 +458,6 @@ const _keyAliases = new Map([
|
|
|
396
458
|
['quote', 'Quote'],
|
|
397
459
|
['semicolon', 'Semicolon'],
|
|
398
460
|
['slash', 'Slash'],
|
|
399
|
-
// Note: '+' as a key name is mapped via 'plus'; bare '+' is the separator so it is filtered out.
|
|
400
461
|
// Media
|
|
401
462
|
['medianexttrack', 'MediaNextTrack'],
|
|
402
463
|
['mediaplaypause', 'MediaPlayPause'],
|
|
@@ -470,6 +531,37 @@ function _isMacOS(platform) {
|
|
|
470
531
|
const p = navigator.platform ?? '';
|
|
471
532
|
return /mac/i.test(p);
|
|
472
533
|
}
|
|
534
|
+
// Copies a successful parse into a caller-owned ParsedAccelerator. `out.modifiers` is cleared and
|
|
535
|
+
// refilled rather than reassigned, so the array the caller allocated with createParsedAccelerator
|
|
536
|
+
// stays the array they hold — an out parameter that swapped the array underneath would leave any
|
|
537
|
+
// retained reference silently stale.
|
|
538
|
+
function _copyParsed(source, out) {
|
|
539
|
+
out.key = source.key;
|
|
540
|
+
out.modifiers.length = 0;
|
|
541
|
+
for (const modifier of source.modifiers)
|
|
542
|
+
out.modifiers.push(modifier);
|
|
543
|
+
return out;
|
|
544
|
+
}
|
|
545
|
+
// Builds the normalized Accelerator string from a _Parsed result.
|
|
546
|
+
function _formatNormalized(parsed) {
|
|
547
|
+
if (parsed.modifiers.length === 0)
|
|
548
|
+
return parsed.key;
|
|
549
|
+
return [...parsed.modifiers, parsed.key].join('+');
|
|
550
|
+
}
|
|
551
|
+
// Normalizes on behalf of a command function, reporting an unparseable input and a missing native
|
|
552
|
+
// backend to the drop guard on the way through. When no guard is installed — the production default
|
|
553
|
+
// — this is exactly normalizeAccelerator plus one null comparison.
|
|
554
|
+
function _normalizeForCommand(accelerator, operation) {
|
|
555
|
+
if (_dropGuard === null)
|
|
556
|
+
return normalizeAccelerator(accelerator);
|
|
557
|
+
const result = _parseDetailed(accelerator);
|
|
558
|
+
if ('reason' in result) {
|
|
559
|
+
_dropGuard({ accelerator, operation, parseError: result, reason: 'unparseable' });
|
|
560
|
+
return null;
|
|
561
|
+
}
|
|
562
|
+
_reportNoNativeBackend(operation, accelerator);
|
|
563
|
+
return _formatNormalized(result);
|
|
564
|
+
}
|
|
473
565
|
// Core parser. Returns a _Parsed on success or null on failure.
|
|
474
566
|
function _parse(input) {
|
|
475
567
|
const result = _parseDetailed(input);
|
|
@@ -479,15 +571,11 @@ function _parse(input) {
|
|
|
479
571
|
}
|
|
480
572
|
// Core parser with error diagnostics.
|
|
481
573
|
function _parseDetailed(input) {
|
|
482
|
-
|
|
483
|
-
return { reason: 'empty', token: '' };
|
|
484
|
-
}
|
|
485
|
-
const tokens = _splitTokens(input.trim());
|
|
574
|
+
const tokens = _splitTokens(input.trim(), _tokenScratch);
|
|
486
575
|
if (tokens.length === 0) {
|
|
487
576
|
return { reason: 'empty', token: '' };
|
|
488
577
|
}
|
|
489
578
|
const modifiers = [];
|
|
490
|
-
const seenModifiers = new Set();
|
|
491
579
|
let key = null;
|
|
492
580
|
// Process all tokens: if a token is a known modifier alias, treat it as a modifier.
|
|
493
581
|
// The last non-modifier token is the key; if all tokens are modifiers, it is missing-key.
|
|
@@ -495,10 +583,10 @@ function _parseDetailed(input) {
|
|
|
495
583
|
const lower = token.toLowerCase();
|
|
496
584
|
const mod = _modifierAliases.get(lower);
|
|
497
585
|
if (mod !== undefined) {
|
|
498
|
-
|
|
586
|
+
// A chord carries at most six modifiers, so a linear scan beats allocating a Set per parse.
|
|
587
|
+
if (modifiers.indexOf(mod) !== -1) {
|
|
499
588
|
return { reason: 'duplicate-modifier', token };
|
|
500
589
|
}
|
|
501
|
-
seenModifiers.add(mod);
|
|
502
590
|
modifiers.push(mod);
|
|
503
591
|
}
|
|
504
592
|
else {
|
|
@@ -522,14 +610,38 @@ function _parseDetailed(input) {
|
|
|
522
610
|
modifiers.sort((a, b) => _modifierOrder.indexOf(a) - _modifierOrder.indexOf(b));
|
|
523
611
|
return { key: canonicalKey, modifiers };
|
|
524
612
|
}
|
|
525
|
-
//
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
613
|
+
// Reports to the drop guard that a command reached the default web backend, whose registry is a
|
|
614
|
+
// sentinel, so the command could not have taken effect on any input. Silent once a native backend is
|
|
615
|
+
// installed: a native backend answering false is a real answer, not a drop.
|
|
616
|
+
function _reportNoNativeBackend(operation, accelerator) {
|
|
617
|
+
if (_dropGuard === null || _backend !== null)
|
|
618
|
+
return;
|
|
619
|
+
_dropGuard({ accelerator, operation, parseError: null, reason: 'no-native-backend' });
|
|
620
|
+
}
|
|
621
|
+
// Splits input into tokens on '+' and '-', writing into `out` and returning it.
|
|
622
|
+
//
|
|
623
|
+
// A separator character only separates when it *terminates* a token, which is what keeps a literal
|
|
624
|
+
// '+' or '-' key reachable: in 'Control+-' the '-' opens a token rather than closing the empty one,
|
|
625
|
+
// so it survives as the key. A naive split on /[+-]/ drops it, and with it the two most common
|
|
626
|
+
// accelerators an application registers — 'CommandOrControl+-' and 'CommandOrControl++' for zoom.
|
|
627
|
+
// The same rule makes a lone '+' or '-' a valid one-key accelerator, and leaves 'Ctrl-Shift-K'
|
|
628
|
+
// (dash as separator) tokenizing exactly as before.
|
|
629
|
+
function _splitTokens(input, out) {
|
|
630
|
+
out.length = 0;
|
|
631
|
+
let start = 0;
|
|
632
|
+
for (let i = 0; i < input.length; i++) {
|
|
633
|
+
const ch = input.charAt(i);
|
|
634
|
+
if ((ch === '+' || ch === '-') && i > start) {
|
|
635
|
+
out.push(input.slice(start, i));
|
|
636
|
+
start = i + 1;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
if (start < input.length)
|
|
640
|
+
out.push(input.slice(start));
|
|
641
|
+
return out;
|
|
534
642
|
}
|
|
643
|
+
// Scratch for _splitTokens. Contained entirely within _parseDetailed — the token strings are read
|
|
644
|
+
// into modifiers/key before the next parse can run, and the array itself never escapes — so reusing
|
|
645
|
+
// it costs no aliasing hazard.
|
|
646
|
+
const _tokenScratch = [];
|
|
535
647
|
//# sourceMappingURL=shortcut.js.map
|
package/dist/shortcut.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shortcut.js","sourceRoot":"","sources":["../src/shortcut.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"shortcut.js","sourceRoot":"","sources":["../src/shortcut.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flighthq/shortcut",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1-next.209.43ef1bc",
|
|
4
|
+
"author": "Joshua Granick and other contributors",
|
|
5
|
+
"license": "MIT",
|
|
4
6
|
"repository": {
|
|
5
7
|
"type": "git",
|
|
6
8
|
"url": "https://github.com/flighthq/flight.git",
|
|
@@ -36,8 +38,9 @@
|
|
|
36
38
|
"clean:dist": "tsx ../../scripts/clean-package-dist.ts"
|
|
37
39
|
},
|
|
38
40
|
"dependencies": {
|
|
39
|
-
"@flighthq/
|
|
40
|
-
"@flighthq/
|
|
41
|
+
"@flighthq/log": "0.3.1-next.209.43ef1bc",
|
|
42
|
+
"@flighthq/signals": "0.3.1-next.209.43ef1bc",
|
|
43
|
+
"@flighthq/types": "0.3.1-next.209.43ef1bc"
|
|
41
44
|
},
|
|
42
45
|
"devDependencies": {
|
|
43
46
|
"typescript": "^5.3.0"
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { addLogSink, createMemoryLogSink, getMemoryLogSinkEntries, removeLogSink } from '@flighthq/log/contract';
|
|
2
|
+
import type { LogEntry, ShortcutBackend, ShortcutDrop } from '@flighthq/types/contract';
|
|
3
|
+
|
|
4
|
+
import { disableShortcutGuards, enableShortcutGuards } from './enableShortcutGuards';
|
|
5
|
+
import { registerGlobalShortcut, setShortcutBackend, setShortcutDropGuard, unregisterGlobalShortcut } from './shortcut';
|
|
6
|
+
|
|
7
|
+
// A native-looking backend, so the no-native-backend drop does not fire and the parse drop can be
|
|
8
|
+
// observed alone.
|
|
9
|
+
function nativeBackend(): ShortcutBackend {
|
|
10
|
+
return {
|
|
11
|
+
getRegistered() {
|
|
12
|
+
return [];
|
|
13
|
+
},
|
|
14
|
+
isRegistered() {
|
|
15
|
+
return false;
|
|
16
|
+
},
|
|
17
|
+
register() {
|
|
18
|
+
return true;
|
|
19
|
+
},
|
|
20
|
+
setAllEnabled() {},
|
|
21
|
+
setEnabled() {
|
|
22
|
+
return false;
|
|
23
|
+
},
|
|
24
|
+
unregister() {
|
|
25
|
+
return true;
|
|
26
|
+
},
|
|
27
|
+
unregisterAll() {},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function captureLog(run: () => void): readonly LogEntry[] {
|
|
32
|
+
const sink = createMemoryLogSink(8);
|
|
33
|
+
addLogSink(sink.sink);
|
|
34
|
+
try {
|
|
35
|
+
run();
|
|
36
|
+
return getMemoryLogSinkEntries(sink);
|
|
37
|
+
} finally {
|
|
38
|
+
removeLogSink(sink.sink);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function messageOf(entry: Readonly<LogEntry>): string {
|
|
43
|
+
return String((entry.data as Record<string, unknown>).message);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
afterEach(() => {
|
|
47
|
+
disableShortcutGuards();
|
|
48
|
+
setShortcutBackend(null);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe('disableShortcutGuards', () => {
|
|
52
|
+
it('uninstalls the guard so a later drop reports nothing', () => {
|
|
53
|
+
setShortcutBackend(nativeBackend());
|
|
54
|
+
enableShortcutGuards();
|
|
55
|
+
disableShortcutGuards();
|
|
56
|
+
const entries = captureLog(() => {
|
|
57
|
+
registerGlobalShortcut('Control+NotAKey', () => {});
|
|
58
|
+
});
|
|
59
|
+
expect(entries.length).toBe(0);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('is safe to call without a prior enable', () => {
|
|
63
|
+
expect(() => disableShortcutGuards()).not.toThrow();
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe('enableShortcutGuards', () => {
|
|
68
|
+
// logOnce dedupes by key for the lifetime of the process, so each reason is asserted in exactly one
|
|
69
|
+
// test in this file and later tests observe the suppressed (zero-entry) behavior instead.
|
|
70
|
+
it('warns once, naming the call and the parse reason, when an accelerator does not parse', () => {
|
|
71
|
+
setShortcutBackend(nativeBackend());
|
|
72
|
+
enableShortcutGuards();
|
|
73
|
+
const entries = captureLog(() => {
|
|
74
|
+
registerGlobalShortcut('Control+NotAKey', () => {});
|
|
75
|
+
});
|
|
76
|
+
expect(entries.length).toBe(1);
|
|
77
|
+
const message = messageOf(entries[0]);
|
|
78
|
+
expect(message).toContain('registerGlobalShortcut');
|
|
79
|
+
expect(message).toContain('Control+NotAKey');
|
|
80
|
+
expect(message).toContain('unknown-key');
|
|
81
|
+
expect(message).toContain("at 'NotAKey'");
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('suppresses a repeat of the same reason', () => {
|
|
85
|
+
setShortcutBackend(nativeBackend());
|
|
86
|
+
enableShortcutGuards();
|
|
87
|
+
const entries = captureLog(() => {
|
|
88
|
+
unregisterGlobalShortcut('Control+AlsoNotAKey');
|
|
89
|
+
});
|
|
90
|
+
expect(entries.length).toBe(0);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('warns once when a command reaches the default web backend, naming the missing native backend', () => {
|
|
94
|
+
enableShortcutGuards();
|
|
95
|
+
const entries = captureLog(() => {
|
|
96
|
+
registerGlobalShortcut('Control+K', () => {});
|
|
97
|
+
});
|
|
98
|
+
expect(entries.length).toBe(1);
|
|
99
|
+
const message = messageOf(entries[0]);
|
|
100
|
+
expect(message).toContain('registerGlobalShortcut');
|
|
101
|
+
expect(message).toContain('no native shortcut backend');
|
|
102
|
+
expect(message).toContain('setShortcutBackend');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('stays silent once a native backend is installed — a native false is an answer, not a drop', () => {
|
|
106
|
+
setShortcutBackend(nativeBackend());
|
|
107
|
+
enableShortcutGuards();
|
|
108
|
+
const entries = captureLog(() => {
|
|
109
|
+
registerGlobalShortcut('Control+K', () => {});
|
|
110
|
+
});
|
|
111
|
+
expect(entries.length).toBe(0);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('is idempotent — a second enable leaves exactly one guard installed', () => {
|
|
115
|
+
enableShortcutGuards();
|
|
116
|
+
enableShortcutGuards();
|
|
117
|
+
const drops: ShortcutDrop[] = [];
|
|
118
|
+
setShortcutDropGuard((drop) => drops.push({ ...drop }));
|
|
119
|
+
registerGlobalShortcut('Control+K', () => {});
|
|
120
|
+
expect(drops.length).toBe(1);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { ShortcutBackend } from '@flighthq/types/contract';
|
|
2
|
+
|
|
3
|
+
import { explainGlobalShortcutRegistration } from './explainGlobalShortcutRegistration';
|
|
4
|
+
import { setShortcutBackend } from './shortcut';
|
|
5
|
+
|
|
6
|
+
function nativeBackend(registered: readonly string[] = []): ShortcutBackend {
|
|
7
|
+
const entries = new Set(registered);
|
|
8
|
+
return {
|
|
9
|
+
getRegistered() {
|
|
10
|
+
return [...entries];
|
|
11
|
+
},
|
|
12
|
+
isRegistered(accelerator) {
|
|
13
|
+
return entries.has(accelerator);
|
|
14
|
+
},
|
|
15
|
+
register(accelerator) {
|
|
16
|
+
entries.add(accelerator);
|
|
17
|
+
return true;
|
|
18
|
+
},
|
|
19
|
+
setAllEnabled() {},
|
|
20
|
+
setEnabled() {
|
|
21
|
+
return true;
|
|
22
|
+
},
|
|
23
|
+
unregister(accelerator) {
|
|
24
|
+
return entries.delete(accelerator);
|
|
25
|
+
},
|
|
26
|
+
unregisterAll() {
|
|
27
|
+
entries.clear();
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
afterEach(() => {
|
|
33
|
+
setShortcutBackend(null);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
describe('explainGlobalShortcutRegistration', () => {
|
|
37
|
+
it('reports ok for a free chord on a native backend', () => {
|
|
38
|
+
setShortcutBackend(nativeBackend());
|
|
39
|
+
expect(explainGlobalShortcutRegistration('Ctrl+Shift+K')).toEqual({
|
|
40
|
+
accelerator: 'Ctrl+Shift+K',
|
|
41
|
+
hasNativeBackend: true,
|
|
42
|
+
normalized: 'Control+Shift+K',
|
|
43
|
+
parseError: null,
|
|
44
|
+
registered: false,
|
|
45
|
+
reason: 'ok',
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('reports already-registered through an alias spelling, since the register path normalizes first', () => {
|
|
50
|
+
setShortcutBackend(nativeBackend(['Control+Shift+K']));
|
|
51
|
+
const explanation = explainGlobalShortcutRegistration('ctrl+shift+k');
|
|
52
|
+
expect(explanation.reason).toBe('already-registered');
|
|
53
|
+
expect(explanation.normalized).toBe('Control+Shift+K');
|
|
54
|
+
expect(explanation.registered).toBe(true);
|
|
55
|
+
expect(explanation.parseError).toBeNull();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('reports no-native-backend on the web default, and never claims a registration there', () => {
|
|
59
|
+
const explanation = explainGlobalShortcutRegistration('Control+K');
|
|
60
|
+
expect(explanation.reason).toBe('no-native-backend');
|
|
61
|
+
expect(explanation.hasNativeBackend).toBe(false);
|
|
62
|
+
expect(explanation.registered).toBe(false);
|
|
63
|
+
expect(explanation.normalized).toBe('Control+K');
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('reports unparseable with the parse error, outranking a missing backend', () => {
|
|
67
|
+
const explanation = explainGlobalShortcutRegistration('Control+NotAKey');
|
|
68
|
+
expect(explanation.reason).toBe('unparseable');
|
|
69
|
+
expect(explanation.normalized).toBeNull();
|
|
70
|
+
expect(explanation.parseError).toEqual({ reason: 'unknown-key', token: 'NotAKey' });
|
|
71
|
+
// The backend is also missing here, but the input error is the root cause and wins.
|
|
72
|
+
expect(explanation.hasNativeBackend).toBe(false);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('echoes the caller spelling rather than the normalized form', () => {
|
|
76
|
+
setShortcutBackend(nativeBackend());
|
|
77
|
+
expect(explainGlobalShortcutRegistration('cmd-shift-p').accelerator).toBe('cmd-shift-p');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('registers nothing and mutates no state', () => {
|
|
81
|
+
const backend = nativeBackend();
|
|
82
|
+
setShortcutBackend(backend);
|
|
83
|
+
explainGlobalShortcutRegistration('Control+K');
|
|
84
|
+
explainGlobalShortcutRegistration('Control+K');
|
|
85
|
+
expect(backend.getRegistered()).toEqual([]);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('does not throw on empty or garbage input', () => {
|
|
89
|
+
expect(explainGlobalShortcutRegistration('').reason).toBe('unparseable');
|
|
90
|
+
expect(explainGlobalShortcutRegistration('').parseError).toEqual({ reason: 'empty', token: '' });
|
|
91
|
+
expect(explainGlobalShortcutRegistration('Control+').parseError).toEqual({ reason: 'missing-key', token: '' });
|
|
92
|
+
});
|
|
93
|
+
});
|
package/src/shortcut.test.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
AcceleratorParseError,
|
|
4
4
|
ParsedAccelerator,
|
|
5
5
|
ShortcutBackend,
|
|
6
|
+
ShortcutDrop,
|
|
6
7
|
ShortcutEvent,
|
|
7
8
|
ShortcutModifier,
|
|
8
9
|
} from '@flighthq/types/contract';
|
|
@@ -12,8 +13,10 @@ import {
|
|
|
12
13
|
createParsedAccelerator,
|
|
13
14
|
createWebShortcutBackend,
|
|
14
15
|
disableGlobalShortcut,
|
|
16
|
+
disposeGlobalShortcutSignals,
|
|
15
17
|
enableGlobalShortcut,
|
|
16
18
|
enableGlobalShortcutSignals,
|
|
19
|
+
findAcceleratorConflict,
|
|
17
20
|
formatAcceleratorForDisplay,
|
|
18
21
|
getAcceleratorKey,
|
|
19
22
|
getAcceleratorKeyLabel,
|
|
@@ -22,6 +25,7 @@ import {
|
|
|
22
25
|
getRegisteredGlobalShortcuts,
|
|
23
26
|
getShortcutBackend,
|
|
24
27
|
hasGlobalShortcutConflict,
|
|
28
|
+
hasNativeShortcutBackend,
|
|
25
29
|
isAcceleratorValid,
|
|
26
30
|
isGlobalShortcutRegistered,
|
|
27
31
|
normalizeAccelerator,
|
|
@@ -31,6 +35,7 @@ import {
|
|
|
31
35
|
resolveCommandOrControlModifier,
|
|
32
36
|
resumeAllGlobalShortcuts,
|
|
33
37
|
setShortcutBackend,
|
|
38
|
+
setShortcutDropGuard,
|
|
34
39
|
suspendAllGlobalShortcuts,
|
|
35
40
|
unregisterAllGlobalShortcuts,
|
|
36
41
|
unregisterGlobalShortcut,
|
|
@@ -78,6 +83,7 @@ function fakeBackend(): FakeBackend {
|
|
|
78
83
|
|
|
79
84
|
afterEach(() => {
|
|
80
85
|
setShortcutBackend(null);
|
|
86
|
+
setShortcutDropGuard(null);
|
|
81
87
|
// Disconnect any signal listeners registered in this test to avoid cross-test bleed.
|
|
82
88
|
const signals = enableGlobalShortcutSignals();
|
|
83
89
|
clearSignal(signals.onTrigger);
|
|
@@ -132,6 +138,49 @@ describe('disableGlobalShortcut', () => {
|
|
|
132
138
|
});
|
|
133
139
|
});
|
|
134
140
|
|
|
141
|
+
describe('disposeGlobalShortcutSignals', () => {
|
|
142
|
+
it('disconnects onTrigger listeners so a later trigger does not reach them', () => {
|
|
143
|
+
const backend = fakeBackend();
|
|
144
|
+
setShortcutBackend(backend);
|
|
145
|
+
const signals = enableGlobalShortcutSignals();
|
|
146
|
+
let fired = 0;
|
|
147
|
+
connectSignal(signals.onTrigger, () => {
|
|
148
|
+
fired++;
|
|
149
|
+
});
|
|
150
|
+
registerGlobalShortcut('Control+K', () => {});
|
|
151
|
+
backend.entries.get('Control+K')!.handler({ accelerator: 'Control+K' });
|
|
152
|
+
expect(fired).toBe(1);
|
|
153
|
+
|
|
154
|
+
disposeGlobalShortcutSignals();
|
|
155
|
+
backend.entries.get('Control+K')!.handler({ accelerator: 'Control+K' });
|
|
156
|
+
expect(fired).toBe(1);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('arms a fresh group on the next enable — identity is not preserved across a dispose', () => {
|
|
160
|
+
const before = enableGlobalShortcutSignals();
|
|
161
|
+
disposeGlobalShortcutSignals();
|
|
162
|
+
expect(enableGlobalShortcutSignals()).not.toBe(before);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('leaves directly-registered handlers firing', () => {
|
|
166
|
+
const backend = fakeBackend();
|
|
167
|
+
setShortcutBackend(backend);
|
|
168
|
+
enableGlobalShortcutSignals();
|
|
169
|
+
let handled = 0;
|
|
170
|
+
registerGlobalShortcut('Control+K', () => {
|
|
171
|
+
handled++;
|
|
172
|
+
});
|
|
173
|
+
disposeGlobalShortcutSignals();
|
|
174
|
+
backend.entries.get('Control+K')!.handler({ accelerator: 'Control+K' });
|
|
175
|
+
expect(handled).toBe(1);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('is a no-op when no group was armed', () => {
|
|
179
|
+
disposeGlobalShortcutSignals();
|
|
180
|
+
expect(() => disposeGlobalShortcutSignals()).not.toThrow();
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
135
184
|
describe('enableGlobalShortcut', () => {
|
|
136
185
|
it('re-enables a disabled shortcut', () => {
|
|
137
186
|
const backend = fakeBackend();
|
|
@@ -235,6 +284,40 @@ describe('equalsAccelerator', () => {
|
|
|
235
284
|
});
|
|
236
285
|
});
|
|
237
286
|
|
|
287
|
+
describe('findAcceleratorConflict', () => {
|
|
288
|
+
it('returns the conflicting candidate, in the caller spelling it was given in', () => {
|
|
289
|
+
expect(findAcceleratorConflict('Control+K', ['Alt+J', 'ctrl-k', 'Meta+P'])).toBe('ctrl-k');
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it('returns null when nothing in the list names the same chord', () => {
|
|
293
|
+
expect(findAcceleratorConflict('Control+K', ['Alt+J', 'Meta+P'])).toBeNull();
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
it('returns the first conflict when several candidates name the chord', () => {
|
|
297
|
+
expect(findAcceleratorConflict('Control+K', ['ctrl+k', 'Control-K'])).toBe('ctrl+k');
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
it('returns null for an unparseable accelerator, even against an identical unparseable candidate', () => {
|
|
301
|
+
expect(findAcceleratorConflict('NotAKey', ['NotAKey'])).toBeNull();
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it('skips unparseable candidates rather than matching them', () => {
|
|
305
|
+
expect(findAcceleratorConflict('Control+K', ['NotAKey', '', 'Ctrl+K'])).toBe('Ctrl+K');
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it('returns null for an empty candidate list', () => {
|
|
309
|
+
expect(findAcceleratorConflict('Control+K', [])).toBeNull();
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
it('sees a pending binding list that hasGlobalShortcutConflict cannot — nothing is registered', () => {
|
|
313
|
+
const backend = fakeBackend();
|
|
314
|
+
setShortcutBackend(backend);
|
|
315
|
+
const pending = ['Control+Shift+P'];
|
|
316
|
+
expect(hasGlobalShortcutConflict('Control+Shift+P')).toBe(false);
|
|
317
|
+
expect(findAcceleratorConflict('Control+Shift+P', pending)).toBe('Control+Shift+P');
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
|
|
238
321
|
describe('formatAcceleratorForDisplay', () => {
|
|
239
322
|
// Tests are environment-neutral: we just check the output is non-empty and contains
|
|
240
323
|
// both the expected modifier component and key. Platform-specific symbol vs text is tested
|
|
@@ -451,6 +534,21 @@ describe('hasGlobalShortcutConflict', () => {
|
|
|
451
534
|
});
|
|
452
535
|
});
|
|
453
536
|
|
|
537
|
+
describe('hasNativeShortcutBackend', () => {
|
|
538
|
+
it('is false on the web default and true once a backend is installed', () => {
|
|
539
|
+
expect(hasNativeShortcutBackend()).toBe(false);
|
|
540
|
+
setShortcutBackend(fakeBackend());
|
|
541
|
+
expect(hasNativeShortcutBackend()).toBe(true);
|
|
542
|
+
setShortcutBackend(null);
|
|
543
|
+
expect(hasNativeShortcutBackend()).toBe(false);
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
it('stays false when getShortcutBackend has lazily built the web default', () => {
|
|
547
|
+
getShortcutBackend();
|
|
548
|
+
expect(hasNativeShortcutBackend()).toBe(false);
|
|
549
|
+
});
|
|
550
|
+
});
|
|
551
|
+
|
|
454
552
|
describe('isAcceleratorValid', () => {
|
|
455
553
|
it('returns true for well-formed accelerators', () => {
|
|
456
554
|
expect(isAcceleratorValid('Control+K')).toBe(true);
|
|
@@ -581,6 +679,46 @@ describe('normalizeAccelerator', () => {
|
|
|
581
679
|
expect(normalizeAccelerator('Ctrl-Shift-K')).toBe('Control+Shift+K');
|
|
582
680
|
});
|
|
583
681
|
|
|
682
|
+
it('reaches a literal +/- key, so the conventional zoom pair parses', () => {
|
|
683
|
+
expect(normalizeAccelerator('CommandOrControl+-')).toBe('CommandOrControl+Minus');
|
|
684
|
+
expect(normalizeAccelerator('CommandOrControl++')).toBe('CommandOrControl+Plus');
|
|
685
|
+
expect(normalizeAccelerator('Ctrl+-')).toBe('Control+Minus');
|
|
686
|
+
expect(normalizeAccelerator('Ctrl++')).toBe('Control+Plus');
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
it('accepts a bare +/- as a one-key accelerator', () => {
|
|
690
|
+
expect(normalizeAccelerator('-')).toBe('Minus');
|
|
691
|
+
expect(normalizeAccelerator('+')).toBe('Plus');
|
|
692
|
+
});
|
|
693
|
+
|
|
694
|
+
it('reaches a literal +/- through the dash separator too', () => {
|
|
695
|
+
expect(normalizeAccelerator('Ctrl-+')).toBe('Control+Plus');
|
|
696
|
+
expect(normalizeAccelerator('Ctrl--')).toBe('Control+Minus');
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
it('round-trips a literal +/- chord through its own normalized form', () => {
|
|
700
|
+
const once = normalizeAccelerator('Ctrl+-');
|
|
701
|
+
expect(normalizeAccelerator(once!)).toBe(once);
|
|
702
|
+
});
|
|
703
|
+
|
|
704
|
+
it('normalizes the named spellings of +/- to the same chord as the literals', () => {
|
|
705
|
+
expect(normalizeAccelerator('Ctrl+Minus')).toBe(normalizeAccelerator('Ctrl+-'));
|
|
706
|
+
expect(normalizeAccelerator('Ctrl+Plus')).toBe(normalizeAccelerator('Ctrl++'));
|
|
707
|
+
});
|
|
708
|
+
|
|
709
|
+
it('normalizes the Electron numpad short spellings', () => {
|
|
710
|
+
expect(normalizeAccelerator('Ctrl+numadd')).toBe('Control+NumpadAdd');
|
|
711
|
+
expect(normalizeAccelerator('Ctrl+numsub')).toBe('Control+NumpadSubtract');
|
|
712
|
+
expect(normalizeAccelerator('Ctrl+nummult')).toBe('Control+NumpadMultiply');
|
|
713
|
+
expect(normalizeAccelerator('Ctrl+numdiv')).toBe('Control+NumpadDivide');
|
|
714
|
+
expect(normalizeAccelerator('Ctrl+numdec')).toBe('Control+NumpadDecimal');
|
|
715
|
+
});
|
|
716
|
+
|
|
717
|
+
it('rejects a separator glued to a key name rather than silently dropping it', () => {
|
|
718
|
+
// 'Ctrl+-K' is malformed: the '-' opens the key token, so the key reads as '-K' and fails.
|
|
719
|
+
expect(normalizeAccelerator('Ctrl+-K')).toBeNull();
|
|
720
|
+
});
|
|
721
|
+
|
|
584
722
|
it('produces stable output (idempotent)', () => {
|
|
585
723
|
const once = normalizeAccelerator('ctrl+shift+k');
|
|
586
724
|
const twice = normalizeAccelerator(once!);
|
|
@@ -626,6 +764,24 @@ describe('parseAccelerator', () => {
|
|
|
626
764
|
expect(out.modifiers).toEqual([]);
|
|
627
765
|
});
|
|
628
766
|
|
|
767
|
+
it('fills the modifiers array in place, keeping a retained reference live', () => {
|
|
768
|
+
const out = createParsedAccelerator();
|
|
769
|
+
const modifiers = out.modifiers;
|
|
770
|
+
parseAccelerator('Control+Shift+K', out);
|
|
771
|
+
expect(out.modifiers).toBe(modifiers);
|
|
772
|
+
expect(modifiers).toEqual(['Control', 'Shift']);
|
|
773
|
+
parseAccelerator('Alt+F', out);
|
|
774
|
+
expect(out.modifiers).toBe(modifiers);
|
|
775
|
+
expect(modifiers).toEqual(['Alt']);
|
|
776
|
+
});
|
|
777
|
+
|
|
778
|
+
it('clears stale modifiers when the new chord has fewer', () => {
|
|
779
|
+
const out = createParsedAccelerator();
|
|
780
|
+
parseAccelerator('Control+Alt+Shift+K', out);
|
|
781
|
+
parseAccelerator('K', out);
|
|
782
|
+
expect(out.modifiers).toEqual([]);
|
|
783
|
+
});
|
|
784
|
+
|
|
629
785
|
it('aliased out — same object as a previously-filled value', () => {
|
|
630
786
|
const out = createParsedAccelerator();
|
|
631
787
|
parseAccelerator('Ctrl+K', out);
|
|
@@ -769,6 +925,97 @@ describe('setShortcutBackend', () => {
|
|
|
769
925
|
});
|
|
770
926
|
});
|
|
771
927
|
|
|
928
|
+
describe('setShortcutDropGuard', () => {
|
|
929
|
+
it('reports an unparseable accelerator with the operation, the raw input, and the parse error', () => {
|
|
930
|
+
setShortcutBackend(fakeBackend());
|
|
931
|
+
const drops: ShortcutDrop[] = [];
|
|
932
|
+
setShortcutDropGuard((drop) => drops.push({ ...drop }));
|
|
933
|
+
expect(registerGlobalShortcut('Control+NotAKey', () => {})).toBe(false);
|
|
934
|
+
expect(drops).toEqual([
|
|
935
|
+
{
|
|
936
|
+
accelerator: 'Control+NotAKey',
|
|
937
|
+
operation: 'registerGlobalShortcut',
|
|
938
|
+
parseError: { reason: 'unknown-key', token: 'NotAKey' },
|
|
939
|
+
reason: 'unparseable',
|
|
940
|
+
},
|
|
941
|
+
]);
|
|
942
|
+
});
|
|
943
|
+
|
|
944
|
+
it('names the operation each command dropped from', () => {
|
|
945
|
+
const seen: string[] = [];
|
|
946
|
+
setShortcutBackend(fakeBackend());
|
|
947
|
+
setShortcutDropGuard((drop) => seen.push(drop.operation));
|
|
948
|
+
disableGlobalShortcut('');
|
|
949
|
+
enableGlobalShortcut('');
|
|
950
|
+
registerGlobalShortcut('', () => {});
|
|
951
|
+
unregisterGlobalShortcut('');
|
|
952
|
+
expect(seen).toEqual([
|
|
953
|
+
'disableGlobalShortcut',
|
|
954
|
+
'enableGlobalShortcut',
|
|
955
|
+
'registerGlobalShortcut',
|
|
956
|
+
'unregisterGlobalShortcut',
|
|
957
|
+
]);
|
|
958
|
+
});
|
|
959
|
+
|
|
960
|
+
it('reports no-native-backend for a parseable chord on the web default, with no parse error', () => {
|
|
961
|
+
const drops: ShortcutDrop[] = [];
|
|
962
|
+
setShortcutDropGuard((drop) => drops.push({ ...drop }));
|
|
963
|
+
registerGlobalShortcut('Control+K', () => {});
|
|
964
|
+
expect(drops).toEqual([
|
|
965
|
+
{
|
|
966
|
+
accelerator: 'Control+K',
|
|
967
|
+
operation: 'registerGlobalShortcut',
|
|
968
|
+
parseError: null,
|
|
969
|
+
reason: 'no-native-backend',
|
|
970
|
+
},
|
|
971
|
+
]);
|
|
972
|
+
});
|
|
973
|
+
|
|
974
|
+
it('reports no-native-backend from the accelerator-free bulk commands too', () => {
|
|
975
|
+
const seen: string[] = [];
|
|
976
|
+
setShortcutDropGuard((drop) => seen.push(drop.operation));
|
|
977
|
+
suspendAllGlobalShortcuts();
|
|
978
|
+
resumeAllGlobalShortcuts();
|
|
979
|
+
unregisterAllGlobalShortcuts();
|
|
980
|
+
expect(seen).toEqual(['suspendAllGlobalShortcuts', 'resumeAllGlobalShortcuts', 'unregisterAllGlobalShortcuts']);
|
|
981
|
+
});
|
|
982
|
+
|
|
983
|
+
it('stays silent once a native backend is installed', () => {
|
|
984
|
+
setShortcutBackend(fakeBackend());
|
|
985
|
+
const drops: ShortcutDrop[] = [];
|
|
986
|
+
setShortcutDropGuard((drop) => drops.push({ ...drop }));
|
|
987
|
+
registerGlobalShortcut('Control+K', () => {});
|
|
988
|
+
unregisterGlobalShortcut('Control+K');
|
|
989
|
+
suspendAllGlobalShortcuts();
|
|
990
|
+
expect(drops).toEqual([]);
|
|
991
|
+
});
|
|
992
|
+
|
|
993
|
+
it('reports the parse failure rather than the missing backend when both apply', () => {
|
|
994
|
+
const drops: ShortcutDrop[] = [];
|
|
995
|
+
setShortcutDropGuard((drop) => drops.push({ ...drop }));
|
|
996
|
+
registerGlobalShortcut('Control+NotAKey', () => {});
|
|
997
|
+
expect(drops.length).toBe(1);
|
|
998
|
+
expect(drops[0].reason).toBe('unparseable');
|
|
999
|
+
});
|
|
1000
|
+
|
|
1001
|
+
it('null uninstalls it', () => {
|
|
1002
|
+
const drops: ShortcutDrop[] = [];
|
|
1003
|
+
setShortcutDropGuard((drop) => drops.push({ ...drop }));
|
|
1004
|
+
setShortcutDropGuard(null);
|
|
1005
|
+
registerGlobalShortcut('Control+NotAKey', () => {});
|
|
1006
|
+
expect(drops).toEqual([]);
|
|
1007
|
+
});
|
|
1008
|
+
|
|
1009
|
+
it('does not change what a command returns', () => {
|
|
1010
|
+
const backend = fakeBackend();
|
|
1011
|
+
setShortcutBackend(backend);
|
|
1012
|
+
setShortcutDropGuard(() => {});
|
|
1013
|
+
expect(registerGlobalShortcut('ctrl+k', () => {})).toBe(true);
|
|
1014
|
+
expect(backend.entries.has('Control+K')).toBe(true);
|
|
1015
|
+
expect(registerGlobalShortcut('Control+NotAKey', () => {})).toBe(false);
|
|
1016
|
+
});
|
|
1017
|
+
});
|
|
1018
|
+
|
|
772
1019
|
describe('suspendAllGlobalShortcuts', () => {
|
|
773
1020
|
it('disables all registered shortcuts', () => {
|
|
774
1021
|
const backend = fakeBackend();
|