@limrun/ui 0.19.0 → 0.20.0

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