@limrun/ui 0.17.0-rc.1 → 0.17.0-rc.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.
Files changed (83) hide show
  1. package/README.md +18 -3
  2. package/dist/{GLTFLoader-DW6wpvyR.mjs → GLTFLoader-Cami_vza.mjs} +1 -1
  3. package/dist/{GLTFLoader-BKnsBFsj.js → GLTFLoader-DeCLxW_q.js} +1 -1
  4. package/dist/components/duo-fold-motion.d.ts +1 -1
  5. package/dist/components/duo-loading.d.ts +8 -0
  6. package/dist/components/duo-view.d.ts +6 -1
  7. package/dist/{duo-frame-BzyYljix.mjs → duo-frame-Cmw4p2uN.mjs} +414 -414
  8. package/dist/{duo-frame-DjfA4gG-.js → duo-frame-iMtrvx_a.js} +18 -18
  9. package/dist/duo-view-BAh-w2Kz.js +1 -0
  10. package/dist/duo-view-D9Ae00rj.mjs +512 -0
  11. package/dist/index.cjs +1 -1
  12. package/dist/index.css +1 -1
  13. package/dist/index.js +2 -2
  14. package/dist/lite.cjs +1 -1
  15. package/dist/lite.js +1 -1
  16. package/dist/remote-control-B2jZpf3c.js +1 -0
  17. package/dist/remote-control-DiddxS8l.mjs +2883 -0
  18. package/package.json +5 -1
  19. package/dist/demo.d.ts +0 -1
  20. package/dist/duo-view-COZg8ieG.js +0 -1
  21. package/dist/duo-view-o1yxIzxu.mjs +0 -654
  22. package/dist/remote-control-CQjSEVDF.mjs +0 -2673
  23. package/dist/remote-control-DVRXfCR2.js +0 -1
  24. package/index.html +0 -199
  25. package/src/assets/Apple_logo_white.svg +0 -4
  26. package/src/assets/android_boot.gif +0 -0
  27. package/src/assets/android_boot.webp +0 -0
  28. package/src/assets/iphone16pro_black.webp +0 -0
  29. package/src/assets/iphone16pro_black_bg.webp +0 -0
  30. package/src/assets/iphone16pro_black_landscape.webp +0 -0
  31. package/src/assets/iphone16pro_black_landscape_bg.webp +0 -0
  32. package/src/assets/pixel9_black.webp +0 -0
  33. package/src/assets/pixel9_black_landscape.webp +0 -0
  34. package/src/assets/pixel_tablet_landscape.webp +0 -0
  35. package/src/assets/pixel_tablet_portrait.webp +0 -0
  36. package/src/components/device-install/index.ts +0 -1
  37. package/src/components/duo-button-hinge.test.tsx +0 -138
  38. package/src/components/duo-button-hinge.ts +0 -75
  39. package/src/components/duo-controls.tsx +0 -142
  40. package/src/components/duo-flat-frame.tsx +0 -145
  41. package/src/components/duo-flat-geometry.test.ts +0 -63
  42. package/src/components/duo-flat-geometry.ts +0 -97
  43. package/src/components/duo-fold-motion.test.tsx +0 -245
  44. package/src/components/duo-fold-motion.tsx +0 -192
  45. package/src/components/duo-fold-renderer.test.ts +0 -29
  46. package/src/components/duo-fold-renderer.ts +0 -397
  47. package/src/components/duo-fold-timing.test.ts +0 -44
  48. package/src/components/duo-fold-timing.ts +0 -9
  49. package/src/components/duo-frame.tsx +0 -579
  50. package/src/components/duo-hardware.test.ts +0 -61
  51. package/src/components/duo-hardware.ts +0 -61
  52. package/src/components/duo-model.test.ts +0 -243
  53. package/src/components/duo-model.ts +0 -607
  54. package/src/components/duo-screen-handoff.ts +0 -52
  55. package/src/components/duo-view.test.tsx +0 -104
  56. package/src/components/duo-view.tsx +0 -315
  57. package/src/components/inspect-overlay.css +0 -223
  58. package/src/components/inspect-overlay.tsx +0 -437
  59. package/src/components/remote-control-framed.tsx +0 -14
  60. package/src/components/remote-control.css +0 -441
  61. package/src/components/remote-control.test.ts +0 -34
  62. package/src/components/remote-control.tsx +0 -3989
  63. package/src/core/ax-fetcher.test.ts +0 -418
  64. package/src/core/ax-fetcher.ts +0 -387
  65. package/src/core/ax-tree.test.ts +0 -491
  66. package/src/core/ax-tree.ts +0 -416
  67. package/src/core/camera.test.ts +0 -155
  68. package/src/core/camera.ts +0 -133
  69. package/src/core/constants.ts +0 -344
  70. package/src/core/duo.test.ts +0 -142
  71. package/src/core/duo.ts +0 -156
  72. package/src/core/webrtc-messages.ts +0 -148
  73. package/src/demo.tsx +0 -283
  74. package/src/frame-assets.ts +0 -22
  75. package/src/hooks/index.ts +0 -1
  76. package/src/index.ts +0 -29
  77. package/src/lite.test.ts +0 -30
  78. package/src/lite.ts +0 -30
  79. package/src/vite-env.d.ts +0 -1
  80. package/tsconfig.json +0 -26
  81. package/tsconfig.node.json +0 -26
  82. package/vite.config.ts +0 -35
  83. package/vitest.config.ts +0 -24
