@expofp/debug 3.4.1 → 3.4.3

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 listenerRef = null;
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
- function onKeyDown(e) {
11
- // Ignore modifier keys
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
- listenerRef = onKeyDown;
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 && listenerRef) {
33
- document.removeEventListener('keydown', listenerRef);
34
- listenerRef = null;
64
+ if (callbacks.length === 0 && teardown) {
65
+ teardown();
66
+ teardown = null;
35
67
  initialized = false;
36
68
  }
37
69
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expofp/debug",
3
- "version": "3.4.1",
3
+ "version": "3.4.3",
4
4
  "type": "module",
5
5
  "description": "ExpoFP SDK internal: debug utilities",
6
6
  "homepage": "https://developer.expofp.com/",