@expofp/debug 3.4.1 → 3.4.2
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.
|
@@ -1,37 +1,69 @@
|
|
|
1
1
|
const SECRET_PHRASE = 'dbg123';
|
|
2
2
|
const callbacks = [];
|
|
3
3
|
let initialized = false;
|
|
4
|
-
let
|
|
4
|
+
let teardown = null;
|
|
5
5
|
export function addDebugSecretListener(callback) {
|
|
6
6
|
callbacks.push(callback);
|
|
7
7
|
if (!initialized) {
|
|
8
8
|
initialized = true;
|
|
9
9
|
let buffer = '';
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
// A physical keypress fires both `keydown` and `input`. When `keydown`
|
|
11
|
+
// already fed a real character, this flag tells the `input` handler to skip
|
|
12
|
+
// the paired event so the character is not counted twice.
|
|
13
|
+
let consumedByKeydown = false;
|
|
14
|
+
const feed = (text) => {
|
|
15
|
+
for (const ch of text.toLowerCase()) {
|
|
16
|
+
buffer = (buffer + ch).slice(-SECRET_PHRASE.length);
|
|
17
|
+
if (buffer === SECRET_PHRASE) {
|
|
18
|
+
buffer = '';
|
|
19
|
+
callbacks.forEach((cb) => cb());
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
// Physical keyboards expose the real character here. Android soft keyboards
|
|
25
|
+
// instead report keyCode 229 / key 'Unidentified' (IME composition), so
|
|
26
|
+
// those keystrokes fall through to the `input` handler below.
|
|
27
|
+
const onKeyDown = (e) => {
|
|
12
28
|
if (e.ctrlKey || e.metaKey || e.altKey)
|
|
13
29
|
return;
|
|
14
|
-
if (e.key.length !== 1)
|
|
30
|
+
if (e.isComposing || e.key.length !== 1) {
|
|
31
|
+
consumedByKeydown = false;
|
|
15
32
|
return;
|
|
16
|
-
buffer += e.key.toLowerCase();
|
|
17
|
-
// Keep buffer length sane
|
|
18
|
-
buffer = buffer.slice(-SECRET_PHRASE.length);
|
|
19
|
-
if (buffer === SECRET_PHRASE) {
|
|
20
|
-
buffer = '';
|
|
21
|
-
callbacks.forEach((cb) => cb());
|
|
22
33
|
}
|
|
23
|
-
|
|
24
|
-
|
|
34
|
+
consumedByKeydown = true;
|
|
35
|
+
feed(e.key);
|
|
36
|
+
};
|
|
37
|
+
// Soft keyboards / IMEs deliver the typed text only as `InputEvent.data`.
|
|
38
|
+
// Listen in the capture phase so we still see it when an input component
|
|
39
|
+
// stops propagation. `data` is null for deletions, and we ignore in-flight
|
|
40
|
+
// composition to avoid re-counting the running composition string.
|
|
41
|
+
const onInput = (e) => {
|
|
42
|
+
if (consumedByKeydown) {
|
|
43
|
+
consumedByKeydown = false;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const ie = e;
|
|
47
|
+
if (ie.isComposing)
|
|
48
|
+
return;
|
|
49
|
+
if (ie.data)
|
|
50
|
+
feed(ie.data);
|
|
51
|
+
};
|
|
25
52
|
document.addEventListener('keydown', onKeyDown);
|
|
53
|
+
document.addEventListener('input', onInput, true);
|
|
54
|
+
teardown = () => {
|
|
55
|
+
document.removeEventListener('keydown', onKeyDown);
|
|
56
|
+
document.removeEventListener('input', onInput, true);
|
|
57
|
+
};
|
|
26
58
|
}
|
|
27
59
|
return () => {
|
|
28
60
|
const index = callbacks.indexOf(callback);
|
|
29
61
|
if (index !== -1) {
|
|
30
62
|
callbacks.splice(index, 1);
|
|
31
63
|
}
|
|
32
|
-
if (callbacks.length === 0 &&
|
|
33
|
-
|
|
34
|
-
|
|
64
|
+
if (callbacks.length === 0 && teardown) {
|
|
65
|
+
teardown();
|
|
66
|
+
teardown = null;
|
|
35
67
|
initialized = false;
|
|
36
68
|
}
|
|
37
69
|
};
|