@@ -0,0 +1,2883 @@
1
+ import { jsxs as V, jsx as v, Fragment as nr } from "react/jsx-runtime";
2
+ import Yn, { useId as Kn, useRef as D, useState as q, useEffect as le, memo as or, useMemo as Ye, useCallback as kn, lazy as Pn, forwardRef as Un, useImperativeHandle as Ln, Suspense as xn } from "react";
3
+ import { createPortal as Fn } from "react-dom";
4
+ import './index.css';function Hr(r) {
5
+ var e, i, c = "";
6
+ if (typeof r == "string" || typeof r == "number") c += r;
7
+ else if (typeof r == "object") if (Array.isArray(r)) {
8
+ var l = r.length;
9
+ for (e = 0; e < l; e++) r[e] && (i = Hr(r[e])) && (c && (c += " "), c += i);
10
+ } else for (i in r) r[i] && (c && (c += " "), c += i);
11
+ return c;
12
+ }
13
+ function Ke() {
14
+ for (var r, e, i = 0, c = "", l = arguments.length; i < l; i++) (r = arguments[i]) && (e = Hr(r)) && (c && (c += " "), c += e);
15
+ return c;
16
+ }
17
+ function er(r, e, i, c, l, u) {
18
+ return "M" + (r + l) + "," + e + "H" + (r + i - u) + "a" + u + "," + u + " 0 0 1 " + u + "," + u + "V" + (e + c - u) + "a" + u + "," + u + " 0 0 1 " + -u + "," + u + "H" + (r + l) + "a" + l + "," + l + " 0 0 1 " + -l + "," + -l + "V" + (e + l) + "a" + l + "," + l + " 0 0 1 " + l + "," + -l + "Z";
19
+ }
20
+ function Wn({ inner: r, width: e, height: i }) {
21
+ const c = Kn().replace(/:/g, ""), l = r ? 8.4 : 1.25, u = 8.4;
22
+ return /* @__PURE__ */ V("svg", { className: "rc-duo-flat-frame", viewBox: "0 0 " + e + " " + i, "aria-hidden": "true", children: [
23
+ /* @__PURE__ */ V("defs", { children: [
24
+ /* @__PURE__ */ V("linearGradient", { id: c + "-silver", x1: "0", y1: "0", x2: "1", y2: "1", children: [
25
+ /* @__PURE__ */ v("stop", { offset: "0", stopColor: "#62676b" }),
26
+ /* @__PURE__ */ v("stop", { offset: "0.035", stopColor: "#f9faf9" }),
27
+ /* @__PURE__ */ v("stop", { offset: "0.11", stopColor: "#b0b4b6" }),
28
+ /* @__PURE__ */ v("stop", { offset: "0.31", stopColor: "#fdfefd" }),
29
+ /* @__PURE__ */ v("stop", { offset: "0.43", stopColor: "#797f84" }),
30
+ /* @__PURE__ */ v("stop", { offset: "0.51", stopColor: "#e8eaea" }),
31
+ /* @__PURE__ */ v("stop", { offset: "0.7", stopColor: "#979da1" }),
32
+ /* @__PURE__ */ v("stop", { offset: "0.87", stopColor: "#fafbf9" }),
33
+ /* @__PURE__ */ v("stop", { offset: "1", stopColor: "#5f676c" })
34
+ ] }),
35
+ /* @__PURE__ */ V("linearGradient", { id: c + "-spine", children: [
36
+ /* @__PURE__ */ v("stop", { stopColor: "#4a5154" }),
37
+ /* @__PURE__ */ v("stop", { offset: "0.16", stopColor: "#d6d9d9" }),
38
+ /* @__PURE__ */ v("stop", { offset: "0.4", stopColor: "#f8f9f7" }),
39
+ /* @__PURE__ */ v("stop", { offset: "0.62", stopColor: "#a2a8ab" }),
40
+ /* @__PURE__ */ v("stop", { offset: "0.83", stopColor: "#e4e7e5" }),
41
+ /* @__PURE__ */ v("stop", { offset: "1", stopColor: "#666e72" })
42
+ ] })
43
+ ] }),
44
+ !r && /* @__PURE__ */ V(nr, { children: [
45
+ /* @__PURE__ */ v(
46
+ "rect",
47
+ {
48
+ x: "-2.3",
49
+ y: "0.7",
50
+ width: "3.3",
51
+ height: i - 1.4,
52
+ rx: "0.85",
53
+ fill: "url(#" + c + "-spine)",
54
+ stroke: "#8b9296",
55
+ strokeWidth: "0.15"
56
+ }
57
+ ),
58
+ /* @__PURE__ */ v("path", { d: "M-.6 2V" + (i - 2), stroke: "#f5f6f4", strokeWidth: "0.22" })
59
+ ] }),
60
+ /* @__PURE__ */ v(
61
+ "path",
62
+ {
63
+ d: er(0, 0, e, i, l, u),
64
+ fill: "url(#" + c + "-silver)",
65
+ stroke: "#696f72",
66
+ strokeWidth: "0.24"
67
+ }
68
+ ),
69
+ /* @__PURE__ */ v(
70
+ "path",
71
+ {
72
+ d: er(0.48, 0.48, e - 0.96, i - 0.96, Math.max(0.5, l - 0.48), u - 0.48),
73
+ fill: "none",
74
+ stroke: "#ffffff",
75
+ strokeOpacity: "0.85",
76
+ strokeWidth: "0.2"
77
+ }
78
+ ),
79
+ /* @__PURE__ */ v(
80
+ "path",
81
+ {
82
+ d: er(1.12, 1.12, e - 2.24, i - 2.24, r ? 7.15 : 0.65, 7.15),
83
+ fill: "#090b0d",
84
+ stroke: "#34393c",
85
+ strokeWidth: "0.2"
86
+ }
87
+ ),
88
+ [e - 16, r ? 19 : 16].map((E) => /* @__PURE__ */ v(Yn.Fragment, { children: /* @__PURE__ */ v(
89
+ "path",
90
+ {
91
+ d: "M" + E + ",0.17v0.82M" + E + "," + (i - 1) + "v0.82",
92
+ stroke: "#b1b2ac",
93
+ strokeWidth: "1.1"
94
+ }
95
+ ) }, E)),
96
+ r && [0, i - 0.6].map((E) => /* @__PURE__ */ v(
97
+ "rect",
98
+ {
99
+ x: e / 2 - 2.2,
100
+ y: E,
101
+ width: "4.4",
102
+ height: "0.6",
103
+ rx: "0.18",
104
+ fill: "url(#" + c + "-spine)",
105
+ stroke: "#697074",
106
+ strokeWidth: "0.14"
107
+ },
108
+ E
109
+ )),
110
+ /* @__PURE__ */ v(
111
+ "path",
112
+ {
113
+ d: "M" + (e - 0.1) + ",20h-.9m.9," + (i - 40) + "h-.9",
114
+ stroke: "#b1b2ac",
115
+ strokeWidth: "1.05"
116
+ }
117
+ )
118
+ ] });
119
+ }
120
+ const kr = { width: 164.6, height: 117.8, depth: 5.2 };
121
+ function Ho(r, e, i) {
122
+ return r = Math.max(0, Math.min(1, r)), e = Math.max(0, Math.min(1, e)), i === 1 ? { x: e, y: 1 - r } : i === 2 ? { x: 1 - r, y: 1 - e } : i === 3 ? { x: 1 - e, y: r } : { x: r, y: e };
123
+ }
124
+ function Hn(r) {
125
+ return Number.isFinite(r) && r >= 0 && r <= 180;
126
+ }
127
+ function $o(r, e) {
128
+ return { x: Math.max(0, Math.min(1, r)), y: Math.max(0, Math.min(1, 1 - e)) };
129
+ }
130
+ function Xo(r, e, i) {
131
+ return e && (r || !i) ? "touch" : r ? "ignore" : "orbit";
132
+ }
133
+ function $n(r, e, i, c) {
134
+ if (!Number.isInteger(r) || r < 0 || r > 3 || !Number.isInteger(e) || e < 1 || e > 255 || !Number.isFinite(i) || !Number.isFinite(c) || i < 0 || i > 1 || c < 0 || c > 1)
135
+ throw new RangeError("Invalid display touch coordinates");
136
+ const l = new ArrayBuffer(12), u = new DataView(l);
137
+ return u.setUint8(0, 19), u.setUint8(1, r), u.setUint8(2, e), u.setFloat32(4, i, !0), u.setFloat32(8, c, !0), l;
138
+ }
139
+ class Bo {
140
+ constructor(e, i) {
141
+ this.send = e, this.failed = i;
142
+ }
143
+ send;
144
+ failed;
145
+ latest;
146
+ running = !1;
147
+ stopped = !1;
148
+ set(e) {
149
+ this.stopped || !Hn(e) || (this.latest = e, this.flush());
150
+ }
151
+ stop() {
152
+ this.stopped = !0, this.latest = void 0;
153
+ }
154
+ async flush() {
155
+ if (!(this.running || this.stopped)) {
156
+ this.running = !0;
157
+ try {
158
+ for (; this.latest !== void 0 && !this.stopped; ) {
159
+ const e = this.latest;
160
+ this.latest = void 0, await this.send(e);
161
+ }
162
+ } catch (e) {
163
+ this.latest = void 0, this.stopped || this.failed(e);
164
+ } finally {
165
+ this.running = !1;
166
+ }
167
+ }
168
+ }
169
+ }
170
+ const qo = {
171
+ side: "Sleep/Wake",
172
+ volumeUp: "Volume Up",
173
+ volumeDown: "Volume Down"
174
+ };
175
+ class Vo {
176
+ constructor(e, i) {
177
+ this.send = e, this.failed = i;
178
+ }
179
+ send;
180
+ failed;
181
+ held;
182
+ tail = Promise.resolve();
183
+ timeout;
184
+ press(e) {
185
+ this.held || (this.held = e, this.enqueue(e, !0), this.timeout = setTimeout(() => this.release(), 1e4));
186
+ }
187
+ release() {
188
+ if (!this.held) return;
189
+ clearTimeout(this.timeout);
190
+ const e = this.held;
191
+ this.held = void 0, this.enqueue(e, !1);
192
+ }
193
+ enqueue(e, i) {
194
+ this.tail = this.tail.then(() => this.send(e, i)).catch(this.failed);
195
+ }
196
+ }
197
+ function Xn(r, e, i, c) {
198
+ const l = kr.width / (r ? 1 : 2), u = kr.height, E = r ? 157.5 : 77.1, y = r ? 110.8 : 112.2, w = (e + (r ? 3 : 0)) % 4, O = Math.max(
199
+ 0,
200
+ Math.min(
201
+ (i - 120) / (w % 2 ? u : l),
202
+ (c - 120) / (w % 2 ? l : u)
203
+ )
204
+ ), R = (S, F) => {
205
+ S = (S - l / 2) * O, F = (F - u / 2) * O;
206
+ const re = w === 1 ? { x: -F, y: S } : w === 2 ? { x: -S, y: -F } : w === 3 ? { x: F, y: -S } : { x: S, y: F };
207
+ return { x: re.x + i / 2, y: re.y + c / 2 };
208
+ }, N = (w % 2 ? u : l) * O, j = (w % 2 ? l : u) * O, ee = {
209
+ min: { x: (i - N) / 2, y: (c - j) / 2 },
210
+ max: { x: (i + N) / 2, y: (c + j) / 2 }
211
+ }, fe = [
212
+ { button: "volumeDown", x: l - 37, y: -0.32, width: 9.5, height: 0.65, edge: "top" },
213
+ { button: "volumeUp", x: l - 25, y: -0.32, width: 9.5, height: 0.65, edge: "top" },
214
+ { button: "side", x: l + 0.35, y: u / 2 - 21, width: 0.7, height: 13, edge: "right" }
215
+ ], Oe = ["top", "right", "bottom", "left"], ge = fe.map((S) => {
216
+ const F = Oe[(Oe.indexOf(S.edge) + w) % 4], re = R(S.x, S.y);
217
+ return F === "top" && (re.y = ee.min.y - 28), F === "bottom" && (re.y = ee.max.y + 28), F === "left" && (re.x = ee.min.x - 28), F === "right" && (re.x = ee.max.x + 28), { button: S.button, edge: F, ...re, targetX: re.x, targetY: re.y };
218
+ }), U = ge.filter((S) => S.button !== "side"), Q = w % 2 ? "y" : "x";
219
+ U.sort((S, F) => S[Q] - F[Q]);
220
+ const te = w % 2 ? "targetY" : "targetX";
221
+ if (U[1][Q] - U[0][Q] < 44) {
222
+ const S = (U[0][Q] + U[1][Q]) / 2;
223
+ U[0][te] = S - 22, U[1][te] = S + 22;
224
+ }
225
+ return {
226
+ bodyWidth: l,
227
+ bodyHeight: u,
228
+ screenWidth: E,
229
+ screenHeight: y,
230
+ scale: O,
231
+ turns: w,
232
+ buttons: fe,
233
+ guides: ge,
234
+ rect: ee,
235
+ iconSize: Math.min(Bn(ee), 12 * O)
236
+ };
237
+ }
238
+ function Bn(r) {
239
+ return Math.max(12, Math.min(24, Math.max(r.max.x - r.min.x, r.max.y - r.min.y) / 24));
240
+ }
241
+ function Go(r, e, i) {
242
+ return [
243
+ ["top", i.min.y - e, r, i.min.x, i.max.x],
244
+ ["bottom", e - i.max.y, r, i.min.x, i.max.x],
245
+ ["left", i.min.x - r, e, i.min.y, i.max.y],
246
+ ["right", r - i.max.x, e, i.min.y, i.max.y]
247
+ ].filter(
248
+ ([, l, u, E, y]) => l >= -7 && l <= 52 && u >= E - 12 && u <= y + 12
249
+ ).sort((l, u) => Math.abs(l[1]) - Math.abs(u[1]))[0]?.[0];
250
+ }
251
+ function qn({ logo: r }) {
252
+ return /* @__PURE__ */ v("div", { className: "rc-duo-loading-screen", role: "status", "aria-label": "Connecting to iPhone Duo", children: r && /* @__PURE__ */ v("img", { src: r, alt: "" }) });
253
+ }
254
+ function Pr({ logo: r, showFrame: e }) {
255
+ const i = D(null), [c, l] = q({ width: 0, height: 0 });
256
+ le(() => {
257
+ const O = new ResizeObserver(([R]) => {
258
+ R && l({ width: R.contentRect.width, height: R.contentRect.height });
259
+ });
260
+ return i.current && O.observe(i.current), () => O.disconnect();
261
+ }, []);
262
+ const u = Xn(!1, 0, c.width, c.height), E = e ? u.scale : Math.min(c.width / u.screenWidth, c.height / u.screenHeight), y = e ? u.bodyWidth : u.screenWidth, w = e ? u.bodyHeight : u.screenHeight;
263
+ return /* @__PURE__ */ v("div", { className: "rc-duo-view", children: /* @__PURE__ */ V("div", { className: e ? "rc-duo" : "rc-duo rc-duo-frameless", children: [
264
+ /* @__PURE__ */ v("div", { ref: i, className: "rc-duo-flat-stage", children: /* @__PURE__ */ V(
265
+ "div",
266
+ {
267
+ className: "rc-duo-flat-device",
268
+ style: { width: y * E, height: w * E, transform: "translate(-50%, -50%)" },
269
+ children: [
270
+ e && /* @__PURE__ */ v(Wn, { inner: !1, width: y, height: w }),
271
+ /* @__PURE__ */ v(
272
+ "div",
273
+ {
274
+ className: "rc-duo-flat-screen",
275
+ style: {
276
+ width: u.screenWidth * E,
277
+ height: u.screenHeight * E,
278
+ left: (y - u.screenWidth) / 2 * E,
279
+ top: (w - u.screenHeight) / 2 * E,
280
+ borderRadius: e ? [0.8, 6.6, 6.6, 0.8].map((O) => O * E + "px").join(" ") : 0
281
+ },
282
+ children: /* @__PURE__ */ v(qn, { logo: r })
283
+ }
284
+ )
285
+ ]
286
+ }
287
+ ) }),
288
+ e && /* @__PURE__ */ v("div", { className: "rc-duo-loading-controls", "aria-hidden": "true" })
289
+ ] }) });
290
+ }
291
+ const Ut = {
292
+ INJECT_KEYCODE: 0,
293
+ INJECT_TOUCH_EVENT: 2,
294
+ // iOS-specific: send two touch points in one message (Option/Alt+drag pinch)
295
+ INJECT_TWO_FINGER_TOUCH_EVENT: 18,
296
+ SET_CLIPBOARD: 9
297
+ }, x = {
298
+ ACTION_DOWN: 0,
299
+ ACTION_UP: 1,
300
+ ACTION_MOVE: 2,
301
+ ACTION_CANCEL: 3,
302
+ ACTION_POINTER_DOWN: 5,
303
+ ACTION_POINTER_UP: 6,
304
+ BUTTON_PRIMARY: 1,
305
+ BUTTON_SECONDARY: 2,
306
+ BUTTON_TERTIARY: 4
307
+ }, a = {
308
+ // Actions
309
+ ACTION_DOWN: 0,
310
+ ACTION_UP: 1,
311
+ // Meta state flags (from android.view.KeyEvent)
312
+ META_NONE: 0,
313
+ META_SHIFT_ON: 1,
314
+ META_ALT_ON: 2,
315
+ META_CTRL_ON: 4096,
316
+ // META_CTRL_LEFT_ON | META_CTRL_RIGHT_ON
317
+ META_META_ON: 65536,
318
+ KEYCODE_0: 7,
319
+ KEYCODE_1: 8,
320
+ KEYCODE_2: 9,
321
+ KEYCODE_3: 10,
322
+ KEYCODE_4: 11,
323
+ KEYCODE_5: 12,
324
+ KEYCODE_6: 13,
325
+ KEYCODE_7: 14,
326
+ KEYCODE_8: 15,
327
+ KEYCODE_9: 16,
328
+ DPAD_UP: 19,
329
+ // KEYCODE_DPAD_UP
330
+ DPAD_DOWN: 20,
331
+ // KEYCODE_DPAD_DOWN
332
+ DPAD_LEFT: 21,
333
+ // KEYCODE_DPAD_LEFT
334
+ DPAD_RIGHT: 22,
335
+ KEYCODE_A: 29,
336
+ KEYCODE_B: 30,
337
+ KEYCODE_C: 31,
338
+ KEYCODE_D: 32,
339
+ KEYCODE_E: 33,
340
+ KEYCODE_F: 34,
341
+ KEYCODE_G: 35,
342
+ KEYCODE_H: 36,
343
+ KEYCODE_I: 37,
344
+ KEYCODE_J: 38,
345
+ KEYCODE_K: 39,
346
+ KEYCODE_L: 40,
347
+ KEYCODE_M: 41,
348
+ KEYCODE_N: 42,
349
+ KEYCODE_O: 43,
350
+ KEYCODE_P: 44,
351
+ KEYCODE_Q: 45,
352
+ KEYCODE_R: 46,
353
+ KEYCODE_S: 47,
354
+ KEYCODE_T: 48,
355
+ KEYCODE_U: 49,
356
+ KEYCODE_V: 50,
357
+ KEYCODE_W: 51,
358
+ KEYCODE_X: 52,
359
+ KEYCODE_Y: 53,
360
+ KEYCODE_Z: 54,
361
+ KEYCODE_COMMA: 55,
362
+ KEYCODE_PERIOD: 56,
363
+ KEYCODE_ALT_LEFT: 57,
364
+ KEYCODE_ALT_RIGHT: 58,
365
+ KEYCODE_SHIFT_LEFT: 59,
366
+ KEYCODE_SHIFT_RIGHT: 60,
367
+ KEYCODE_TAB: 61,
368
+ KEYCODE_SPACE: 62,
369
+ ENTER: 66,
370
+ // KEYCODE_ENTER
371
+ DEL: 67,
372
+ // KEYCODE_DEL (Backspace)
373
+ KEYCODE_GRAVE: 68,
374
+ // `
375
+ KEYCODE_MINUS: 69,
376
+ // -
377
+ KEYCODE_EQUALS: 70,
378
+ // =
379
+ KEYCODE_LEFT_BRACKET: 71,
380
+ // [
381
+ KEYCODE_RIGHT_BRACKET: 72,
382
+ // ]
383
+ KEYCODE_BACKSLASH: 73,
384
+ // \
385
+ KEYCODE_SEMICOLON: 74,
386
+ // ;
387
+ KEYCODE_APOSTROPHE: 75,
388
+ // '
389
+ KEYCODE_SLASH: 76,
390
+ MENU: 82,
391
+ KEYCODE_PAGE_UP: 92,
392
+ KEYCODE_PAGE_DOWN: 93,
393
+ KEYCODE_ESCAPE: 111,
394
+ FORWARD_DEL: 112,
395
+ // KEYCODE_FORWARD_DEL (Delete key)
396
+ KEYCODE_CTRL_LEFT: 113,
397
+ KEYCODE_CTRL_RIGHT: 114,
398
+ KEYCODE_META_LEFT: 117,
399
+ KEYCODE_META_RIGHT: 118,
400
+ KEYCODE_MOVE_HOME: 122,
401
+ KEYCODE_MOVE_END: 123,
402
+ KEYCODE_INSERT: 124,
403
+ KEYCODE_F1: 131,
404
+ KEYCODE_F2: 132,
405
+ KEYCODE_F3: 133,
406
+ KEYCODE_F4: 134,
407
+ KEYCODE_F5: 135,
408
+ KEYCODE_F6: 136,
409
+ KEYCODE_F7: 137,
410
+ KEYCODE_F8: 138,
411
+ KEYCODE_F9: 139,
412
+ KEYCODE_F10: 140,
413
+ KEYCODE_F11: 141,
414
+ KEYCODE_F12: 142,
415
+ KEYCODE_NUMPAD_0: 144,
416
+ KEYCODE_NUMPAD_1: 145,
417
+ KEYCODE_NUMPAD_2: 146,
418
+ KEYCODE_NUMPAD_3: 147,
419
+ KEYCODE_NUMPAD_4: 148,
420
+ KEYCODE_NUMPAD_5: 149,
421
+ KEYCODE_NUMPAD_6: 150,
422
+ KEYCODE_NUMPAD_7: 151,
423
+ KEYCODE_NUMPAD_8: 152,
424
+ KEYCODE_NUMPAD_9: 153,
425
+ KEYCODE_NUMPAD_DIVIDE: 154,
426
+ KEYCODE_NUMPAD_MULTIPLY: 155,
427
+ KEYCODE_NUMPAD_SUBTRACT: 156,
428
+ KEYCODE_NUMPAD_ADD: 157,
429
+ KEYCODE_NUMPAD_DOT: 158,
430
+ KEYCODE_NUMPAD_COMMA: 159,
431
+ KEYCODE_NUMPAD_ENTER: 160,
432
+ KEYCODE_NUMPAD_EQUALS: 161
433
+ }, $r = {
434
+ KeyA: a.KEYCODE_A,
435
+ KeyB: a.KEYCODE_B,
436
+ KeyC: a.KEYCODE_C,
437
+ KeyD: a.KEYCODE_D,
438
+ KeyE: a.KEYCODE_E,
439
+ KeyF: a.KEYCODE_F,
440
+ KeyG: a.KEYCODE_G,
441
+ KeyH: a.KEYCODE_H,
442
+ KeyI: a.KEYCODE_I,
443
+ KeyJ: a.KEYCODE_J,
444
+ KeyK: a.KEYCODE_K,
445
+ KeyL: a.KEYCODE_L,
446
+ KeyM: a.KEYCODE_M,
447
+ KeyN: a.KEYCODE_N,
448
+ KeyO: a.KEYCODE_O,
449
+ KeyP: a.KEYCODE_P,
450
+ KeyQ: a.KEYCODE_Q,
451
+ KeyR: a.KEYCODE_R,
452
+ KeyS: a.KEYCODE_S,
453
+ KeyT: a.KEYCODE_T,
454
+ KeyU: a.KEYCODE_U,
455
+ KeyV: a.KEYCODE_V,
456
+ KeyW: a.KEYCODE_W,
457
+ KeyX: a.KEYCODE_X,
458
+ KeyY: a.KEYCODE_Y,
459
+ KeyZ: a.KEYCODE_Z,
460
+ Digit0: a.KEYCODE_0,
461
+ Digit1: a.KEYCODE_1,
462
+ Digit2: a.KEYCODE_2,
463
+ Digit3: a.KEYCODE_3,
464
+ Digit4: a.KEYCODE_4,
465
+ Digit5: a.KEYCODE_5,
466
+ Digit6: a.KEYCODE_6,
467
+ Digit7: a.KEYCODE_7,
468
+ Digit8: a.KEYCODE_8,
469
+ Digit9: a.KEYCODE_9,
470
+ Backquote: a.KEYCODE_GRAVE,
471
+ Minus: a.KEYCODE_MINUS,
472
+ Equal: a.KEYCODE_EQUALS,
473
+ BracketLeft: a.KEYCODE_LEFT_BRACKET,
474
+ BracketRight: a.KEYCODE_RIGHT_BRACKET,
475
+ Backslash: a.KEYCODE_BACKSLASH,
476
+ Semicolon: a.KEYCODE_SEMICOLON,
477
+ Quote: a.KEYCODE_APOSTROPHE,
478
+ Comma: a.KEYCODE_COMMA,
479
+ Period: a.KEYCODE_PERIOD,
480
+ Slash: a.KEYCODE_SLASH,
481
+ Space: a.KEYCODE_SPACE,
482
+ Tab: a.KEYCODE_TAB,
483
+ Escape: a.KEYCODE_ESCAPE,
484
+ ArrowUp: a.DPAD_UP,
485
+ ArrowDown: a.DPAD_DOWN,
486
+ ArrowLeft: a.DPAD_LEFT,
487
+ ArrowRight: a.DPAD_RIGHT,
488
+ Enter: a.ENTER,
489
+ Backspace: a.DEL,
490
+ Delete: a.FORWARD_DEL,
491
+ Home: a.KEYCODE_MOVE_HOME,
492
+ End: a.KEYCODE_MOVE_END,
493
+ PageUp: a.KEYCODE_PAGE_UP,
494
+ PageDown: a.KEYCODE_PAGE_DOWN,
495
+ Insert: a.KEYCODE_INSERT,
496
+ F1: a.KEYCODE_F1,
497
+ F2: a.KEYCODE_F2,
498
+ F3: a.KEYCODE_F3,
499
+ F4: a.KEYCODE_F4,
500
+ F5: a.KEYCODE_F5,
501
+ F6: a.KEYCODE_F6,
502
+ F7: a.KEYCODE_F7,
503
+ F8: a.KEYCODE_F8,
504
+ F9: a.KEYCODE_F9,
505
+ F10: a.KEYCODE_F10,
506
+ F11: a.KEYCODE_F11,
507
+ F12: a.KEYCODE_F12,
508
+ ShiftLeft: a.KEYCODE_SHIFT_LEFT,
509
+ ShiftRight: a.KEYCODE_SHIFT_RIGHT,
510
+ ControlLeft: a.KEYCODE_CTRL_LEFT,
511
+ ControlRight: a.KEYCODE_CTRL_RIGHT,
512
+ AltLeft: a.KEYCODE_ALT_LEFT,
513
+ AltRight: a.KEYCODE_ALT_RIGHT,
514
+ MetaLeft: a.KEYCODE_META_LEFT,
515
+ MetaRight: a.KEYCODE_META_RIGHT,
516
+ // Windows/Command key
517
+ ContextMenu: a.MENU,
518
+ // Often the Menu key
519
+ // Numpad mappings
520
+ Numpad0: a.KEYCODE_NUMPAD_0,
521
+ Numpad1: a.KEYCODE_NUMPAD_1,
522
+ Numpad2: a.KEYCODE_NUMPAD_2,
523
+ Numpad3: a.KEYCODE_NUMPAD_3,
524
+ Numpad4: a.KEYCODE_NUMPAD_4,
525
+ Numpad5: a.KEYCODE_NUMPAD_5,
526
+ Numpad6: a.KEYCODE_NUMPAD_6,
527
+ Numpad7: a.KEYCODE_NUMPAD_7,
528
+ Numpad8: a.KEYCODE_NUMPAD_8,
529
+ Numpad9: a.KEYCODE_NUMPAD_9,
530
+ NumpadDivide: a.KEYCODE_NUMPAD_DIVIDE,
531
+ NumpadMultiply: a.KEYCODE_NUMPAD_MULTIPLY,
532
+ NumpadSubtract: a.KEYCODE_NUMPAD_SUBTRACT,
533
+ NumpadAdd: a.KEYCODE_NUMPAD_ADD,
534
+ NumpadDecimal: a.KEYCODE_NUMPAD_DOT,
535
+ NumpadComma: a.KEYCODE_NUMPAD_COMMA,
536
+ // Some numpads have comma
537
+ NumpadEnter: a.KEYCODE_NUMPAD_ENTER,
538
+ NumpadEqual: a.KEYCODE_NUMPAD_EQUALS
539
+ };
540
+ function Kt(r, e, i, c, l, u, E = 1, y = 0, w = 0) {
541
+ const O = new ArrayBuffer(32), R = new DataView(O);
542
+ let N = 0;
543
+ return R.setUint8(N, Ut.INJECT_TOUCH_EVENT), N += 1, R.setUint8(N, r), N += 1, R.setBigInt64(N, BigInt(e), !0), N += 8, R.setInt32(N, Math.round(l), !0), N += 4, R.setInt32(N, Math.round(u), !0), N += 4, R.setUint16(N, i, !0), N += 2, R.setUint16(N, c, !0), N += 2, R.setInt16(N, Math.round(E * 65535), !0), N += 2, R.setInt32(N, y, !0), N += 4, R.setInt32(N, w, !0), O;
544
+ }
545
+ function Vn(r, e, i, c, l, u, E) {
546
+ const y = new ArrayBuffer(24), w = new DataView(y);
547
+ let O = 0;
548
+ return w.setUint8(O, Ut.INJECT_TWO_FINGER_TOUCH_EVENT), O += 1, w.setUint8(O, r), O += 1, w.setInt32(O, Math.round(c), !0), O += 4, w.setInt32(O, Math.round(l), !0), O += 4, w.setInt32(O, Math.round(u), !0), O += 4, w.setInt32(O, Math.round(E), !0), O += 4, w.setUint16(O, e, !0), O += 2, w.setUint16(O, i, !0), O += 2, w.setUint16(O, 0, !0), y;
549
+ }
550
+ function Gn(r, e = !0) {
551
+ const c = new TextEncoder().encode(r), l = new ArrayBuffer(14 + c.length), u = new DataView(l);
552
+ let E = 0;
553
+ return u.setUint8(E, Ut.SET_CLIPBOARD), E += 1, u.setBigInt64(E, BigInt(0), !1), E += 8, u.setUint8(E, e ? 1 : 0), E += 1, u.setUint32(E, c.length, !1), E += 4, new Uint8Array(l, E).set(c), l;
554
+ }
555
+ function Et(r, e, i = 0, c = 0) {
556
+ const l = new ArrayBuffer(14), u = new DataView(l);
557
+ let E = 0;
558
+ return u.setUint8(E, Ut.INJECT_KEYCODE), E += 1, u.setUint8(E, r), E += 1, u.setInt32(E, e, !0), E += 4, u.setInt32(E, i, !0), E += 4, u.setInt32(E, c, !0), l;
559
+ }
560
+ const tr = "Accessibility unavailable on this device.", Pt = 500, Xr = (r, e) => Math.abs(r.x - e.x) < 0.5 && Math.abs(r.y - e.y) < 0.5 && Math.abs(r.width - e.width) < 0.5 && Math.abs(r.height - e.height) < 0.5, Jn = (r) => Math.max(0, r.width) * Math.max(0, r.height), zn = (r) => {
561
+ const e = r.find((i) => i.frame && i.frame.width > 0 && i.frame.height > 0);
562
+ return e?.frame ? ((Math.abs(e.frame.x) > 0.5 || Math.abs(e.frame.y) > 0.5) && console.warn(
563
+ `[ax-tree] iOS root frame is not anchored at (0,0): (${e.frame.x},${e.frame.y}). Element positions may be slightly off from the rendered video.`
564
+ ), { x: 0, y: 0, width: e.frame.width, height: e.frame.height }) : { x: 0, y: 0, width: 1, height: 1 };
565
+ }, jn = (r) => {
566
+ const e = {};
567
+ return typeof r.AXUniqueId == "string" && r.AXUniqueId.length > 0 && (e.AXUniqueId = r.AXUniqueId), typeof r.AXLabel == "string" && r.AXLabel.length > 0 && (e.AXLabel = r.AXLabel), typeof r.type == "string" && r.type.length > 0 && (e.className = r.type), e;
568
+ }, Qn = (r) => {
569
+ const e = {};
570
+ for (const [i, c] of Object.entries(r))
571
+ i !== "children" && (e[i] = c);
572
+ return e;
573
+ };
574
+ function Zn(r) {
575
+ const e = Array.isArray(r) ? r : [r], i = zn(e), c = [], l = (u, E) => {
576
+ if (c.length >= Pt) return;
577
+ const y = u.frame;
578
+ if (y && y.width > 0 && y.height > 0 && !Xr(y, i)) {
579
+ const O = u.role_description || u.role || "", R = (typeof u.AXLabel == "string" ? u.AXLabel : "") || (typeof u.title == "string" ? u.title : "") || "";
580
+ c.push({
581
+ id: typeof u.AXUniqueId == "string" && u.AXUniqueId.length > 0 ? u.AXUniqueId : E,
582
+ path: E,
583
+ label: R,
584
+ value: typeof u.AXValue == "string" ? u.AXValue : "",
585
+ role: O,
586
+ type: typeof u.type == "string" ? u.type : "",
587
+ enabled: u.enabled !== !1,
588
+ focused: u.focused === !0,
589
+ frame: { x: y.x, y: y.y, width: y.width, height: y.height },
590
+ selectors: jn(u),
591
+ raw: Qn(u)
592
+ });
593
+ }
594
+ const w = Array.isArray(u.children) ? u.children : [];
595
+ for (let O = 0; O < w.length && c.length < Pt; O++)
596
+ l(w[O], `${E}.${O}`);
597
+ };
598
+ for (let u = 0; u < e.length && c.length < Pt; u++)
599
+ l(e[u], String(u));
600
+ return {
601
+ platform: "ios",
602
+ screen: { width: i.width, height: i.height },
603
+ elements: c,
604
+ capturedAt: Date.now()
605
+ };
606
+ }
607
+ const eo = (r) => {
608
+ let e = { x: 0, y: 0, width: 1, height: 1 }, i = 0;
609
+ for (const c of r) {
610
+ const l = c.parsedBounds;
611
+ if (!l) continue;
612
+ const u = l.right - l.left, E = l.bottom - l.top, y = Math.max(0, u) * Math.max(0, E);
613
+ y > i && (i = y, e = { x: 0, y: 0, width: u, height: E });
614
+ }
615
+ return e;
616
+ }, to = (r) => {
617
+ const e = {};
618
+ return typeof r.resourceId == "string" && r.resourceId.length > 0 && (e.resourceId = r.resourceId), typeof r.contentDesc == "string" && r.contentDesc.length > 0 && (e.contentDesc = r.contentDesc), typeof r.text == "string" && r.text.length > 0 && (e.text = r.text), typeof r.className == "string" && r.className.length > 0 && (e.className = r.className), e;
619
+ };
620
+ function ro(r) {
621
+ const e = eo(r), i = [];
622
+ for (let c = 0; c < r.length && i.length < Pt; c++) {
623
+ const l = r[c], u = l.parsedBounds;
624
+ if (!u) continue;
625
+ const E = Math.max(0, u.right - u.left), y = Math.max(0, u.bottom - u.top);
626
+ if (E <= 0 || y <= 0) continue;
627
+ const w = { x: u.left, y: u.top, width: E, height: y };
628
+ if (Xr(w, { x: 0, y: 0, width: e.width, height: e.height })) continue;
629
+ const O = l.contentDesc || l.text || "", R = l.className || "";
630
+ i.push({
631
+ id: l.resourceId && l.resourceId.length > 0 ? l.resourceId : l.contentDesc && l.contentDesc.length > 0 ? `cd:${l.contentDesc}` : String(c),
632
+ path: String(c),
633
+ label: O,
634
+ value: typeof l.text == "string" ? l.text : "",
635
+ role: R,
636
+ type: R,
637
+ enabled: l.enabled !== !1,
638
+ focused: l.focused === !0,
639
+ frame: w,
640
+ selectors: to(l),
641
+ raw: { ...l }
642
+ });
643
+ }
644
+ return {
645
+ platform: "android",
646
+ screen: { width: e.width, height: e.height },
647
+ elements: i,
648
+ capturedAt: Date.now()
649
+ };
650
+ }
651
+ function no(r, e) {
652
+ const i = Math.max(0, r.x), c = Math.max(0, r.y), l = Math.min(e.width, r.x + r.width), u = Math.min(e.height, r.y + r.height), E = Math.max(0, l - i), y = Math.max(0, u - c);
653
+ return E > 0 && y > 0 ? { x: i, y: c, width: E, height: y } : null;
654
+ }
655
+ function Br(r, e) {
656
+ if (r === e) return !0;
657
+ if (r.id !== e.id || r.path !== e.path || r.label !== e.label || r.value !== e.value || r.role !== e.role || r.type !== e.type || r.enabled !== e.enabled || r.focused !== e.focused) return !1;
658
+ const i = r.frame, c = e.frame;
659
+ return i.x === c.x && i.y === c.y && i.width === c.width && i.height === c.height;
660
+ }
661
+ function qr(r, e) {
662
+ if (r === e) return !0;
663
+ if (!r || !e || r.platform !== e.platform || r.screen.width !== e.screen.width || r.screen.height !== e.screen.height || r.elements.length !== e.elements.length) return !1;
664
+ for (let i = 0; i < r.elements.length; i++)
665
+ if (!Br(r.elements[i], e.elements[i])) return !1;
666
+ return !0;
667
+ }
668
+ function oo(r, e, i) {
669
+ let c = null, l = 1 / 0;
670
+ for (const u of r.elements) {
671
+ const E = u.frame;
672
+ if (e < E.x || i < E.y || e > E.x + E.width || i > E.y + E.height) continue;
673
+ const y = Jn(E);
674
+ y < l && (l = y, c = u);
675
+ }
676
+ return c;
677
+ }
678
+ function io(r, e) {
679
+ if (e === "ios") {
680
+ if (r.selectors.AXUniqueId)
681
+ return `client.tapElement({ AXUniqueId: ${JSON.stringify(r.selectors.AXUniqueId)} })`;
682
+ if (r.selectors.AXLabel) {
683
+ const i = r.selectors.className ? `, type: ${JSON.stringify(r.selectors.className)}` : "";
684
+ return `client.tapElement({ AXLabel: ${JSON.stringify(r.selectors.AXLabel)}${i} })`;
685
+ }
686
+ return null;
687
+ }
688
+ return r.selectors.resourceId ? `client.tap({ selector: { resourceId: ${JSON.stringify(r.selectors.resourceId)} } })` : r.selectors.contentDesc ? `client.tap({ selector: { contentDesc: ${JSON.stringify(r.selectors.contentDesc)} } })` : r.selectors.text ? `client.tap({ selector: { text: ${JSON.stringify(r.selectors.text)} } })` : null;
689
+ }
690
+ function Vr(r) {
691
+ const e = r.role || r.type || "";
692
+ if (!e) return "element";
693
+ let i = e.replace(/^AX/, "");
694
+ return i.includes(".") && (i = i.split(".").pop()), i === "GenericElement" ? "Element" : (i = i.replace(/([a-z])([A-Z])/g, "$1 $2"), i);
695
+ }
696
+ const Ur = 80;
697
+ function Gr(r) {
698
+ const e = Vr(r), i = r.label || r.value || "";
699
+ if (!i) return e;
700
+ const c = i.length > Ur ? i.slice(0, Ur).trimEnd() + "…" : i;
701
+ return `${e} · ${c}`;
702
+ }
703
+ const so = 500, co = 2e3, Lr = 5e3, ao = 8e3, uo = 1200, lo = 250, fo = () => `ax-rc-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
704
+ class ho {
705
+ platform;
706
+ send;
707
+ onSnapshot;
708
+ onStatusChange;
709
+ baseIntervalMs;
710
+ maxBackoffMs;
711
+ androidElementTreeOptions;
712
+ pending = /* @__PURE__ */ new Map();
713
+ running = !1;
714
+ timer;
715
+ currentInterval;
716
+ lastSnapshot = null;
717
+ // Single-flight: only one outstanding request at a time. Avoids piling
718
+ // identical requests on a slow server.
719
+ inflight = !1;
720
+ // Rate-limit floor for bumpActivity so high-frequency input (drags,
721
+ // typing) doesn't trigger a request storm.
722
+ lastBumpAtMs = 0;
723
+ // Wall-clock timestamp until which we're in "activity boost" mode and
724
+ // schedule fetches at ACTIVITY_BOOST_INTERVAL_MS instead of the normal
725
+ // backed-off interval. Set by bumpActivity().
726
+ boostUntilMs = 0;
727
+ // Coarse-grained current status; deduplicated before emission so
728
+ // identical-to-current transitions are no-ops.
729
+ status = "idle";
730
+ constructor(e) {
731
+ this.platform = e.platform, this.send = e.send, this.onSnapshot = e.onSnapshot, this.onStatusChange = e.onStatusChange, this.baseIntervalMs = e.baseIntervalMs ?? so, this.maxBackoffMs = e.maxBackoffMs ?? co, this.androidElementTreeOptions = e.androidElementTreeOptions, this.currentInterval = this.baseIntervalMs;
732
+ }
733
+ start() {
734
+ this.running || (this.running = !0, this.currentInterval = this.baseIntervalMs, this.boostUntilMs = 0, this.setStatus("starting"), this.runOnce());
735
+ }
736
+ stop() {
737
+ this.running && (this.running = !1, this.timer !== void 0 && (window.clearTimeout(this.timer), this.timer = void 0), this.failAllPending("Inspector stopped"), this.lastSnapshot = null, this.setStatus("idle"), this.onSnapshot(null));
738
+ }
739
+ getStatus() {
740
+ return this.status;
741
+ }
742
+ setStatus(e, i) {
743
+ if (this.status !== e && (this.status = e, !!this.onStatusChange))
744
+ try {
745
+ this.onStatusChange(e, i);
746
+ } catch (c) {
747
+ console.error("[AxFetcher] onStatusChange threw:", c);
748
+ }
749
+ }
750
+ // Called after any user-driven action that's likely to change the UI
751
+ // (taps, scrolls, key events, openUrl, app termination, orientation
752
+ // change, etc.). Has two effects:
753
+ //
754
+ // 1. Resets the polling interval to base and triggers an immediate
755
+ // fetch (rate-limited so drags / rapid typing don't request-storm).
756
+ // 2. Enters a brief "boost" window during which scheduleNext() uses a
757
+ // shorter interval (ACTIVITY_BOOST_INTERVAL_MS), so we capture the
758
+ // mid- and post-animation tree without waiting for the next
759
+ // back-off cycle.
760
+ bumpActivity() {
761
+ if (!this.running) return;
762
+ const e = Date.now();
763
+ this.boostUntilMs = e + uo;
764
+ const i = Math.max(150, Math.floor(this.baseIntervalMs / 2));
765
+ if (e - this.lastBumpAtMs < i) {
766
+ this.currentInterval = this.baseIntervalMs;
767
+ return;
768
+ }
769
+ this.lastBumpAtMs = e, this.currentInterval = this.baseIntervalMs, this.timer !== void 0 && (window.clearTimeout(this.timer), this.timer = void 0), this.inflight || this.runOnce();
770
+ }
771
+ // Fire a one-shot fetch independent of the poll loop. Useful for the
772
+ // imperative refresh() ref method customers may call.
773
+ //
774
+ // Goes through the same change-detect path as the regular poll loop —
775
+ // identical-to-last-snapshot responses do NOT re-emit via onSnapshot, so
776
+ // a customer calling refresh() in a tight loop doesn't see a stream of
777
+ // duplicate snapshots. The returned promise still resolves with the
778
+ // (possibly identical) snapshot for the caller's own use.
779
+ async refresh() {
780
+ const e = await this.requestOnce();
781
+ return this.running && this.deliver(e), e;
782
+ }
783
+ // Returns the latest snapshot delivered to onSnapshot. May be stale.
784
+ getLatest() {
785
+ return this.lastSnapshot;
786
+ }
787
+ // Called by RemoteControl's ws.onmessage when it sees a message type we own.
788
+ // Returns true when the message was a response we were waiting for.
789
+ handleMessage(e) {
790
+ if (!e || typeof e.id != "string") return !1;
791
+ const i = e.id;
792
+ if (!this.pending.get(i)) return !1;
793
+ if (this.platform === "ios") {
794
+ if (e.type !== "elementTreeResult") return !1;
795
+ const y = typeof e.error == "string" ? e.error : null;
796
+ if (y)
797
+ return this.settleReject(i, new Error(y)), !0;
798
+ const w = typeof e.json == "string" ? e.json : "";
799
+ try {
800
+ const O = JSON.parse(w), R = Zn(O);
801
+ this.settleResolve(i, R);
802
+ } catch (O) {
803
+ this.settleReject(i, O instanceof Error ? O : new Error(String(O)));
804
+ }
805
+ return !0;
806
+ }
807
+ if (e.type !== "getElementTreeResult") return !1;
808
+ const l = e.error;
809
+ if (l && typeof l == "object") {
810
+ const y = typeof l.message == "string" ? l.message : "getElementTree failed";
811
+ return this.settleReject(i, new Error(y)), !0;
812
+ }
813
+ const u = e.payload, E = Array.isArray(u?.nodes) ? u.nodes : [];
814
+ try {
815
+ const y = ro(E);
816
+ this.settleResolve(i, y);
817
+ } catch (y) {
818
+ this.settleReject(i, y instanceof Error ? y : new Error(String(y)));
819
+ }
820
+ return !0;
821
+ }
822
+ buildRequest(e) {
823
+ return this.platform === "ios" ? { type: "elementTree", id: e } : { type: "getElementTree", id: e, ...this.androidElementTreeOptions };
824
+ }
825
+ async requestOnce() {
826
+ const e = fo();
827
+ return new Promise((i, c) => {
828
+ const l = window.setTimeout(
829
+ () => {
830
+ this.pending.delete(e), c(new Error("elementTree request timed out"));
831
+ },
832
+ ao + (this.androidElementTreeOptions?.waitForIdleTimeoutMs ?? 0)
833
+ );
834
+ this.pending.set(e, { resolve: i, reject: c, timer: l }), this.send(this.buildRequest(e)) || (window.clearTimeout(l), this.pending.delete(e), c(new Error("elementTree send failed (WebSocket not open)")));
835
+ });
836
+ }
837
+ async runOnce() {
838
+ if (this.running && !this.inflight) {
839
+ this.inflight = !0;
840
+ try {
841
+ const e = await this.requestOnce();
842
+ if (!this.running) return;
843
+ this.deliver(e);
844
+ } catch (e) {
845
+ if (!this.running) return;
846
+ const i = e instanceof Error ? e.message : String(e), c = /unavailable|not (yet )?running|failed|timeout/i.test(i);
847
+ this.currentInterval = c ? Lr : Math.min(this.currentInterval * 2, this.maxBackoffMs), this.setStatus(c ? "unavailable" : "error", i);
848
+ } finally {
849
+ this.inflight = !1, this.scheduleNext();
850
+ }
851
+ }
852
+ }
853
+ deliver(e) {
854
+ const i = this.lastSnapshot;
855
+ if (qr(i, e)) {
856
+ this.currentInterval = Math.min(this.currentInterval * 2, this.maxBackoffMs), this.lastSnapshot = e, e.errors?.includes(tr) || this.setStatus("ready");
857
+ return;
858
+ }
859
+ this.lastSnapshot = e, this.currentInterval = this.baseIntervalMs, e.errors?.includes(tr) ? (this.currentInterval = Lr, this.setStatus("unavailable", tr)) : this.setStatus("ready"), this.onSnapshot(e);
860
+ }
861
+ scheduleNext() {
862
+ if (!this.running) return;
863
+ this.timer !== void 0 && window.clearTimeout(this.timer);
864
+ const e = Date.now() < this.boostUntilMs ? Math.min(lo, this.currentInterval) : this.currentInterval;
865
+ this.timer = window.setTimeout(() => {
866
+ this.timer = void 0, this.runOnce();
867
+ }, e);
868
+ }
869
+ settleResolve(e, i) {
870
+ const c = this.pending.get(e);
871
+ c && (window.clearTimeout(c.timer), this.pending.delete(e), c.resolve(i));
872
+ }
873
+ settleReject(e, i) {
874
+ const c = this.pending.get(e);
875
+ c && (window.clearTimeout(c.timer), this.pending.delete(e), c.reject(i));
876
+ }
877
+ failAllPending(e) {
878
+ for (const [i, c] of this.pending.entries())
879
+ window.clearTimeout(c.timer), c.reject(new Error(e)), this.pending.delete(i);
880
+ }
881
+ }
882
+ class po {
883
+ generation = 0;
884
+ tail = Promise.resolve();
885
+ get currentGeneration() {
886
+ return this.generation;
887
+ }
888
+ enqueue(e) {
889
+ const i = ++this.generation;
890
+ return this.append(i, e);
891
+ }
892
+ /**
893
+ * Queues related work without superseding an already queued request.
894
+ *
895
+ * The operation retains the generation current at enqueue time and becomes
896
+ * stale if a later camera request increments it before this work starts.
897
+ */
898
+ enqueueCurrent(e) {
899
+ return this.append(this.generation, e);
900
+ }
901
+ append(e, i) {
902
+ const c = {
903
+ generation: e,
904
+ isCurrent: () => e === this.generation
905
+ }, l = this.tail.then(() => i(c));
906
+ return this.tail = l.catch(() => {
907
+ }), l;
908
+ }
909
+ invalidate() {
910
+ ++this.generation;
911
+ }
912
+ }
913
+ function mo(r) {
914
+ if (!r || typeof r != "object") return null;
915
+ const e = r;
916
+ if (e.type !== "cameraRequest" || typeof e.active != "boolean") return null;
917
+ const i = { active: e.active };
918
+ return (e.facingMode === "user" || e.facingMode === "environment") && (i.facingMode = e.facingMode), i;
919
+ }
920
+ function Eo(r) {
921
+ const e = {
922
+ frameRate: { ideal: 30, max: 30 }
923
+ };
924
+ return r?.facingMode && (e.facingMode = { ideal: r.facingMode }), e;
925
+ }
926
+ function go(r, e) {
927
+ return !r || r.facingMode !== e.facingMode;
928
+ }
929
+ function Co(r) {
930
+ const e = r.getSettings();
931
+ return {
932
+ width: e.width,
933
+ height: e.height,
934
+ frameRate: e.frameRate,
935
+ deviceId: e.deviceId,
936
+ label: r.label || void 0,
937
+ facingMode: e.facingMode
938
+ };
939
+ }
940
+ function yo(r) {
941
+ return {
942
+ type: "cameraResult",
943
+ granted: !0,
944
+ camera: Co(r)
945
+ };
946
+ }
947
+ const vo = async (r) => {
948
+ if (!r) return !1;
949
+ try {
950
+ if (typeof navigator < "u" && navigator.clipboard?.writeText)
951
+ return await navigator.clipboard.writeText(r), !0;
952
+ } catch {
953
+ }
954
+ try {
955
+ const e = document.createElement("textarea");
956
+ e.value = r, e.style.position = "fixed", e.style.opacity = "0", document.body.appendChild(e), e.select();
957
+ const i = document.execCommand("copy");
958
+ return document.body.removeChild(e), i;
959
+ } catch {
960
+ return !1;
961
+ }
962
+ }, Oo = or(
963
+ function({ element: e, screen: i, highlighted: c, selected: l, selectable: u, onClick: E }) {
964
+ const y = no(e.frame, i);
965
+ if (!y) return null;
966
+ const w = Gr(e);
967
+ return /* @__PURE__ */ v(
968
+ "button",
969
+ {
970
+ type: "button",
971
+ className: Ke("rc-inspect-box", !e.enabled && "rc-inspect-box-disabled"),
972
+ "data-ax-id": e.id,
973
+ "data-ax-path": e.path,
974
+ "data-ax-label": e.label || void 0,
975
+ "data-ax-role": e.role || void 0,
976
+ "data-highlighted": c ? "true" : "false",
977
+ "data-selected": l ? "true" : "false",
978
+ "aria-label": w,
979
+ onClick: (O) => {
980
+ u && (O.preventDefault(), O.stopPropagation(), E(e, { x: O.clientX, y: O.clientY }));
981
+ },
982
+ style: {
983
+ left: `${y.x / i.width * 100}%`,
984
+ top: `${y.y / i.height * 100}%`,
985
+ width: `${y.width / i.width * 100}%`,
986
+ height: `${y.height / i.height * 100}%`
987
+ }
988
+ }
989
+ );
990
+ },
991
+ (r, e) => r.highlighted === e.highlighted && r.selected === e.selected && r.selectable === e.selectable && r.screen.width === e.screen.width && r.screen.height === e.screen.height && r.onClick === e.onClick && Br(r.element, e.element)
992
+ ), _o = 260, Do = 220, To = 6, wo = 8, bo = or(function({
993
+ element: e,
994
+ platform: i,
995
+ anchor: c,
996
+ cursorAnchored: l,
997
+ showActions: u,
998
+ onTap: E
999
+ }) {
1000
+ const [y, w] = q(null);
1001
+ le(() => {
1002
+ if (!y) return;
1003
+ const U = window.setTimeout(() => w(null), 1100);
1004
+ return () => window.clearTimeout(U);
1005
+ }, [y]);
1006
+ const O = Ye(() => {
1007
+ const U = _o, Q = Do, te = To, S = wo, F = typeof window < "u" ? window.innerWidth : 1024, re = typeof window < "u" ? window.innerHeight : 768, ke = c.x + te + U <= F - S, Ce = c.y - te - Q >= S;
1008
+ let $ = ke ? c.x + te : c.x - te, Pe = Ce ? c.y - te : c.y + te;
1009
+ const se = `translate(${ke ? "0" : "-100%"}, ${Ce ? "-100%" : "0"})`;
1010
+ return $ = Math.max(S + (ke ? 0 : U), Math.min(F - S - (ke ? U : 0), $)), Pe = Math.max(S + (Ce ? Q : 0), Math.min(re - S - (Ce ? 0 : Q), Pe)), { left: `${$}px`, top: `${Pe}px`, transform: se };
1011
+ }, [c.x, c.y]), R = Ye(() => io(e, i), [e, i]), N = i === "ios" ? e.selectors.AXUniqueId : e.selectors.resourceId, j = i === "ios" ? "AXUniqueId" : "resourceId", ee = kn(async (U, Q) => {
1012
+ if (!U) return;
1013
+ await vo(U) && w(Q);
1014
+ }, []), fe = Vr(e), Oe = e.label || e.value || fe, ge = Gr(e);
1015
+ return Fn(
1016
+ /* @__PURE__ */ V(
1017
+ "div",
1018
+ {
1019
+ className: "rc-inspect-card",
1020
+ "data-cursor-anchored": l ? "true" : "false",
1021
+ style: O,
1022
+ onClick: (U) => U.stopPropagation(),
1023
+ onMouseDown: (U) => U.stopPropagation(),
1024
+ onMouseMove: (U) => U.stopPropagation(),
1025
+ children: [
1026
+ /* @__PURE__ */ V("div", { className: "rc-inspect-card-header", children: [
1027
+ /* @__PURE__ */ v("span", { className: "rc-inspect-card-role", children: fe }),
1028
+ !e.enabled && /* @__PURE__ */ v("span", { className: "rc-inspect-card-tag", children: "disabled" }),
1029
+ e.focused && /* @__PURE__ */ v("span", { className: "rc-inspect-card-tag rc-inspect-card-tag-blue", children: "focused" })
1030
+ ] }),
1031
+ /* @__PURE__ */ v("p", { className: "rc-inspect-card-title", title: ge, children: Oe }),
1032
+ N && /* @__PURE__ */ V("div", { className: "rc-inspect-card-row", children: [
1033
+ /* @__PURE__ */ V("span", { className: "rc-inspect-card-row-label", children: [
1034
+ j,
1035
+ ":"
1036
+ ] }),
1037
+ /* @__PURE__ */ v("span", { className: "rc-inspect-card-row-value", children: N })
1038
+ ] }),
1039
+ e.value && e.value !== e.label && /* @__PURE__ */ V("div", { className: "rc-inspect-card-row", children: [
1040
+ /* @__PURE__ */ v("span", { className: "rc-inspect-card-row-label", children: "value:" }),
1041
+ /* @__PURE__ */ v("span", { className: "rc-inspect-card-row-value", children: e.value })
1042
+ ] }),
1043
+ /* @__PURE__ */ V("div", { className: "rc-inspect-card-row", children: [
1044
+ /* @__PURE__ */ v("span", { className: "rc-inspect-card-row-label", children: "frame:" }),
1045
+ /* @__PURE__ */ V("span", { className: "rc-inspect-card-row-value", children: [
1046
+ Math.round(e.frame.width),
1047
+ "×",
1048
+ Math.round(e.frame.height),
1049
+ " @ ",
1050
+ Math.round(e.frame.x),
1051
+ ",",
1052
+ Math.round(e.frame.y)
1053
+ ] })
1054
+ ] }),
1055
+ u && /* @__PURE__ */ V("div", { className: "rc-inspect-card-actions", children: [
1056
+ /* @__PURE__ */ v(
1057
+ "button",
1058
+ {
1059
+ type: "button",
1060
+ className: "rc-inspect-card-btn rc-inspect-card-btn-primary",
1061
+ onClick: () => E(e, c),
1062
+ children: "Tap"
1063
+ }
1064
+ ),
1065
+ /* @__PURE__ */ v(
1066
+ "button",
1067
+ {
1068
+ type: "button",
1069
+ className: Ke("rc-inspect-card-btn", y === "selector" && "rc-inspect-card-btn-copied"),
1070
+ disabled: !R,
1071
+ title: R ?? "No usable selector for this element",
1072
+ onClick: () => ee(R ?? void 0, "selector"),
1073
+ children: y === "selector" ? "Copied!" : "Copy selector"
1074
+ }
1075
+ ),
1076
+ /* @__PURE__ */ v(
1077
+ "button",
1078
+ {
1079
+ type: "button",
1080
+ className: Ke("rc-inspect-card-btn", y === "id" && "rc-inspect-card-btn-copied"),
1081
+ disabled: !N,
1082
+ title: N ?? `No ${j}`,
1083
+ onClick: () => ee(N, "id"),
1084
+ children: y === "id" ? "Copied!" : `Copy ${j}`
1085
+ }
1086
+ )
1087
+ ] })
1088
+ ]
1089
+ }
1090
+ ),
1091
+ document.body
1092
+ );
1093
+ }), Ao = or(function({
1094
+ snapshot: e,
1095
+ geometry: i,
1096
+ highlightedId: c,
1097
+ selectedId: l,
1098
+ mode: u,
1099
+ cursorPosition: E,
1100
+ frozenCursorPosition: y,
1101
+ onSelectChange: w,
1102
+ onTapElement: O
1103
+ }) {
1104
+ const R = u === "select", N = R ? c !== null && c !== l : c !== null, j = R ? c ?? l : c, ee = Ye(() => {
1105
+ const S = /* @__PURE__ */ new Map();
1106
+ if (!e) return S;
1107
+ for (const F of e.elements) S.set(F.id, F);
1108
+ return S;
1109
+ }, [e]), fe = Ye(() => j ? ee.get(j) ?? null : null, [j, ee]);
1110
+ if (!(!!e && !!i && e.screen.width > 0 && e.screen.height > 0 && e.elements.length > 0)) return null;
1111
+ const ge = N ? E : y ?? E, U = N, Q = R && !N && l !== null, te = (S) => {
1112
+ R && S.target === S.currentTarget && w(null, null);
1113
+ };
1114
+ return /* @__PURE__ */ V(nr, { children: [
1115
+ /* @__PURE__ */ v(
1116
+ "div",
1117
+ {
1118
+ className: Ke("rc-inspect-overlay", R && "rc-inspect-overlay-select"),
1119
+ style: {
1120
+ left: `${i.left}px`,
1121
+ top: `${i.top}px`,
1122
+ width: `${i.width}px`,
1123
+ height: `${i.height}px`
1124
+ },
1125
+ onClick: te,
1126
+ children: e.elements.map((S) => /* @__PURE__ */ v(
1127
+ Oo,
1128
+ {
1129
+ element: S,
1130
+ screen: e.screen,
1131
+ highlighted: S.id === c,
1132
+ selected: S.id === l,
1133
+ selectable: R,
1134
+ onClick: w
1135
+ },
1136
+ S.id
1137
+ ))
1138
+ }
1139
+ ),
1140
+ fe && ge && /* @__PURE__ */ v(
1141
+ bo,
1142
+ {
1143
+ element: fe,
1144
+ platform: e.platform,
1145
+ anchor: ge,
1146
+ cursorAnchored: U,
1147
+ showActions: Q,
1148
+ onTap: O
1149
+ }
1150
+ )
1151
+ ] });
1152
+ }), Jr = () => import("./duo-view-D9Ae00rj.mjs").then((r) => r.d), Mo = Pn(Jr), H = (...r) => {
1153
+ window.debugRemoteControl && console.log(...r);
1154
+ }, A = (...r) => {
1155
+ window.debugRemoteControl && console.warn(...r);
1156
+ }, W = (r, e, ...i) => {
1157
+ if (e)
1158
+ try {
1159
+ e(...i);
1160
+ } catch (c) {
1161
+ console.error(`[RemoteControl] customer callback "${r}" threw:`, c);
1162
+ }
1163
+ }, kt = (r) => Object.entries(x).find(
1164
+ ([i, c]) => i.startsWith("ACTION_") && c === r
1165
+ )?.[0] ?? String(r), So = (r) => r.includes("/android_") ? "android" : "ios", xr = (r, e) => {
1166
+ const i = new URL(r);
1167
+ return i.searchParams.set("token", e), i.toString();
1168
+ }, Fr = 1920, Wr = 1200, rr = 3, Ro = 1e3, No = 15e3, Io = 3e3, Yo = 4e3, Ko = (r, e) => r === Fr && e === Wr || r === Wr && e === Fr, ko = {
1169
+ ios: {
1170
+ videoBorderRadiusMultiplier: 0.15,
1171
+ loadingLogoSize: "20%",
1172
+ // Video position as percentage of frame dimensions
1173
+ videoPosition: {
1174
+ portrait: { heightMultiplier: 0.9678 },
1175
+ landscape: { widthMultiplier: 0.9678 }
1176
+ }
1177
+ },
1178
+ android: {
1179
+ videoBorderRadiusMultiplier: 0.13,
1180
+ loadingLogoSize: "40%",
1181
+ // Video position as percentage of frame dimensions
1182
+ videoPosition: {
1183
+ portrait: { heightMultiplier: 0.967 },
1184
+ landscape: { widthMultiplier: 0.962 }
1185
+ }
1186
+ }
1187
+ };
1188
+ function Po(r) {
1189
+ const e = r.code, i = $r[e];
1190
+ if (!i)
1191
+ return A(`Unknown event.code: ${e}, key: ${r.key}`), null;
1192
+ let c = a.META_NONE;
1193
+ const l = e >= "KeyA" && e <= "KeyZ", u = r.getModifierState("CapsLock"), E = r.shiftKey;
1194
+ let y = E;
1195
+ return l && (y = E !== u), y && (c |= a.META_SHIFT_ON), r.ctrlKey && (c |= a.META_CTRL_ON), r.altKey && (c |= a.META_ALT_ON), r.metaKey && (c |= a.META_META_ON), { keycode: i, metaState: c };
1196
+ }
1197
+ const Jo = Un(
1198
+ ({
1199
+ className: r,
1200
+ url: e,
1201
+ token: i,
1202
+ sessionId: c,
1203
+ openUrl: l,
1204
+ showFrame: u = !0,
1205
+ deviceModel: E,
1206
+ duoModelUrl: y,
1207
+ autoReconnect: w = !1,
1208
+ onTerminated: O,
1209
+ assets: R,
1210
+ onConnectionStateChange: N,
1211
+ inspectMode: j,
1212
+ onAxSnapshotChange: ee,
1213
+ onInspectSelectionChange: fe,
1214
+ onAxStatusChange: Oe,
1215
+ axPollIntervalMs: ge,
1216
+ axMaxBackoffMs: U,
1217
+ androidElementTreeOptions: Q,
1218
+ onCameraDemandChange: te,
1219
+ onCameraStats: S,
1220
+ microphoneEnabled: F = !1,
1221
+ onMicrophoneStateChange: re
1222
+ }, ke) => {
1223
+ const Ce = D(null), $ = D(null), Pe = D(null), [ir, sr] = q(!1), se = E === "iphone-duo" || ir;
1224
+ le(() => {
1225
+ se && Jr().catch(() => {
1226
+ });
1227
+ }, [se]);
1228
+ const tt = D(null), [Lt, cr] = q(null), [ar, ur] = q(), Ue = D(
1229
+ /* @__PURE__ */ new Map()
1230
+ ), xt = (t, s) => new Promise((o, n) => {
1231
+ const f = b.current;
1232
+ if (!f || f.readyState !== WebSocket.OPEN) {
1233
+ n(new Error("Simulator disconnected"));
1234
+ return;
1235
+ }
1236
+ const d = crypto.randomUUID(), p = setTimeout(() => {
1237
+ Ue.current.delete(d), n(new Error("Device control timed out"));
1238
+ }, 5e3);
1239
+ Ue.current.set(d, { resolve: o, reject: n, timer: p }), f.send(JSON.stringify({ type: t, id: d, ...s }));
1240
+ }), [zr, Ft] = q(!1), [jr, gt] = q(!1), [Qr, dr] = q(!1), Le = D(!1), Wt = D(!1), [lr, Zr] = q(!1), [en, tn] = q(!1), [rn, fr] = q({}), b = D(null), X = D(null), L = D(null), xe = D(void 0), rt = D(void 0), nt = D(void 0), Ct = D(void 0), Fe = D(void 0), Te = D(0), yt = D(0), We = D(!1), Ht = D(w);
1241
+ Ht.current = w;
1242
+ const we = D(null), ce = D(null), be = D(void 0), $t = Ye(() => new po(), []), ye = D(te);
1243
+ ye.current = te;
1244
+ const vt = D(S);
1245
+ vt.current = S;
1246
+ const ot = D(null), Ot = D(null), Xt = D(F);
1247
+ Xt.current = F;
1248
+ const Bt = D(!1), it = D(re);
1249
+ it.current = re;
1250
+ const st = D(null), me = D(null), _t = D(0), hr = D(Promise.resolve()), He = D(null), ct = D(!1), _e = D(/* @__PURE__ */ new Map()), ve = D(/* @__PURE__ */ new Map()), Ae = D(/* @__PURE__ */ new Map()), Me = D(/* @__PURE__ */ new Map()), Z = D(/* @__PURE__ */ new Map()), Se = D(!1), [nn, on] = q(!1), G = D(null), $e = D(null), at = D({
1251
+ handle: () => {
1252
+ },
1253
+ end: () => {
1254
+ }
1255
+ }), [Re, Dt] = q(null), ne = D(null), [pr, mr] = q(null), [qt, ut] = q(null), [Vt, Tt] = q(null), [sn, Er] = q(null), [cn, gr] = q(null), wt = D(null), de = D(void 0), Cr = (t) => {
1256
+ wt.current = t, de.current === void 0 && (de.current = window.requestAnimationFrame(() => {
1257
+ de.current = void 0, gr(wt.current);
1258
+ }));
1259
+ }, [an, Xe] = q(null), Be = D(j);
1260
+ Be.current = j;
1261
+ const qe = D(null);
1262
+ qe.current = pr;
1263
+ const Gt = D(ee);
1264
+ Gt.current = ee;
1265
+ const Ve = D(fe);
1266
+ Ve.current = fe;
1267
+ const yr = D(Oe);
1268
+ yr.current = Oe;
1269
+ const vr = D(O);
1270
+ vr.current = O;
1271
+ const Or = D(N);
1272
+ Or.current = N;
1273
+ const Jt = D(null), Ge = (t) => {
1274
+ Jt.current !== t && (Jt.current = t, W("onConnectionStateChange", Or.current, t));
1275
+ }, dt = j === !0 || j === "hover-only", un = j === "hover-only" ? "hover-only" : "select", he = Ye(
1276
+ () => c || Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15),
1277
+ [c]
1278
+ ), Ee = Ye(() => So(e), [e]), Je = ko[Ee], lt = R?.[Ee], _r = Ee === "android" && en ? lr ? lt?.tabletFrameLandscape : lt?.tabletFrame : lr ? lt?.frameLandscape : lt?.frame, ft = lt?.loadingLogo, bt = !se && u && !!_r, k = (t) => {
1279
+ H(t);
1280
+ }, pe = (t) => {
1281
+ !L.current || L.current.readyState !== "open" || (L.current.send(t), ne.current?.bumpActivity());
1282
+ }, Dr = -10, Tr = (t, s) => {
1283
+ const o = ht();
1284
+ if (!o) return;
1285
+ const n = je(o, t, s);
1286
+ if (!n) return;
1287
+ const { videoX: f, videoY: d, videoWidth: p, videoHeight: g } = n, C = Kt(
1288
+ x.ACTION_DOWN,
1289
+ Dr,
1290
+ p,
1291
+ g,
1292
+ f,
1293
+ d,
1294
+ 1,
1295
+ x.BUTTON_PRIMARY,
1296
+ x.BUTTON_PRIMARY
1297
+ );
1298
+ C && pe(C), window.setTimeout(() => {
1299
+ const m = Kt(
1300
+ x.ACTION_UP,
1301
+ Dr,
1302
+ p,
1303
+ g,
1304
+ f,
1305
+ d,
1306
+ 0,
1307
+ x.BUTTON_PRIMARY,
1308
+ x.BUTTON_PRIMARY
1309
+ );
1310
+ m && pe(m);
1311
+ }, 60);
1312
+ }, dn = (t, s) => {
1313
+ const o = ht();
1314
+ if (!o || s.screen.width <= 0 || s.screen.height <= 0) return;
1315
+ const n = t.frame.x + t.frame.width / 2, f = t.frame.y + t.frame.height / 2, d = n / s.screen.width * o.actualWidth, p = f / s.screen.height * o.actualHeight, g = o.videoRect.left + o.offsetX + d, C = o.videoRect.top + o.offsetY + p;
1316
+ Tr(g, C);
1317
+ }, At = -1, Mt = -2, Ne = -3, ze = (t, s, o, n, f, d) => {
1318
+ const p = Kt(
1319
+ t,
1320
+ s,
1321
+ o,
1322
+ n,
1323
+ f,
1324
+ d,
1325
+ 1,
1326
+ // pressure
1327
+ x.BUTTON_PRIMARY,
1328
+ x.BUTTON_PRIMARY
1329
+ );
1330
+ p && (H("[rc-touch] sendSingleTouch", {
1331
+ action: t,
1332
+ actionName: kt(t),
1333
+ pointerId: s,
1334
+ x: f,
1335
+ y: d,
1336
+ video: { width: o, height: n }
1337
+ }), pe(p));
1338
+ }, Ie = (t, s, o) => {
1339
+ if (!o) return;
1340
+ const { videoX: n, videoY: f, videoWidth: d, videoHeight: p } = o;
1341
+ let g = null, C = null, m = 1;
1342
+ const I = x.BUTTON_PRIMARY;
1343
+ switch (s) {
1344
+ case "down":
1345
+ t !== Ne && at.current.end(), g = Z.current.size === 0 ? x.ACTION_DOWN : x.ACTION_POINTER_DOWN, C = { x: n, y: f }, Z.current.set(t, C), t === -1 && $.current?.focus();
1346
+ break;
1347
+ case "move":
1348
+ Z.current.has(t) && (g = x.ACTION_MOVE, C = { x: n, y: f }, Z.current.set(t, C));
1349
+ break;
1350
+ case "up":
1351
+ case "cancel":
1352
+ Z.current.has(t) && (C = Z.current.get(t), Z.current.delete(t), s === "cancel" ? g = x.ACTION_CANCEL : g = Z.current.size === 0 ? x.ACTION_UP : x.ACTION_POINTER_UP);
1353
+ break;
1354
+ }
1355
+ if (g !== null && C !== null) {
1356
+ H("[rc-touch][mouse->touch] sending", {
1357
+ pointerId: t,
1358
+ eventType: s,
1359
+ action: g,
1360
+ actionName: kt(g),
1361
+ positionToSend: C,
1362
+ video: { width: d, height: p },
1363
+ altHeld: Se.current,
1364
+ activePointersAfter: Array.from(Z.current.entries()).map(([Y, B]) => ({
1365
+ id: Y,
1366
+ x: B.x,
1367
+ y: B.y
1368
+ }))
1369
+ });
1370
+ const T = Kt(
1371
+ g,
1372
+ t,
1373
+ d,
1374
+ p,
1375
+ C.x,
1376
+ C.y,
1377
+ m,
1378
+ I,
1379
+ I
1380
+ );
1381
+ T && (H("[rc-touch][mouse->touch] buffer", {
1382
+ pointerId: t,
1383
+ actionName: kt(g),
1384
+ byteLength: T.byteLength
1385
+ }), pe(T));
1386
+ } else (s === "up" || s === "cancel") && Z.current.delete(t);
1387
+ }, zt = (t) => {
1388
+ if (Se.current !== t && (Se.current = t, on(t), t || Dt(null), H("[rc-touch][alt] updateAltHeld", {
1389
+ nextHeld: t,
1390
+ activePointerIds: Array.from(Z.current.keys())
1391
+ }), Ee === "ios" && L.current && L.current.readyState === "open")) {
1392
+ const s = t ? a.ACTION_DOWN : a.ACTION_UP, o = Et(
1393
+ s,
1394
+ a.KEYCODE_ALT_LEFT,
1395
+ 0,
1396
+ a.META_NONE
1397
+ );
1398
+ H("[rc-touch][alt] sending Indigo modifier keycode", {
1399
+ action: s,
1400
+ keycode: a.KEYCODE_ALT_LEFT
1401
+ }), o && pe(o);
1402
+ }
1403
+ }, ht = () => {
1404
+ const t = $.current, s = Ce.current;
1405
+ if (!t || !s) return null;
1406
+ const o = t.videoWidth, n = t.videoHeight;
1407
+ if (!o || !n) return null;
1408
+ const f = t.getBoundingClientRect(), d = s.getBoundingClientRect(), p = f.width, g = f.height, C = o / n, m = p / g;
1409
+ let I = p, T = g;
1410
+ C > m ? T = p / C : I = g * C;
1411
+ const Y = (p - I) / 2, B = (g - T) / 2;
1412
+ return {
1413
+ videoWidth: o,
1414
+ videoHeight: n,
1415
+ videoRect: f,
1416
+ containerRect: d,
1417
+ actualWidth: I,
1418
+ actualHeight: T,
1419
+ offsetX: Y,
1420
+ offsetY: B
1421
+ };
1422
+ }, je = (t, s, o) => {
1423
+ const n = s - t.videoRect.left - t.offsetX, f = o - t.videoRect.top - t.offsetY, d = Math.max(0, Math.min(t.actualWidth, n)), p = Math.max(0, Math.min(t.actualHeight, f)), g = Math.max(
1424
+ 0,
1425
+ Math.min(t.videoWidth, d / t.actualWidth * t.videoWidth)
1426
+ ), C = Math.max(
1427
+ 0,
1428
+ Math.min(t.videoHeight, p / t.actualHeight * t.videoHeight)
1429
+ );
1430
+ return {
1431
+ videoX: g,
1432
+ videoY: C,
1433
+ videoWidth: t.videoWidth,
1434
+ videoHeight: t.videoHeight
1435
+ };
1436
+ }, ln = (t, s, o) => {
1437
+ const n = s - t.videoRect.left - t.offsetX, f = o - t.videoRect.top - t.offsetY, d = Math.max(0, Math.min(t.actualWidth, n)), p = Math.max(0, Math.min(t.actualHeight, f)), g = Math.max(
1438
+ 0,
1439
+ Math.min(t.videoWidth, d / t.actualWidth * t.videoWidth)
1440
+ ), C = Math.max(
1441
+ 0,
1442
+ Math.min(t.videoHeight, p / t.actualHeight * t.videoHeight)
1443
+ ), m = t.videoWidth - g, I = t.videoHeight - C, T = t.videoRect.left + t.offsetX, Y = t.videoRect.top + t.offsetY, B = T - t.containerRect.left + d, ae = Y - t.containerRect.top + p, z = T - t.containerRect.left + (t.actualWidth - d), _ = Y - t.containerRect.top + (t.actualHeight - p);
1444
+ return {
1445
+ containerX: B,
1446
+ containerY: ae,
1447
+ mirrorContainerX: z,
1448
+ mirrorContainerY: _,
1449
+ videoX: g,
1450
+ videoY: C,
1451
+ mirrorVideoX: m,
1452
+ mirrorVideoY: I,
1453
+ videoWidth: t.videoWidth,
1454
+ videoHeight: t.videoHeight
1455
+ };
1456
+ }, fn = (t, s, o, n, f, d, p) => {
1457
+ const g = Vn(t, s, o, n, f, d, p);
1458
+ H("[rc-touch2] sendTwoFingerMessage (iOS)", {
1459
+ actionName: kt(t),
1460
+ video: { width: s, height: o },
1461
+ p0: { x: n, y: f },
1462
+ p1: { x: d, y: p },
1463
+ byteLength: g.byteLength
1464
+ }), pe(g);
1465
+ }, Qe = (t, s, o, n, f, d, p, g, C) => {
1466
+ if (H("[rc-touch2] applyTwoFingerEvent", {
1467
+ platform: Ee,
1468
+ eventType: t,
1469
+ video: { width: s, height: o },
1470
+ p0: { x: n, y: f, id: g },
1471
+ p1: { x: d, y: p, id: C }
1472
+ }), t === "down" && at.current.end(), Ee === "ios") {
1473
+ const m = t === "down" ? x.ACTION_DOWN : t === "move" ? x.ACTION_MOVE : x.ACTION_UP;
1474
+ fn(m, s, o, n, f, d, p);
1475
+ } else
1476
+ t === "down" ? (ze(x.ACTION_DOWN, g, s, o, n, f), ze(x.ACTION_POINTER_DOWN, C, s, o, d, p)) : t === "move" ? (ze(x.ACTION_MOVE, g, s, o, n, f), ze(x.ACTION_MOVE, C, s, o, d, p)) : (ze(x.ACTION_POINTER_UP, C, s, o, d, p), ze(x.ACTION_UP, g, s, o, n, f));
1477
+ }, hn = (t, s, o) => {
1478
+ if (!Se.current) {
1479
+ Re !== null && Dt(null);
1480
+ return;
1481
+ }
1482
+ const n = ln(t, s, o);
1483
+ Dt(n);
1484
+ }, pn = (t, s, o) => {
1485
+ const n = qe.current;
1486
+ if (!n || n.screen.width <= 0 || n.screen.height <= 0) return null;
1487
+ const f = s - t.videoRect.left - t.offsetX, d = o - t.videoRect.top - t.offsetY;
1488
+ if (f < 0 || d < 0 || f > t.actualWidth || d > t.actualHeight) return null;
1489
+ const p = f / t.actualWidth * n.screen.width, g = d / t.actualHeight * n.screen.height;
1490
+ return oo(n, p, g);
1491
+ }, De = (t) => {
1492
+ if (se) return;
1493
+ t.preventDefault(), t.stopPropagation();
1494
+ const s = ht();
1495
+ if ((Be.current === !0 || Be.current === "hover-only") && !("touches" in t))
1496
+ if (t.type === "mousemove") {
1497
+ if (Cr({ x: t.clientX, y: t.clientY }), s) {
1498
+ const n = pn(s, t.clientX, t.clientY);
1499
+ ut(n?.id ?? null);
1500
+ }
1501
+ } else t.type === "mouseleave" && (Cr(null), ut(null));
1502
+ if (Be.current !== !0 && (!("touches" in t) && s && (t.type === "mousemove" ? hn(s, t.clientX, t.clientY) : t.type === "mouseleave" && Dt(null)), !(!L.current || L.current.readyState !== "open" || !$.current || !s)))
1503
+ if ("touches" in t) {
1504
+ const n = t.touches, f = t.changedTouches;
1505
+ let d;
1506
+ switch (t.type) {
1507
+ case "touchstart":
1508
+ d = "down";
1509
+ break;
1510
+ case "touchmove":
1511
+ d = "move";
1512
+ break;
1513
+ case "touchend":
1514
+ d = "up";
1515
+ break;
1516
+ case "touchcancel":
1517
+ d = "cancel";
1518
+ break;
1519
+ default:
1520
+ return;
1521
+ }
1522
+ if (n.length === 2) {
1523
+ const p = n[0], g = n[1], C = je(s, p.clientX, p.clientY), m = je(s, g.clientX, g.clientY);
1524
+ if (!C || !m) return;
1525
+ G.current ? G.current.source === "real-touch" && (G.current.finger0 = { x: C.videoX, y: C.videoY }, G.current.finger1 = { x: m.videoX, y: m.videoY }, Qe(
1526
+ "move",
1527
+ C.videoWidth,
1528
+ C.videoHeight,
1529
+ C.videoX,
1530
+ C.videoY,
1531
+ m.videoX,
1532
+ m.videoY,
1533
+ G.current.pointerId0,
1534
+ G.current.pointerId1
1535
+ )) : (G.current = {
1536
+ finger0: { x: C.videoX, y: C.videoY },
1537
+ finger1: { x: m.videoX, y: m.videoY },
1538
+ videoSize: { width: C.videoWidth, height: C.videoHeight },
1539
+ source: "real-touch",
1540
+ pointerId0: p.identifier,
1541
+ pointerId1: g.identifier
1542
+ }, Qe(
1543
+ "down",
1544
+ C.videoWidth,
1545
+ C.videoHeight,
1546
+ C.videoX,
1547
+ C.videoY,
1548
+ m.videoX,
1549
+ m.videoY,
1550
+ p.identifier,
1551
+ g.identifier
1552
+ ));
1553
+ } else if (n.length < 2 && G.current?.source === "real-touch") {
1554
+ const p = G.current;
1555
+ Qe(
1556
+ "up",
1557
+ p.videoSize.width,
1558
+ p.videoSize.height,
1559
+ p.finger0.x,
1560
+ p.finger0.y,
1561
+ p.finger1.x,
1562
+ p.finger1.y,
1563
+ p.pointerId0,
1564
+ p.pointerId1
1565
+ ), G.current = null;
1566
+ return;
1567
+ } else {
1568
+ if (n.length > 2)
1569
+ return;
1570
+ {
1571
+ const p = f[0];
1572
+ if (p) {
1573
+ const g = je(s, p.clientX, p.clientY);
1574
+ Ie(p.identifier, d, g);
1575
+ }
1576
+ }
1577
+ }
1578
+ } else {
1579
+ let f = null;
1580
+ const d = G.current?.source === "alt-mouse";
1581
+ switch (t.type) {
1582
+ case "mousedown":
1583
+ t.button === 0 && (f = "down");
1584
+ break;
1585
+ case "mousemove":
1586
+ (d || Z.current.has(-1)) && (f = "move");
1587
+ break;
1588
+ case "mouseup":
1589
+ t.button === 0 && (f = "up");
1590
+ break;
1591
+ case "mouseleave":
1592
+ (d || Z.current.has(-1)) && (f = "up");
1593
+ break;
1594
+ }
1595
+ if (f) {
1596
+ const p = je(s, t.clientX, t.clientY);
1597
+ if (!p)
1598
+ return;
1599
+ H("[rc-touch][mouse] event", {
1600
+ domType: t.type,
1601
+ eventType: f,
1602
+ button: t.button,
1603
+ buttons: t.buttons,
1604
+ client: { x: t.clientX, y: t.clientY },
1605
+ altHeldRef: Se.current,
1606
+ inTwoFingerMode: d,
1607
+ geometry: {
1608
+ videoX: p.videoX,
1609
+ videoY: p.videoY,
1610
+ videoWidth: p.videoWidth,
1611
+ videoHeight: p.videoHeight
1612
+ },
1613
+ activePointerIds: Array.from(Z.current.keys())
1614
+ }), Se.current || d ? mn(f, p) : Ie(-1, f, p);
1615
+ }
1616
+ }
1617
+ }, mn = (t, s) => {
1618
+ const { videoX: o, videoY: n, videoWidth: f, videoHeight: d } = s, p = f - o, g = d - n;
1619
+ if (t === "down") {
1620
+ G.current = {
1621
+ finger0: { x: o, y: n },
1622
+ finger1: { x: p, y: g },
1623
+ videoSize: { width: f, height: d },
1624
+ source: "alt-mouse",
1625
+ pointerId0: At,
1626
+ pointerId1: Mt
1627
+ }, $.current?.focus(), Qe(
1628
+ "down",
1629
+ f,
1630
+ d,
1631
+ o,
1632
+ n,
1633
+ p,
1634
+ g,
1635
+ At,
1636
+ Mt
1637
+ );
1638
+ return;
1639
+ }
1640
+ if (t === "move") {
1641
+ G.current?.source === "alt-mouse" && (G.current.finger0 = { x: o, y: n }, G.current.finger1 = { x: p, y: g }, Qe(
1642
+ "move",
1643
+ f,
1644
+ d,
1645
+ o,
1646
+ n,
1647
+ p,
1648
+ g,
1649
+ At,
1650
+ Mt
1651
+ ));
1652
+ return;
1653
+ }
1654
+ if (t === "up" || t === "cancel") {
1655
+ const C = G.current;
1656
+ if (C?.source === "alt-mouse") {
1657
+ const { finger0: m, finger1: I, videoSize: T } = C;
1658
+ Qe(
1659
+ "up",
1660
+ T.width,
1661
+ T.height,
1662
+ m.x,
1663
+ m.y,
1664
+ I.x,
1665
+ I.y,
1666
+ At,
1667
+ Mt
1668
+ ), G.current = null;
1669
+ }
1670
+ return;
1671
+ }
1672
+ }, En = 150, wr = () => {
1673
+ const t = $e.current;
1674
+ t && (window.clearTimeout(t.endTimer), Ie(Ne, "up", t.pos), $e.current = null);
1675
+ }, gn = (t) => {
1676
+ if (t.ctrlKey || Se.current || G.current) return;
1677
+ const s = Z.current.size;
1678
+ if (s > 1 || s === 1 && !Z.current.has(Ne)) return;
1679
+ const o = ht();
1680
+ if (!o) return;
1681
+ const n = t.clientX - o.videoRect.left - o.offsetX, f = t.clientY - o.videoRect.top - o.offsetY;
1682
+ if (n < 0 || n > o.actualWidth || f < 0 || f > o.actualHeight)
1683
+ return;
1684
+ const d = je(o, t.clientX, t.clientY);
1685
+ if (!d) return;
1686
+ t.preventDefault();
1687
+ const p = (t.deltaMode === 1 ? 16 : t.deltaMode === 2 ? o.actualWidth : 1) * (o.videoWidth / o.actualWidth), g = (t.deltaMode === 1 ? 16 : t.deltaMode === 2 ? o.actualHeight : 1) * (o.videoHeight / o.actualHeight), C = -t.deltaX * p, m = -t.deltaY * g, I = (_) => {
1688
+ window.clearTimeout(_.endTimer), _.endTimer = window.setTimeout(wr, En);
1689
+ };
1690
+ if (C === 0 && m === 0) {
1691
+ $e.current && I($e.current);
1692
+ return;
1693
+ }
1694
+ const T = () => ({
1695
+ videoWidth: d.videoWidth,
1696
+ videoHeight: d.videoHeight,
1697
+ videoX: Math.abs(C) > Math.abs(m) ? Math.min(Math.max(d.videoX, d.videoWidth * 0.2), d.videoWidth * 0.8) : d.videoX,
1698
+ videoY: Math.abs(m) >= Math.abs(C) ? Math.min(Math.max(d.videoY, d.videoHeight * 0.2), d.videoHeight * 0.8) : d.videoY
1699
+ }), Y = (_) => ({
1700
+ ..._,
1701
+ videoX: Math.min(Math.max(_.videoX + C, 0), _.videoWidth),
1702
+ videoY: Math.min(Math.max(_.videoY + m, 0), _.videoHeight)
1703
+ });
1704
+ let B = $e.current;
1705
+ if (B)
1706
+ window.clearTimeout(B.endTimer);
1707
+ else {
1708
+ const _ = T();
1709
+ Ie(Ne, "down", _), B = { pos: _, endTimer: 0 }, $e.current = B;
1710
+ }
1711
+ let ae = B.pos, z = Y(ae);
1712
+ z.videoX === ae.videoX && z.videoY === ae.videoY && (Ie(Ne, "up", ae), ae = T(), Ie(Ne, "down", ae), z = Y(ae)), Ie(Ne, "move", z), B.pos = z, I(B);
1713
+ };
1714
+ le(() => {
1715
+ at.current = { handle: gn, end: wr };
1716
+ }), le(() => {
1717
+ const t = Ce.current;
1718
+ if (!t) return;
1719
+ const s = (o) => at.current.handle(o);
1720
+ return t.addEventListener("wheel", s, { passive: !1 }), () => {
1721
+ at.current.end(), t.removeEventListener("wheel", s);
1722
+ };
1723
+ }, []), le(() => {
1724
+ const t = (n) => {
1725
+ n.key === "Alt" && zt(!0);
1726
+ }, s = (n) => {
1727
+ n.key === "Alt" && zt(!1);
1728
+ }, o = () => {
1729
+ zt(!1);
1730
+ };
1731
+ return window.addEventListener("keydown", t, !0), window.addEventListener("keyup", s, !0), window.addEventListener("blur", o), () => {
1732
+ window.removeEventListener("keydown", t, !0), window.removeEventListener("keyup", s, !0), window.removeEventListener("blur", o);
1733
+ };
1734
+ }, []);
1735
+ const St = (t) => {
1736
+ t.preventDefault(), t.stopPropagation();
1737
+ const s = document.activeElement === $.current || se && document.activeElement === t.currentTarget;
1738
+ if (H("Keyboard event:", {
1739
+ type: t.type,
1740
+ key: t.key,
1741
+ keyCode: t.keyCode,
1742
+ code: t.code,
1743
+ target: t.target.tagName,
1744
+ focused: s
1745
+ }), !s) {
1746
+ A("Simulator input not focused, skipping keyboard event");
1747
+ return;
1748
+ }
1749
+ if (!L.current || L.current.readyState !== "open") {
1750
+ A("Data channel not ready for keyboard event:", L.current?.readyState);
1751
+ return;
1752
+ }
1753
+ if (t.type === "keydown") {
1754
+ if (t.key.toLowerCase() === "v" && (t.metaKey || t.ctrlKey)) {
1755
+ H("Paste shortcut detected"), navigator.clipboard.readText().then((n) => {
1756
+ if (n) {
1757
+ H(
1758
+ "Pasting text via SET_CLIPBOARD:",
1759
+ n.substring(0, 20) + (n.length > 20 ? "..." : "")
1760
+ );
1761
+ const f = Gn(n, !0);
1762
+ pe(f);
1763
+ }
1764
+ }).catch((n) => {
1765
+ console.error("Failed to read clipboard contents: ", n);
1766
+ });
1767
+ return;
1768
+ }
1769
+ if (t.key.toLowerCase() === "m" && (t.metaKey || t.ctrlKey)) {
1770
+ H("Menu shortcut detected");
1771
+ const n = Et(
1772
+ a.ACTION_DOWN,
1773
+ a.MENU,
1774
+ 0,
1775
+ a.META_NONE
1776
+ // Modifiers are handled by the shortcut check, not passed down
1777
+ );
1778
+ pe(n);
1779
+ const f = Et(
1780
+ a.ACTION_UP,
1781
+ a.MENU,
1782
+ 0,
1783
+ a.META_NONE
1784
+ );
1785
+ pe(f);
1786
+ return;
1787
+ }
1788
+ }
1789
+ const o = Po(t);
1790
+ if (o) {
1791
+ const { keycode: n, metaState: f } = o, d = t.type === "keydown" ? a.ACTION_DOWN : a.ACTION_UP;
1792
+ H(`Sending Keycode: key=${t.key}, code=${n}, action=${d}, meta=${f}`);
1793
+ const p = Et(
1794
+ d,
1795
+ n,
1796
+ 0,
1797
+ // repeat count, typically 0 for single presses
1798
+ f
1799
+ );
1800
+ pe(p);
1801
+ } else
1802
+ H(`Ignoring unhandled key event: type=${t.type}, key=${t.key}`);
1803
+ }, Cn = () => {
1804
+ b.current && b.current.readyState === WebSocket.OPEN && b.current.send(
1805
+ JSON.stringify({
1806
+ type: "keepAlive",
1807
+ sessionId: he
1808
+ })
1809
+ );
1810
+ }, br = () => {
1811
+ xe.current && window.clearInterval(xe.current), xe.current = window.setInterval(Cn, 1e4);
1812
+ }, Ar = () => {
1813
+ xe.current && (window.clearInterval(xe.current), xe.current = void 0);
1814
+ }, Rt = () => {
1815
+ rt.current && (window.clearTimeout(rt.current), rt.current = void 0);
1816
+ }, Nt = () => {
1817
+ nt.current && (window.clearTimeout(nt.current), nt.current = void 0);
1818
+ }, pt = () => {
1819
+ Ct.current && (window.clearInterval(Ct.current), Ct.current = void 0);
1820
+ }, mt = () => {
1821
+ Fe.current !== void 0 && (window.clearTimeout(Fe.current), Fe.current = void 0);
1822
+ }, yn = () => {
1823
+ ct.current || (ct.current = !0, pt(), Ft(!0), Ge("connected"));
1824
+ }, oe = (t) => {
1825
+ for (const s of t.getTracks())
1826
+ try {
1827
+ s.stop();
1828
+ } catch (o) {
1829
+ A("track.stop() failed:", o);
1830
+ }
1831
+ }, vn = () => {
1832
+ const t = ce.current;
1833
+ t && (ce.current = null, oe(t));
1834
+ }, Mr = (t) => {
1835
+ const s = hr.current.then(t).catch((o) => {
1836
+ A("microphone operation failed:", o);
1837
+ });
1838
+ return hr.current = s, s;
1839
+ }, jt = () => Xt.current || Bt.current, Sr = (t) => {
1840
+ const s = `ui-mic-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
1841
+ He.current = s, t.send(JSON.stringify({ type: "microphoneStart", id: s }));
1842
+ }, Qt = () => Mr(() => On()), On = async () => {
1843
+ const t = _t.current, s = () => t === _t.current && jt(), o = (g) => {
1844
+ W("onMicrophoneStateChange", it.current, {
1845
+ active: !1,
1846
+ error: g
1847
+ });
1848
+ };
1849
+ if (!s()) return;
1850
+ const n = b.current, f = st.current;
1851
+ if (!n || n.readyState !== WebSocket.OPEN || !f || me.current) return;
1852
+ if (!navigator.mediaDevices || typeof navigator.mediaDevices.getUserMedia != "function") {
1853
+ console.warn(
1854
+ "[RemoteControl] navigator.mediaDevices.getUserMedia unavailable. getUserMedia requires a secure context (https or http://localhost)."
1855
+ ), o("Microphone capture requires a secure context (https)");
1856
+ return;
1857
+ }
1858
+ let d = null;
1859
+ try {
1860
+ d = await navigator.mediaDevices.getUserMedia({ audio: !0, video: !1 });
1861
+ } catch (g) {
1862
+ console.warn("[RemoteControl] microphone getUserMedia denied/failed:", g);
1863
+ }
1864
+ if (!s()) {
1865
+ d && oe(d);
1866
+ return;
1867
+ }
1868
+ if (!d) {
1869
+ o("Microphone permission denied or no device available");
1870
+ return;
1871
+ }
1872
+ const p = d.getAudioTracks()[0] ?? null;
1873
+ if (!p) {
1874
+ oe(d), o("Captured stream has no audio track");
1875
+ return;
1876
+ }
1877
+ try {
1878
+ await f.replaceTrack(p);
1879
+ } catch (g) {
1880
+ A("replaceTrack(audioTrack) failed:", g), oe(d), o("Failed to attach the microphone track to the connection");
1881
+ return;
1882
+ }
1883
+ if (!s()) {
1884
+ try {
1885
+ await f.replaceTrack(null);
1886
+ } catch (g) {
1887
+ A("replaceTrack(null) on stale mic attach failed:", g);
1888
+ }
1889
+ oe(d);
1890
+ return;
1891
+ }
1892
+ me.current = d, p.onended = () => {
1893
+ me.current === d && It("microphone capture ended by the browser");
1894
+ }, Sr(n), W("onMicrophoneStateChange", it.current, {
1895
+ active: !0,
1896
+ label: p.label || void 0
1897
+ });
1898
+ }, It = (t) => (++_t.current, He.current = null, Mr(async () => {
1899
+ const s = st.current, o = me.current;
1900
+ if (me.current = null, s && o)
1901
+ try {
1902
+ await s.replaceTrack(null);
1903
+ } catch (f) {
1904
+ A("replaceTrack(null) on mic detach failed:", f);
1905
+ }
1906
+ o && oe(o);
1907
+ const n = b.current;
1908
+ if (o && n && n.readyState === WebSocket.OPEN) {
1909
+ const f = `ui-mic-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
1910
+ n.send(JSON.stringify({ type: "microphoneStop", id: f }));
1911
+ }
1912
+ (o || t) && W("onMicrophoneStateChange", it.current, {
1913
+ active: !1,
1914
+ ...t !== void 0 && { error: t }
1915
+ });
1916
+ })), Rr = (t, s) => {
1917
+ let o;
1918
+ try {
1919
+ o = yo(s), console.info(
1920
+ `[RemoteControl] camera capture: ${o.camera?.width}x${o.camera?.height} @ ${o.camera?.frameRate ?? "?"}fps` + (o.camera?.label ? ` — ${o.camera.label}` : "")
1921
+ );
1922
+ } catch (n) {
1923
+ A("getSettings() on outbound camera track failed:", n), o = {
1924
+ type: "cameraResult",
1925
+ granted: !0,
1926
+ camera: {
1927
+ label: s.label || void 0
1928
+ }
1929
+ };
1930
+ }
1931
+ t.send(JSON.stringify(o)), W("onCameraDemandChange", ye.current, !0, !0, o.camera);
1932
+ }, _n = (t) => {
1933
+ if (!t) return;
1934
+ const s = t.indexOf("/"), n = (s >= 0 ? t.slice(s + 1) : t).toUpperCase();
1935
+ return n === "HEVC" ? "H265" : n;
1936
+ }, Dn = async () => {
1937
+ const t = we.current, s = vt.current;
1938
+ if (!t || !s) return;
1939
+ let o;
1940
+ try {
1941
+ o = await t.getStats();
1942
+ } catch {
1943
+ return;
1944
+ }
1945
+ let n, f, d;
1946
+ if (o.forEach((Y) => {
1947
+ Y.type === "outbound-rtp" && Y.kind === "video" ? n = Y : Y.type === "remote-inbound-rtp" && Y.kind === "video" && (d = Y);
1948
+ }), n?.codecId) {
1949
+ const Y = o.get(n.codecId);
1950
+ Y && (f = Y.mimeType);
1951
+ }
1952
+ if (!n) return;
1953
+ const p = n.timestamp ?? Date.now(), g = Ot.current;
1954
+ let C, m, I;
1955
+ if (g && p > g.timestamp) {
1956
+ const Y = (p - g.timestamp) / 1e3;
1957
+ if (typeof n.framesEncoded == "number" && typeof g.framesEncoded == "number" && (C = Math.max(0, (n.framesEncoded - g.framesEncoded) / Y)), typeof n.bytesSent == "number" && typeof g.bytesSent == "number" && (m = Math.max(0, (n.bytesSent - g.bytesSent) * 8 / Y)), typeof n.packetsSent == "number" && typeof g.packetsSent == "number" && d && typeof d.packetsLost == "number" && typeof g.packetsLost == "number") {
1958
+ const B = n.packetsSent - g.packetsSent, ae = d.packetsLost - g.packetsLost;
1959
+ B > 0 && (I = Math.max(0, Math.min(100, ae / B * 100)));
1960
+ }
1961
+ }
1962
+ Ot.current = {
1963
+ timestamp: p,
1964
+ framesEncoded: n.framesEncoded,
1965
+ bytesSent: n.bytesSent,
1966
+ packetsSent: n.packetsSent,
1967
+ packetsLost: d?.packetsLost
1968
+ };
1969
+ const T = {
1970
+ codec: _n(f),
1971
+ encoderImplementation: n.encoderImplementation,
1972
+ hardwareAccelerated: typeof n.powerEfficientEncoder == "boolean" ? n.powerEfficientEncoder : void 0,
1973
+ framesPerSecond: C,
1974
+ framesEncoded: n.framesEncoded,
1975
+ bitrateBps: m,
1976
+ width: n.frameWidth,
1977
+ height: n.frameHeight,
1978
+ qualityLimitationReason: n.qualityLimitationReason,
1979
+ rttMs: typeof d?.roundTripTime == "number" ? d.roundTripTime * 1e3 : void 0,
1980
+ packetsLostPct: I
1981
+ };
1982
+ W("onCameraStats", vt.current, T);
1983
+ }, Nr = () => {
1984
+ ot.current === null && (Ot.current = null, ot.current = setInterval(() => {
1985
+ Dn();
1986
+ }, 1e3));
1987
+ }, Yt = () => {
1988
+ ot.current !== null && (clearInterval(ot.current), ot.current = null), Ot.current = null, W("onCameraStats", vt.current, null);
1989
+ }, Tn = (t, s, o, n) => $t.enqueue(async ({ isCurrent: f }) => {
1990
+ const d = () => f() && n() && b.current === s && we.current === o;
1991
+ if (!d()) return;
1992
+ if (!t.active) {
1993
+ const T = ce.current;
1994
+ try {
1995
+ await o.replaceTrack(null);
1996
+ } catch (Y) {
1997
+ A("replaceTrack(null) on camera detach failed:", Y);
1998
+ }
1999
+ if (ce.current === T && (ce.current = null, be.current = void 0, T && oe(T)), Yt(), !d()) return;
2000
+ W("onCameraDemandChange", ye.current, !1);
2001
+ return;
2002
+ }
2003
+ W("onCameraDemandChange", ye.current, !0);
2004
+ const p = ce.current, g = p?.getVideoTracks()[0], C = be.current;
2005
+ if (g?.readyState === "live" && C && !go(C, t)) {
2006
+ be.current = t, Rr(s, g), Nr();
2007
+ return;
2008
+ }
2009
+ if (p) {
2010
+ try {
2011
+ await o.replaceTrack(null);
2012
+ } catch (T) {
2013
+ A("replaceTrack(null) before camera switch failed:", T);
2014
+ }
2015
+ if (ce.current === p && (ce.current = null, be.current = void 0, oe(p)), Yt(), !d()) return;
2016
+ }
2017
+ if (!navigator.mediaDevices || typeof navigator.mediaDevices.getUserMedia != "function") {
2018
+ if (console.warn(
2019
+ "[RemoteControl] navigator.mediaDevices.getUserMedia unavailable. getUserMedia requires a secure context (https or http://localhost). Replying cameraResult granted=false so limulator falls back to black frames."
2020
+ ), !d()) return;
2021
+ s.send(JSON.stringify({ type: "cameraResult", granted: !1 })), W("onCameraDemandChange", ye.current, !0, !1);
2022
+ return;
2023
+ }
2024
+ let m = null;
2025
+ try {
2026
+ m = await navigator.mediaDevices.getUserMedia({
2027
+ video: Eo(t),
2028
+ audio: !1
2029
+ });
2030
+ } catch (T) {
2031
+ console.warn("[RemoteControl] getUserMedia denied/failed:", T);
2032
+ }
2033
+ if (!d()) {
2034
+ m && oe(m);
2035
+ return;
2036
+ }
2037
+ if (!m) {
2038
+ s.send(JSON.stringify({ type: "cameraResult", granted: !1 })), W("onCameraDemandChange", ye.current, !0, !1);
2039
+ return;
2040
+ }
2041
+ const I = m.getVideoTracks()[0] ?? null;
2042
+ if (!I) {
2043
+ if (oe(m), !d()) return;
2044
+ s.send(JSON.stringify({ type: "cameraResult", granted: !1 })), W("onCameraDemandChange", ye.current, !0, !1);
2045
+ return;
2046
+ }
2047
+ try {
2048
+ I.contentHint = "motion";
2049
+ } catch {
2050
+ }
2051
+ try {
2052
+ await o.replaceTrack(I);
2053
+ } catch (T) {
2054
+ if (A("replaceTrack(videoTrack) failed:", T), oe(m), !d()) return;
2055
+ s.send(JSON.stringify({ type: "cameraResult", granted: !1 })), W("onCameraDemandChange", ye.current, !0, !1);
2056
+ return;
2057
+ }
2058
+ if (!d()) {
2059
+ try {
2060
+ await o.replaceTrack(null);
2061
+ } catch (T) {
2062
+ A("replaceTrack(null) for stale camera attach failed:", T);
2063
+ }
2064
+ oe(m);
2065
+ return;
2066
+ }
2067
+ try {
2068
+ const T = o.getParameters();
2069
+ (!T.encodings || T.encodings.length === 0) && (T.encodings = [{}]), T.encodings[0].maxBitrate = 8e6, T.encodings[0].maxFramerate = 30, T.degradationPreference = "maintain-framerate", await o.setParameters(T);
2070
+ } catch (T) {
2071
+ A("setParameters on outbound camera failed:", T);
2072
+ }
2073
+ if (!d()) {
2074
+ try {
2075
+ await o.replaceTrack(null);
2076
+ } catch (T) {
2077
+ A("replaceTrack(null) for stale camera finalize failed:", T);
2078
+ }
2079
+ oe(m);
2080
+ return;
2081
+ }
2082
+ ce.current = m, be.current = t, I.onended = () => {
2083
+ ce.current === m && $t.enqueueCurrent(async ({ isCurrent: T }) => {
2084
+ if (!(!T() || ce.current !== m || !n() || b.current !== s || we.current !== o)) {
2085
+ try {
2086
+ await o.replaceTrack(null);
2087
+ } catch (Y) {
2088
+ A("replaceTrack(null) after camera ended failed:", Y);
2089
+ }
2090
+ !T() || ce.current !== m || !n() || b.current !== s || we.current !== o || (ce.current = null, be.current = void 0, oe(m), Yt(), s.send(JSON.stringify({ type: "cameraResult", granted: !1 })), W("onCameraDemandChange", ye.current, !0, !1));
2091
+ }
2092
+ }).catch((T) => A("camera ended cleanup failed:", T));
2093
+ }, d() && (Rr(s, I), Nr());
2094
+ }), Ze = () => {
2095
+ for (const t of Ue.current.values())
2096
+ clearTimeout(t.timer), t.reject(new Error("Simulator disconnected"));
2097
+ Ue.current.clear(), cr(null), tt.current && (tt.current.srcObject = null), Nt(), mt(), pt(), ne.current && (ne.current.stop(), ne.current = null), $t.invalidate(), Yt(), vn(), be.current = void 0, we.current = null, ++_t.current, Bt.current = !1, He.current = null, me.current && (oe(me.current), me.current = null, W("onMicrophoneStateChange", it.current, {
2098
+ active: !1
2099
+ })), st.current = null, de.current !== void 0 && (window.cancelAnimationFrame(de.current), de.current = void 0), b.current && (b.current.onopen = null, b.current.onmessage = null, b.current.onerror = null, b.current.onclose = null, b.current.close(), b.current = null), X.current && (X.current.onconnectionstatechange = null, X.current.oniceconnectionstatechange = null, X.current.ontrack = null, X.current.onicecandidate = null, X.current.close(), X.current = null), $.current && ($.current.srcObject = null), L.current && (L.current.onopen = null, L.current.onclose = null, L.current.onerror = null, L.current.close(), L.current = null);
2100
+ }, Ir = () => {
2101
+ document.hidden ? Ar() : br();
2102
+ }, wn = async () => {
2103
+ if (typeof navigator < "u" && navigator.onLine === !1)
2104
+ return !1;
2105
+ let t;
2106
+ try {
2107
+ const n = new URL(e);
2108
+ n.protocol = n.protocol === "wss:" ? "https:" : n.protocol === "ws:" ? "http:" : n.protocol, t = xr(n.toString(), i);
2109
+ } catch {
2110
+ return !1;
2111
+ }
2112
+ const s = new AbortController(), o = window.setTimeout(() => s.abort(), Yo);
2113
+ try {
2114
+ return (await fetch(t, { method: "GET", cache: "no-store", signal: s.signal })).status === 404;
2115
+ } catch {
2116
+ return !1;
2117
+ } finally {
2118
+ window.clearTimeout(o);
2119
+ }
2120
+ }, bn = () => {
2121
+ Le.current || (Le.current = !0, dr(!0), gt(!1), Te.current += 1, Rt(), Nt(), mt(), Ze(), k("Instance terminated"), Ge("terminated"), W("onTerminated", vr.current));
2122
+ }, An = () => {
2123
+ Le.current || Wt.current || (Wt.current = !0, wn().then((t) => {
2124
+ Wt.current = !1, t && bn();
2125
+ }));
2126
+ }, et = (t, s) => {
2127
+ if (Le.current || s !== Te.current)
2128
+ return;
2129
+ if (An(), We.current) {
2130
+ if (!Ht.current) {
2131
+ k(`Connection failed after it was established: ${t}`), gt(!0), Ge("failed"), Ze();
2132
+ return;
2133
+ }
2134
+ k(`Reconnecting after established session dropped: ${t}`), We.current = !1, yt.current = -1;
2135
+ }
2136
+ Rt();
2137
+ const o = yt.current + 1;
2138
+ if (o >= rr) {
2139
+ k(`Connection failed after ${rr} attempts: ${t}`), gt(!0), Ge("failed"), Ze();
2140
+ return;
2141
+ }
2142
+ k(`Retrying connection (${o + 1}/${rr})`), Ge("reconnecting"), Ze(), rt.current = window.setTimeout(() => {
2143
+ rt.current = void 0, s === Te.current && Yr(o);
2144
+ }, Ro);
2145
+ }, Yr = async (t = 0) => {
2146
+ if (Le.current) return;
2147
+ const s = Te.current + 1;
2148
+ Te.current = s, yt.current = t, We.current = !1, gt(!1), t === 0 && Jt.current !== "reconnecting" && Ge("connecting"), Rt(), Nt(), pt(), ct.current = !1, Ft(!1), Ze();
2149
+ const o = () => s === Te.current;
2150
+ nt.current = window.setTimeout(() => {
2151
+ nt.current = void 0, !(!o() || We.current) && et("Connection did not succeed within 15 seconds", s);
2152
+ }, No);
2153
+ try {
2154
+ const n = new WebSocket(xr(e, i));
2155
+ if (b.current = n, await new Promise((_, h) => {
2156
+ let P = !1;
2157
+ const ie = window.setTimeout(() => h(new Error("WebSocket connection timeout")), 3e4), M = (K) => {
2158
+ P || (P = !0, window.clearTimeout(ie), K());
2159
+ };
2160
+ n.onopen = () => {
2161
+ !o() || b.current !== n || M(_);
2162
+ }, n.onerror = (K) => {
2163
+ !o() || b.current !== n || (k("WebSocket error: " + K), M(() => h(new Error("WebSocket connection failed"))));
2164
+ }, n.onclose = () => {
2165
+ !o() || b.current !== n || (k("WebSocket closed"), M(() => h(new Error("WebSocket closed before connection was established"))));
2166
+ };
2167
+ }), !o() || b.current !== n)
2168
+ return;
2169
+ n.onerror = (_) => {
2170
+ !o() || b.current !== n || k("WebSocket error: " + _);
2171
+ }, n.onclose = () => {
2172
+ !o() || b.current !== n || k("WebSocket closed");
2173
+ };
2174
+ const f = new Promise((_, h) => {
2175
+ const P = (K) => {
2176
+ window.clearTimeout(ie), n.removeEventListener("message", M), K();
2177
+ }, ie = window.setTimeout(
2178
+ () => P(() => h(new Error("RTCConfiguration timeout"))),
2179
+ 3e4
2180
+ ), M = (K) => {
2181
+ if (!(!o() || b.current !== n))
2182
+ try {
2183
+ const J = JSON.parse(K.data);
2184
+ if (J.type === "signalingError" && J.requestType === "requestRtcConfiguration" && J.sessionId === he) {
2185
+ const ue = typeof J.error == "string" ? J.error : "Unable to load streaming configuration";
2186
+ P(() => h(new Error(ue)));
2187
+ } else J.type === "rtcConfiguration" && P(
2188
+ () => _({
2189
+ rtcConfiguration: J.rtcConfiguration,
2190
+ cameraSupported: J.cameraSupported === !0,
2191
+ foldSupported: J.foldSupported === !0
2192
+ })
2193
+ );
2194
+ } catch (J) {
2195
+ console.error("Error handling RTC configuration:", J), P(() => h(J));
2196
+ }
2197
+ };
2198
+ n.addEventListener("message", M), n.send(
2199
+ JSON.stringify({
2200
+ type: "requestRtcConfiguration",
2201
+ sessionId: he
2202
+ })
2203
+ );
2204
+ }), {
2205
+ rtcConfiguration: d,
2206
+ cameraSupported: p,
2207
+ foldSupported: g
2208
+ } = await f;
2209
+ if (!o() || b.current !== n)
2210
+ return;
2211
+ const C = E === "iphone-duo" || g;
2212
+ sr(C);
2213
+ const m = new RTCPeerConnection(d);
2214
+ X.current = m, m.addTransceiver("audio", { direction: "recvonly" });
2215
+ const I = m.addTransceiver("video", { direction: "recvonly" }), T = C ? m.addTransceiver("video", { direction: "recvonly" }) : null, Y = Ee === "ios" || p, B = Y ? m.addTransceiver("video", {
2216
+ direction: "sendonly"
2217
+ }) : null;
2218
+ we.current = B?.sender ?? null;
2219
+ const ae = Y ? m.addTransceiver("audio", {
2220
+ direction: "sendonly"
2221
+ }) : null;
2222
+ if (st.current = ae?.sender ?? null, RTCRtpReceiver.getCapabilities) {
2223
+ const _ = RTCRtpReceiver.getCapabilities("video");
2224
+ if (_ && _.codecs) {
2225
+ const P = _.codecs.sort((ie, M) => {
2226
+ const K = (J) => {
2227
+ const ue = J.mimeType.toLowerCase();
2228
+ return ue.includes("vp9") ? 1 : ue.includes("h265") || ue.includes("hevc") ? 2 : ue.includes("h264") || ue.includes("avc") ? 3 : 4;
2229
+ };
2230
+ return K(ie) - K(M);
2231
+ });
2232
+ I.setCodecPreferences(P), T?.setCodecPreferences(P), H("Set codec preferences:", P.map((ie) => ie.mimeType).join(", "));
2233
+ }
2234
+ }
2235
+ if (B && RTCRtpSender.getCapabilities) {
2236
+ const _ = RTCRtpSender.getCapabilities("video");
2237
+ if (_ && _.codecs) {
2238
+ const h = /* @__PURE__ */ new Set(["42e01f", "42e028", "640c1f"]), P = (M) => {
2239
+ const K = M.mimeType.toLowerCase(), ue = (M.sdpFmtpLine || "").toLowerCase().match(/profile-level-id=([0-9a-f]{6})/), In = ue ? ue[1] : "";
2240
+ return K === "video/h265" || K === "video/hevc" ? 1 : K === "video/h264" && h.has(In) ? 2 : K === "video/h264" ? 3 : K === "video/vp9" ? 4 : K === "video/vp8" ? 5 : K === "video/rtx" || K === "video/red" || K === "video/ulpfec" ? 0 : 6;
2241
+ }, ie = [..._.codecs].sort((M, K) => P(M) - P(K));
2242
+ try {
2243
+ B.setCodecPreferences(ie), H(
2244
+ "Outbound camera codec preferences:",
2245
+ ie.map((M) => `${M.mimeType}${M.sdpFmtpLine ? `[${M.sdpFmtpLine}]` : ""}`).join(", ")
2246
+ );
2247
+ } catch (M) {
2248
+ A("Failed to set outbound camera codec preferences:", M);
2249
+ }
2250
+ }
2251
+ }
2252
+ const z = m.createDataChannel("control", {
2253
+ ordered: !0,
2254
+ negotiated: !0,
2255
+ id: 1
2256
+ });
2257
+ if (L.current = z, z.onopen = () => {
2258
+ if (!o() || L.current !== z || b.current !== n)
2259
+ return;
2260
+ We.current = !0, Nt(), k("Control channel opened"), ne.current || (ne.current = new ho({
2261
+ platform: Ee,
2262
+ baseIntervalMs: ge,
2263
+ maxBackoffMs: U,
2264
+ androidElementTreeOptions: Q,
2265
+ send: (h) => {
2266
+ if (!b.current || b.current.readyState !== WebSocket.OPEN) return !1;
2267
+ try {
2268
+ return b.current.send(JSON.stringify(h)), !0;
2269
+ } catch {
2270
+ return !1;
2271
+ }
2272
+ },
2273
+ onSnapshot: (h) => {
2274
+ mr((P) => qr(P, h) ? P : h), queueMicrotask(() => {
2275
+ W("onAxSnapshotChange", Gt.current, h);
2276
+ });
2277
+ },
2278
+ onStatusChange: (h, P) => {
2279
+ W("onAxStatusChange", yr.current, h, P);
2280
+ }
2281
+ }), (Be.current === !0 || Be.current === "hover-only") && ne.current.start());
2282
+ const _ = () => {
2283
+ !o() || ct.current || L.current !== z || b.current !== n || n.readyState !== WebSocket.OPEN || n.send(JSON.stringify({ type: "requestFrame", sessionId: he }));
2284
+ };
2285
+ if (_(), pt(), Ct.current = window.setInterval(() => {
2286
+ if (!o() || ct.current || L.current !== z || b.current !== n || n.readyState !== WebSocket.OPEN) {
2287
+ pt();
2288
+ return;
2289
+ }
2290
+ _();
2291
+ }, 250), l) {
2292
+ try {
2293
+ const h = decodeURIComponent(l);
2294
+ k("Opening URL"), n.send(
2295
+ JSON.stringify({
2296
+ type: "openUrl",
2297
+ url: h,
2298
+ sessionId: he
2299
+ })
2300
+ );
2301
+ } catch (h) {
2302
+ console.error({ error: h }, "Error decoding URL, falling back to the original URL"), n.send(
2303
+ JSON.stringify({
2304
+ type: "openUrl",
2305
+ url: l,
2306
+ sessionId: he
2307
+ })
2308
+ );
2309
+ }
2310
+ ne.current?.bumpActivity();
2311
+ }
2312
+ }, z.onclose = () => {
2313
+ !o() || L.current !== z || k("Control channel closed");
2314
+ }, z.onerror = (_) => {
2315
+ !o() || L.current !== z || (console.error("Control channel error:", _), k("Control channel error: " + _));
2316
+ }, m.onconnectionstatechange = () => {
2317
+ !o() || X.current !== m || (k("Connection state: " + m.connectionState), m.connectionState === "failed" && et("WebRTC connection entered failed state", s));
2318
+ }, m.oniceconnectionstatechange = () => {
2319
+ if (!o() || X.current !== m)
2320
+ return;
2321
+ const _ = m.iceConnectionState;
2322
+ if (k("ICE state: " + _), _ === "connected" || _ === "completed") {
2323
+ mt(), jt() && !me.current && Qt();
2324
+ return;
2325
+ }
2326
+ if (_ === "failed") {
2327
+ mt(), et("ICE connection entered failed state", s);
2328
+ return;
2329
+ }
2330
+ _ === "disconnected" && Ht.current && Fe.current === void 0 && (Fe.current = window.setTimeout(() => {
2331
+ Fe.current = void 0, !(!o() || X.current !== m) && m.iceConnectionState === "disconnected" && et("ICE stayed disconnected past grace period", s);
2332
+ }, Io));
2333
+ }, m.ontrack = (_) => {
2334
+ if (!(!o() || X.current !== m) && (k("Received remote track: " + _.track.kind), _.track.kind === "video" && $.current)) {
2335
+ H(`[${(/* @__PURE__ */ new Date()).toISOString()}] Video track received:`, _.track);
2336
+ const P = _.track.id === "duo-inner" || _.streams.some((ie) => ie.id === "duo-inner") ? tt.current : $.current;
2337
+ P && (P.srcObject = C ? new MediaStream([_.track]) : _.streams[0] ?? new MediaStream([_.track]), P.play().catch(() => {
2338
+ }));
2339
+ }
2340
+ }, m.onicecandidate = (_) => {
2341
+ if (!(!o() || X.current !== m || b.current !== n))
2342
+ if (_.candidate && n.readyState === WebSocket.OPEN) {
2343
+ const h = {
2344
+ type: "candidate",
2345
+ candidate: _.candidate.candidate,
2346
+ sdpMid: _.candidate.sdpMid,
2347
+ sdpMLineIndex: _.candidate.sdpMLineIndex,
2348
+ sessionId: he
2349
+ };
2350
+ n.send(JSON.stringify(h)), k("Sent ICE candidate");
2351
+ } else
2352
+ k("ICE candidate gathering completed");
2353
+ }, n.onmessage = async (_) => {
2354
+ if (!o() || b.current !== n)
2355
+ return;
2356
+ let h;
2357
+ try {
2358
+ h = JSON.parse(_.data);
2359
+ } catch (P) {
2360
+ A("Error parsing message:", P);
2361
+ return;
2362
+ }
2363
+ if (!ne.current?.handleMessage(h))
2364
+ switch (k("Received: " + h.type), h.type) {
2365
+ case "performActionsResult":
2366
+ case "foldStateResult":
2367
+ case "foldStateChanged": {
2368
+ if (!C) break;
2369
+ h.state ? (cr(h.state), ur(void 0)) : h.id === "duo-capabilities" && ur(h.error || "This instance does not support native iPhone Duo displays.");
2370
+ const M = Ue.current.get(h.id);
2371
+ M && (clearTimeout(M.timer), Ue.current.delete(h.id), h.error ? M.reject(new Error(h.error)) : M.resolve());
2372
+ break;
2373
+ }
2374
+ case "signalingError": {
2375
+ if (h.requestType !== "offer" || h.sessionId !== he)
2376
+ break;
2377
+ const M = typeof h.error == "string" ? h.error : "Unable to establish the streaming connection";
2378
+ k("Error: " + M), et(M, s);
2379
+ break;
2380
+ }
2381
+ case "answer":
2382
+ if (!X.current || X.current !== m) {
2383
+ k("No peer connection, skipping answer");
2384
+ break;
2385
+ }
2386
+ if (await m.setRemoteDescription(
2387
+ new RTCSessionDescription({
2388
+ type: "answer",
2389
+ sdp: h.sdp
2390
+ })
2391
+ ), !o() || X.current !== m)
2392
+ return;
2393
+ k("Set remote description");
2394
+ break;
2395
+ case "candidate":
2396
+ if (!X.current || X.current !== m) {
2397
+ k("No peer connection, skipping candidate");
2398
+ break;
2399
+ }
2400
+ if (await m.addIceCandidate(
2401
+ new RTCIceCandidate({
2402
+ candidate: h.candidate,
2403
+ sdpMid: h.sdpMid,
2404
+ sdpMLineIndex: h.sdpMLineIndex
2405
+ })
2406
+ ), !o() || X.current !== m)
2407
+ return;
2408
+ k("Added ICE candidate");
2409
+ break;
2410
+ case "screenshot":
2411
+ case "screenshotResult": {
2412
+ if (typeof h.id != "string") {
2413
+ A("Received invalid screenshot success message:", h);
2414
+ break;
2415
+ }
2416
+ const M = Uo(h);
2417
+ if (M) {
2418
+ const ue = ve.current.get(h.id);
2419
+ if (!ue) {
2420
+ A(`Received screenshot error for unknown or handled id: ${h.id}`);
2421
+ break;
2422
+ }
2423
+ A(`Received screenshot error for id ${h.id}: ${M}`), ue(new Error(M)), _e.current.delete(h.id), ve.current.delete(h.id);
2424
+ break;
2425
+ }
2426
+ const K = Lo(h);
2427
+ if (!K) {
2428
+ A("Received screenshot message without image data:", h);
2429
+ break;
2430
+ }
2431
+ const J = _e.current.get(h.id);
2432
+ if (!J) {
2433
+ A(`Received screenshot data for unknown or handled id: ${h.id}`);
2434
+ break;
2435
+ }
2436
+ H(`Received screenshot data for id ${h.id}`), J(K), _e.current.delete(h.id), ve.current.delete(h.id);
2437
+ break;
2438
+ }
2439
+ case "screenshotError":
2440
+ if (typeof h.id != "string" || typeof h.message != "string") {
2441
+ A("Received invalid screenshot error message:", h);
2442
+ break;
2443
+ }
2444
+ const P = ve.current.get(h.id);
2445
+ if (!P) {
2446
+ A(`Received screenshot error for unknown or handled id: ${h.id}`);
2447
+ break;
2448
+ }
2449
+ A(`Received screenshot error for id ${h.id}: ${h.message}`), P(new Error(h.message)), _e.current.delete(h.id), ve.current.delete(h.id);
2450
+ break;
2451
+ case "cameraRequest": {
2452
+ const M = we.current;
2453
+ if (!M)
2454
+ break;
2455
+ const K = mo(h);
2456
+ if (!K) {
2457
+ A("Received invalid cameraRequest:", h);
2458
+ break;
2459
+ }
2460
+ console.info("[RemoteControl] cameraRequest received:", K.active, K.facingMode), await Tn(K, n, M, o);
2461
+ break;
2462
+ }
2463
+ case "microphoneRequest": {
2464
+ if (!st.current)
2465
+ break;
2466
+ const M = h.active === !0;
2467
+ if (Bt.current = M, console.info("[RemoteControl] microphoneRequest received, active=", M), !M) {
2468
+ Xt.current || await It();
2469
+ break;
2470
+ }
2471
+ if (me.current) {
2472
+ Sr(n);
2473
+ break;
2474
+ }
2475
+ await Qt();
2476
+ break;
2477
+ }
2478
+ case "microphoneStartResult": {
2479
+ if (He.current === null || h.id !== He.current)
2480
+ break;
2481
+ He.current = null, typeof h.error == "string" && (console.warn("[RemoteControl] microphoneStart rejected by host:", h.error), It(h.error));
2482
+ break;
2483
+ }
2484
+ case "terminateAppResult":
2485
+ if (typeof h.id != "string") {
2486
+ A("Received invalid terminateApp result message:", h);
2487
+ break;
2488
+ }
2489
+ if (typeof h.error == "string") {
2490
+ const M = Me.current.get(h.id);
2491
+ if (!M) {
2492
+ A(`Received terminateApp error for unknown or handled id: ${h.id}`);
2493
+ break;
2494
+ }
2495
+ A(`Received terminateApp error for id ${h.id}: ${h.error}`), M(new Error(h.error)), Ae.current.delete(h.id), Me.current.delete(h.id);
2496
+ break;
2497
+ }
2498
+ const ie = Ae.current.get(h.id);
2499
+ if (!ie) {
2500
+ A(`Received terminateApp result for unknown or handled id: ${h.id}`);
2501
+ break;
2502
+ }
2503
+ H(`Received terminateApp success for id ${h.id}`), ie(), Ae.current.delete(h.id), Me.current.delete(h.id);
2504
+ break;
2505
+ default:
2506
+ A(`Received unhandled message type: ${h.type}`, h);
2507
+ break;
2508
+ }
2509
+ }, C && n.send(JSON.stringify({ type: "getFoldState", id: "duo-capabilities" })), X.current === m) {
2510
+ const _ = await m.createOffer({
2511
+ offerToReceiveVideo: !0,
2512
+ offerToReceiveAudio: !1
2513
+ });
2514
+ if (!o() || X.current !== m || (await m.setLocalDescription(_), !o() || X.current !== m))
2515
+ return;
2516
+ o() && b.current === n && n.readyState === WebSocket.OPEN && n.send(
2517
+ JSON.stringify({
2518
+ type: "offer",
2519
+ ...C ? { displayStreams: !0 } : {},
2520
+ sdp: _.sdp,
2521
+ sessionId: he
2522
+ })
2523
+ ), k("Sent offer");
2524
+ }
2525
+ } catch (n) {
2526
+ if (!o())
2527
+ return;
2528
+ const f = n instanceof Error ? n.message : String(n);
2529
+ k("Error: " + f), et(f, s);
2530
+ }
2531
+ }, Zt = () => {
2532
+ Le.current = !1, dr(!1), Yr(0);
2533
+ }, Mn = () => {
2534
+ Te.current += 1, yt.current = 0, We.current = !1, Rt(), mt(), Ze(), k("Stopped");
2535
+ }, Sn = (t) => {
2536
+ t.stopPropagation(), Zt();
2537
+ };
2538
+ le(() => {
2539
+ jt() ? Qt() : It();
2540
+ }, [F]), le(() => (Ft(!1), Zt(), document.hidden || br(), document.addEventListener("visibilitychange", Ir), () => {
2541
+ Ar(), Mn(), document.removeEventListener("visibilitychange", Ir);
2542
+ }), [e, i, c, E]);
2543
+ const Kr = () => {
2544
+ const t = ht();
2545
+ if (!t) {
2546
+ Er(null);
2547
+ return;
2548
+ }
2549
+ const s = {
2550
+ left: t.videoRect.left - t.containerRect.left + t.offsetX,
2551
+ top: t.videoRect.top - t.containerRect.top + t.offsetY,
2552
+ width: t.actualWidth,
2553
+ height: t.actualHeight
2554
+ };
2555
+ Er(
2556
+ (o) => o && o.left === s.left && o.top === s.top && o.width === s.width && o.height === s.height ? o : s
2557
+ );
2558
+ };
2559
+ le(() => {
2560
+ const t = $.current, s = Pe.current, o = Ce.current;
2561
+ if (!t) return;
2562
+ const n = () => {
2563
+ if (!bt || !s) {
2564
+ fr({}), Kr();
2565
+ return;
2566
+ }
2567
+ const p = s.clientWidth, g = s.clientHeight;
2568
+ if (p === 0 || g === 0) return;
2569
+ const C = t.videoWidth > t.videoHeight;
2570
+ Zr(C), tn(
2571
+ Ee === "android" && Ko(t.videoWidth, t.videoHeight)
2572
+ );
2573
+ const m = C ? Je.videoPosition.landscape : Je.videoPosition.portrait;
2574
+ let I = {};
2575
+ m.heightMultiplier ? (I.height = `${g * m.heightMultiplier}px`, I.width = "auto") : m.widthMultiplier && (I.width = `${p * m.widthMultiplier}px`, I.height = "auto"), I.borderRadius = `${C ? g * Je.videoBorderRadiusMultiplier : p * Je.videoBorderRadiusMultiplier}px`, fr(I), Kr();
2576
+ }, f = new ResizeObserver(() => {
2577
+ n();
2578
+ });
2579
+ s && f.observe(s), f.observe(t), o && f.observe(o), s && s.addEventListener("load", n), t.addEventListener("loadedmetadata", n), t.addEventListener("resize", n);
2580
+ const d = () => ne.current?.bumpActivity();
2581
+ return t.addEventListener("resize", d), n(), () => {
2582
+ f.disconnect(), t.removeEventListener("loadedmetadata", n), t.removeEventListener("resize", n), t.removeEventListener("resize", d), s && s.removeEventListener("load", n);
2583
+ };
2584
+ }, [Je, bt]), le(() => {
2585
+ const t = ne.current;
2586
+ dt ? t?.start() : (t?.stop(), mr(null), ut(null), Tt(null), gr(null), Xe(null), wt.current = null, de.current !== void 0 && (window.cancelAnimationFrame(de.current), de.current = void 0), W("onAxSnapshotChange", Gt.current, null));
2587
+ }, [dt]), le(() => () => {
2588
+ de.current !== void 0 && (window.cancelAnimationFrame(de.current), de.current = void 0);
2589
+ }, []), le(() => {
2590
+ if (!dt) return;
2591
+ const t = (s) => {
2592
+ s.key === "Escape" && (Vt || qt) && (Tt(null), ut(null), Xe(null), W("onInspectSelectionChange", Ve.current, null));
2593
+ };
2594
+ return window.addEventListener("keydown", t), () => window.removeEventListener("keydown", t);
2595
+ }, [dt, Vt, qt]);
2596
+ const Rn = () => {
2597
+ $.current && $.current.focus();
2598
+ };
2599
+ Ln(ke, () => ({
2600
+ openUrl: (t) => {
2601
+ if (!b.current || b.current.readyState !== WebSocket.OPEN) {
2602
+ A("WebSocket not open, cannot send open_url command via ref.");
2603
+ return;
2604
+ }
2605
+ try {
2606
+ const s = decodeURIComponent(t);
2607
+ k("Opening URL"), b.current.send(
2608
+ JSON.stringify({
2609
+ type: "openUrl",
2610
+ url: s,
2611
+ sessionId: he
2612
+ })
2613
+ );
2614
+ } catch (s) {
2615
+ A("Error decoding or sending URL via ref:", { error: s, url: t }), b.current.send(
2616
+ JSON.stringify({
2617
+ type: "openUrl",
2618
+ url: t,
2619
+ sessionId: he
2620
+ })
2621
+ );
2622
+ }
2623
+ ne.current?.bumpActivity();
2624
+ },
2625
+ sendKeyEvent: (t) => {
2626
+ if (!L.current || L.current.readyState !== "open") {
2627
+ A("Data channel not ready for imperative key command:", L.current?.readyState);
2628
+ return;
2629
+ }
2630
+ const s = $r[t.code];
2631
+ if (!s) {
2632
+ A(`Unknown event.code for imperative command: ${t.code}`);
2633
+ return;
2634
+ }
2635
+ let o = a.META_NONE;
2636
+ t.shiftKey && (o |= a.META_SHIFT_ON), t.altKey && (o |= a.META_ALT_ON), t.ctrlKey && (o |= a.META_CTRL_ON), t.metaKey && (o |= a.META_META_ON);
2637
+ const n = t.type === "keydown" ? a.ACTION_DOWN : a.ACTION_UP;
2638
+ H(
2639
+ `Sending Imperative Key Command: code=${t.code}, keycode=${s}, action=${n}, meta=${o}`
2640
+ );
2641
+ const f = Et(
2642
+ n,
2643
+ s,
2644
+ 0,
2645
+ // repeat count, typically 0 for single presses
2646
+ o
2647
+ );
2648
+ f && pe(f);
2649
+ },
2650
+ screenshot: (t) => new Promise((s, o) => {
2651
+ if (!b.current || b.current.readyState !== WebSocket.OPEN)
2652
+ return A("WebSocket not open, cannot send screenshot command."), o(new Error("WebSocket is not connected or connection is not open."));
2653
+ const n = `ui-ss-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`, f = {
2654
+ type: t ? "screenshotDisplay" : "screenshot",
2655
+ ...t ? { display: t } : {},
2656
+ id: n
2657
+ };
2658
+ _e.current.set(n, s), ve.current.set(n, o), H("Sending screenshot request:", f);
2659
+ try {
2660
+ b.current.send(JSON.stringify(f));
2661
+ } catch (d) {
2662
+ A("Failed to send screenshot request immediately:", d), _e.current.delete(n), ve.current.delete(n), o(d);
2663
+ return;
2664
+ }
2665
+ setTimeout(() => {
2666
+ _e.current.has(n) && (A(`Screenshot request timed out for id ${n}`), ve.current.get(n)?.(new Error("Screenshot request timed out")), _e.current.delete(n), ve.current.delete(n));
2667
+ }, 3e4);
2668
+ }),
2669
+ terminateApp: (t) => new Promise((s, o) => {
2670
+ if (!b.current || b.current.readyState !== WebSocket.OPEN)
2671
+ return A("WebSocket not open, cannot send terminateApp command."), o(new Error("WebSocket is not connected or connection is not open."));
2672
+ const n = `ui-term-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`, f = {
2673
+ type: "terminateApp",
2674
+ id: n,
2675
+ bundleId: t
2676
+ };
2677
+ Ae.current.set(n, s), Me.current.set(n, o), H("Sending terminateApp request:", f);
2678
+ try {
2679
+ b.current.send(JSON.stringify(f));
2680
+ } catch (d) {
2681
+ A("Failed to send terminateApp request immediately:", d), Ae.current.delete(n), Me.current.delete(n), o(d);
2682
+ return;
2683
+ }
2684
+ ne.current?.bumpActivity(), setTimeout(() => {
2685
+ Ae.current.has(n) && (A(`terminateApp request timed out for id ${n}`), Me.current.get(n)?.(new Error("terminateApp request timed out")), Ae.current.delete(n), Me.current.delete(n));
2686
+ }, 3e4);
2687
+ }),
2688
+ reconnect: () => Zt(),
2689
+ refreshAxTree: async () => {
2690
+ const t = ne.current;
2691
+ if (!t)
2692
+ throw new Error("Inspect mode is not active");
2693
+ return t.refresh();
2694
+ },
2695
+ getAxSnapshot: () => qe.current,
2696
+ setInspectHighlight: (t) => {
2697
+ ut(t?.id ?? null);
2698
+ },
2699
+ setInspectSelection: (t) => {
2700
+ Tt(t?.id ?? null), Xe(t ? wt.current : null);
2701
+ const s = qe.current;
2702
+ t && s ? W("onInspectSelectionChange", Ve.current, { element: t, snapshot: s }) : W("onInspectSelectionChange", Ve.current, null);
2703
+ },
2704
+ getAxStatus: () => ne.current?.getStatus() ?? "idle"
2705
+ }));
2706
+ const Nn = nn && Re !== null;
2707
+ return /* @__PURE__ */ V(
2708
+ "div",
2709
+ {
2710
+ ref: Ce,
2711
+ className: Ke("rc-container", r),
2712
+ style: { touchAction: "none" },
2713
+ onMouseDown: De,
2714
+ onMouseMove: De,
2715
+ onMouseUp: De,
2716
+ onMouseLeave: De,
2717
+ onTouchStart: De,
2718
+ onTouchMove: De,
2719
+ onTouchEnd: De,
2720
+ onTouchCancel: De,
2721
+ children: [
2722
+ Nn && Re && /* @__PURE__ */ V(nr, { children: [
2723
+ /* @__PURE__ */ v(
2724
+ "div",
2725
+ {
2726
+ className: "rc-touch-indicator",
2727
+ style: {
2728
+ left: `${Re.containerX}px`,
2729
+ top: `${Re.containerY}px`
2730
+ }
2731
+ }
2732
+ ),
2733
+ /* @__PURE__ */ v(
2734
+ "div",
2735
+ {
2736
+ className: "rc-touch-indicator",
2737
+ style: {
2738
+ left: `${Re.mirrorContainerX}px`,
2739
+ top: `${Re.mirrorContainerY}px`
2740
+ }
2741
+ }
2742
+ )
2743
+ ] }),
2744
+ bt && /* @__PURE__ */ v(
2745
+ "img",
2746
+ {
2747
+ ref: Pe,
2748
+ src: _r,
2749
+ alt: "",
2750
+ className: Ee === "ios" ? Ke("rc-phone-frame", "rc-phone-frame-ios") : "rc-phone-frame",
2751
+ draggable: !1
2752
+ }
2753
+ ),
2754
+ /* @__PURE__ */ v(
2755
+ "video",
2756
+ {
2757
+ ref: $,
2758
+ className: Ke(
2759
+ "rc-video",
2760
+ !bt && "rc-video-frameless",
2761
+ !zr && "rc-video-loading"
2762
+ ),
2763
+ style: {
2764
+ ...rn,
2765
+ ...se ? { opacity: 0, width: 1, height: 1, pointerEvents: "none" } : {},
2766
+ ...ft ? {
2767
+ backgroundImage: `url("${ft}")`,
2768
+ backgroundRepeat: "no-repeat",
2769
+ backgroundPosition: "center",
2770
+ backgroundSize: Je.loadingLogoSize
2771
+ } : {}
2772
+ },
2773
+ autoPlay: !0,
2774
+ playsInline: !0,
2775
+ muted: !0,
2776
+ tabIndex: se ? -1 : 0,
2777
+ onKeyDown: St,
2778
+ onKeyUp: St,
2779
+ onClick: Rn,
2780
+ onLoadedData: yn,
2781
+ onFocus: () => {
2782
+ $.current && ($.current.style.outline = "none");
2783
+ },
2784
+ onBlur: () => {
2785
+ $.current && ($.current.style.outline = "none");
2786
+ }
2787
+ }
2788
+ ),
2789
+ se && /* @__PURE__ */ v(
2790
+ "video",
2791
+ {
2792
+ ref: tt,
2793
+ autoPlay: !0,
2794
+ playsInline: !0,
2795
+ muted: !0,
2796
+ style: { position: "absolute", width: 1, height: 1, opacity: 0, pointerEvents: "none" }
2797
+ }
2798
+ ),
2799
+ se && !Lt && /* @__PURE__ */ v(Pr, { logo: ft, showFrame: u }),
2800
+ se && Lt && /* @__PURE__ */ v(xn, { fallback: /* @__PURE__ */ v(Pr, { logo: ft, showFrame: u }), children: /* @__PURE__ */ v(
2801
+ Mo,
2802
+ {
2803
+ loadingLogo: ft,
2804
+ showFrame: u,
2805
+ modelUrl: y,
2806
+ outer: $.current,
2807
+ inner: tt.current,
2808
+ state: Lt,
2809
+ setAngle: (t) => xt("setHingeAngle", { angleDegrees: t }),
2810
+ setOrientation: (t) => xt("setDuoOrientation", { orientation: t }),
2811
+ button: (t, s) => xt("performActions", {
2812
+ actions: [{ type: s ? "buttonDown" : "buttonUp", button: t }]
2813
+ }),
2814
+ touch: (t, s, o, n) => {
2815
+ const f = L.current;
2816
+ f?.readyState === "open" && f.send($n(t, s, o, n));
2817
+ },
2818
+ onKeyDown: St,
2819
+ onKeyUp: St
2820
+ }
2821
+ ) }),
2822
+ se && ar && /* @__PURE__ */ v("div", { role: "alert", className: "rc-duo-error", children: ar }),
2823
+ !se && dt && /* @__PURE__ */ v(
2824
+ Ao,
2825
+ {
2826
+ snapshot: pr,
2827
+ geometry: sn,
2828
+ highlightedId: qt,
2829
+ selectedId: Vt,
2830
+ mode: un,
2831
+ cursorPosition: cn,
2832
+ frozenCursorPosition: an,
2833
+ onSelectChange: (t, s) => {
2834
+ Tt(t?.id ?? null), t && s ? Xe(s) : t || Xe(null);
2835
+ const o = qe.current;
2836
+ t && o ? W("onInspectSelectionChange", Ve.current, {
2837
+ element: t,
2838
+ snapshot: o
2839
+ }) : W("onInspectSelectionChange", Ve.current, null);
2840
+ },
2841
+ onTapElement: (t, s) => {
2842
+ if (s) {
2843
+ Tr(s.x, s.y);
2844
+ return;
2845
+ }
2846
+ const o = qe.current;
2847
+ o && dn(t, o);
2848
+ }
2849
+ }
2850
+ ),
2851
+ Qr ? /* @__PURE__ */ V("div", { className: "rc-terminated", role: "status", children: [
2852
+ /* @__PURE__ */ v("div", { className: "rc-terminated-title", children: "Instance terminated" }),
2853
+ /* @__PURE__ */ v("div", { className: "rc-terminated-message", children: "This instance no longer exists and can't be reconnected." })
2854
+ ] }) : jr && /* @__PURE__ */ v("button", { type: "button", className: "rc-retry-button", onClick: Sn, children: "Retry" })
2855
+ ]
2856
+ }
2857
+ );
2858
+ }
2859
+ ), Uo = (r) => typeof r.message == "string" ? r.message : typeof r.error == "string" ? r.error : null, Lo = (r) => typeof r.dataUri == "string" ? { dataUri: r.dataUri } : typeof r.base64 == "string" ? r.base64.startsWith("data:") ? { dataUri: r.base64 } : { dataUri: `data:${r.base64.startsWith("/9j/") ? "image/jpeg" : "image/png"};base64,${r.base64}` } : null;
2860
+ export {
2861
+ tr as A,
2862
+ Wn as D,
2863
+ Bo as H,
2864
+ Jo as R,
2865
+ oo as a,
2866
+ io as b,
2867
+ Gr as c,
2868
+ Br as d,
2869
+ qr as e,
2870
+ no as f,
2871
+ Zn as g,
2872
+ Xn as h,
2873
+ Vo as i,
2874
+ qn as j,
2875
+ qo as k,
2876
+ Go as l,
2877
+ Ho as m,
2878
+ ro as n,
2879
+ kr as o,
2880
+ Bn as p,
2881
+ Xo as q,
2882
+ $o as r
2883
+ };