@limrun/ui 0.17.1 → 0.18.1

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