@limrun/ui 0.17.0 → 0.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{GLTFLoader-J_X4Rf5c.js → GLTFLoader-C8IUEj4c.js} +1 -1
- package/dist/{GLTFLoader-ByeC7669.mjs → GLTFLoader-Cfw5hgaY.mjs} +1 -1
- package/dist/{duo-frame-CWvQkgHw.js → duo-frame-Do1d2J-W.js} +2 -2
- package/dist/{duo-frame-R2ZgsqRJ.mjs → duo-frame-dYldPOq-.mjs} +3 -3
- package/dist/{duo-view-DJSSQKg7.js → duo-view--EopHG5S.js} +1 -1
- package/dist/{duo-view-D1WxkDni.mjs → duo-view-BNktEtvj.mjs} +2 -2
- package/dist/index.cjs +1 -1
- package/dist/index.js +2 -2
- package/dist/lite.cjs +1 -1
- package/dist/lite.js +1 -1
- package/dist/{remote-control-B7C7_cm-.js → remote-control-CwGLAbIU.js} +1 -1
- package/dist/{remote-control-BGXbOBCk.mjs → remote-control-MECm114K.mjs} +138 -138
- package/package.json +1 -1
package/dist/lite.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./remote-control-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./remote-control-CwGLAbIU.js");exports.AX_UNAVAILABLE_ERROR=e.AX_UNAVAILABLE_ERROR;exports.RemoteControl=e.RemoteControl;exports.axElementAtPoint=e.axElementAtPoint;exports.axElementSelectorExpression=e.axElementSelectorExpression;exports.axElementSummary=e.axElementSummary;exports.axElementsEqual=e.axElementsEqual;exports.axSnapshotsEqual=e.axSnapshotsEqual;exports.clampAxFrameForScreen=e.clampAxFrameForScreen;exports.normalizeAndroidTree=e.normalizeAndroidTree;exports.normalizeIosTree=e.normalizeIosTree;
|
package/dist/lite.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as s, R as o, a as r, b as n, c as m, d as l, e as t, f as E, n as x, g as A } from "./remote-control-
|
|
1
|
+
import { A as s, R as o, a as r, b as n, c as m, d as l, e as t, f as E, n as x, g as A } from "./remote-control-MECm114K.mjs";
|
|
2
2
|
export {
|
|
3
3
|
s as AX_UNAVAILABLE_ERROR,
|
|
4
4
|
o as RemoteControl,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";require('./index.css');const w=require("react/jsx-runtime"),l=require("react"),An=require("react-dom");function Pr(r){var t,s,a="";if(typeof r=="string"||typeof r=="number")a+=r;else if(typeof r=="object")if(Array.isArray(r)){var g=r.length;for(t=0;t<g;t++)r[t]&&(s=Pr(r[t]))&&(a&&(a+=" "),a+=s)}else for(s in r)r[s]&&(a&&(a+=" "),a+=s);return a}function Se(){for(var r,t,s=0,a="",g=arguments.length;s<g;s++)(r=arguments[s])&&(t=Pr(r))&&(a&&(a+=" "),a+=t);return a}const Mn={width:164.6,height:117.8,depth:5.2};function bn(r,t,s){return r=Math.max(0,Math.min(1,r)),t=Math.max(0,Math.min(1,t)),s===1?{x:t,y:1-r}:s===2?{x:1-r,y:1-t}:s===3?{x:1-t,y:r}:{x:r,y:t}}function Nn(r){return Number.isFinite(r)&&r>=0&&r<=180}function In(r,t){return{x:Math.max(0,Math.min(1,r)),y:Math.max(0,Math.min(1,1-t))}}function Yn(r,t,s){return t&&(r||!s)?"touch":r?"ignore":"orbit"}function Kn(r,t,s,a){if(!Number.isInteger(r)||r<0||r>3||!Number.isInteger(t)||t<1||t>255||!Number.isFinite(s)||!Number.isFinite(a)||s<0||s>1||a<0||a>1)throw new RangeError("Invalid display touch coordinates");const g=new ArrayBuffer(12),p=new DataView(g);return p.setUint8(0,19),p.setUint8(1,r),p.setUint8(2,t),p.setFloat32(4,s,!0),p.setFloat32(8,a,!0),g}class kn{constructor(t,s){this.send=t,this.failed=s}send;failed;latest;running=!1;stopped=!1;set(t){this.stopped||!Nn(t)||(this.latest=t,this.flush())}stop(){this.stopped=!0,this.latest=void 0}async flush(){if(!(this.running||this.stopped)){this.running=!0;try{for(;this.latest!==void 0&&!this.stopped;){const t=this.latest;this.latest=void 0,await this.send(t)}}catch(t){this.latest=void 0,this.stopped||this.failed(t)}finally{this.running=!1}}}}const Pn={side:"Sleep/Wake",volumeUp:"Volume Up",volumeDown:"Volume Down"};class Un{constructor(t,s){this.send=t,this.failed=s}send;failed;held;tail=Promise.resolve();timeout;press(t){this.held||(this.held=t,this.enqueue(t,!0),this.timeout=setTimeout(()=>this.release(),1e4))}release(){if(!this.held)return;clearTimeout(this.timeout);const t=this.held;this.held=void 0,this.enqueue(t,!1)}enqueue(t,s){this.tail=this.tail.then(()=>this.send(t,s)).catch(this.failed)}}const Yt={INJECT_KEYCODE:0,INJECT_TOUCH_EVENT:2,INJECT_TWO_FINGER_TOUCH_EVENT:18,SET_CLIPBOARD:9},U={ACTION_DOWN:0,ACTION_UP:1,ACTION_MOVE:2,ACTION_CANCEL:3,ACTION_POINTER_DOWN:5,ACTION_POINTER_UP:6,BUTTON_PRIMARY:1,BUTTON_SECONDARY:2,BUTTON_TERTIARY:4},c={ACTION_DOWN:0,ACTION_UP:1,META_NONE:0,META_SHIFT_ON:1,META_ALT_ON:2,META_CTRL_ON:4096,META_META_ON:65536,KEYCODE_0:7,KEYCODE_1:8,KEYCODE_2:9,KEYCODE_3:10,KEYCODE_4:11,KEYCODE_5:12,KEYCODE_6:13,KEYCODE_7:14,KEYCODE_8:15,KEYCODE_9:16,DPAD_UP:19,DPAD_DOWN:20,DPAD_LEFT:21,DPAD_RIGHT:22,KEYCODE_A:29,KEYCODE_B:30,KEYCODE_C:31,KEYCODE_D:32,KEYCODE_E:33,KEYCODE_F:34,KEYCODE_G:35,KEYCODE_H:36,KEYCODE_I:37,KEYCODE_J:38,KEYCODE_K:39,KEYCODE_L:40,KEYCODE_M:41,KEYCODE_N:42,KEYCODE_O:43,KEYCODE_P:44,KEYCODE_Q:45,KEYCODE_R:46,KEYCODE_S:47,KEYCODE_T:48,KEYCODE_U:49,KEYCODE_V:50,KEYCODE_W:51,KEYCODE_X:52,KEYCODE_Y:53,KEYCODE_Z:54,KEYCODE_COMMA:55,KEYCODE_PERIOD:56,KEYCODE_ALT_LEFT:57,KEYCODE_ALT_RIGHT:58,KEYCODE_SHIFT_LEFT:59,KEYCODE_SHIFT_RIGHT:60,KEYCODE_TAB:61,KEYCODE_SPACE:62,ENTER:66,DEL:67,KEYCODE_GRAVE:68,KEYCODE_MINUS:69,KEYCODE_EQUALS:70,KEYCODE_LEFT_BRACKET:71,KEYCODE_RIGHT_BRACKET:72,KEYCODE_BACKSLASH:73,KEYCODE_SEMICOLON:74,KEYCODE_APOSTROPHE:75,KEYCODE_SLASH:76,MENU:82,KEYCODE_PAGE_UP:92,KEYCODE_PAGE_DOWN:93,KEYCODE_ESCAPE:111,FORWARD_DEL:112,KEYCODE_CTRL_LEFT:113,KEYCODE_CTRL_RIGHT:114,KEYCODE_META_LEFT:117,KEYCODE_META_RIGHT:118,KEYCODE_MOVE_HOME:122,KEYCODE_MOVE_END:123,KEYCODE_INSERT:124,KEYCODE_F1:131,KEYCODE_F2:132,KEYCODE_F3:133,KEYCODE_F4:134,KEYCODE_F5:135,KEYCODE_F6:136,KEYCODE_F7:137,KEYCODE_F8:138,KEYCODE_F9:139,KEYCODE_F10:140,KEYCODE_F11:141,KEYCODE_F12:142,KEYCODE_NUMPAD_0:144,KEYCODE_NUMPAD_1:145,KEYCODE_NUMPAD_2:146,KEYCODE_NUMPAD_3:147,KEYCODE_NUMPAD_4:148,KEYCODE_NUMPAD_5:149,KEYCODE_NUMPAD_6:150,KEYCODE_NUMPAD_7:151,KEYCODE_NUMPAD_8:152,KEYCODE_NUMPAD_9:153,KEYCODE_NUMPAD_DIVIDE:154,KEYCODE_NUMPAD_MULTIPLY:155,KEYCODE_NUMPAD_SUBTRACT:156,KEYCODE_NUMPAD_ADD:157,KEYCODE_NUMPAD_DOT:158,KEYCODE_NUMPAD_COMMA:159,KEYCODE_NUMPAD_ENTER:160,KEYCODE_NUMPAD_EQUALS:161},Ur={KeyA:c.KEYCODE_A,KeyB:c.KEYCODE_B,KeyC:c.KEYCODE_C,KeyD:c.KEYCODE_D,KeyE:c.KEYCODE_E,KeyF:c.KEYCODE_F,KeyG:c.KEYCODE_G,KeyH:c.KEYCODE_H,KeyI:c.KEYCODE_I,KeyJ:c.KEYCODE_J,KeyK:c.KEYCODE_K,KeyL:c.KEYCODE_L,KeyM:c.KEYCODE_M,KeyN:c.KEYCODE_N,KeyO:c.KEYCODE_O,KeyP:c.KEYCODE_P,KeyQ:c.KEYCODE_Q,KeyR:c.KEYCODE_R,KeyS:c.KEYCODE_S,KeyT:c.KEYCODE_T,KeyU:c.KEYCODE_U,KeyV:c.KEYCODE_V,KeyW:c.KEYCODE_W,KeyX:c.KEYCODE_X,KeyY:c.KEYCODE_Y,KeyZ:c.KEYCODE_Z,Digit0:c.KEYCODE_0,Digit1:c.KEYCODE_1,Digit2:c.KEYCODE_2,Digit3:c.KEYCODE_3,Digit4:c.KEYCODE_4,Digit5:c.KEYCODE_5,Digit6:c.KEYCODE_6,Digit7:c.KEYCODE_7,Digit8:c.KEYCODE_8,Digit9:c.KEYCODE_9,Backquote:c.KEYCODE_GRAVE,Minus:c.KEYCODE_MINUS,Equal:c.KEYCODE_EQUALS,BracketLeft:c.KEYCODE_LEFT_BRACKET,BracketRight:c.KEYCODE_RIGHT_BRACKET,Backslash:c.KEYCODE_BACKSLASH,Semicolon:c.KEYCODE_SEMICOLON,Quote:c.KEYCODE_APOSTROPHE,Comma:c.KEYCODE_COMMA,Period:c.KEYCODE_PERIOD,Slash:c.KEYCODE_SLASH,Space:c.KEYCODE_SPACE,Tab:c.KEYCODE_TAB,Escape:c.KEYCODE_ESCAPE,ArrowUp:c.DPAD_UP,ArrowDown:c.DPAD_DOWN,ArrowLeft:c.DPAD_LEFT,ArrowRight:c.DPAD_RIGHT,Enter:c.ENTER,Backspace:c.DEL,Delete:c.FORWARD_DEL,Home:c.KEYCODE_MOVE_HOME,End:c.KEYCODE_MOVE_END,PageUp:c.KEYCODE_PAGE_UP,PageDown:c.KEYCODE_PAGE_DOWN,Insert:c.KEYCODE_INSERT,F1:c.KEYCODE_F1,F2:c.KEYCODE_F2,F3:c.KEYCODE_F3,F4:c.KEYCODE_F4,F5:c.KEYCODE_F5,F6:c.KEYCODE_F6,F7:c.KEYCODE_F7,F8:c.KEYCODE_F8,F9:c.KEYCODE_F9,F10:c.KEYCODE_F10,F11:c.KEYCODE_F11,F12:c.KEYCODE_F12,ShiftLeft:c.KEYCODE_SHIFT_LEFT,ShiftRight:c.KEYCODE_SHIFT_RIGHT,ControlLeft:c.KEYCODE_CTRL_LEFT,ControlRight:c.KEYCODE_CTRL_RIGHT,AltLeft:c.KEYCODE_ALT_LEFT,AltRight:c.KEYCODE_ALT_RIGHT,MetaLeft:c.KEYCODE_META_LEFT,MetaRight:c.KEYCODE_META_RIGHT,ContextMenu:c.MENU,Numpad0:c.KEYCODE_NUMPAD_0,Numpad1:c.KEYCODE_NUMPAD_1,Numpad2:c.KEYCODE_NUMPAD_2,Numpad3:c.KEYCODE_NUMPAD_3,Numpad4:c.KEYCODE_NUMPAD_4,Numpad5:c.KEYCODE_NUMPAD_5,Numpad6:c.KEYCODE_NUMPAD_6,Numpad7:c.KEYCODE_NUMPAD_7,Numpad8:c.KEYCODE_NUMPAD_8,Numpad9:c.KEYCODE_NUMPAD_9,NumpadDivide:c.KEYCODE_NUMPAD_DIVIDE,NumpadMultiply:c.KEYCODE_NUMPAD_MULTIPLY,NumpadSubtract:c.KEYCODE_NUMPAD_SUBTRACT,NumpadAdd:c.KEYCODE_NUMPAD_ADD,NumpadDecimal:c.KEYCODE_NUMPAD_DOT,NumpadComma:c.KEYCODE_NUMPAD_COMMA,NumpadEnter:c.KEYCODE_NUMPAD_ENTER,NumpadEqual:c.KEYCODE_NUMPAD_EQUALS};function Mt(r,t,s,a,g,p,y=1,O=0,b=0){const D=new ArrayBuffer(32),N=new DataView(D);let A=0;return N.setUint8(A,Yt.INJECT_TOUCH_EVENT),A+=1,N.setUint8(A,r),A+=1,N.setBigInt64(A,BigInt(t),!0),A+=8,N.setInt32(A,Math.round(g),!0),A+=4,N.setInt32(A,Math.round(p),!0),A+=4,N.setUint16(A,s,!0),A+=2,N.setUint16(A,a,!0),A+=2,N.setInt16(A,Math.round(y*65535),!0),A+=2,N.setInt32(A,O,!0),A+=4,N.setInt32(A,b,!0),D}function Ln(r,t,s,a,g,p,y){const O=new ArrayBuffer(24),b=new DataView(O);let D=0;return b.setUint8(D,Yt.INJECT_TWO_FINGER_TOUCH_EVENT),D+=1,b.setUint8(D,r),D+=1,b.setInt32(D,Math.round(a),!0),D+=4,b.setInt32(D,Math.round(g),!0),D+=4,b.setInt32(D,Math.round(p),!0),D+=4,b.setInt32(D,Math.round(y),!0),D+=4,b.setUint16(D,t,!0),D+=2,b.setUint16(D,s,!0),D+=2,b.setUint16(D,0,!0),O}function xn(r,t=!0){const a=new TextEncoder().encode(r),g=new ArrayBuffer(14+a.length),p=new DataView(g);let y=0;return p.setUint8(y,Yt.SET_CLIPBOARD),y+=1,p.setBigInt64(y,BigInt(0),!1),y+=8,p.setUint8(y,t?1:0),y+=1,p.setUint32(y,a.length,!1),y+=4,new Uint8Array(g,y).set(a),g}function lt(r,t,s=0,a=0){const g=new ArrayBuffer(14),p=new DataView(g);let y=0;return p.setUint8(y,Yt.INJECT_KEYCODE),y+=1,p.setUint8(y,r),y+=1,p.setInt32(y,t,!0),y+=4,p.setInt32(y,s,!0),y+=4,p.setInt32(y,a,!0),g}const Nt="Accessibility unavailable on this device.",It=500,Lr=(r,t)=>Math.abs(r.x-t.x)<.5&&Math.abs(r.y-t.y)<.5&&Math.abs(r.width-t.width)<.5&&Math.abs(r.height-t.height)<.5,Fn=r=>Math.max(0,r.width)*Math.max(0,r.height),Wn=r=>{const t=r.find(s=>s.frame&&s.frame.width>0&&s.frame.height>0);return t?.frame?((Math.abs(t.frame.x)>.5||Math.abs(t.frame.y)>.5)&&console.warn(`[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.`),{x:0,y:0,width:t.frame.width,height:t.frame.height}):{x:0,y:0,width:1,height:1}},Hn=r=>{const t={};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},$n=r=>{const t={};for(const[s,a]of Object.entries(r))s!=="children"&&(t[s]=a);return t};function xr(r){const t=Array.isArray(r)?r:[r],s=Wn(t),a=[],g=(p,y)=>{if(a.length>=It)return;const O=p.frame;if(O&&O.width>0&&O.height>0&&!Lr(O,s)){const D=p.role_description||p.role||"",N=(typeof p.AXLabel=="string"?p.AXLabel:"")||(typeof p.title=="string"?p.title:"")||"";a.push({id:typeof p.AXUniqueId=="string"&&p.AXUniqueId.length>0?p.AXUniqueId:y,path:y,label:N,value:typeof p.AXValue=="string"?p.AXValue:"",role:D,type:typeof p.type=="string"?p.type:"",enabled:p.enabled!==!1,focused:p.focused===!0,frame:{x:O.x,y:O.y,width:O.width,height:O.height},selectors:Hn(p),raw:$n(p)})}const b=Array.isArray(p.children)?p.children:[];for(let D=0;D<b.length&&a.length<It;D++)g(b[D],`${y}.${D}`)};for(let p=0;p<t.length&&a.length<It;p++)g(t[p],String(p));return{platform:"ios",screen:{width:s.width,height:s.height},elements:a,capturedAt:Date.now()}}const Xn=r=>{let t={x:0,y:0,width:1,height:1},s=0;for(const a of r){const g=a.parsedBounds;if(!g)continue;const p=g.right-g.left,y=g.bottom-g.top,O=Math.max(0,p)*Math.max(0,y);O>s&&(s=O,t={x:0,y:0,width:p,height:y})}return t},Bn=r=>{const t={};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};function Fr(r){const t=Xn(r),s=[];for(let a=0;a<r.length&&s.length<It;a++){const g=r[a],p=g.parsedBounds;if(!p)continue;const y=Math.max(0,p.right-p.left),O=Math.max(0,p.bottom-p.top);if(y<=0||O<=0)continue;const b={x:p.left,y:p.top,width:y,height:O};if(Lr(b,{x:0,y:0,width:t.width,height:t.height}))continue;const D=g.contentDesc||g.text||"",N=g.className||"";s.push({id:g.resourceId&&g.resourceId.length>0?g.resourceId:g.contentDesc&&g.contentDesc.length>0?`cd:${g.contentDesc}`:String(a),path:String(a),label:D,value:typeof g.text=="string"?g.text:"",role:N,type:N,enabled:g.enabled!==!1,focused:g.focused===!0,frame:b,selectors:Bn(g),raw:{...g}})}return{platform:"android",screen:{width:t.width,height:t.height},elements:s,capturedAt:Date.now()}}function Wr(r,t){const s=Math.max(0,r.x),a=Math.max(0,r.y),g=Math.min(t.width,r.x+r.width),p=Math.min(t.height,r.y+r.height),y=Math.max(0,g-s),O=Math.max(0,p-a);return y>0&&O>0?{x:s,y:a,width:y,height:O}:null}function Jt(r,t){if(r===t)return!0;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;const s=r.frame,a=t.frame;return s.x===a.x&&s.y===a.y&&s.width===a.width&&s.height===a.height}function zt(r,t){if(r===t)return!0;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;for(let s=0;s<r.elements.length;s++)if(!Jt(r.elements[s],t.elements[s]))return!1;return!0}function Hr(r,t,s){let a=null,g=1/0;for(const p of r.elements){const y=p.frame;if(t<y.x||s<y.y||t>y.x+y.width||s>y.y+y.height)continue;const O=Fn(y);O<g&&(g=O,a=p)}return a}function $r(r,t){if(t==="ios"){if(r.selectors.AXUniqueId)return`client.tapElement({ AXUniqueId: ${JSON.stringify(r.selectors.AXUniqueId)} })`;if(r.selectors.AXLabel){const s=r.selectors.className?`, type: ${JSON.stringify(r.selectors.className)}`:"";return`client.tapElement({ AXLabel: ${JSON.stringify(r.selectors.AXLabel)}${s} })`}return null}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}function Xr(r){const t=r.role||r.type||"";if(!t)return"element";let s=t.replace(/^AX/,"");return s.includes(".")&&(s=s.split(".").pop()),s==="GenericElement"?"Element":(s=s.replace(/([a-z])([A-Z])/g,"$1 $2"),s)}const Nr=80;function Qt(r){const t=Xr(r),s=r.label||r.value||"";if(!s)return t;const a=s.length>Nr?s.slice(0,Nr).trimEnd()+"…":s;return`${t} · ${a}`}const qn=500,Vn=2e3,Ir=5e3,jn=8e3,Gn=1200,Jn=250,zn=()=>`ax-rc-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;class Qn{platform;send;onSnapshot;onStatusChange;baseIntervalMs;maxBackoffMs;androidElementTreeOptions;pending=new Map;running=!1;timer;currentInterval;lastSnapshot=null;inflight=!1;lastBumpAtMs=0;boostUntilMs=0;status="idle";constructor(t){this.platform=t.platform,this.send=t.send,this.onSnapshot=t.onSnapshot,this.onStatusChange=t.onStatusChange,this.baseIntervalMs=t.baseIntervalMs??qn,this.maxBackoffMs=t.maxBackoffMs??Vn,this.androidElementTreeOptions=t.androidElementTreeOptions,this.currentInterval=this.baseIntervalMs}start(){this.running||(this.running=!0,this.currentInterval=this.baseIntervalMs,this.boostUntilMs=0,this.setStatus("starting"),this.runOnce())}stop(){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))}getStatus(){return this.status}setStatus(t,s){if(this.status!==t&&(this.status=t,!!this.onStatusChange))try{this.onStatusChange(t,s)}catch(a){console.error("[AxFetcher] onStatusChange threw:",a)}}bumpActivity(){if(!this.running)return;const t=Date.now();this.boostUntilMs=t+Gn;const s=Math.max(150,Math.floor(this.baseIntervalMs/2));if(t-this.lastBumpAtMs<s){this.currentInterval=this.baseIntervalMs;return}this.lastBumpAtMs=t,this.currentInterval=this.baseIntervalMs,this.timer!==void 0&&(window.clearTimeout(this.timer),this.timer=void 0),this.inflight||this.runOnce()}async refresh(){const t=await this.requestOnce();return this.running&&this.deliver(t),t}getLatest(){return this.lastSnapshot}handleMessage(t){if(!t||typeof t.id!="string")return!1;const s=t.id;if(!this.pending.get(s))return!1;if(this.platform==="ios"){if(t.type!=="elementTreeResult")return!1;const O=typeof t.error=="string"?t.error:null;if(O)return this.settleReject(s,new Error(O)),!0;const b=typeof t.json=="string"?t.json:"";try{const D=JSON.parse(b),N=xr(D);this.settleResolve(s,N)}catch(D){this.settleReject(s,D instanceof Error?D:new Error(String(D)))}return!0}if(t.type!=="getElementTreeResult")return!1;const g=t.error;if(g&&typeof g=="object"){const O=typeof g.message=="string"?g.message:"getElementTree failed";return this.settleReject(s,new Error(O)),!0}const p=t.payload,y=Array.isArray(p?.nodes)?p.nodes:[];try{const O=Fr(y);this.settleResolve(s,O)}catch(O){this.settleReject(s,O instanceof Error?O:new Error(String(O)))}return!0}buildRequest(t){return this.platform==="ios"?{type:"elementTree",id:t}:{type:"getElementTree",id:t,...this.androidElementTreeOptions}}async requestOnce(){const t=zn();return new Promise((s,a)=>{const g=window.setTimeout(()=>{this.pending.delete(t),a(new Error("elementTree request timed out"))},jn+(this.androidElementTreeOptions?.waitForIdleTimeoutMs??0));this.pending.set(t,{resolve:s,reject:a,timer:g}),this.send(this.buildRequest(t))||(window.clearTimeout(g),this.pending.delete(t),a(new Error("elementTree send failed (WebSocket not open)")))})}async runOnce(){if(this.running&&!this.inflight){this.inflight=!0;try{const t=await this.requestOnce();if(!this.running)return;this.deliver(t)}catch(t){if(!this.running)return;const s=t instanceof Error?t.message:String(t),a=/unavailable|not (yet )?running|failed|timeout/i.test(s);this.currentInterval=a?Ir:Math.min(this.currentInterval*2,this.maxBackoffMs),this.setStatus(a?"unavailable":"error",s)}finally{this.inflight=!1,this.scheduleNext()}}}deliver(t){const s=this.lastSnapshot;if(zt(s,t)){this.currentInterval=Math.min(this.currentInterval*2,this.maxBackoffMs),this.lastSnapshot=t,t.errors?.includes(Nt)||this.setStatus("ready");return}this.lastSnapshot=t,this.currentInterval=this.baseIntervalMs,t.errors?.includes(Nt)?(this.currentInterval=Ir,this.setStatus("unavailable",Nt)):this.setStatus("ready"),this.onSnapshot(t)}scheduleNext(){if(!this.running)return;this.timer!==void 0&&window.clearTimeout(this.timer);const t=Date.now()<this.boostUntilMs?Math.min(Jn,this.currentInterval):this.currentInterval;this.timer=window.setTimeout(()=>{this.timer=void 0,this.runOnce()},t)}settleResolve(t,s){const a=this.pending.get(t);a&&(window.clearTimeout(a.timer),this.pending.delete(t),a.resolve(s))}settleReject(t,s){const a=this.pending.get(t);a&&(window.clearTimeout(a.timer),this.pending.delete(t),a.reject(s))}failAllPending(t){for(const[s,a]of this.pending.entries())window.clearTimeout(a.timer),a.reject(new Error(t)),this.pending.delete(s)}}class Zn{generation=0;tail=Promise.resolve();get currentGeneration(){return this.generation}enqueue(t){const s=++this.generation;return this.append(s,t)}enqueueCurrent(t){return this.append(this.generation,t)}append(t,s){const a={generation:t,isCurrent:()=>t===this.generation},g=this.tail.then(()=>s(a));return this.tail=g.catch(()=>{}),g}invalidate(){++this.generation}}function ei(r){if(!r||typeof r!="object")return null;const t=r;if(t.type!=="cameraRequest"||typeof t.active!="boolean")return null;const s={active:t.active};return(t.facingMode==="user"||t.facingMode==="environment")&&(s.facingMode=t.facingMode),s}function ti(r){const t={frameRate:{ideal:30,max:30}};return r?.facingMode&&(t.facingMode={ideal:r.facingMode}),t}function ri(r,t){return!r||r.facingMode!==t.facingMode}function ni(r){const t=r.getSettings();return{width:t.width,height:t.height,frameRate:t.frameRate,deviceId:t.deviceId,label:r.label||void 0,facingMode:t.facingMode}}function ii(r){return{type:"cameraResult",granted:!0,camera:ni(r)}}const oi=async r=>{if(!r)return!1;try{if(typeof navigator<"u"&&navigator.clipboard?.writeText)return await navigator.clipboard.writeText(r),!0}catch{}try{const t=document.createElement("textarea");t.value=r,t.style.position="fixed",t.style.opacity="0",document.body.appendChild(t),t.select();const s=document.execCommand("copy");return document.body.removeChild(t),s}catch{return!1}},si=l.memo(function({element:t,screen:s,highlighted:a,selected:g,selectable:p,onClick:y}){const O=Wr(t.frame,s);if(!O)return null;const b=Qt(t);return w.jsx("button",{type:"button",className:Se("rc-inspect-box",!t.enabled&&"rc-inspect-box-disabled"),"data-ax-id":t.id,"data-ax-path":t.path,"data-ax-label":t.label||void 0,"data-ax-role":t.role||void 0,"data-highlighted":a?"true":"false","data-selected":g?"true":"false","aria-label":b,onClick:D=>{p&&(D.preventDefault(),D.stopPropagation(),y(t,{x:D.clientX,y:D.clientY}))},style:{left:`${O.x/s.width*100}%`,top:`${O.y/s.height*100}%`,width:`${O.width/s.width*100}%`,height:`${O.height/s.height*100}%`}})},(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&&Jt(r.element,t.element)),ci=260,ai=220,ui=6,li=8,di=l.memo(function({element:t,platform:s,anchor:a,cursorAnchored:g,showActions:p,onTap:y}){const[O,b]=l.useState(null);l.useEffect(()=>{if(!O)return;const X=window.setTimeout(()=>b(null),1100);return()=>window.clearTimeout(X)},[O]);const D=l.useMemo(()=>{const X=ci,ue=ai,re=ui,H=li,le=typeof window<"u"?window.innerWidth:1024,dt=typeof window<"u"?window.innerHeight:768,Me=a.x+re+X<=le-H,de=a.y-re-ue>=H;let F=Me?a.x+re:a.x-re,be=de?a.y-re:a.y+re;const ie=`translate(${Me?"0":"-100%"}, ${de?"-100%":"0"})`;return F=Math.max(H+(Me?0:X),Math.min(le-H-(Me?X:0),F)),be=Math.max(H+(de?ue:0),Math.min(dt-H-(de?0:ue),be)),{left:`${F}px`,top:`${be}px`,transform:ie}},[a.x,a.y]),N=l.useMemo(()=>$r(t,s),[t,s]),A=s==="ios"?t.selectors.AXUniqueId:t.selectors.resourceId,Q=s==="ios"?"AXUniqueId":"resourceId",me=l.useCallback(async(X,ue)=>{if(!X)return;await oi(X)&&b(ue)},[]),pe=Xr(t),Ge=t.label||t.value||pe,Ae=Qt(t);return An.createPortal(w.jsxs("div",{className:"rc-inspect-card","data-cursor-anchored":g?"true":"false",style:D,onClick:X=>X.stopPropagation(),onMouseDown:X=>X.stopPropagation(),onMouseMove:X=>X.stopPropagation(),children:[w.jsxs("div",{className:"rc-inspect-card-header",children:[w.jsx("span",{className:"rc-inspect-card-role",children:pe}),!t.enabled&&w.jsx("span",{className:"rc-inspect-card-tag",children:"disabled"}),t.focused&&w.jsx("span",{className:"rc-inspect-card-tag rc-inspect-card-tag-blue",children:"focused"})]}),w.jsx("p",{className:"rc-inspect-card-title",title:Ae,children:Ge}),A&&w.jsxs("div",{className:"rc-inspect-card-row",children:[w.jsxs("span",{className:"rc-inspect-card-row-label",children:[Q,":"]}),w.jsx("span",{className:"rc-inspect-card-row-value",children:A})]}),t.value&&t.value!==t.label&&w.jsxs("div",{className:"rc-inspect-card-row",children:[w.jsx("span",{className:"rc-inspect-card-row-label",children:"value:"}),w.jsx("span",{className:"rc-inspect-card-row-value",children:t.value})]}),w.jsxs("div",{className:"rc-inspect-card-row",children:[w.jsx("span",{className:"rc-inspect-card-row-label",children:"frame:"}),w.jsxs("span",{className:"rc-inspect-card-row-value",children:[Math.round(t.frame.width),"×",Math.round(t.frame.height)," @ ",Math.round(t.frame.x),",",Math.round(t.frame.y)]})]}),p&&w.jsxs("div",{className:"rc-inspect-card-actions",children:[w.jsx("button",{type:"button",className:"rc-inspect-card-btn rc-inspect-card-btn-primary",onClick:()=>y(t,a),children:"Tap"}),w.jsx("button",{type:"button",className:Se("rc-inspect-card-btn",O==="selector"&&"rc-inspect-card-btn-copied"),disabled:!N,title:N??"No usable selector for this element",onClick:()=>me(N??void 0,"selector"),children:O==="selector"?"Copied!":"Copy selector"}),w.jsx("button",{type:"button",className:Se("rc-inspect-card-btn",O==="id"&&"rc-inspect-card-btn-copied"),disabled:!A,title:A??`No ${Q}`,onClick:()=>me(A,"id"),children:O==="id"?"Copied!":`Copy ${Q}`})]})]}),document.body)}),fi=l.memo(function({snapshot:t,geometry:s,highlightedId:a,selectedId:g,mode:p,cursorPosition:y,frozenCursorPosition:O,onSelectChange:b,onTapElement:D}){const N=p==="select",A=N?a!==null&&a!==g:a!==null,Q=N?a??g:a,me=l.useMemo(()=>{const H=new Map;if(!t)return H;for(const le of t.elements)H.set(le.id,le);return H},[t]),pe=l.useMemo(()=>Q?me.get(Q)??null:null,[Q,me]);if(!(!!t&&!!s&&t.screen.width>0&&t.screen.height>0&&t.elements.length>0))return null;const Ae=A?y:O??y,X=A,ue=N&&!A&&g!==null,re=H=>{N&&H.target===H.currentTarget&&b(null,null)};return w.jsxs(w.Fragment,{children:[w.jsx("div",{className:Se("rc-inspect-overlay",N&&"rc-inspect-overlay-select"),style:{left:`${s.left}px`,top:`${s.top}px`,width:`${s.width}px`,height:`${s.height}px`},onClick:re,children:t.elements.map(H=>w.jsx(si,{element:H,screen:t.screen,highlighted:H.id===a,selected:H.id===g,selectable:N,onClick:b},H.id))}),pe&&Ae&&w.jsx(di,{element:pe,platform:t.platform,anchor:Ae,cursorAnchored:X,showActions:ue,onTap:D})]})}),hi=l.lazy(()=>Promise.resolve().then(()=>require("./duo-view-DJSSQKg7.js")).then(r=>r.duoView)),x=(...r)=>{window.debugRemoteControl&&console.log(...r)},R=(...r)=>{window.debugRemoteControl&&console.warn(...r)},L=(r,t,...s)=>{if(t)try{t(...s)}catch(a){console.error(`[RemoteControl] customer callback "${r}" threw:`,a)}},bt=r=>Object.entries(U).find(([s,a])=>s.startsWith("ACTION_")&&a===r)?.[0]??String(r),mi=r=>r.includes("/android_")?"android":"ios",Yr=(r,t)=>{const s=new URL(r);return s.searchParams.set("token",t),s.toString()},Kr=1920,kr=1200,Gt=3,pi=1e3,Ei=15e3,gi=3e3,Ci=4e3,yi=(r,t)=>r===Kr&&t===kr||r===kr&&t===Kr,vi={ios:{videoBorderRadiusMultiplier:.15,loadingLogoSize:"20%",videoPosition:{portrait:{heightMultiplier:.9678},landscape:{widthMultiplier:.9678}}},android:{videoBorderRadiusMultiplier:.13,loadingLogoSize:"40%",videoPosition:{portrait:{heightMultiplier:.967},landscape:{widthMultiplier:.962}}}};function Oi(r){const t=r.code,s=Ur[t];if(!s)return R(`Unknown event.code: ${t}, key: ${r.key}`),null;let a=c.META_NONE;const g=t>="KeyA"&&t<="KeyZ",p=r.getModifierState("CapsLock"),y=r.shiftKey;let O=y;return g&&(O=y!==p),O&&(a|=c.META_SHIFT_ON),r.ctrlKey&&(a|=c.META_CTRL_ON),r.altKey&&(a|=c.META_ALT_ON),r.metaKey&&(a|=c.META_META_ON),{keycode:s,metaState:a}}const _i=l.forwardRef(({className:r,url:t,token:s,sessionId:a,openUrl:g,showFrame:p=!0,deviceModel:y,duoModelUrl:O,autoReconnect:b=!1,onTerminated:D,assets:N,onConnectionStateChange:A,inspectMode:Q,onAxSnapshotChange:me,onInspectSelectionChange:pe,onAxStatusChange:Ge,axPollIntervalMs:Ae,axMaxBackoffMs:X,androidElementTreeOptions:ue,onCameraDemandChange:re,onCameraStats:H,microphoneEnabled:le=!1,onMicrophoneStateChange:dt},Me)=>{const de=l.useRef(null),F=l.useRef(null),be=l.useRef(null),[Zt,er]=l.useState(!1),ie=y==="iphone-duo"||Zt,Je=l.useRef(null),[tr,rr]=l.useState(null),[nr,ir]=l.useState(),Ne=l.useRef(new Map),Kt=(e,o)=>new Promise((i,n)=>{const d=T.current;if(!d||d.readyState!==WebSocket.OPEN){n(new Error("Simulator disconnected"));return}const u=crypto.randomUUID(),h=setTimeout(()=>{Ne.current.delete(u),n(new Error("Device control timed out"))},5e3);Ne.current.set(u,{resolve:i,reject:n,timer:h}),d.send(JSON.stringify({type:e,id:u,...o}))}),[Br,kt]=l.useState(!1),[qr,ft]=l.useState(!1),[Vr,or]=l.useState(!1),Ie=l.useRef(!1),Pt=l.useRef(!1),[sr,jr]=l.useState(!1),[Gr,Jr]=l.useState(!1),[zr,cr]=l.useState({}),T=l.useRef(null),W=l.useRef(null),P=l.useRef(null),Ye=l.useRef(void 0),ze=l.useRef(void 0),Qe=l.useRef(void 0),ht=l.useRef(void 0),Ke=l.useRef(void 0),Ce=l.useRef(0),mt=l.useRef(0),ke=l.useRef(!1),Ut=l.useRef(b);Ut.current=b;const ye=l.useRef(null),Z=l.useRef(null),ve=l.useRef(void 0),Lt=l.useMemo(()=>new Zn,[]),fe=l.useRef(re);fe.current=re;const pt=l.useRef(H);pt.current=H;const Ze=l.useRef(null),Et=l.useRef(null),xt=l.useRef(le);xt.current=le;const Ft=l.useRef(!1),et=l.useRef(dt);et.current=dt;const tt=l.useRef(null),ce=l.useRef(null),gt=l.useRef(0),ar=l.useRef(Promise.resolve()),Pe=l.useRef(null),rt=l.useRef(!1),Ee=l.useRef(new Map),he=l.useRef(new Map),Oe=l.useRef(new Map),_e=l.useRef(new Map),j=l.useRef(new Map),De=l.useRef(!1),[Qr,Zr]=l.useState(!1),B=l.useRef(null),Ue=l.useRef(null),nt=l.useRef({handle:()=>{},end:()=>{}}),[Te,Ct]=l.useState(null),G=l.useRef(null),[ur,lr]=l.useState(null),[Wt,it]=l.useState(null),[Ht,yt]=l.useState(null),[en,dr]=l.useState(null),[tn,fr]=l.useState(null),vt=l.useRef(null),ne=l.useRef(void 0),hr=e=>{vt.current=e,ne.current===void 0&&(ne.current=window.requestAnimationFrame(()=>{ne.current=void 0,fr(vt.current)}))},[rn,Le]=l.useState(null),xe=l.useRef(Q);xe.current=Q;const Fe=l.useRef(null);Fe.current=ur;const $t=l.useRef(me);$t.current=me;const We=l.useRef(pe);We.current=pe;const mr=l.useRef(Ge);mr.current=Ge;const pr=l.useRef(D);pr.current=D;const Er=l.useRef(A);Er.current=A;const Xt=l.useRef(null),He=e=>{Xt.current!==e&&(Xt.current=e,L("onConnectionStateChange",Er.current,e))},ot=Q===!0||Q==="hover-only",nn=Q==="hover-only"?"hover-only":"select",oe=l.useMemo(()=>a||Math.random().toString(36).substring(2,15)+Math.random().toString(36).substring(2,15),[a]),ae=l.useMemo(()=>mi(t),[t]),$e=vi[ae],st=N?.[ae],gr=ae==="android"&&Gr?sr?st?.tabletFrameLandscape:st?.tabletFrame:sr?st?.frameLandscape:st?.frame,Cr=st?.loadingLogo,Ot=!ie&&p&&!!gr,K=e=>{x(e)},se=e=>{!P.current||P.current.readyState!=="open"||(P.current.send(e),G.current?.bumpActivity())},yr=-10,vr=(e,o)=>{const i=ct();if(!i)return;const n=Be(i,e,o);if(!n)return;const{videoX:d,videoY:u,videoWidth:h,videoHeight:E}=n,C=Mt(U.ACTION_DOWN,yr,h,E,d,u,1,U.BUTTON_PRIMARY,U.BUTTON_PRIMARY);C&&se(C),window.setTimeout(()=>{const m=Mt(U.ACTION_UP,yr,h,E,d,u,0,U.BUTTON_PRIMARY,U.BUTTON_PRIMARY);m&&se(m)},60)},on=(e,o)=>{const i=ct();if(!i||o.screen.width<=0||o.screen.height<=0)return;const n=e.frame.x+e.frame.width/2,d=e.frame.y+e.frame.height/2,u=n/o.screen.width*i.actualWidth,h=d/o.screen.height*i.actualHeight,E=i.videoRect.left+i.offsetX+u,C=i.videoRect.top+i.offsetY+h;vr(E,C)},_t=-1,Dt=-2,Re=-3,Xe=(e,o,i,n,d,u)=>{const h=Mt(e,o,i,n,d,u,1,U.BUTTON_PRIMARY,U.BUTTON_PRIMARY);h&&(x("[rc-touch] sendSingleTouch",{action:e,actionName:bt(e),pointerId:o,x:d,y:u,video:{width:i,height:n}}),se(h))},we=(e,o,i)=>{if(!i)return;const{videoX:n,videoY:d,videoWidth:u,videoHeight:h}=i;let E=null,C=null,m=1;const M=U.BUTTON_PRIMARY;switch(o){case"down":e!==Re&&nt.current.end(),E=j.current.size===0?U.ACTION_DOWN:U.ACTION_POINTER_DOWN,C={x:n,y:d},j.current.set(e,C),e===-1&&F.current?.focus();break;case"move":j.current.has(e)&&(E=U.ACTION_MOVE,C={x:n,y:d},j.current.set(e,C));break;case"up":case"cancel":j.current.has(e)&&(C=j.current.get(e),j.current.delete(e),o==="cancel"?E=U.ACTION_CANCEL:E=j.current.size===0?U.ACTION_UP:U.ACTION_POINTER_UP);break}if(E!==null&&C!==null){x("[rc-touch][mouse->touch] sending",{pointerId:e,eventType:o,action:E,actionName:bt(E),positionToSend:C,video:{width:u,height:h},altHeld:De.current,activePointersAfter:Array.from(j.current.entries()).map(([I,$])=>({id:I,x:$.x,y:$.y}))});const _=Mt(E,e,u,h,C.x,C.y,m,M,M);_&&(x("[rc-touch][mouse->touch] buffer",{pointerId:e,actionName:bt(E),byteLength:_.byteLength}),se(_))}else(o==="up"||o==="cancel")&&j.current.delete(e)},Bt=e=>{if(De.current!==e&&(De.current=e,Zr(e),e||Ct(null),x("[rc-touch][alt] updateAltHeld",{nextHeld:e,activePointerIds:Array.from(j.current.keys())}),ae==="ios"&&P.current&&P.current.readyState==="open")){const o=e?c.ACTION_DOWN:c.ACTION_UP,i=lt(o,c.KEYCODE_ALT_LEFT,0,c.META_NONE);x("[rc-touch][alt] sending Indigo modifier keycode",{action:o,keycode:c.KEYCODE_ALT_LEFT}),i&&se(i)}},ct=()=>{const e=F.current,o=de.current;if(!e||!o)return null;const i=e.videoWidth,n=e.videoHeight;if(!i||!n)return null;const d=e.getBoundingClientRect(),u=o.getBoundingClientRect(),h=d.width,E=d.height,C=i/n,m=h/E;let M=h,_=E;C>m?_=h/C:M=E*C;const I=(h-M)/2,$=(E-_)/2;return{videoWidth:i,videoHeight:n,videoRect:d,containerRect:u,actualWidth:M,actualHeight:_,offsetX:I,offsetY:$}},Be=(e,o,i)=>{const n=o-e.videoRect.left-e.offsetX,d=i-e.videoRect.top-e.offsetY,u=Math.max(0,Math.min(e.actualWidth,n)),h=Math.max(0,Math.min(e.actualHeight,d)),E=Math.max(0,Math.min(e.videoWidth,u/e.actualWidth*e.videoWidth)),C=Math.max(0,Math.min(e.videoHeight,h/e.actualHeight*e.videoHeight));return{videoX:E,videoY:C,videoWidth:e.videoWidth,videoHeight:e.videoHeight}},sn=(e,o,i)=>{const n=o-e.videoRect.left-e.offsetX,d=i-e.videoRect.top-e.offsetY,u=Math.max(0,Math.min(e.actualWidth,n)),h=Math.max(0,Math.min(e.actualHeight,d)),E=Math.max(0,Math.min(e.videoWidth,u/e.actualWidth*e.videoWidth)),C=Math.max(0,Math.min(e.videoHeight,h/e.actualHeight*e.videoHeight)),m=e.videoWidth-E,M=e.videoHeight-C,_=e.videoRect.left+e.offsetX,I=e.videoRect.top+e.offsetY,$=_-e.containerRect.left+u,ee=I-e.containerRect.top+h,V=_-e.containerRect.left+(e.actualWidth-u),v=I-e.containerRect.top+(e.actualHeight-h);return{containerX:$,containerY:ee,mirrorContainerX:V,mirrorContainerY:v,videoX:E,videoY:C,mirrorVideoX:m,mirrorVideoY:M,videoWidth:e.videoWidth,videoHeight:e.videoHeight}},cn=(e,o,i,n,d,u,h)=>{const E=Ln(e,o,i,n,d,u,h);x("[rc-touch2] sendTwoFingerMessage (iOS)",{actionName:bt(e),video:{width:o,height:i},p0:{x:n,y:d},p1:{x:u,y:h},byteLength:E.byteLength}),se(E)},qe=(e,o,i,n,d,u,h,E,C)=>{if(x("[rc-touch2] applyTwoFingerEvent",{platform:ae,eventType:e,video:{width:o,height:i},p0:{x:n,y:d,id:E},p1:{x:u,y:h,id:C}}),e==="down"&&nt.current.end(),ae==="ios"){const m=e==="down"?U.ACTION_DOWN:e==="move"?U.ACTION_MOVE:U.ACTION_UP;cn(m,o,i,n,d,u,h)}else e==="down"?(Xe(U.ACTION_DOWN,E,o,i,n,d),Xe(U.ACTION_POINTER_DOWN,C,o,i,u,h)):e==="move"?(Xe(U.ACTION_MOVE,E,o,i,n,d),Xe(U.ACTION_MOVE,C,o,i,u,h)):(Xe(U.ACTION_POINTER_UP,C,o,i,u,h),Xe(U.ACTION_UP,E,o,i,n,d))},an=(e,o,i)=>{if(!De.current){Te!==null&&Ct(null);return}const n=sn(e,o,i);Ct(n)},un=(e,o,i)=>{const n=Fe.current;if(!n||n.screen.width<=0||n.screen.height<=0)return null;const d=o-e.videoRect.left-e.offsetX,u=i-e.videoRect.top-e.offsetY;if(d<0||u<0||d>e.actualWidth||u>e.actualHeight)return null;const h=d/e.actualWidth*n.screen.width,E=u/e.actualHeight*n.screen.height;return Hr(n,h,E)},ge=e=>{if(ie)return;e.preventDefault(),e.stopPropagation();const o=ct();if((xe.current===!0||xe.current==="hover-only")&&!("touches"in e))if(e.type==="mousemove"){if(hr({x:e.clientX,y:e.clientY}),o){const n=un(o,e.clientX,e.clientY);it(n?.id??null)}}else e.type==="mouseleave"&&(hr(null),it(null));if(xe.current!==!0&&(!("touches"in e)&&o&&(e.type==="mousemove"?an(o,e.clientX,e.clientY):e.type==="mouseleave"&&Ct(null)),!(!P.current||P.current.readyState!=="open"||!F.current||!o)))if("touches"in e){const n=e.touches,d=e.changedTouches;let u;switch(e.type){case"touchstart":u="down";break;case"touchmove":u="move";break;case"touchend":u="up";break;case"touchcancel":u="cancel";break;default:return}if(n.length===2){const h=n[0],E=n[1],C=Be(o,h.clientX,h.clientY),m=Be(o,E.clientX,E.clientY);if(!C||!m)return;B.current?B.current.source==="real-touch"&&(B.current.finger0={x:C.videoX,y:C.videoY},B.current.finger1={x:m.videoX,y:m.videoY},qe("move",C.videoWidth,C.videoHeight,C.videoX,C.videoY,m.videoX,m.videoY,B.current.pointerId0,B.current.pointerId1)):(B.current={finger0:{x:C.videoX,y:C.videoY},finger1:{x:m.videoX,y:m.videoY},videoSize:{width:C.videoWidth,height:C.videoHeight},source:"real-touch",pointerId0:h.identifier,pointerId1:E.identifier},qe("down",C.videoWidth,C.videoHeight,C.videoX,C.videoY,m.videoX,m.videoY,h.identifier,E.identifier))}else if(n.length<2&&B.current?.source==="real-touch"){const h=B.current;qe("up",h.videoSize.width,h.videoSize.height,h.finger0.x,h.finger0.y,h.finger1.x,h.finger1.y,h.pointerId0,h.pointerId1),B.current=null;return}else{if(n.length>2)return;{const h=d[0];if(h){const E=Be(o,h.clientX,h.clientY);we(h.identifier,u,E)}}}}else{let d=null;const u=B.current?.source==="alt-mouse";switch(e.type){case"mousedown":e.button===0&&(d="down");break;case"mousemove":(u||j.current.has(-1))&&(d="move");break;case"mouseup":e.button===0&&(d="up");break;case"mouseleave":(u||j.current.has(-1))&&(d="up");break}if(d){const h=Be(o,e.clientX,e.clientY);if(!h)return;x("[rc-touch][mouse] event",{domType:e.type,eventType:d,button:e.button,buttons:e.buttons,client:{x:e.clientX,y:e.clientY},altHeldRef:De.current,inTwoFingerMode:u,geometry:{videoX:h.videoX,videoY:h.videoY,videoWidth:h.videoWidth,videoHeight:h.videoHeight},activePointerIds:Array.from(j.current.keys())}),De.current||u?ln(d,h):we(-1,d,h)}}},ln=(e,o)=>{const{videoX:i,videoY:n,videoWidth:d,videoHeight:u}=o,h=d-i,E=u-n;if(e==="down"){B.current={finger0:{x:i,y:n},finger1:{x:h,y:E},videoSize:{width:d,height:u},source:"alt-mouse",pointerId0:_t,pointerId1:Dt},F.current?.focus(),qe("down",d,u,i,n,h,E,_t,Dt);return}if(e==="move"){B.current?.source==="alt-mouse"&&(B.current.finger0={x:i,y:n},B.current.finger1={x:h,y:E},qe("move",d,u,i,n,h,E,_t,Dt));return}if(e==="up"||e==="cancel"){const C=B.current;if(C?.source==="alt-mouse"){const{finger0:m,finger1:M,videoSize:_}=C;qe("up",_.width,_.height,m.x,m.y,M.x,M.y,_t,Dt),B.current=null}return}},dn=150,Or=()=>{const e=Ue.current;e&&(window.clearTimeout(e.endTimer),we(Re,"up",e.pos),Ue.current=null)},fn=e=>{if(e.ctrlKey||De.current||B.current)return;const o=j.current.size;if(o>1||o===1&&!j.current.has(Re))return;const i=ct();if(!i)return;const n=e.clientX-i.videoRect.left-i.offsetX,d=e.clientY-i.videoRect.top-i.offsetY;if(n<0||n>i.actualWidth||d<0||d>i.actualHeight)return;const u=Be(i,e.clientX,e.clientY);if(!u)return;e.preventDefault();const h=(e.deltaMode===1?16:e.deltaMode===2?i.actualWidth:1)*(i.videoWidth/i.actualWidth),E=(e.deltaMode===1?16:e.deltaMode===2?i.actualHeight:1)*(i.videoHeight/i.actualHeight),C=-e.deltaX*h,m=-e.deltaY*E,M=v=>{window.clearTimeout(v.endTimer),v.endTimer=window.setTimeout(Or,dn)};if(C===0&&m===0){Ue.current&&M(Ue.current);return}const _=()=>({videoWidth:u.videoWidth,videoHeight:u.videoHeight,videoX:Math.abs(C)>Math.abs(m)?Math.min(Math.max(u.videoX,u.videoWidth*.2),u.videoWidth*.8):u.videoX,videoY:Math.abs(m)>=Math.abs(C)?Math.min(Math.max(u.videoY,u.videoHeight*.2),u.videoHeight*.8):u.videoY}),I=v=>({...v,videoX:Math.min(Math.max(v.videoX+C,0),v.videoWidth),videoY:Math.min(Math.max(v.videoY+m,0),v.videoHeight)});let $=Ue.current;if($)window.clearTimeout($.endTimer);else{const v=_();we(Re,"down",v),$={pos:v,endTimer:0},Ue.current=$}let ee=$.pos,V=I(ee);V.videoX===ee.videoX&&V.videoY===ee.videoY&&(we(Re,"up",ee),ee=_(),we(Re,"down",ee),V=I(ee)),we(Re,"move",V),$.pos=V,M($)};l.useEffect(()=>{nt.current={handle:fn,end:Or}}),l.useEffect(()=>{const e=de.current;if(!e)return;const o=i=>nt.current.handle(i);return e.addEventListener("wheel",o,{passive:!1}),()=>{nt.current.end(),e.removeEventListener("wheel",o)}},[]),l.useEffect(()=>{const e=n=>{n.key==="Alt"&&Bt(!0)},o=n=>{n.key==="Alt"&&Bt(!1)},i=()=>{Bt(!1)};return window.addEventListener("keydown",e,!0),window.addEventListener("keyup",o,!0),window.addEventListener("blur",i),()=>{window.removeEventListener("keydown",e,!0),window.removeEventListener("keyup",o,!0),window.removeEventListener("blur",i)}},[]);const Tt=e=>{e.preventDefault(),e.stopPropagation();const o=document.activeElement===F.current||ie&&document.activeElement===e.currentTarget;if(x("Keyboard event:",{type:e.type,key:e.key,keyCode:e.keyCode,code:e.code,target:e.target.tagName,focused:o}),!o){R("Simulator input not focused, skipping keyboard event");return}if(!P.current||P.current.readyState!=="open"){R("Data channel not ready for keyboard event:",P.current?.readyState);return}if(e.type==="keydown"){if(e.key.toLowerCase()==="v"&&(e.metaKey||e.ctrlKey)){x("Paste shortcut detected"),navigator.clipboard.readText().then(n=>{if(n){x("Pasting text via SET_CLIPBOARD:",n.substring(0,20)+(n.length>20?"...":""));const d=xn(n,!0);se(d)}}).catch(n=>{console.error("Failed to read clipboard contents: ",n)});return}if(e.key.toLowerCase()==="m"&&(e.metaKey||e.ctrlKey)){x("Menu shortcut detected");const n=lt(c.ACTION_DOWN,c.MENU,0,c.META_NONE);se(n);const d=lt(c.ACTION_UP,c.MENU,0,c.META_NONE);se(d);return}}const i=Oi(e);if(i){const{keycode:n,metaState:d}=i,u=e.type==="keydown"?c.ACTION_DOWN:c.ACTION_UP;x(`Sending Keycode: key=${e.key}, code=${n}, action=${u}, meta=${d}`);const h=lt(u,n,0,d);se(h)}else x(`Ignoring unhandled key event: type=${e.type}, key=${e.key}`)},hn=()=>{T.current&&T.current.readyState===WebSocket.OPEN&&T.current.send(JSON.stringify({type:"keepAlive",sessionId:oe}))},_r=()=>{Ye.current&&window.clearInterval(Ye.current),Ye.current=window.setInterval(hn,1e4)},Dr=()=>{Ye.current&&(window.clearInterval(Ye.current),Ye.current=void 0)},Rt=()=>{ze.current&&(window.clearTimeout(ze.current),ze.current=void 0)},wt=()=>{Qe.current&&(window.clearTimeout(Qe.current),Qe.current=void 0)},at=()=>{ht.current&&(window.clearInterval(ht.current),ht.current=void 0)},ut=()=>{Ke.current!==void 0&&(window.clearTimeout(Ke.current),Ke.current=void 0)},mn=()=>{rt.current||(rt.current=!0,at(),kt(!0),He("connected"))},J=e=>{for(const o of e.getTracks())try{o.stop()}catch(i){R("track.stop() failed:",i)}},pn=()=>{const e=Z.current;e&&(Z.current=null,J(e))},Tr=e=>{const o=ar.current.then(e).catch(i=>{R("microphone operation failed:",i)});return ar.current=o,o},qt=()=>xt.current||Ft.current,Rr=e=>{const o=`ui-mic-${Date.now()}-${Math.random().toString(36).substring(2,9)}`;Pe.current=o,e.send(JSON.stringify({type:"microphoneStart",id:o}))},Vt=()=>Tr(()=>En()),En=async()=>{const e=gt.current,o=()=>e===gt.current&&qt(),i=E=>{L("onMicrophoneStateChange",et.current,{active:!1,error:E})};if(!o())return;const n=T.current,d=tt.current;if(!n||n.readyState!==WebSocket.OPEN||!d||ce.current)return;if(!navigator.mediaDevices||typeof navigator.mediaDevices.getUserMedia!="function"){console.warn("[RemoteControl] navigator.mediaDevices.getUserMedia unavailable. getUserMedia requires a secure context (https or http://localhost)."),i("Microphone capture requires a secure context (https)");return}let u=null;try{u=await navigator.mediaDevices.getUserMedia({audio:!0,video:!1})}catch(E){console.warn("[RemoteControl] microphone getUserMedia denied/failed:",E)}if(!o()){u&&J(u);return}if(!u){i("Microphone permission denied or no device available");return}const h=u.getAudioTracks()[0]??null;if(!h){J(u),i("Captured stream has no audio track");return}try{await d.replaceTrack(h)}catch(E){R("replaceTrack(audioTrack) failed:",E),J(u),i("Failed to attach the microphone track to the connection");return}if(!o()){try{await d.replaceTrack(null)}catch(E){R("replaceTrack(null) on stale mic attach failed:",E)}J(u);return}ce.current=u,h.onended=()=>{ce.current===u&&St("microphone capture ended by the browser")},Rr(n),L("onMicrophoneStateChange",et.current,{active:!0,label:h.label||void 0})},St=e=>(++gt.current,Pe.current=null,Tr(async()=>{const o=tt.current,i=ce.current;if(ce.current=null,o&&i)try{await o.replaceTrack(null)}catch(d){R("replaceTrack(null) on mic detach failed:",d)}i&&J(i);const n=T.current;if(i&&n&&n.readyState===WebSocket.OPEN){const d=`ui-mic-${Date.now()}-${Math.random().toString(36).substring(2,9)}`;n.send(JSON.stringify({type:"microphoneStop",id:d}))}(i||e)&&L("onMicrophoneStateChange",et.current,{active:!1,...e!==void 0&&{error:e}})})),wr=(e,o)=>{let i;try{i=ii(o),console.info(`[RemoteControl] camera capture: ${i.camera?.width}x${i.camera?.height} @ ${i.camera?.frameRate??"?"}fps`+(i.camera?.label?` — ${i.camera.label}`:""))}catch(n){R("getSettings() on outbound camera track failed:",n),i={type:"cameraResult",granted:!0,camera:{label:o.label||void 0}}}e.send(JSON.stringify(i)),L("onCameraDemandChange",fe.current,!0,!0,i.camera)},gn=e=>{if(!e)return;const o=e.indexOf("/"),n=(o>=0?e.slice(o+1):e).toUpperCase();return n==="HEVC"?"H265":n},Cn=async()=>{const e=ye.current,o=pt.current;if(!e||!o)return;let i;try{i=await e.getStats()}catch{return}let n,d,u;if(i.forEach(I=>{I.type==="outbound-rtp"&&I.kind==="video"?n=I:I.type==="remote-inbound-rtp"&&I.kind==="video"&&(u=I)}),n?.codecId){const I=i.get(n.codecId);I&&(d=I.mimeType)}if(!n)return;const h=n.timestamp??Date.now(),E=Et.current;let C,m,M;if(E&&h>E.timestamp){const I=(h-E.timestamp)/1e3;if(typeof n.framesEncoded=="number"&&typeof E.framesEncoded=="number"&&(C=Math.max(0,(n.framesEncoded-E.framesEncoded)/I)),typeof n.bytesSent=="number"&&typeof E.bytesSent=="number"&&(m=Math.max(0,(n.bytesSent-E.bytesSent)*8/I)),typeof n.packetsSent=="number"&&typeof E.packetsSent=="number"&&u&&typeof u.packetsLost=="number"&&typeof E.packetsLost=="number"){const $=n.packetsSent-E.packetsSent,ee=u.packetsLost-E.packetsLost;$>0&&(M=Math.max(0,Math.min(100,ee/$*100)))}}Et.current={timestamp:h,framesEncoded:n.framesEncoded,bytesSent:n.bytesSent,packetsSent:n.packetsSent,packetsLost:u?.packetsLost};const _={codec:gn(d),encoderImplementation:n.encoderImplementation,hardwareAccelerated:typeof n.powerEfficientEncoder=="boolean"?n.powerEfficientEncoder:void 0,framesPerSecond:C,framesEncoded:n.framesEncoded,bitrateBps:m,width:n.frameWidth,height:n.frameHeight,qualityLimitationReason:n.qualityLimitationReason,rttMs:typeof u?.roundTripTime=="number"?u.roundTripTime*1e3:void 0,packetsLostPct:M};L("onCameraStats",pt.current,_)},Sr=()=>{Ze.current===null&&(Et.current=null,Ze.current=setInterval(()=>{Cn()},1e3))},At=()=>{Ze.current!==null&&(clearInterval(Ze.current),Ze.current=null),Et.current=null,L("onCameraStats",pt.current,null)},yn=(e,o,i,n)=>Lt.enqueue(async({isCurrent:d})=>{const u=()=>d()&&n()&&T.current===o&&ye.current===i;if(!u())return;if(!e.active){const _=Z.current;try{await i.replaceTrack(null)}catch(I){R("replaceTrack(null) on camera detach failed:",I)}if(Z.current===_&&(Z.current=null,ve.current=void 0,_&&J(_)),At(),!u())return;L("onCameraDemandChange",fe.current,!1);return}L("onCameraDemandChange",fe.current,!0);const h=Z.current,E=h?.getVideoTracks()[0],C=ve.current;if(E?.readyState==="live"&&C&&!ri(C,e)){ve.current=e,wr(o,E),Sr();return}if(h){try{await i.replaceTrack(null)}catch(_){R("replaceTrack(null) before camera switch failed:",_)}if(Z.current===h&&(Z.current=null,ve.current=void 0,J(h)),At(),!u())return}if(!navigator.mediaDevices||typeof navigator.mediaDevices.getUserMedia!="function"){if(console.warn("[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."),!u())return;o.send(JSON.stringify({type:"cameraResult",granted:!1})),L("onCameraDemandChange",fe.current,!0,!1);return}let m=null;try{m=await navigator.mediaDevices.getUserMedia({video:ti(e),audio:!1})}catch(_){console.warn("[RemoteControl] getUserMedia denied/failed:",_)}if(!u()){m&&J(m);return}if(!m){o.send(JSON.stringify({type:"cameraResult",granted:!1})),L("onCameraDemandChange",fe.current,!0,!1);return}const M=m.getVideoTracks()[0]??null;if(!M){if(J(m),!u())return;o.send(JSON.stringify({type:"cameraResult",granted:!1})),L("onCameraDemandChange",fe.current,!0,!1);return}try{M.contentHint="motion"}catch{}try{await i.replaceTrack(M)}catch(_){if(R("replaceTrack(videoTrack) failed:",_),J(m),!u())return;o.send(JSON.stringify({type:"cameraResult",granted:!1})),L("onCameraDemandChange",fe.current,!0,!1);return}if(!u()){try{await i.replaceTrack(null)}catch(_){R("replaceTrack(null) for stale camera attach failed:",_)}J(m);return}try{const _=i.getParameters();(!_.encodings||_.encodings.length===0)&&(_.encodings=[{}]),_.encodings[0].maxBitrate=8e6,_.encodings[0].maxFramerate=30,_.degradationPreference="maintain-framerate",await i.setParameters(_)}catch(_){R("setParameters on outbound camera failed:",_)}if(!u()){try{await i.replaceTrack(null)}catch(_){R("replaceTrack(null) for stale camera finalize failed:",_)}J(m);return}Z.current=m,ve.current=e,M.onended=()=>{Z.current===m&&Lt.enqueueCurrent(async({isCurrent:_})=>{if(!(!_()||Z.current!==m||!n()||T.current!==o||ye.current!==i)){try{await i.replaceTrack(null)}catch(I){R("replaceTrack(null) after camera ended failed:",I)}!_()||Z.current!==m||!n()||T.current!==o||ye.current!==i||(Z.current=null,ve.current=void 0,J(m),At(),o.send(JSON.stringify({type:"cameraResult",granted:!1})),L("onCameraDemandChange",fe.current,!0,!1))}}).catch(_=>R("camera ended cleanup failed:",_))},u()&&(wr(o,M),Sr())}),Ve=()=>{for(const e of Ne.current.values())clearTimeout(e.timer),e.reject(new Error("Simulator disconnected"));Ne.current.clear(),rr(null),Je.current&&(Je.current.srcObject=null),wt(),ut(),at(),G.current&&(G.current.stop(),G.current=null),Lt.invalidate(),At(),pn(),ve.current=void 0,ye.current=null,++gt.current,Ft.current=!1,Pe.current=null,ce.current&&(J(ce.current),ce.current=null,L("onMicrophoneStateChange",et.current,{active:!1})),tt.current=null,ne.current!==void 0&&(window.cancelAnimationFrame(ne.current),ne.current=void 0),T.current&&(T.current.onopen=null,T.current.onmessage=null,T.current.onerror=null,T.current.onclose=null,T.current.close(),T.current=null),W.current&&(W.current.onconnectionstatechange=null,W.current.oniceconnectionstatechange=null,W.current.ontrack=null,W.current.onicecandidate=null,W.current.close(),W.current=null),F.current&&(F.current.srcObject=null),P.current&&(P.current.onopen=null,P.current.onclose=null,P.current.onerror=null,P.current.close(),P.current=null)},Ar=()=>{document.hidden?Dr():_r()},vn=async()=>{if(typeof navigator<"u"&&navigator.onLine===!1)return!1;let e;try{const n=new URL(t);n.protocol=n.protocol==="wss:"?"https:":n.protocol==="ws:"?"http:":n.protocol,e=Yr(n.toString(),s)}catch{return!1}const o=new AbortController,i=window.setTimeout(()=>o.abort(),Ci);try{return(await fetch(e,{method:"GET",cache:"no-store",signal:o.signal})).status===404}catch{return!1}finally{window.clearTimeout(i)}},On=()=>{Ie.current||(Ie.current=!0,or(!0),ft(!1),Ce.current+=1,Rt(),wt(),ut(),Ve(),K("Instance terminated"),He("terminated"),L("onTerminated",pr.current))},_n=()=>{Ie.current||Pt.current||(Pt.current=!0,vn().then(e=>{Pt.current=!1,e&&On()}))},je=(e,o)=>{if(Ie.current||o!==Ce.current)return;if(_n(),ke.current){if(!Ut.current){K(`Connection failed after it was established: ${e}`),ft(!0),He("failed"),Ve();return}K(`Reconnecting after established session dropped: ${e}`),ke.current=!1,mt.current=-1}Rt();const i=mt.current+1;if(i>=Gt){K(`Connection failed after ${Gt} attempts: ${e}`),ft(!0),He("failed"),Ve();return}K(`Retrying connection (${i+1}/${Gt})`),He("reconnecting"),Ve(),ze.current=window.setTimeout(()=>{ze.current=void 0,o===Ce.current&&Mr(i)},pi)},Mr=async(e=0)=>{if(Ie.current)return;const o=Ce.current+1;Ce.current=o,mt.current=e,ke.current=!1,ft(!1),e===0&&Xt.current!=="reconnecting"&&He("connecting"),Rt(),wt(),at(),rt.current=!1,kt(!1),Ve();const i=()=>o===Ce.current;Qe.current=window.setTimeout(()=>{Qe.current=void 0,!(!i()||ke.current)&&je("Connection did not succeed within 15 seconds",o)},Ei);try{const n=new WebSocket(Yr(t,s));if(T.current=n,await new Promise((v,f)=>{let k=!1;const z=window.setTimeout(()=>f(new Error("WebSocket connection timeout")),3e4),S=Y=>{k||(k=!0,window.clearTimeout(z),Y())};n.onopen=()=>{!i()||T.current!==n||S(v)},n.onerror=Y=>{!i()||T.current!==n||(K("WebSocket error: "+Y),S(()=>f(new Error("WebSocket connection failed"))))},n.onclose=()=>{!i()||T.current!==n||(K("WebSocket closed"),S(()=>f(new Error("WebSocket closed before connection was established"))))}}),!i()||T.current!==n)return;n.onerror=v=>{!i()||T.current!==n||K("WebSocket error: "+v)},n.onclose=()=>{!i()||T.current!==n||K("WebSocket closed")};const d=new Promise((v,f)=>{const k=Y=>{window.clearTimeout(z),n.removeEventListener("message",S),Y()},z=window.setTimeout(()=>k(()=>f(new Error("RTCConfiguration timeout"))),3e4),S=Y=>{if(!(!i()||T.current!==n))try{const q=JSON.parse(Y.data);if(q.type==="signalingError"&&q.requestType==="requestRtcConfiguration"&&q.sessionId===oe){const te=typeof q.error=="string"?q.error:"Unable to load streaming configuration";k(()=>f(new Error(te)))}else q.type==="rtcConfiguration"&&k(()=>v({rtcConfiguration:q.rtcConfiguration,cameraSupported:q.cameraSupported===!0,foldSupported:q.foldSupported===!0}))}catch(q){console.error("Error handling RTC configuration:",q),k(()=>f(q))}};n.addEventListener("message",S),n.send(JSON.stringify({type:"requestRtcConfiguration",sessionId:oe}))}),{rtcConfiguration:u,cameraSupported:h,foldSupported:E}=await d;if(!i()||T.current!==n)return;const C=y==="iphone-duo"||E;er(C);const m=new RTCPeerConnection({...u,iceTransportPolicy:"relay"});W.current=m,m.addTransceiver("audio",{direction:"recvonly"});const M=m.addTransceiver("video",{direction:"recvonly"}),_=C?m.addTransceiver("video",{direction:"recvonly"}):null,I=ae==="ios"||h,$=I?m.addTransceiver("video",{direction:"sendonly"}):null;ye.current=$?.sender??null;const ee=I?m.addTransceiver("audio",{direction:"sendonly"}):null;if(tt.current=ee?.sender??null,RTCRtpReceiver.getCapabilities){const v=RTCRtpReceiver.getCapabilities("video");if(v&&v.codecs){const k=v.codecs.sort((z,S)=>{const Y=q=>{const te=q.mimeType.toLowerCase();return te.includes("vp9")?1:te.includes("h265")||te.includes("hevc")?2:te.includes("h264")||te.includes("avc")?3:4};return Y(z)-Y(S)});M.setCodecPreferences(k),_?.setCodecPreferences(k),x("Set codec preferences:",k.map(z=>z.mimeType).join(", "))}}if($&&RTCRtpSender.getCapabilities){const v=RTCRtpSender.getCapabilities("video");if(v&&v.codecs){const f=new Set(["42e01f","42e028","640c1f"]),k=S=>{const Y=S.mimeType.toLowerCase(),te=(S.sdpFmtpLine||"").toLowerCase().match(/profile-level-id=([0-9a-f]{6})/),Sn=te?te[1]:"";return Y==="video/h265"||Y==="video/hevc"?1:Y==="video/h264"&&f.has(Sn)?2:Y==="video/h264"?3:Y==="video/vp9"?4:Y==="video/vp8"?5:Y==="video/rtx"||Y==="video/red"||Y==="video/ulpfec"?0:6},z=[...v.codecs].sort((S,Y)=>k(S)-k(Y));try{$.setCodecPreferences(z),x("Outbound camera codec preferences:",z.map(S=>`${S.mimeType}${S.sdpFmtpLine?`[${S.sdpFmtpLine}]`:""}`).join(", "))}catch(S){R("Failed to set outbound camera codec preferences:",S)}}}const V=m.createDataChannel("control",{ordered:!0,negotiated:!0,id:1});if(P.current=V,V.onopen=()=>{if(!i()||P.current!==V||T.current!==n)return;ke.current=!0,wt(),K("Control channel opened"),C&&n.send(JSON.stringify({type:"getFoldState",id:"duo-capabilities"})),G.current||(G.current=new Qn({platform:ae,baseIntervalMs:Ae,maxBackoffMs:X,androidElementTreeOptions:ue,send:f=>{if(!T.current||T.current.readyState!==WebSocket.OPEN)return!1;try{return T.current.send(JSON.stringify(f)),!0}catch{return!1}},onSnapshot:f=>{lr(k=>zt(k,f)?k:f),queueMicrotask(()=>{L("onAxSnapshotChange",$t.current,f)})},onStatusChange:(f,k)=>{L("onAxStatusChange",mr.current,f,k)}}),(xe.current===!0||xe.current==="hover-only")&&G.current.start());const v=()=>{!i()||rt.current||P.current!==V||T.current!==n||n.readyState!==WebSocket.OPEN||n.send(JSON.stringify({type:"requestFrame",sessionId:oe}))};if(v(),at(),ht.current=window.setInterval(()=>{if(!i()||rt.current||P.current!==V||T.current!==n||n.readyState!==WebSocket.OPEN){at();return}v()},250),g){try{const f=decodeURIComponent(g);K("Opening URL"),n.send(JSON.stringify({type:"openUrl",url:f,sessionId:oe}))}catch(f){console.error({error:f},"Error decoding URL, falling back to the original URL"),n.send(JSON.stringify({type:"openUrl",url:g,sessionId:oe}))}G.current?.bumpActivity()}},V.onclose=()=>{!i()||P.current!==V||K("Control channel closed")},V.onerror=v=>{!i()||P.current!==V||(console.error("Control channel error:",v),K("Control channel error: "+v))},m.onconnectionstatechange=()=>{!i()||W.current!==m||(K("Connection state: "+m.connectionState),m.connectionState==="failed"&&je("WebRTC connection entered failed state",o))},m.oniceconnectionstatechange=()=>{if(!i()||W.current!==m)return;const v=m.iceConnectionState;if(K("ICE state: "+v),v==="connected"||v==="completed"){ut(),qt()&&!ce.current&&Vt();return}if(v==="failed"){ut(),je("ICE connection entered failed state",o);return}v==="disconnected"&&Ut.current&&Ke.current===void 0&&(Ke.current=window.setTimeout(()=>{Ke.current=void 0,!(!i()||W.current!==m)&&m.iceConnectionState==="disconnected"&&je("ICE stayed disconnected past grace period",o)},gi))},m.ontrack=v=>{if(!(!i()||W.current!==m)&&(K("Received remote track: "+v.track.kind),v.track.kind==="video"&&F.current)){x(`[${new Date().toISOString()}] Video track received:`,v.track);const k=v.track.id==="duo-inner"||v.streams.some(z=>z.id==="duo-inner")?Je.current:F.current;k&&(k.srcObject=C?new MediaStream([v.track]):v.streams[0]??new MediaStream([v.track]),k.play().catch(()=>{}))}},m.onicecandidate=v=>{if(!(!i()||W.current!==m||T.current!==n))if(v.candidate&&n.readyState===WebSocket.OPEN){const f={type:"candidate",candidate:v.candidate.candidate,sdpMid:v.candidate.sdpMid,sdpMLineIndex:v.candidate.sdpMLineIndex,sessionId:oe};n.send(JSON.stringify(f)),K("Sent ICE candidate")}else K("ICE candidate gathering completed")},n.onmessage=async v=>{if(!i()||T.current!==n)return;let f;try{f=JSON.parse(v.data)}catch(k){R("Error parsing message:",k);return}if(!G.current?.handleMessage(f))switch(K("Received: "+f.type),f.type){case"performActionsResult":case"foldStateResult":case"foldStateChanged":{if(!C)break;f.state?(rr(f.state),ir(void 0)):f.id==="duo-capabilities"&&ir(f.error||"This instance does not support native iPhone Duo displays.");const S=Ne.current.get(f.id);S&&(clearTimeout(S.timer),Ne.current.delete(f.id),f.error?S.reject(new Error(f.error)):S.resolve());break}case"signalingError":{if(f.requestType!=="offer"||f.sessionId!==oe)break;const S=typeof f.error=="string"?f.error:"Unable to establish the streaming connection";K("Error: "+S),je(S,o);break}case"answer":if(!W.current||W.current!==m){K("No peer connection, skipping answer");break}if(await m.setRemoteDescription(new RTCSessionDescription({type:"answer",sdp:f.sdp})),!i()||W.current!==m)return;K("Set remote description");break;case"candidate":if(!W.current||W.current!==m){K("No peer connection, skipping candidate");break}if(await m.addIceCandidate(new RTCIceCandidate({candidate:f.candidate,sdpMid:f.sdpMid,sdpMLineIndex:f.sdpMLineIndex})),!i()||W.current!==m)return;K("Added ICE candidate");break;case"screenshot":case"screenshotResult":{if(typeof f.id!="string"){R("Received invalid screenshot success message:",f);break}const S=Di(f);if(S){const te=he.current.get(f.id);if(!te){R(`Received screenshot error for unknown or handled id: ${f.id}`);break}R(`Received screenshot error for id ${f.id}: ${S}`),te(new Error(S)),Ee.current.delete(f.id),he.current.delete(f.id);break}const Y=Ti(f);if(!Y){R("Received screenshot message without image data:",f);break}const q=Ee.current.get(f.id);if(!q){R(`Received screenshot data for unknown or handled id: ${f.id}`);break}x(`Received screenshot data for id ${f.id}`),q(Y),Ee.current.delete(f.id),he.current.delete(f.id);break}case"screenshotError":if(typeof f.id!="string"||typeof f.message!="string"){R("Received invalid screenshot error message:",f);break}const k=he.current.get(f.id);if(!k){R(`Received screenshot error for unknown or handled id: ${f.id}`);break}R(`Received screenshot error for id ${f.id}: ${f.message}`),k(new Error(f.message)),Ee.current.delete(f.id),he.current.delete(f.id);break;case"cameraRequest":{const S=ye.current;if(!S)break;const Y=ei(f);if(!Y){R("Received invalid cameraRequest:",f);break}console.info("[RemoteControl] cameraRequest received:",Y.active,Y.facingMode),await yn(Y,n,S,i);break}case"microphoneRequest":{if(!tt.current)break;const S=f.active===!0;if(Ft.current=S,console.info("[RemoteControl] microphoneRequest received, active=",S),!S){xt.current||await St();break}if(ce.current){Rr(n);break}await Vt();break}case"microphoneStartResult":{if(Pe.current===null||f.id!==Pe.current)break;Pe.current=null,typeof f.error=="string"&&(console.warn("[RemoteControl] microphoneStart rejected by host:",f.error),St(f.error));break}case"terminateAppResult":if(typeof f.id!="string"){R("Received invalid terminateApp result message:",f);break}if(typeof f.error=="string"){const S=_e.current.get(f.id);if(!S){R(`Received terminateApp error for unknown or handled id: ${f.id}`);break}R(`Received terminateApp error for id ${f.id}: ${f.error}`),S(new Error(f.error)),Oe.current.delete(f.id),_e.current.delete(f.id);break}const z=Oe.current.get(f.id);if(!z){R(`Received terminateApp result for unknown or handled id: ${f.id}`);break}x(`Received terminateApp success for id ${f.id}`),z(),Oe.current.delete(f.id),_e.current.delete(f.id);break;default:R(`Received unhandled message type: ${f.type}`,f);break}},W.current===m){const v=await m.createOffer({offerToReceiveVideo:!0,offerToReceiveAudio:!1});if(!i()||W.current!==m||(await m.setLocalDescription(v),!i()||W.current!==m))return;i()&&T.current===n&&n.readyState===WebSocket.OPEN&&n.send(JSON.stringify({type:"offer",...C?{displayStreams:!0}:{},sdp:v.sdp,sessionId:oe})),K("Sent offer")}}catch(n){if(!i())return;const d=n instanceof Error?n.message:String(n);K("Error: "+d),je(d,o)}},jt=()=>{Ie.current=!1,or(!1),Mr(0)},Dn=()=>{Ce.current+=1,mt.current=0,ke.current=!1,Rt(),ut(),Ve(),K("Stopped")},Tn=e=>{e.stopPropagation(),jt()};l.useEffect(()=>{qt()?Vt():St()},[le]),l.useEffect(()=>(kt(!1),jt(),document.hidden||_r(),document.addEventListener("visibilitychange",Ar),()=>{Dr(),Dn(),document.removeEventListener("visibilitychange",Ar)}),[t,s,a,y]);const br=()=>{const e=ct();if(!e){dr(null);return}const o={left:e.videoRect.left-e.containerRect.left+e.offsetX,top:e.videoRect.top-e.containerRect.top+e.offsetY,width:e.actualWidth,height:e.actualHeight};dr(i=>i&&i.left===o.left&&i.top===o.top&&i.width===o.width&&i.height===o.height?i:o)};l.useEffect(()=>{const e=F.current,o=be.current,i=de.current;if(!e)return;const n=()=>{if(!Ot||!o){cr({}),br();return}const h=o.clientWidth,E=o.clientHeight;if(h===0||E===0)return;const C=e.videoWidth>e.videoHeight;jr(C),Jr(ae==="android"&&yi(e.videoWidth,e.videoHeight));const m=C?$e.videoPosition.landscape:$e.videoPosition.portrait;let M={};m.heightMultiplier?(M.height=`${E*m.heightMultiplier}px`,M.width="auto"):m.widthMultiplier&&(M.width=`${h*m.widthMultiplier}px`,M.height="auto"),M.borderRadius=`${C?E*$e.videoBorderRadiusMultiplier:h*$e.videoBorderRadiusMultiplier}px`,cr(M),br()},d=new ResizeObserver(()=>{n()});o&&d.observe(o),d.observe(e),i&&d.observe(i),o&&o.addEventListener("load",n),e.addEventListener("loadedmetadata",n),e.addEventListener("resize",n);const u=()=>G.current?.bumpActivity();return e.addEventListener("resize",u),n(),()=>{d.disconnect(),e.removeEventListener("loadedmetadata",n),e.removeEventListener("resize",n),e.removeEventListener("resize",u),o&&o.removeEventListener("load",n)}},[$e,Ot]),l.useEffect(()=>{const e=G.current;ot?e?.start():(e?.stop(),lr(null),it(null),yt(null),fr(null),Le(null),vt.current=null,ne.current!==void 0&&(window.cancelAnimationFrame(ne.current),ne.current=void 0),L("onAxSnapshotChange",$t.current,null))},[ot]),l.useEffect(()=>()=>{ne.current!==void 0&&(window.cancelAnimationFrame(ne.current),ne.current=void 0)},[]),l.useEffect(()=>{if(!ot)return;const e=o=>{o.key==="Escape"&&(Ht||Wt)&&(yt(null),it(null),Le(null),L("onInspectSelectionChange",We.current,null))};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[ot,Ht,Wt]);const Rn=()=>{F.current&&F.current.focus()};l.useImperativeHandle(Me,()=>({openUrl:e=>{if(!T.current||T.current.readyState!==WebSocket.OPEN){R("WebSocket not open, cannot send open_url command via ref.");return}try{const o=decodeURIComponent(e);K("Opening URL"),T.current.send(JSON.stringify({type:"openUrl",url:o,sessionId:oe}))}catch(o){R("Error decoding or sending URL via ref:",{error:o,url:e}),T.current.send(JSON.stringify({type:"openUrl",url:e,sessionId:oe}))}G.current?.bumpActivity()},sendKeyEvent:e=>{if(!P.current||P.current.readyState!=="open"){R("Data channel not ready for imperative key command:",P.current?.readyState);return}const o=Ur[e.code];if(!o){R(`Unknown event.code for imperative command: ${e.code}`);return}let i=c.META_NONE;e.shiftKey&&(i|=c.META_SHIFT_ON),e.altKey&&(i|=c.META_ALT_ON),e.ctrlKey&&(i|=c.META_CTRL_ON),e.metaKey&&(i|=c.META_META_ON);const n=e.type==="keydown"?c.ACTION_DOWN:c.ACTION_UP;x(`Sending Imperative Key Command: code=${e.code}, keycode=${o}, action=${n}, meta=${i}`);const d=lt(n,o,0,i);d&&se(d)},screenshot:e=>new Promise((o,i)=>{if(!T.current||T.current.readyState!==WebSocket.OPEN)return R("WebSocket not open, cannot send screenshot command."),i(new Error("WebSocket is not connected or connection is not open."));const n=`ui-ss-${Date.now()}-${Math.random().toString(36).substring(2,9)}`,d={type:e?"screenshotDisplay":"screenshot",...e?{display:e}:{},id:n};Ee.current.set(n,o),he.current.set(n,i),x("Sending screenshot request:",d);try{T.current.send(JSON.stringify(d))}catch(u){R("Failed to send screenshot request immediately:",u),Ee.current.delete(n),he.current.delete(n),i(u);return}setTimeout(()=>{Ee.current.has(n)&&(R(`Screenshot request timed out for id ${n}`),he.current.get(n)?.(new Error("Screenshot request timed out")),Ee.current.delete(n),he.current.delete(n))},3e4)}),terminateApp:e=>new Promise((o,i)=>{if(!T.current||T.current.readyState!==WebSocket.OPEN)return R("WebSocket not open, cannot send terminateApp command."),i(new Error("WebSocket is not connected or connection is not open."));const n=`ui-term-${Date.now()}-${Math.random().toString(36).substring(2,9)}`,d={type:"terminateApp",id:n,bundleId:e};Oe.current.set(n,o),_e.current.set(n,i),x("Sending terminateApp request:",d);try{T.current.send(JSON.stringify(d))}catch(u){R("Failed to send terminateApp request immediately:",u),Oe.current.delete(n),_e.current.delete(n),i(u);return}G.current?.bumpActivity(),setTimeout(()=>{Oe.current.has(n)&&(R(`terminateApp request timed out for id ${n}`),_e.current.get(n)?.(new Error("terminateApp request timed out")),Oe.current.delete(n),_e.current.delete(n))},3e4)}),reconnect:()=>jt(),refreshAxTree:async()=>{const e=G.current;if(!e)throw new Error("Inspect mode is not active");return e.refresh()},getAxSnapshot:()=>Fe.current,setInspectHighlight:e=>{it(e?.id??null)},setInspectSelection:e=>{yt(e?.id??null),Le(e?vt.current:null);const o=Fe.current;e&&o?L("onInspectSelectionChange",We.current,{element:e,snapshot:o}):L("onInspectSelectionChange",We.current,null)},getAxStatus:()=>G.current?.getStatus()??"idle"}));const wn=Qr&&Te!==null;return w.jsxs("div",{ref:de,className:Se("rc-container",r),style:{touchAction:"none"},onMouseDown:ge,onMouseMove:ge,onMouseUp:ge,onMouseLeave:ge,onTouchStart:ge,onTouchMove:ge,onTouchEnd:ge,onTouchCancel:ge,children:[wn&&Te&&w.jsxs(w.Fragment,{children:[w.jsx("div",{className:"rc-touch-indicator",style:{left:`${Te.containerX}px`,top:`${Te.containerY}px`}}),w.jsx("div",{className:"rc-touch-indicator",style:{left:`${Te.mirrorContainerX}px`,top:`${Te.mirrorContainerY}px`}})]}),Ot&&w.jsx("img",{ref:be,src:gr,alt:"",className:ae==="ios"?Se("rc-phone-frame","rc-phone-frame-ios"):"rc-phone-frame",draggable:!1}),w.jsx("video",{ref:F,className:Se("rc-video",!Ot&&"rc-video-frameless",!Br&&"rc-video-loading"),style:{...zr,...ie?{opacity:0,width:1,height:1,pointerEvents:"none"}:{},...Cr?{backgroundImage:`url("${Cr}")`,backgroundRepeat:"no-repeat",backgroundPosition:"center",backgroundSize:$e.loadingLogoSize}:{}},autoPlay:!0,playsInline:!0,muted:!0,tabIndex:ie?-1:0,onKeyDown:Tt,onKeyUp:Tt,onClick:Rn,onLoadedData:mn,onFocus:()=>{F.current&&(F.current.style.outline="none")},onBlur:()=>{F.current&&(F.current.style.outline="none")}}),ie&&w.jsx("video",{ref:Je,autoPlay:!0,playsInline:!0,muted:!0,style:{position:"absolute",width:1,height:1,opacity:0,pointerEvents:"none"}}),ie&&tr&&w.jsx(l.Suspense,{fallback:w.jsx("div",{children:"Loading iPhone Duo…"}),children:w.jsx(hi,{showFrame:p,modelUrl:O,outer:F.current,inner:Je.current,state:tr,setAngle:e=>Kt("setHingeAngle",{angleDegrees:e}),setOrientation:e=>Kt("setDuoOrientation",{orientation:e}),button:(e,o)=>Kt("performActions",{actions:[{type:o?"buttonDown":"buttonUp",button:e}]}),touch:(e,o,i,n)=>{const d=P.current;d?.readyState==="open"&&d.send(Kn(e,o,i,n))},onKeyDown:Tt,onKeyUp:Tt})}),ie&&nr&&w.jsx("div",{role:"alert",className:"rc-duo-error",children:nr}),!ie&&ot&&w.jsx(fi,{snapshot:ur,geometry:en,highlightedId:Wt,selectedId:Ht,mode:nn,cursorPosition:tn,frozenCursorPosition:rn,onSelectChange:(e,o)=>{yt(e?.id??null),e&&o?Le(o):e||Le(null);const i=Fe.current;e&&i?L("onInspectSelectionChange",We.current,{element:e,snapshot:i}):L("onInspectSelectionChange",We.current,null)},onTapElement:(e,o)=>{if(o){vr(o.x,o.y);return}const i=Fe.current;i&&on(e,i)}}),Vr?w.jsxs("div",{className:"rc-terminated",role:"status",children:[w.jsx("div",{className:"rc-terminated-title",children:"Instance terminated"}),w.jsx("div",{className:"rc-terminated-message",children:"This instance no longer exists and can't be reconnected."})]}):qr&&w.jsx("button",{type:"button",className:"rc-retry-button",onClick:Tn,children:"Retry"})]})}),Di=r=>typeof r.message=="string"?r.message:typeof r.error=="string"?r.error:null,Ti=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;exports.AX_UNAVAILABLE_ERROR=Nt;exports.DUO_BUTTONS=Pn;exports.DUO_DIMENSIONS=Mn;exports.DuoButtonSender=Un;exports.HingeSender=kn;exports.RemoteControl=_i;exports.axElementAtPoint=Hr;exports.axElementSelectorExpression=$r;exports.axElementSummary=Qt;exports.axElementsEqual=Jt;exports.axSnapshotsEqual=zt;exports.clampAxFrameForScreen=Wr;exports.duoPointerMode=Yn;exports.flatDisplayTouch=bn;exports.normalizeAndroidTree=Fr;exports.normalizeIosTree=xr;exports.panelTouch=In;
|
|
1
|
+
"use strict";require('./index.css');const w=require("react/jsx-runtime"),l=require("react"),An=require("react-dom");function Pr(r){var t,s,a="";if(typeof r=="string"||typeof r=="number")a+=r;else if(typeof r=="object")if(Array.isArray(r)){var g=r.length;for(t=0;t<g;t++)r[t]&&(s=Pr(r[t]))&&(a&&(a+=" "),a+=s)}else for(s in r)r[s]&&(a&&(a+=" "),a+=s);return a}function Ae(){for(var r,t,s=0,a="",g=arguments.length;s<g;s++)(r=arguments[s])&&(t=Pr(r))&&(a&&(a+=" "),a+=t);return a}const Mn={width:164.6,height:117.8,depth:5.2};function bn(r,t,s){return r=Math.max(0,Math.min(1,r)),t=Math.max(0,Math.min(1,t)),s===1?{x:t,y:1-r}:s===2?{x:1-r,y:1-t}:s===3?{x:1-t,y:r}:{x:r,y:t}}function Nn(r){return Number.isFinite(r)&&r>=0&&r<=180}function In(r,t){return{x:Math.max(0,Math.min(1,r)),y:Math.max(0,Math.min(1,1-t))}}function Yn(r,t,s){return t&&(r||!s)?"touch":r?"ignore":"orbit"}function Kn(r,t,s,a){if(!Number.isInteger(r)||r<0||r>3||!Number.isInteger(t)||t<1||t>255||!Number.isFinite(s)||!Number.isFinite(a)||s<0||s>1||a<0||a>1)throw new RangeError("Invalid display touch coordinates");const g=new ArrayBuffer(12),p=new DataView(g);return p.setUint8(0,19),p.setUint8(1,r),p.setUint8(2,t),p.setFloat32(4,s,!0),p.setFloat32(8,a,!0),g}class kn{constructor(t,s){this.send=t,this.failed=s}send;failed;latest;running=!1;stopped=!1;set(t){this.stopped||!Nn(t)||(this.latest=t,this.flush())}stop(){this.stopped=!0,this.latest=void 0}async flush(){if(!(this.running||this.stopped)){this.running=!0;try{for(;this.latest!==void 0&&!this.stopped;){const t=this.latest;this.latest=void 0,await this.send(t)}}catch(t){this.latest=void 0,this.stopped||this.failed(t)}finally{this.running=!1}}}}const Pn={side:"Sleep/Wake",volumeUp:"Volume Up",volumeDown:"Volume Down"};class Un{constructor(t,s){this.send=t,this.failed=s}send;failed;held;tail=Promise.resolve();timeout;press(t){this.held||(this.held=t,this.enqueue(t,!0),this.timeout=setTimeout(()=>this.release(),1e4))}release(){if(!this.held)return;clearTimeout(this.timeout);const t=this.held;this.held=void 0,this.enqueue(t,!1)}enqueue(t,s){this.tail=this.tail.then(()=>this.send(t,s)).catch(this.failed)}}const Yt={INJECT_KEYCODE:0,INJECT_TOUCH_EVENT:2,INJECT_TWO_FINGER_TOUCH_EVENT:18,SET_CLIPBOARD:9},U={ACTION_DOWN:0,ACTION_UP:1,ACTION_MOVE:2,ACTION_CANCEL:3,ACTION_POINTER_DOWN:5,ACTION_POINTER_UP:6,BUTTON_PRIMARY:1,BUTTON_SECONDARY:2,BUTTON_TERTIARY:4},c={ACTION_DOWN:0,ACTION_UP:1,META_NONE:0,META_SHIFT_ON:1,META_ALT_ON:2,META_CTRL_ON:4096,META_META_ON:65536,KEYCODE_0:7,KEYCODE_1:8,KEYCODE_2:9,KEYCODE_3:10,KEYCODE_4:11,KEYCODE_5:12,KEYCODE_6:13,KEYCODE_7:14,KEYCODE_8:15,KEYCODE_9:16,DPAD_UP:19,DPAD_DOWN:20,DPAD_LEFT:21,DPAD_RIGHT:22,KEYCODE_A:29,KEYCODE_B:30,KEYCODE_C:31,KEYCODE_D:32,KEYCODE_E:33,KEYCODE_F:34,KEYCODE_G:35,KEYCODE_H:36,KEYCODE_I:37,KEYCODE_J:38,KEYCODE_K:39,KEYCODE_L:40,KEYCODE_M:41,KEYCODE_N:42,KEYCODE_O:43,KEYCODE_P:44,KEYCODE_Q:45,KEYCODE_R:46,KEYCODE_S:47,KEYCODE_T:48,KEYCODE_U:49,KEYCODE_V:50,KEYCODE_W:51,KEYCODE_X:52,KEYCODE_Y:53,KEYCODE_Z:54,KEYCODE_COMMA:55,KEYCODE_PERIOD:56,KEYCODE_ALT_LEFT:57,KEYCODE_ALT_RIGHT:58,KEYCODE_SHIFT_LEFT:59,KEYCODE_SHIFT_RIGHT:60,KEYCODE_TAB:61,KEYCODE_SPACE:62,ENTER:66,DEL:67,KEYCODE_GRAVE:68,KEYCODE_MINUS:69,KEYCODE_EQUALS:70,KEYCODE_LEFT_BRACKET:71,KEYCODE_RIGHT_BRACKET:72,KEYCODE_BACKSLASH:73,KEYCODE_SEMICOLON:74,KEYCODE_APOSTROPHE:75,KEYCODE_SLASH:76,MENU:82,KEYCODE_PAGE_UP:92,KEYCODE_PAGE_DOWN:93,KEYCODE_ESCAPE:111,FORWARD_DEL:112,KEYCODE_CTRL_LEFT:113,KEYCODE_CTRL_RIGHT:114,KEYCODE_META_LEFT:117,KEYCODE_META_RIGHT:118,KEYCODE_MOVE_HOME:122,KEYCODE_MOVE_END:123,KEYCODE_INSERT:124,KEYCODE_F1:131,KEYCODE_F2:132,KEYCODE_F3:133,KEYCODE_F4:134,KEYCODE_F5:135,KEYCODE_F6:136,KEYCODE_F7:137,KEYCODE_F8:138,KEYCODE_F9:139,KEYCODE_F10:140,KEYCODE_F11:141,KEYCODE_F12:142,KEYCODE_NUMPAD_0:144,KEYCODE_NUMPAD_1:145,KEYCODE_NUMPAD_2:146,KEYCODE_NUMPAD_3:147,KEYCODE_NUMPAD_4:148,KEYCODE_NUMPAD_5:149,KEYCODE_NUMPAD_6:150,KEYCODE_NUMPAD_7:151,KEYCODE_NUMPAD_8:152,KEYCODE_NUMPAD_9:153,KEYCODE_NUMPAD_DIVIDE:154,KEYCODE_NUMPAD_MULTIPLY:155,KEYCODE_NUMPAD_SUBTRACT:156,KEYCODE_NUMPAD_ADD:157,KEYCODE_NUMPAD_DOT:158,KEYCODE_NUMPAD_COMMA:159,KEYCODE_NUMPAD_ENTER:160,KEYCODE_NUMPAD_EQUALS:161},Ur={KeyA:c.KEYCODE_A,KeyB:c.KEYCODE_B,KeyC:c.KEYCODE_C,KeyD:c.KEYCODE_D,KeyE:c.KEYCODE_E,KeyF:c.KEYCODE_F,KeyG:c.KEYCODE_G,KeyH:c.KEYCODE_H,KeyI:c.KEYCODE_I,KeyJ:c.KEYCODE_J,KeyK:c.KEYCODE_K,KeyL:c.KEYCODE_L,KeyM:c.KEYCODE_M,KeyN:c.KEYCODE_N,KeyO:c.KEYCODE_O,KeyP:c.KEYCODE_P,KeyQ:c.KEYCODE_Q,KeyR:c.KEYCODE_R,KeyS:c.KEYCODE_S,KeyT:c.KEYCODE_T,KeyU:c.KEYCODE_U,KeyV:c.KEYCODE_V,KeyW:c.KEYCODE_W,KeyX:c.KEYCODE_X,KeyY:c.KEYCODE_Y,KeyZ:c.KEYCODE_Z,Digit0:c.KEYCODE_0,Digit1:c.KEYCODE_1,Digit2:c.KEYCODE_2,Digit3:c.KEYCODE_3,Digit4:c.KEYCODE_4,Digit5:c.KEYCODE_5,Digit6:c.KEYCODE_6,Digit7:c.KEYCODE_7,Digit8:c.KEYCODE_8,Digit9:c.KEYCODE_9,Backquote:c.KEYCODE_GRAVE,Minus:c.KEYCODE_MINUS,Equal:c.KEYCODE_EQUALS,BracketLeft:c.KEYCODE_LEFT_BRACKET,BracketRight:c.KEYCODE_RIGHT_BRACKET,Backslash:c.KEYCODE_BACKSLASH,Semicolon:c.KEYCODE_SEMICOLON,Quote:c.KEYCODE_APOSTROPHE,Comma:c.KEYCODE_COMMA,Period:c.KEYCODE_PERIOD,Slash:c.KEYCODE_SLASH,Space:c.KEYCODE_SPACE,Tab:c.KEYCODE_TAB,Escape:c.KEYCODE_ESCAPE,ArrowUp:c.DPAD_UP,ArrowDown:c.DPAD_DOWN,ArrowLeft:c.DPAD_LEFT,ArrowRight:c.DPAD_RIGHT,Enter:c.ENTER,Backspace:c.DEL,Delete:c.FORWARD_DEL,Home:c.KEYCODE_MOVE_HOME,End:c.KEYCODE_MOVE_END,PageUp:c.KEYCODE_PAGE_UP,PageDown:c.KEYCODE_PAGE_DOWN,Insert:c.KEYCODE_INSERT,F1:c.KEYCODE_F1,F2:c.KEYCODE_F2,F3:c.KEYCODE_F3,F4:c.KEYCODE_F4,F5:c.KEYCODE_F5,F6:c.KEYCODE_F6,F7:c.KEYCODE_F7,F8:c.KEYCODE_F8,F9:c.KEYCODE_F9,F10:c.KEYCODE_F10,F11:c.KEYCODE_F11,F12:c.KEYCODE_F12,ShiftLeft:c.KEYCODE_SHIFT_LEFT,ShiftRight:c.KEYCODE_SHIFT_RIGHT,ControlLeft:c.KEYCODE_CTRL_LEFT,ControlRight:c.KEYCODE_CTRL_RIGHT,AltLeft:c.KEYCODE_ALT_LEFT,AltRight:c.KEYCODE_ALT_RIGHT,MetaLeft:c.KEYCODE_META_LEFT,MetaRight:c.KEYCODE_META_RIGHT,ContextMenu:c.MENU,Numpad0:c.KEYCODE_NUMPAD_0,Numpad1:c.KEYCODE_NUMPAD_1,Numpad2:c.KEYCODE_NUMPAD_2,Numpad3:c.KEYCODE_NUMPAD_3,Numpad4:c.KEYCODE_NUMPAD_4,Numpad5:c.KEYCODE_NUMPAD_5,Numpad6:c.KEYCODE_NUMPAD_6,Numpad7:c.KEYCODE_NUMPAD_7,Numpad8:c.KEYCODE_NUMPAD_8,Numpad9:c.KEYCODE_NUMPAD_9,NumpadDivide:c.KEYCODE_NUMPAD_DIVIDE,NumpadMultiply:c.KEYCODE_NUMPAD_MULTIPLY,NumpadSubtract:c.KEYCODE_NUMPAD_SUBTRACT,NumpadAdd:c.KEYCODE_NUMPAD_ADD,NumpadDecimal:c.KEYCODE_NUMPAD_DOT,NumpadComma:c.KEYCODE_NUMPAD_COMMA,NumpadEnter:c.KEYCODE_NUMPAD_ENTER,NumpadEqual:c.KEYCODE_NUMPAD_EQUALS};function Mt(r,t,s,a,g,p,y=1,O=0,b=0){const D=new ArrayBuffer(32),N=new DataView(D);let A=0;return N.setUint8(A,Yt.INJECT_TOUCH_EVENT),A+=1,N.setUint8(A,r),A+=1,N.setBigInt64(A,BigInt(t),!0),A+=8,N.setInt32(A,Math.round(g),!0),A+=4,N.setInt32(A,Math.round(p),!0),A+=4,N.setUint16(A,s,!0),A+=2,N.setUint16(A,a,!0),A+=2,N.setInt16(A,Math.round(y*65535),!0),A+=2,N.setInt32(A,O,!0),A+=4,N.setInt32(A,b,!0),D}function Ln(r,t,s,a,g,p,y){const O=new ArrayBuffer(24),b=new DataView(O);let D=0;return b.setUint8(D,Yt.INJECT_TWO_FINGER_TOUCH_EVENT),D+=1,b.setUint8(D,r),D+=1,b.setInt32(D,Math.round(a),!0),D+=4,b.setInt32(D,Math.round(g),!0),D+=4,b.setInt32(D,Math.round(p),!0),D+=4,b.setInt32(D,Math.round(y),!0),D+=4,b.setUint16(D,t,!0),D+=2,b.setUint16(D,s,!0),D+=2,b.setUint16(D,0,!0),O}function xn(r,t=!0){const a=new TextEncoder().encode(r),g=new ArrayBuffer(14+a.length),p=new DataView(g);let y=0;return p.setUint8(y,Yt.SET_CLIPBOARD),y+=1,p.setBigInt64(y,BigInt(0),!1),y+=8,p.setUint8(y,t?1:0),y+=1,p.setUint32(y,a.length,!1),y+=4,new Uint8Array(g,y).set(a),g}function lt(r,t,s=0,a=0){const g=new ArrayBuffer(14),p=new DataView(g);let y=0;return p.setUint8(y,Yt.INJECT_KEYCODE),y+=1,p.setUint8(y,r),y+=1,p.setInt32(y,t,!0),y+=4,p.setInt32(y,s,!0),y+=4,p.setInt32(y,a,!0),g}const Nt="Accessibility unavailable on this device.",It=500,Lr=(r,t)=>Math.abs(r.x-t.x)<.5&&Math.abs(r.y-t.y)<.5&&Math.abs(r.width-t.width)<.5&&Math.abs(r.height-t.height)<.5,Fn=r=>Math.max(0,r.width)*Math.max(0,r.height),Wn=r=>{const t=r.find(s=>s.frame&&s.frame.width>0&&s.frame.height>0);return t?.frame?((Math.abs(t.frame.x)>.5||Math.abs(t.frame.y)>.5)&&console.warn(`[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.`),{x:0,y:0,width:t.frame.width,height:t.frame.height}):{x:0,y:0,width:1,height:1}},Hn=r=>{const t={};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},$n=r=>{const t={};for(const[s,a]of Object.entries(r))s!=="children"&&(t[s]=a);return t};function xr(r){const t=Array.isArray(r)?r:[r],s=Wn(t),a=[],g=(p,y)=>{if(a.length>=It)return;const O=p.frame;if(O&&O.width>0&&O.height>0&&!Lr(O,s)){const D=p.role_description||p.role||"",N=(typeof p.AXLabel=="string"?p.AXLabel:"")||(typeof p.title=="string"?p.title:"")||"";a.push({id:typeof p.AXUniqueId=="string"&&p.AXUniqueId.length>0?p.AXUniqueId:y,path:y,label:N,value:typeof p.AXValue=="string"?p.AXValue:"",role:D,type:typeof p.type=="string"?p.type:"",enabled:p.enabled!==!1,focused:p.focused===!0,frame:{x:O.x,y:O.y,width:O.width,height:O.height},selectors:Hn(p),raw:$n(p)})}const b=Array.isArray(p.children)?p.children:[];for(let D=0;D<b.length&&a.length<It;D++)g(b[D],`${y}.${D}`)};for(let p=0;p<t.length&&a.length<It;p++)g(t[p],String(p));return{platform:"ios",screen:{width:s.width,height:s.height},elements:a,capturedAt:Date.now()}}const Xn=r=>{let t={x:0,y:0,width:1,height:1},s=0;for(const a of r){const g=a.parsedBounds;if(!g)continue;const p=g.right-g.left,y=g.bottom-g.top,O=Math.max(0,p)*Math.max(0,y);O>s&&(s=O,t={x:0,y:0,width:p,height:y})}return t},Bn=r=>{const t={};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};function Fr(r){const t=Xn(r),s=[];for(let a=0;a<r.length&&s.length<It;a++){const g=r[a],p=g.parsedBounds;if(!p)continue;const y=Math.max(0,p.right-p.left),O=Math.max(0,p.bottom-p.top);if(y<=0||O<=0)continue;const b={x:p.left,y:p.top,width:y,height:O};if(Lr(b,{x:0,y:0,width:t.width,height:t.height}))continue;const D=g.contentDesc||g.text||"",N=g.className||"";s.push({id:g.resourceId&&g.resourceId.length>0?g.resourceId:g.contentDesc&&g.contentDesc.length>0?`cd:${g.contentDesc}`:String(a),path:String(a),label:D,value:typeof g.text=="string"?g.text:"",role:N,type:N,enabled:g.enabled!==!1,focused:g.focused===!0,frame:b,selectors:Bn(g),raw:{...g}})}return{platform:"android",screen:{width:t.width,height:t.height},elements:s,capturedAt:Date.now()}}function Wr(r,t){const s=Math.max(0,r.x),a=Math.max(0,r.y),g=Math.min(t.width,r.x+r.width),p=Math.min(t.height,r.y+r.height),y=Math.max(0,g-s),O=Math.max(0,p-a);return y>0&&O>0?{x:s,y:a,width:y,height:O}:null}function Jt(r,t){if(r===t)return!0;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;const s=r.frame,a=t.frame;return s.x===a.x&&s.y===a.y&&s.width===a.width&&s.height===a.height}function zt(r,t){if(r===t)return!0;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;for(let s=0;s<r.elements.length;s++)if(!Jt(r.elements[s],t.elements[s]))return!1;return!0}function Hr(r,t,s){let a=null,g=1/0;for(const p of r.elements){const y=p.frame;if(t<y.x||s<y.y||t>y.x+y.width||s>y.y+y.height)continue;const O=Fn(y);O<g&&(g=O,a=p)}return a}function $r(r,t){if(t==="ios"){if(r.selectors.AXUniqueId)return`client.tapElement({ AXUniqueId: ${JSON.stringify(r.selectors.AXUniqueId)} })`;if(r.selectors.AXLabel){const s=r.selectors.className?`, type: ${JSON.stringify(r.selectors.className)}`:"";return`client.tapElement({ AXLabel: ${JSON.stringify(r.selectors.AXLabel)}${s} })`}return null}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}function Xr(r){const t=r.role||r.type||"";if(!t)return"element";let s=t.replace(/^AX/,"");return s.includes(".")&&(s=s.split(".").pop()),s==="GenericElement"?"Element":(s=s.replace(/([a-z])([A-Z])/g,"$1 $2"),s)}const Nr=80;function Qt(r){const t=Xr(r),s=r.label||r.value||"";if(!s)return t;const a=s.length>Nr?s.slice(0,Nr).trimEnd()+"…":s;return`${t} · ${a}`}const qn=500,Vn=2e3,Ir=5e3,jn=8e3,Gn=1200,Jn=250,zn=()=>`ax-rc-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;class Qn{platform;send;onSnapshot;onStatusChange;baseIntervalMs;maxBackoffMs;androidElementTreeOptions;pending=new Map;running=!1;timer;currentInterval;lastSnapshot=null;inflight=!1;lastBumpAtMs=0;boostUntilMs=0;status="idle";constructor(t){this.platform=t.platform,this.send=t.send,this.onSnapshot=t.onSnapshot,this.onStatusChange=t.onStatusChange,this.baseIntervalMs=t.baseIntervalMs??qn,this.maxBackoffMs=t.maxBackoffMs??Vn,this.androidElementTreeOptions=t.androidElementTreeOptions,this.currentInterval=this.baseIntervalMs}start(){this.running||(this.running=!0,this.currentInterval=this.baseIntervalMs,this.boostUntilMs=0,this.setStatus("starting"),this.runOnce())}stop(){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))}getStatus(){return this.status}setStatus(t,s){if(this.status!==t&&(this.status=t,!!this.onStatusChange))try{this.onStatusChange(t,s)}catch(a){console.error("[AxFetcher] onStatusChange threw:",a)}}bumpActivity(){if(!this.running)return;const t=Date.now();this.boostUntilMs=t+Gn;const s=Math.max(150,Math.floor(this.baseIntervalMs/2));if(t-this.lastBumpAtMs<s){this.currentInterval=this.baseIntervalMs;return}this.lastBumpAtMs=t,this.currentInterval=this.baseIntervalMs,this.timer!==void 0&&(window.clearTimeout(this.timer),this.timer=void 0),this.inflight||this.runOnce()}async refresh(){const t=await this.requestOnce();return this.running&&this.deliver(t),t}getLatest(){return this.lastSnapshot}handleMessage(t){if(!t||typeof t.id!="string")return!1;const s=t.id;if(!this.pending.get(s))return!1;if(this.platform==="ios"){if(t.type!=="elementTreeResult")return!1;const O=typeof t.error=="string"?t.error:null;if(O)return this.settleReject(s,new Error(O)),!0;const b=typeof t.json=="string"?t.json:"";try{const D=JSON.parse(b),N=xr(D);this.settleResolve(s,N)}catch(D){this.settleReject(s,D instanceof Error?D:new Error(String(D)))}return!0}if(t.type!=="getElementTreeResult")return!1;const g=t.error;if(g&&typeof g=="object"){const O=typeof g.message=="string"?g.message:"getElementTree failed";return this.settleReject(s,new Error(O)),!0}const p=t.payload,y=Array.isArray(p?.nodes)?p.nodes:[];try{const O=Fr(y);this.settleResolve(s,O)}catch(O){this.settleReject(s,O instanceof Error?O:new Error(String(O)))}return!0}buildRequest(t){return this.platform==="ios"?{type:"elementTree",id:t}:{type:"getElementTree",id:t,...this.androidElementTreeOptions}}async requestOnce(){const t=zn();return new Promise((s,a)=>{const g=window.setTimeout(()=>{this.pending.delete(t),a(new Error("elementTree request timed out"))},jn+(this.androidElementTreeOptions?.waitForIdleTimeoutMs??0));this.pending.set(t,{resolve:s,reject:a,timer:g}),this.send(this.buildRequest(t))||(window.clearTimeout(g),this.pending.delete(t),a(new Error("elementTree send failed (WebSocket not open)")))})}async runOnce(){if(this.running&&!this.inflight){this.inflight=!0;try{const t=await this.requestOnce();if(!this.running)return;this.deliver(t)}catch(t){if(!this.running)return;const s=t instanceof Error?t.message:String(t),a=/unavailable|not (yet )?running|failed|timeout/i.test(s);this.currentInterval=a?Ir:Math.min(this.currentInterval*2,this.maxBackoffMs),this.setStatus(a?"unavailable":"error",s)}finally{this.inflight=!1,this.scheduleNext()}}}deliver(t){const s=this.lastSnapshot;if(zt(s,t)){this.currentInterval=Math.min(this.currentInterval*2,this.maxBackoffMs),this.lastSnapshot=t,t.errors?.includes(Nt)||this.setStatus("ready");return}this.lastSnapshot=t,this.currentInterval=this.baseIntervalMs,t.errors?.includes(Nt)?(this.currentInterval=Ir,this.setStatus("unavailable",Nt)):this.setStatus("ready"),this.onSnapshot(t)}scheduleNext(){if(!this.running)return;this.timer!==void 0&&window.clearTimeout(this.timer);const t=Date.now()<this.boostUntilMs?Math.min(Jn,this.currentInterval):this.currentInterval;this.timer=window.setTimeout(()=>{this.timer=void 0,this.runOnce()},t)}settleResolve(t,s){const a=this.pending.get(t);a&&(window.clearTimeout(a.timer),this.pending.delete(t),a.resolve(s))}settleReject(t,s){const a=this.pending.get(t);a&&(window.clearTimeout(a.timer),this.pending.delete(t),a.reject(s))}failAllPending(t){for(const[s,a]of this.pending.entries())window.clearTimeout(a.timer),a.reject(new Error(t)),this.pending.delete(s)}}class Zn{generation=0;tail=Promise.resolve();get currentGeneration(){return this.generation}enqueue(t){const s=++this.generation;return this.append(s,t)}enqueueCurrent(t){return this.append(this.generation,t)}append(t,s){const a={generation:t,isCurrent:()=>t===this.generation},g=this.tail.then(()=>s(a));return this.tail=g.catch(()=>{}),g}invalidate(){++this.generation}}function ei(r){if(!r||typeof r!="object")return null;const t=r;if(t.type!=="cameraRequest"||typeof t.active!="boolean")return null;const s={active:t.active};return(t.facingMode==="user"||t.facingMode==="environment")&&(s.facingMode=t.facingMode),s}function ti(r){const t={frameRate:{ideal:30,max:30}};return r?.facingMode&&(t.facingMode={ideal:r.facingMode}),t}function ri(r,t){return!r||r.facingMode!==t.facingMode}function ni(r){const t=r.getSettings();return{width:t.width,height:t.height,frameRate:t.frameRate,deviceId:t.deviceId,label:r.label||void 0,facingMode:t.facingMode}}function ii(r){return{type:"cameraResult",granted:!0,camera:ni(r)}}const oi=async r=>{if(!r)return!1;try{if(typeof navigator<"u"&&navigator.clipboard?.writeText)return await navigator.clipboard.writeText(r),!0}catch{}try{const t=document.createElement("textarea");t.value=r,t.style.position="fixed",t.style.opacity="0",document.body.appendChild(t),t.select();const s=document.execCommand("copy");return document.body.removeChild(t),s}catch{return!1}},si=l.memo(function({element:t,screen:s,highlighted:a,selected:g,selectable:p,onClick:y}){const O=Wr(t.frame,s);if(!O)return null;const b=Qt(t);return w.jsx("button",{type:"button",className:Ae("rc-inspect-box",!t.enabled&&"rc-inspect-box-disabled"),"data-ax-id":t.id,"data-ax-path":t.path,"data-ax-label":t.label||void 0,"data-ax-role":t.role||void 0,"data-highlighted":a?"true":"false","data-selected":g?"true":"false","aria-label":b,onClick:D=>{p&&(D.preventDefault(),D.stopPropagation(),y(t,{x:D.clientX,y:D.clientY}))},style:{left:`${O.x/s.width*100}%`,top:`${O.y/s.height*100}%`,width:`${O.width/s.width*100}%`,height:`${O.height/s.height*100}%`}})},(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&&Jt(r.element,t.element)),ci=260,ai=220,ui=6,li=8,di=l.memo(function({element:t,platform:s,anchor:a,cursorAnchored:g,showActions:p,onTap:y}){const[O,b]=l.useState(null);l.useEffect(()=>{if(!O)return;const X=window.setTimeout(()=>b(null),1100);return()=>window.clearTimeout(X)},[O]);const D=l.useMemo(()=>{const X=ci,ue=ai,re=ui,H=li,le=typeof window<"u"?window.innerWidth:1024,dt=typeof window<"u"?window.innerHeight:768,be=a.x+re+X<=le-H,de=a.y-re-ue>=H;let F=be?a.x+re:a.x-re,Ne=de?a.y-re:a.y+re;const ie=`translate(${be?"0":"-100%"}, ${de?"-100%":"0"})`;return F=Math.max(H+(be?0:X),Math.min(le-H-(be?X:0),F)),Ne=Math.max(H+(de?ue:0),Math.min(dt-H-(de?0:ue),Ne)),{left:`${F}px`,top:`${Ne}px`,transform:ie}},[a.x,a.y]),N=l.useMemo(()=>$r(t,s),[t,s]),A=s==="ios"?t.selectors.AXUniqueId:t.selectors.resourceId,Q=s==="ios"?"AXUniqueId":"resourceId",pe=l.useCallback(async(X,ue)=>{if(!X)return;await oi(X)&&b(ue)},[]),Ee=Xr(t),Ge=t.label||t.value||Ee,Me=Qt(t);return An.createPortal(w.jsxs("div",{className:"rc-inspect-card","data-cursor-anchored":g?"true":"false",style:D,onClick:X=>X.stopPropagation(),onMouseDown:X=>X.stopPropagation(),onMouseMove:X=>X.stopPropagation(),children:[w.jsxs("div",{className:"rc-inspect-card-header",children:[w.jsx("span",{className:"rc-inspect-card-role",children:Ee}),!t.enabled&&w.jsx("span",{className:"rc-inspect-card-tag",children:"disabled"}),t.focused&&w.jsx("span",{className:"rc-inspect-card-tag rc-inspect-card-tag-blue",children:"focused"})]}),w.jsx("p",{className:"rc-inspect-card-title",title:Me,children:Ge}),A&&w.jsxs("div",{className:"rc-inspect-card-row",children:[w.jsxs("span",{className:"rc-inspect-card-row-label",children:[Q,":"]}),w.jsx("span",{className:"rc-inspect-card-row-value",children:A})]}),t.value&&t.value!==t.label&&w.jsxs("div",{className:"rc-inspect-card-row",children:[w.jsx("span",{className:"rc-inspect-card-row-label",children:"value:"}),w.jsx("span",{className:"rc-inspect-card-row-value",children:t.value})]}),w.jsxs("div",{className:"rc-inspect-card-row",children:[w.jsx("span",{className:"rc-inspect-card-row-label",children:"frame:"}),w.jsxs("span",{className:"rc-inspect-card-row-value",children:[Math.round(t.frame.width),"×",Math.round(t.frame.height)," @ ",Math.round(t.frame.x),",",Math.round(t.frame.y)]})]}),p&&w.jsxs("div",{className:"rc-inspect-card-actions",children:[w.jsx("button",{type:"button",className:"rc-inspect-card-btn rc-inspect-card-btn-primary",onClick:()=>y(t,a),children:"Tap"}),w.jsx("button",{type:"button",className:Ae("rc-inspect-card-btn",O==="selector"&&"rc-inspect-card-btn-copied"),disabled:!N,title:N??"No usable selector for this element",onClick:()=>pe(N??void 0,"selector"),children:O==="selector"?"Copied!":"Copy selector"}),w.jsx("button",{type:"button",className:Ae("rc-inspect-card-btn",O==="id"&&"rc-inspect-card-btn-copied"),disabled:!A,title:A??`No ${Q}`,onClick:()=>pe(A,"id"),children:O==="id"?"Copied!":`Copy ${Q}`})]})]}),document.body)}),fi=l.memo(function({snapshot:t,geometry:s,highlightedId:a,selectedId:g,mode:p,cursorPosition:y,frozenCursorPosition:O,onSelectChange:b,onTapElement:D}){const N=p==="select",A=N?a!==null&&a!==g:a!==null,Q=N?a??g:a,pe=l.useMemo(()=>{const H=new Map;if(!t)return H;for(const le of t.elements)H.set(le.id,le);return H},[t]),Ee=l.useMemo(()=>Q?pe.get(Q)??null:null,[Q,pe]);if(!(!!t&&!!s&&t.screen.width>0&&t.screen.height>0&&t.elements.length>0))return null;const Me=A?y:O??y,X=A,ue=N&&!A&&g!==null,re=H=>{N&&H.target===H.currentTarget&&b(null,null)};return w.jsxs(w.Fragment,{children:[w.jsx("div",{className:Ae("rc-inspect-overlay",N&&"rc-inspect-overlay-select"),style:{left:`${s.left}px`,top:`${s.top}px`,width:`${s.width}px`,height:`${s.height}px`},onClick:re,children:t.elements.map(H=>w.jsx(si,{element:H,screen:t.screen,highlighted:H.id===a,selected:H.id===g,selectable:N,onClick:b},H.id))}),Ee&&Me&&w.jsx(di,{element:Ee,platform:t.platform,anchor:Me,cursorAnchored:X,showActions:ue,onTap:D})]})}),hi=l.lazy(()=>Promise.resolve().then(()=>require("./duo-view--EopHG5S.js")).then(r=>r.duoView)),x=(...r)=>{window.debugRemoteControl&&console.log(...r)},R=(...r)=>{window.debugRemoteControl&&console.warn(...r)},L=(r,t,...s)=>{if(t)try{t(...s)}catch(a){console.error(`[RemoteControl] customer callback "${r}" threw:`,a)}},bt=r=>Object.entries(U).find(([s,a])=>s.startsWith("ACTION_")&&a===r)?.[0]??String(r),mi=r=>r.includes("/android_")?"android":"ios",Yr=(r,t)=>{const s=new URL(r);return s.searchParams.set("token",t),s.toString()},Kr=1920,kr=1200,Gt=3,pi=1e3,Ei=15e3,gi=3e3,Ci=4e3,yi=(r,t)=>r===Kr&&t===kr||r===kr&&t===Kr,vi={ios:{videoBorderRadiusMultiplier:.15,loadingLogoSize:"20%",videoPosition:{portrait:{heightMultiplier:.9678},landscape:{widthMultiplier:.9678}}},android:{videoBorderRadiusMultiplier:.13,loadingLogoSize:"40%",videoPosition:{portrait:{heightMultiplier:.967},landscape:{widthMultiplier:.962}}}};function Oi(r){const t=r.code,s=Ur[t];if(!s)return R(`Unknown event.code: ${t}, key: ${r.key}`),null;let a=c.META_NONE;const g=t>="KeyA"&&t<="KeyZ",p=r.getModifierState("CapsLock"),y=r.shiftKey;let O=y;return g&&(O=y!==p),O&&(a|=c.META_SHIFT_ON),r.ctrlKey&&(a|=c.META_CTRL_ON),r.altKey&&(a|=c.META_ALT_ON),r.metaKey&&(a|=c.META_META_ON),{keycode:s,metaState:a}}const _i=l.forwardRef(({className:r,url:t,token:s,sessionId:a,openUrl:g,showFrame:p=!0,deviceModel:y,duoModelUrl:O,autoReconnect:b=!1,onTerminated:D,assets:N,onConnectionStateChange:A,inspectMode:Q,onAxSnapshotChange:pe,onInspectSelectionChange:Ee,onAxStatusChange:Ge,axPollIntervalMs:Me,axMaxBackoffMs:X,androidElementTreeOptions:ue,onCameraDemandChange:re,onCameraStats:H,microphoneEnabled:le=!1,onMicrophoneStateChange:dt},be)=>{const de=l.useRef(null),F=l.useRef(null),Ne=l.useRef(null),[Zt,er]=l.useState(!1),ie=y==="iphone-duo"||Zt,Je=l.useRef(null),[tr,rr]=l.useState(null),[nr,ir]=l.useState(),Ie=l.useRef(new Map),Kt=(e,o)=>new Promise((i,n)=>{const d=T.current;if(!d||d.readyState!==WebSocket.OPEN){n(new Error("Simulator disconnected"));return}const u=crypto.randomUUID(),h=setTimeout(()=>{Ie.current.delete(u),n(new Error("Device control timed out"))},5e3);Ie.current.set(u,{resolve:i,reject:n,timer:h}),d.send(JSON.stringify({type:e,id:u,...o}))}),[Br,kt]=l.useState(!1),[qr,ft]=l.useState(!1),[Vr,or]=l.useState(!1),Ye=l.useRef(!1),Pt=l.useRef(!1),[sr,jr]=l.useState(!1),[Gr,Jr]=l.useState(!1),[zr,cr]=l.useState({}),T=l.useRef(null),W=l.useRef(null),P=l.useRef(null),Ke=l.useRef(void 0),ze=l.useRef(void 0),Qe=l.useRef(void 0),ht=l.useRef(void 0),ke=l.useRef(void 0),ye=l.useRef(0),mt=l.useRef(0),fe=l.useRef(!1),Ut=l.useRef(b);Ut.current=b;const ve=l.useRef(null),Z=l.useRef(null),Oe=l.useRef(void 0),Lt=l.useMemo(()=>new Zn,[]),he=l.useRef(re);he.current=re;const pt=l.useRef(H);pt.current=H;const Ze=l.useRef(null),Et=l.useRef(null),xt=l.useRef(le);xt.current=le;const Ft=l.useRef(!1),et=l.useRef(dt);et.current=dt;const tt=l.useRef(null),ce=l.useRef(null),gt=l.useRef(0),ar=l.useRef(Promise.resolve()),Pe=l.useRef(null),rt=l.useRef(!1),ge=l.useRef(new Map),me=l.useRef(new Map),_e=l.useRef(new Map),De=l.useRef(new Map),j=l.useRef(new Map),Te=l.useRef(!1),[Qr,Zr]=l.useState(!1),B=l.useRef(null),Ue=l.useRef(null),nt=l.useRef({handle:()=>{},end:()=>{}}),[Re,Ct]=l.useState(null),G=l.useRef(null),[ur,lr]=l.useState(null),[Wt,it]=l.useState(null),[Ht,yt]=l.useState(null),[en,dr]=l.useState(null),[tn,fr]=l.useState(null),vt=l.useRef(null),ne=l.useRef(void 0),hr=e=>{vt.current=e,ne.current===void 0&&(ne.current=window.requestAnimationFrame(()=>{ne.current=void 0,fr(vt.current)}))},[rn,Le]=l.useState(null),xe=l.useRef(Q);xe.current=Q;const Fe=l.useRef(null);Fe.current=ur;const $t=l.useRef(pe);$t.current=pe;const We=l.useRef(Ee);We.current=Ee;const mr=l.useRef(Ge);mr.current=Ge;const pr=l.useRef(D);pr.current=D;const Er=l.useRef(A);Er.current=A;const Xt=l.useRef(null),He=e=>{Xt.current!==e&&(Xt.current=e,L("onConnectionStateChange",Er.current,e))},ot=Q===!0||Q==="hover-only",nn=Q==="hover-only"?"hover-only":"select",oe=l.useMemo(()=>a||Math.random().toString(36).substring(2,15)+Math.random().toString(36).substring(2,15),[a]),ae=l.useMemo(()=>mi(t),[t]),$e=vi[ae],st=N?.[ae],gr=ae==="android"&&Gr?sr?st?.tabletFrameLandscape:st?.tabletFrame:sr?st?.frameLandscape:st?.frame,Cr=st?.loadingLogo,Ot=!ie&&p&&!!gr,K=e=>{x(e)},se=e=>{!P.current||P.current.readyState!=="open"||(P.current.send(e),G.current?.bumpActivity())},yr=-10,vr=(e,o)=>{const i=ct();if(!i)return;const n=Be(i,e,o);if(!n)return;const{videoX:d,videoY:u,videoWidth:h,videoHeight:E}=n,C=Mt(U.ACTION_DOWN,yr,h,E,d,u,1,U.BUTTON_PRIMARY,U.BUTTON_PRIMARY);C&&se(C),window.setTimeout(()=>{const m=Mt(U.ACTION_UP,yr,h,E,d,u,0,U.BUTTON_PRIMARY,U.BUTTON_PRIMARY);m&&se(m)},60)},on=(e,o)=>{const i=ct();if(!i||o.screen.width<=0||o.screen.height<=0)return;const n=e.frame.x+e.frame.width/2,d=e.frame.y+e.frame.height/2,u=n/o.screen.width*i.actualWidth,h=d/o.screen.height*i.actualHeight,E=i.videoRect.left+i.offsetX+u,C=i.videoRect.top+i.offsetY+h;vr(E,C)},_t=-1,Dt=-2,we=-3,Xe=(e,o,i,n,d,u)=>{const h=Mt(e,o,i,n,d,u,1,U.BUTTON_PRIMARY,U.BUTTON_PRIMARY);h&&(x("[rc-touch] sendSingleTouch",{action:e,actionName:bt(e),pointerId:o,x:d,y:u,video:{width:i,height:n}}),se(h))},Se=(e,o,i)=>{if(!i)return;const{videoX:n,videoY:d,videoWidth:u,videoHeight:h}=i;let E=null,C=null,m=1;const M=U.BUTTON_PRIMARY;switch(o){case"down":e!==we&&nt.current.end(),E=j.current.size===0?U.ACTION_DOWN:U.ACTION_POINTER_DOWN,C={x:n,y:d},j.current.set(e,C),e===-1&&F.current?.focus();break;case"move":j.current.has(e)&&(E=U.ACTION_MOVE,C={x:n,y:d},j.current.set(e,C));break;case"up":case"cancel":j.current.has(e)&&(C=j.current.get(e),j.current.delete(e),o==="cancel"?E=U.ACTION_CANCEL:E=j.current.size===0?U.ACTION_UP:U.ACTION_POINTER_UP);break}if(E!==null&&C!==null){x("[rc-touch][mouse->touch] sending",{pointerId:e,eventType:o,action:E,actionName:bt(E),positionToSend:C,video:{width:u,height:h},altHeld:Te.current,activePointersAfter:Array.from(j.current.entries()).map(([I,$])=>({id:I,x:$.x,y:$.y}))});const _=Mt(E,e,u,h,C.x,C.y,m,M,M);_&&(x("[rc-touch][mouse->touch] buffer",{pointerId:e,actionName:bt(E),byteLength:_.byteLength}),se(_))}else(o==="up"||o==="cancel")&&j.current.delete(e)},Bt=e=>{if(Te.current!==e&&(Te.current=e,Zr(e),e||Ct(null),x("[rc-touch][alt] updateAltHeld",{nextHeld:e,activePointerIds:Array.from(j.current.keys())}),ae==="ios"&&P.current&&P.current.readyState==="open")){const o=e?c.ACTION_DOWN:c.ACTION_UP,i=lt(o,c.KEYCODE_ALT_LEFT,0,c.META_NONE);x("[rc-touch][alt] sending Indigo modifier keycode",{action:o,keycode:c.KEYCODE_ALT_LEFT}),i&&se(i)}},ct=()=>{const e=F.current,o=de.current;if(!e||!o)return null;const i=e.videoWidth,n=e.videoHeight;if(!i||!n)return null;const d=e.getBoundingClientRect(),u=o.getBoundingClientRect(),h=d.width,E=d.height,C=i/n,m=h/E;let M=h,_=E;C>m?_=h/C:M=E*C;const I=(h-M)/2,$=(E-_)/2;return{videoWidth:i,videoHeight:n,videoRect:d,containerRect:u,actualWidth:M,actualHeight:_,offsetX:I,offsetY:$}},Be=(e,o,i)=>{const n=o-e.videoRect.left-e.offsetX,d=i-e.videoRect.top-e.offsetY,u=Math.max(0,Math.min(e.actualWidth,n)),h=Math.max(0,Math.min(e.actualHeight,d)),E=Math.max(0,Math.min(e.videoWidth,u/e.actualWidth*e.videoWidth)),C=Math.max(0,Math.min(e.videoHeight,h/e.actualHeight*e.videoHeight));return{videoX:E,videoY:C,videoWidth:e.videoWidth,videoHeight:e.videoHeight}},sn=(e,o,i)=>{const n=o-e.videoRect.left-e.offsetX,d=i-e.videoRect.top-e.offsetY,u=Math.max(0,Math.min(e.actualWidth,n)),h=Math.max(0,Math.min(e.actualHeight,d)),E=Math.max(0,Math.min(e.videoWidth,u/e.actualWidth*e.videoWidth)),C=Math.max(0,Math.min(e.videoHeight,h/e.actualHeight*e.videoHeight)),m=e.videoWidth-E,M=e.videoHeight-C,_=e.videoRect.left+e.offsetX,I=e.videoRect.top+e.offsetY,$=_-e.containerRect.left+u,ee=I-e.containerRect.top+h,V=_-e.containerRect.left+(e.actualWidth-u),v=I-e.containerRect.top+(e.actualHeight-h);return{containerX:$,containerY:ee,mirrorContainerX:V,mirrorContainerY:v,videoX:E,videoY:C,mirrorVideoX:m,mirrorVideoY:M,videoWidth:e.videoWidth,videoHeight:e.videoHeight}},cn=(e,o,i,n,d,u,h)=>{const E=Ln(e,o,i,n,d,u,h);x("[rc-touch2] sendTwoFingerMessage (iOS)",{actionName:bt(e),video:{width:o,height:i},p0:{x:n,y:d},p1:{x:u,y:h},byteLength:E.byteLength}),se(E)},qe=(e,o,i,n,d,u,h,E,C)=>{if(x("[rc-touch2] applyTwoFingerEvent",{platform:ae,eventType:e,video:{width:o,height:i},p0:{x:n,y:d,id:E},p1:{x:u,y:h,id:C}}),e==="down"&&nt.current.end(),ae==="ios"){const m=e==="down"?U.ACTION_DOWN:e==="move"?U.ACTION_MOVE:U.ACTION_UP;cn(m,o,i,n,d,u,h)}else e==="down"?(Xe(U.ACTION_DOWN,E,o,i,n,d),Xe(U.ACTION_POINTER_DOWN,C,o,i,u,h)):e==="move"?(Xe(U.ACTION_MOVE,E,o,i,n,d),Xe(U.ACTION_MOVE,C,o,i,u,h)):(Xe(U.ACTION_POINTER_UP,C,o,i,u,h),Xe(U.ACTION_UP,E,o,i,n,d))},an=(e,o,i)=>{if(!Te.current){Re!==null&&Ct(null);return}const n=sn(e,o,i);Ct(n)},un=(e,o,i)=>{const n=Fe.current;if(!n||n.screen.width<=0||n.screen.height<=0)return null;const d=o-e.videoRect.left-e.offsetX,u=i-e.videoRect.top-e.offsetY;if(d<0||u<0||d>e.actualWidth||u>e.actualHeight)return null;const h=d/e.actualWidth*n.screen.width,E=u/e.actualHeight*n.screen.height;return Hr(n,h,E)},Ce=e=>{if(ie)return;e.preventDefault(),e.stopPropagation();const o=ct();if((xe.current===!0||xe.current==="hover-only")&&!("touches"in e))if(e.type==="mousemove"){if(hr({x:e.clientX,y:e.clientY}),o){const n=un(o,e.clientX,e.clientY);it(n?.id??null)}}else e.type==="mouseleave"&&(hr(null),it(null));if(xe.current!==!0&&(!("touches"in e)&&o&&(e.type==="mousemove"?an(o,e.clientX,e.clientY):e.type==="mouseleave"&&Ct(null)),!(!P.current||P.current.readyState!=="open"||!F.current||!o)))if("touches"in e){const n=e.touches,d=e.changedTouches;let u;switch(e.type){case"touchstart":u="down";break;case"touchmove":u="move";break;case"touchend":u="up";break;case"touchcancel":u="cancel";break;default:return}if(n.length===2){const h=n[0],E=n[1],C=Be(o,h.clientX,h.clientY),m=Be(o,E.clientX,E.clientY);if(!C||!m)return;B.current?B.current.source==="real-touch"&&(B.current.finger0={x:C.videoX,y:C.videoY},B.current.finger1={x:m.videoX,y:m.videoY},qe("move",C.videoWidth,C.videoHeight,C.videoX,C.videoY,m.videoX,m.videoY,B.current.pointerId0,B.current.pointerId1)):(B.current={finger0:{x:C.videoX,y:C.videoY},finger1:{x:m.videoX,y:m.videoY},videoSize:{width:C.videoWidth,height:C.videoHeight},source:"real-touch",pointerId0:h.identifier,pointerId1:E.identifier},qe("down",C.videoWidth,C.videoHeight,C.videoX,C.videoY,m.videoX,m.videoY,h.identifier,E.identifier))}else if(n.length<2&&B.current?.source==="real-touch"){const h=B.current;qe("up",h.videoSize.width,h.videoSize.height,h.finger0.x,h.finger0.y,h.finger1.x,h.finger1.y,h.pointerId0,h.pointerId1),B.current=null;return}else{if(n.length>2)return;{const h=d[0];if(h){const E=Be(o,h.clientX,h.clientY);Se(h.identifier,u,E)}}}}else{let d=null;const u=B.current?.source==="alt-mouse";switch(e.type){case"mousedown":e.button===0&&(d="down");break;case"mousemove":(u||j.current.has(-1))&&(d="move");break;case"mouseup":e.button===0&&(d="up");break;case"mouseleave":(u||j.current.has(-1))&&(d="up");break}if(d){const h=Be(o,e.clientX,e.clientY);if(!h)return;x("[rc-touch][mouse] event",{domType:e.type,eventType:d,button:e.button,buttons:e.buttons,client:{x:e.clientX,y:e.clientY},altHeldRef:Te.current,inTwoFingerMode:u,geometry:{videoX:h.videoX,videoY:h.videoY,videoWidth:h.videoWidth,videoHeight:h.videoHeight},activePointerIds:Array.from(j.current.keys())}),Te.current||u?ln(d,h):Se(-1,d,h)}}},ln=(e,o)=>{const{videoX:i,videoY:n,videoWidth:d,videoHeight:u}=o,h=d-i,E=u-n;if(e==="down"){B.current={finger0:{x:i,y:n},finger1:{x:h,y:E},videoSize:{width:d,height:u},source:"alt-mouse",pointerId0:_t,pointerId1:Dt},F.current?.focus(),qe("down",d,u,i,n,h,E,_t,Dt);return}if(e==="move"){B.current?.source==="alt-mouse"&&(B.current.finger0={x:i,y:n},B.current.finger1={x:h,y:E},qe("move",d,u,i,n,h,E,_t,Dt));return}if(e==="up"||e==="cancel"){const C=B.current;if(C?.source==="alt-mouse"){const{finger0:m,finger1:M,videoSize:_}=C;qe("up",_.width,_.height,m.x,m.y,M.x,M.y,_t,Dt),B.current=null}return}},dn=150,Or=()=>{const e=Ue.current;e&&(window.clearTimeout(e.endTimer),Se(we,"up",e.pos),Ue.current=null)},fn=e=>{if(e.ctrlKey||Te.current||B.current)return;const o=j.current.size;if(o>1||o===1&&!j.current.has(we))return;const i=ct();if(!i)return;const n=e.clientX-i.videoRect.left-i.offsetX,d=e.clientY-i.videoRect.top-i.offsetY;if(n<0||n>i.actualWidth||d<0||d>i.actualHeight)return;const u=Be(i,e.clientX,e.clientY);if(!u)return;e.preventDefault();const h=(e.deltaMode===1?16:e.deltaMode===2?i.actualWidth:1)*(i.videoWidth/i.actualWidth),E=(e.deltaMode===1?16:e.deltaMode===2?i.actualHeight:1)*(i.videoHeight/i.actualHeight),C=-e.deltaX*h,m=-e.deltaY*E,M=v=>{window.clearTimeout(v.endTimer),v.endTimer=window.setTimeout(Or,dn)};if(C===0&&m===0){Ue.current&&M(Ue.current);return}const _=()=>({videoWidth:u.videoWidth,videoHeight:u.videoHeight,videoX:Math.abs(C)>Math.abs(m)?Math.min(Math.max(u.videoX,u.videoWidth*.2),u.videoWidth*.8):u.videoX,videoY:Math.abs(m)>=Math.abs(C)?Math.min(Math.max(u.videoY,u.videoHeight*.2),u.videoHeight*.8):u.videoY}),I=v=>({...v,videoX:Math.min(Math.max(v.videoX+C,0),v.videoWidth),videoY:Math.min(Math.max(v.videoY+m,0),v.videoHeight)});let $=Ue.current;if($)window.clearTimeout($.endTimer);else{const v=_();Se(we,"down",v),$={pos:v,endTimer:0},Ue.current=$}let ee=$.pos,V=I(ee);V.videoX===ee.videoX&&V.videoY===ee.videoY&&(Se(we,"up",ee),ee=_(),Se(we,"down",ee),V=I(ee)),Se(we,"move",V),$.pos=V,M($)};l.useEffect(()=>{nt.current={handle:fn,end:Or}}),l.useEffect(()=>{const e=de.current;if(!e)return;const o=i=>nt.current.handle(i);return e.addEventListener("wheel",o,{passive:!1}),()=>{nt.current.end(),e.removeEventListener("wheel",o)}},[]),l.useEffect(()=>{const e=n=>{n.key==="Alt"&&Bt(!0)},o=n=>{n.key==="Alt"&&Bt(!1)},i=()=>{Bt(!1)};return window.addEventListener("keydown",e,!0),window.addEventListener("keyup",o,!0),window.addEventListener("blur",i),()=>{window.removeEventListener("keydown",e,!0),window.removeEventListener("keyup",o,!0),window.removeEventListener("blur",i)}},[]);const Tt=e=>{e.preventDefault(),e.stopPropagation();const o=document.activeElement===F.current||ie&&document.activeElement===e.currentTarget;if(x("Keyboard event:",{type:e.type,key:e.key,keyCode:e.keyCode,code:e.code,target:e.target.tagName,focused:o}),!o){R("Simulator input not focused, skipping keyboard event");return}if(!P.current||P.current.readyState!=="open"){R("Data channel not ready for keyboard event:",P.current?.readyState);return}if(e.type==="keydown"){if(e.key.toLowerCase()==="v"&&(e.metaKey||e.ctrlKey)){x("Paste shortcut detected"),navigator.clipboard.readText().then(n=>{if(n){x("Pasting text via SET_CLIPBOARD:",n.substring(0,20)+(n.length>20?"...":""));const d=xn(n,!0);se(d)}}).catch(n=>{console.error("Failed to read clipboard contents: ",n)});return}if(e.key.toLowerCase()==="m"&&(e.metaKey||e.ctrlKey)){x("Menu shortcut detected");const n=lt(c.ACTION_DOWN,c.MENU,0,c.META_NONE);se(n);const d=lt(c.ACTION_UP,c.MENU,0,c.META_NONE);se(d);return}}const i=Oi(e);if(i){const{keycode:n,metaState:d}=i,u=e.type==="keydown"?c.ACTION_DOWN:c.ACTION_UP;x(`Sending Keycode: key=${e.key}, code=${n}, action=${u}, meta=${d}`);const h=lt(u,n,0,d);se(h)}else x(`Ignoring unhandled key event: type=${e.type}, key=${e.key}`)},hn=()=>{T.current&&T.current.readyState===WebSocket.OPEN&&T.current.send(JSON.stringify({type:"keepAlive",sessionId:oe}))},_r=()=>{Ke.current&&window.clearInterval(Ke.current),Ke.current=window.setInterval(hn,1e4)},Dr=()=>{Ke.current&&(window.clearInterval(Ke.current),Ke.current=void 0)},Rt=()=>{ze.current&&(window.clearTimeout(ze.current),ze.current=void 0)},wt=()=>{Qe.current&&(window.clearTimeout(Qe.current),Qe.current=void 0)},at=()=>{ht.current&&(window.clearInterval(ht.current),ht.current=void 0)},ut=()=>{ke.current!==void 0&&(window.clearTimeout(ke.current),ke.current=void 0)},mn=()=>{rt.current||(rt.current=!0,at(),kt(!0),He("connected"))},J=e=>{for(const o of e.getTracks())try{o.stop()}catch(i){R("track.stop() failed:",i)}},pn=()=>{const e=Z.current;e&&(Z.current=null,J(e))},Tr=e=>{const o=ar.current.then(e).catch(i=>{R("microphone operation failed:",i)});return ar.current=o,o},qt=()=>xt.current||Ft.current,Rr=e=>{const o=`ui-mic-${Date.now()}-${Math.random().toString(36).substring(2,9)}`;Pe.current=o,e.send(JSON.stringify({type:"microphoneStart",id:o}))},Vt=()=>Tr(()=>En()),En=async()=>{const e=gt.current,o=()=>e===gt.current&&qt(),i=E=>{L("onMicrophoneStateChange",et.current,{active:!1,error:E})};if(!o())return;const n=T.current,d=tt.current;if(!n||n.readyState!==WebSocket.OPEN||!d||ce.current)return;if(!navigator.mediaDevices||typeof navigator.mediaDevices.getUserMedia!="function"){console.warn("[RemoteControl] navigator.mediaDevices.getUserMedia unavailable. getUserMedia requires a secure context (https or http://localhost)."),i("Microphone capture requires a secure context (https)");return}let u=null;try{u=await navigator.mediaDevices.getUserMedia({audio:!0,video:!1})}catch(E){console.warn("[RemoteControl] microphone getUserMedia denied/failed:",E)}if(!o()){u&&J(u);return}if(!u){i("Microphone permission denied or no device available");return}const h=u.getAudioTracks()[0]??null;if(!h){J(u),i("Captured stream has no audio track");return}try{await d.replaceTrack(h)}catch(E){R("replaceTrack(audioTrack) failed:",E),J(u),i("Failed to attach the microphone track to the connection");return}if(!o()){try{await d.replaceTrack(null)}catch(E){R("replaceTrack(null) on stale mic attach failed:",E)}J(u);return}ce.current=u,h.onended=()=>{ce.current===u&&St("microphone capture ended by the browser")},Rr(n),L("onMicrophoneStateChange",et.current,{active:!0,label:h.label||void 0})},St=e=>(++gt.current,Pe.current=null,Tr(async()=>{const o=tt.current,i=ce.current;if(ce.current=null,o&&i)try{await o.replaceTrack(null)}catch(d){R("replaceTrack(null) on mic detach failed:",d)}i&&J(i);const n=T.current;if(i&&n&&n.readyState===WebSocket.OPEN){const d=`ui-mic-${Date.now()}-${Math.random().toString(36).substring(2,9)}`;n.send(JSON.stringify({type:"microphoneStop",id:d}))}(i||e)&&L("onMicrophoneStateChange",et.current,{active:!1,...e!==void 0&&{error:e}})})),wr=(e,o)=>{let i;try{i=ii(o),console.info(`[RemoteControl] camera capture: ${i.camera?.width}x${i.camera?.height} @ ${i.camera?.frameRate??"?"}fps`+(i.camera?.label?` — ${i.camera.label}`:""))}catch(n){R("getSettings() on outbound camera track failed:",n),i={type:"cameraResult",granted:!0,camera:{label:o.label||void 0}}}e.send(JSON.stringify(i)),L("onCameraDemandChange",he.current,!0,!0,i.camera)},gn=e=>{if(!e)return;const o=e.indexOf("/"),n=(o>=0?e.slice(o+1):e).toUpperCase();return n==="HEVC"?"H265":n},Cn=async()=>{const e=ve.current,o=pt.current;if(!e||!o)return;let i;try{i=await e.getStats()}catch{return}let n,d,u;if(i.forEach(I=>{I.type==="outbound-rtp"&&I.kind==="video"?n=I:I.type==="remote-inbound-rtp"&&I.kind==="video"&&(u=I)}),n?.codecId){const I=i.get(n.codecId);I&&(d=I.mimeType)}if(!n)return;const h=n.timestamp??Date.now(),E=Et.current;let C,m,M;if(E&&h>E.timestamp){const I=(h-E.timestamp)/1e3;if(typeof n.framesEncoded=="number"&&typeof E.framesEncoded=="number"&&(C=Math.max(0,(n.framesEncoded-E.framesEncoded)/I)),typeof n.bytesSent=="number"&&typeof E.bytesSent=="number"&&(m=Math.max(0,(n.bytesSent-E.bytesSent)*8/I)),typeof n.packetsSent=="number"&&typeof E.packetsSent=="number"&&u&&typeof u.packetsLost=="number"&&typeof E.packetsLost=="number"){const $=n.packetsSent-E.packetsSent,ee=u.packetsLost-E.packetsLost;$>0&&(M=Math.max(0,Math.min(100,ee/$*100)))}}Et.current={timestamp:h,framesEncoded:n.framesEncoded,bytesSent:n.bytesSent,packetsSent:n.packetsSent,packetsLost:u?.packetsLost};const _={codec:gn(d),encoderImplementation:n.encoderImplementation,hardwareAccelerated:typeof n.powerEfficientEncoder=="boolean"?n.powerEfficientEncoder:void 0,framesPerSecond:C,framesEncoded:n.framesEncoded,bitrateBps:m,width:n.frameWidth,height:n.frameHeight,qualityLimitationReason:n.qualityLimitationReason,rttMs:typeof u?.roundTripTime=="number"?u.roundTripTime*1e3:void 0,packetsLostPct:M};L("onCameraStats",pt.current,_)},Sr=()=>{Ze.current===null&&(Et.current=null,Ze.current=setInterval(()=>{Cn()},1e3))},At=()=>{Ze.current!==null&&(clearInterval(Ze.current),Ze.current=null),Et.current=null,L("onCameraStats",pt.current,null)},yn=(e,o,i,n)=>Lt.enqueue(async({isCurrent:d})=>{const u=()=>d()&&n()&&T.current===o&&ve.current===i;if(!u())return;if(!e.active){const _=Z.current;try{await i.replaceTrack(null)}catch(I){R("replaceTrack(null) on camera detach failed:",I)}if(Z.current===_&&(Z.current=null,Oe.current=void 0,_&&J(_)),At(),!u())return;L("onCameraDemandChange",he.current,!1);return}L("onCameraDemandChange",he.current,!0);const h=Z.current,E=h?.getVideoTracks()[0],C=Oe.current;if(E?.readyState==="live"&&C&&!ri(C,e)){Oe.current=e,wr(o,E),Sr();return}if(h){try{await i.replaceTrack(null)}catch(_){R("replaceTrack(null) before camera switch failed:",_)}if(Z.current===h&&(Z.current=null,Oe.current=void 0,J(h)),At(),!u())return}if(!navigator.mediaDevices||typeof navigator.mediaDevices.getUserMedia!="function"){if(console.warn("[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."),!u())return;o.send(JSON.stringify({type:"cameraResult",granted:!1})),L("onCameraDemandChange",he.current,!0,!1);return}let m=null;try{m=await navigator.mediaDevices.getUserMedia({video:ti(e),audio:!1})}catch(_){console.warn("[RemoteControl] getUserMedia denied/failed:",_)}if(!u()){m&&J(m);return}if(!m){o.send(JSON.stringify({type:"cameraResult",granted:!1})),L("onCameraDemandChange",he.current,!0,!1);return}const M=m.getVideoTracks()[0]??null;if(!M){if(J(m),!u())return;o.send(JSON.stringify({type:"cameraResult",granted:!1})),L("onCameraDemandChange",he.current,!0,!1);return}try{M.contentHint="motion"}catch{}try{await i.replaceTrack(M)}catch(_){if(R("replaceTrack(videoTrack) failed:",_),J(m),!u())return;o.send(JSON.stringify({type:"cameraResult",granted:!1})),L("onCameraDemandChange",he.current,!0,!1);return}if(!u()){try{await i.replaceTrack(null)}catch(_){R("replaceTrack(null) for stale camera attach failed:",_)}J(m);return}try{const _=i.getParameters();(!_.encodings||_.encodings.length===0)&&(_.encodings=[{}]),_.encodings[0].maxBitrate=8e6,_.encodings[0].maxFramerate=30,_.degradationPreference="maintain-framerate",await i.setParameters(_)}catch(_){R("setParameters on outbound camera failed:",_)}if(!u()){try{await i.replaceTrack(null)}catch(_){R("replaceTrack(null) for stale camera finalize failed:",_)}J(m);return}Z.current=m,Oe.current=e,M.onended=()=>{Z.current===m&&Lt.enqueueCurrent(async({isCurrent:_})=>{if(!(!_()||Z.current!==m||!n()||T.current!==o||ve.current!==i)){try{await i.replaceTrack(null)}catch(I){R("replaceTrack(null) after camera ended failed:",I)}!_()||Z.current!==m||!n()||T.current!==o||ve.current!==i||(Z.current=null,Oe.current=void 0,J(m),At(),o.send(JSON.stringify({type:"cameraResult",granted:!1})),L("onCameraDemandChange",he.current,!0,!1))}}).catch(_=>R("camera ended cleanup failed:",_))},u()&&(wr(o,M),Sr())}),Ve=()=>{for(const e of Ie.current.values())clearTimeout(e.timer),e.reject(new Error("Simulator disconnected"));Ie.current.clear(),rr(null),Je.current&&(Je.current.srcObject=null),wt(),ut(),at(),G.current&&(G.current.stop(),G.current=null),Lt.invalidate(),At(),pn(),Oe.current=void 0,ve.current=null,++gt.current,Ft.current=!1,Pe.current=null,ce.current&&(J(ce.current),ce.current=null,L("onMicrophoneStateChange",et.current,{active:!1})),tt.current=null,ne.current!==void 0&&(window.cancelAnimationFrame(ne.current),ne.current=void 0),T.current&&(T.current.onopen=null,T.current.onmessage=null,T.current.onerror=null,T.current.onclose=null,T.current.close(),T.current=null),W.current&&(W.current.onconnectionstatechange=null,W.current.oniceconnectionstatechange=null,W.current.ontrack=null,W.current.onicecandidate=null,W.current.close(),W.current=null),F.current&&(F.current.srcObject=null),P.current&&(P.current.onopen=null,P.current.onclose=null,P.current.onerror=null,P.current.close(),P.current=null)},Ar=()=>{document.hidden?Dr():_r()},vn=async()=>{if(typeof navigator<"u"&&navigator.onLine===!1)return!1;let e;try{const n=new URL(t);n.protocol=n.protocol==="wss:"?"https:":n.protocol==="ws:"?"http:":n.protocol,e=Yr(n.toString(),s)}catch{return!1}const o=new AbortController,i=window.setTimeout(()=>o.abort(),Ci);try{return(await fetch(e,{method:"GET",cache:"no-store",signal:o.signal})).status===404}catch{return!1}finally{window.clearTimeout(i)}},On=()=>{Ye.current||(Ye.current=!0,or(!0),ft(!1),ye.current+=1,Rt(),wt(),ut(),Ve(),K("Instance terminated"),He("terminated"),L("onTerminated",pr.current))},_n=()=>{Ye.current||Pt.current||(Pt.current=!0,vn().then(e=>{Pt.current=!1,e&&On()}))},je=(e,o)=>{if(Ye.current||o!==ye.current)return;if(_n(),fe.current){if(!Ut.current){K(`Connection failed after it was established: ${e}`),ft(!0),He("failed"),Ve();return}K(`Reconnecting after established session dropped: ${e}`),fe.current=!1,mt.current=-1}Rt();const i=mt.current+1;if(i>=Gt){K(`Connection failed after ${Gt} attempts: ${e}`),ft(!0),He("failed"),Ve();return}K(`Retrying connection (${i+1}/${Gt})`),He("reconnecting"),Ve(),ze.current=window.setTimeout(()=>{ze.current=void 0,o===ye.current&&Mr(i)},pi)},Mr=async(e=0)=>{if(Ye.current)return;const o=ye.current+1;ye.current=o,mt.current=e,fe.current=!1,ft(!1),e===0&&Xt.current!=="reconnecting"&&He("connecting"),Rt(),wt(),at(),rt.current=!1,kt(!1),Ve();const i=()=>o===ye.current;Qe.current=window.setTimeout(()=>{Qe.current=void 0,!(!i()||fe.current)&&je("Connection did not succeed within 15 seconds",o)},Ei);try{const n=new WebSocket(Yr(t,s));if(T.current=n,await new Promise((v,f)=>{let k=!1;const z=window.setTimeout(()=>f(new Error("WebSocket connection timeout")),3e4),S=Y=>{k||(k=!0,window.clearTimeout(z),Y())};n.onopen=()=>{!i()||T.current!==n||S(v)},n.onerror=Y=>{!i()||T.current!==n||(K("WebSocket error: "+Y),S(()=>f(new Error("WebSocket connection failed"))))},n.onclose=()=>{!i()||T.current!==n||(K("WebSocket closed"),S(()=>f(new Error("WebSocket closed before connection was established"))))}}),!i()||T.current!==n)return;n.onerror=v=>{!i()||T.current!==n||K("WebSocket error: "+v)},n.onclose=()=>{!i()||T.current!==n||K("WebSocket closed")};const d=new Promise((v,f)=>{const k=Y=>{window.clearTimeout(z),n.removeEventListener("message",S),Y()},z=window.setTimeout(()=>k(()=>f(new Error("RTCConfiguration timeout"))),3e4),S=Y=>{if(!(!i()||T.current!==n))try{const q=JSON.parse(Y.data);if(q.type==="signalingError"&&q.requestType==="requestRtcConfiguration"&&q.sessionId===oe){const te=typeof q.error=="string"?q.error:"Unable to load streaming configuration";k(()=>f(new Error(te)))}else q.type==="rtcConfiguration"&&k(()=>v({rtcConfiguration:q.rtcConfiguration,cameraSupported:q.cameraSupported===!0,foldSupported:q.foldSupported===!0}))}catch(q){console.error("Error handling RTC configuration:",q),k(()=>f(q))}};n.addEventListener("message",S),n.send(JSON.stringify({type:"requestRtcConfiguration",sessionId:oe}))}),{rtcConfiguration:u,cameraSupported:h,foldSupported:E}=await d;if(!i()||T.current!==n)return;const C=y==="iphone-duo"||E;er(C);const m=new RTCPeerConnection({...u,iceTransportPolicy:"relay"});W.current=m,m.addTransceiver("audio",{direction:"recvonly"});const M=m.addTransceiver("video",{direction:"recvonly"}),_=C?m.addTransceiver("video",{direction:"recvonly"}):null,I=ae==="ios"||h,$=I?m.addTransceiver("video",{direction:"sendonly"}):null;ve.current=$?.sender??null;const ee=I?m.addTransceiver("audio",{direction:"sendonly"}):null;if(tt.current=ee?.sender??null,RTCRtpReceiver.getCapabilities){const v=RTCRtpReceiver.getCapabilities("video");if(v&&v.codecs){const k=v.codecs.sort((z,S)=>{const Y=q=>{const te=q.mimeType.toLowerCase();return te.includes("vp9")?1:te.includes("h265")||te.includes("hevc")?2:te.includes("h264")||te.includes("avc")?3:4};return Y(z)-Y(S)});M.setCodecPreferences(k),_?.setCodecPreferences(k),x("Set codec preferences:",k.map(z=>z.mimeType).join(", "))}}if($&&RTCRtpSender.getCapabilities){const v=RTCRtpSender.getCapabilities("video");if(v&&v.codecs){const f=new Set(["42e01f","42e028","640c1f"]),k=S=>{const Y=S.mimeType.toLowerCase(),te=(S.sdpFmtpLine||"").toLowerCase().match(/profile-level-id=([0-9a-f]{6})/),Sn=te?te[1]:"";return Y==="video/h265"||Y==="video/hevc"?1:Y==="video/h264"&&f.has(Sn)?2:Y==="video/h264"?3:Y==="video/vp9"?4:Y==="video/vp8"?5:Y==="video/rtx"||Y==="video/red"||Y==="video/ulpfec"?0:6},z=[...v.codecs].sort((S,Y)=>k(S)-k(Y));try{$.setCodecPreferences(z),x("Outbound camera codec preferences:",z.map(S=>`${S.mimeType}${S.sdpFmtpLine?`[${S.sdpFmtpLine}]`:""}`).join(", "))}catch(S){R("Failed to set outbound camera codec preferences:",S)}}}const V=m.createDataChannel("control",{ordered:!0,negotiated:!0,id:1});if(P.current=V,V.onopen=()=>{if(!i()||P.current!==V||T.current!==n)return;fe.current=!0,wt(),K("Control channel opened"),C&&n.send(JSON.stringify({type:"getFoldState",id:"duo-capabilities"})),G.current||(G.current=new Qn({platform:ae,baseIntervalMs:Me,maxBackoffMs:X,androidElementTreeOptions:ue,send:f=>{if(!T.current||T.current.readyState!==WebSocket.OPEN)return!1;try{return T.current.send(JSON.stringify(f)),!0}catch{return!1}},onSnapshot:f=>{lr(k=>zt(k,f)?k:f),queueMicrotask(()=>{L("onAxSnapshotChange",$t.current,f)})},onStatusChange:(f,k)=>{L("onAxStatusChange",mr.current,f,k)}}),(xe.current===!0||xe.current==="hover-only")&&G.current.start());const v=()=>{!i()||rt.current||P.current!==V||T.current!==n||n.readyState!==WebSocket.OPEN||n.send(JSON.stringify({type:"requestFrame",sessionId:oe}))};if(v(),at(),ht.current=window.setInterval(()=>{if(!i()||rt.current||P.current!==V||T.current!==n||n.readyState!==WebSocket.OPEN){at();return}v()},250),g){try{const f=decodeURIComponent(g);K("Opening URL"),n.send(JSON.stringify({type:"openUrl",url:f,sessionId:oe}))}catch(f){console.error({error:f},"Error decoding URL, falling back to the original URL"),n.send(JSON.stringify({type:"openUrl",url:g,sessionId:oe}))}G.current?.bumpActivity()}},V.onclose=()=>{!i()||P.current!==V||K("Control channel closed")},V.onerror=v=>{!i()||P.current!==V||(console.error("Control channel error:",v),K("Control channel error: "+v))},m.onconnectionstatechange=()=>{!i()||W.current!==m||(K("Connection state: "+m.connectionState),m.connectionState==="failed"&&fe.current&&je("WebRTC connection entered failed state",o))},m.oniceconnectionstatechange=()=>{if(!i()||W.current!==m)return;const v=m.iceConnectionState;if(K("ICE state: "+v),v==="connected"||v==="completed"){ut(),qt()&&!ce.current&&Vt();return}if(v==="failed"){ut(),fe.current&&je("ICE connection entered failed state",o);return}v==="disconnected"&&fe.current&&Ut.current&&ke.current===void 0&&(ke.current=window.setTimeout(()=>{ke.current=void 0,!(!i()||W.current!==m)&&m.iceConnectionState==="disconnected"&&je("ICE stayed disconnected past grace period",o)},gi))},m.ontrack=v=>{if(!(!i()||W.current!==m)&&(K("Received remote track: "+v.track.kind),v.track.kind==="video"&&F.current)){x(`[${new Date().toISOString()}] Video track received:`,v.track);const k=v.track.id==="duo-inner"||v.streams.some(z=>z.id==="duo-inner")?Je.current:F.current;k&&(k.srcObject=C?new MediaStream([v.track]):v.streams[0]??new MediaStream([v.track]),k.play().catch(()=>{}))}},m.onicecandidate=v=>{if(!(!i()||W.current!==m||T.current!==n))if(v.candidate&&n.readyState===WebSocket.OPEN){const f={type:"candidate",candidate:v.candidate.candidate,sdpMid:v.candidate.sdpMid,sdpMLineIndex:v.candidate.sdpMLineIndex,sessionId:oe};n.send(JSON.stringify(f)),K("Sent ICE candidate")}else K("ICE candidate gathering completed")},n.onmessage=async v=>{if(!i()||T.current!==n)return;let f;try{f=JSON.parse(v.data)}catch(k){R("Error parsing message:",k);return}if(!G.current?.handleMessage(f))switch(K("Received: "+f.type),f.type){case"performActionsResult":case"foldStateResult":case"foldStateChanged":{if(!C)break;f.state?(rr(f.state),ir(void 0)):f.id==="duo-capabilities"&&ir(f.error||"This instance does not support native iPhone Duo displays.");const S=Ie.current.get(f.id);S&&(clearTimeout(S.timer),Ie.current.delete(f.id),f.error?S.reject(new Error(f.error)):S.resolve());break}case"signalingError":{if(f.requestType!=="offer"||f.sessionId!==oe)break;const S=typeof f.error=="string"?f.error:"Unable to establish the streaming connection";K("Error: "+S),je(S,o);break}case"answer":if(!W.current||W.current!==m){K("No peer connection, skipping answer");break}if(await m.setRemoteDescription(new RTCSessionDescription({type:"answer",sdp:f.sdp})),!i()||W.current!==m)return;K("Set remote description");break;case"candidate":if(!W.current||W.current!==m){K("No peer connection, skipping candidate");break}if(await m.addIceCandidate(new RTCIceCandidate({candidate:f.candidate,sdpMid:f.sdpMid,sdpMLineIndex:f.sdpMLineIndex})),!i()||W.current!==m)return;K("Added ICE candidate");break;case"screenshot":case"screenshotResult":{if(typeof f.id!="string"){R("Received invalid screenshot success message:",f);break}const S=Di(f);if(S){const te=me.current.get(f.id);if(!te){R(`Received screenshot error for unknown or handled id: ${f.id}`);break}R(`Received screenshot error for id ${f.id}: ${S}`),te(new Error(S)),ge.current.delete(f.id),me.current.delete(f.id);break}const Y=Ti(f);if(!Y){R("Received screenshot message without image data:",f);break}const q=ge.current.get(f.id);if(!q){R(`Received screenshot data for unknown or handled id: ${f.id}`);break}x(`Received screenshot data for id ${f.id}`),q(Y),ge.current.delete(f.id),me.current.delete(f.id);break}case"screenshotError":if(typeof f.id!="string"||typeof f.message!="string"){R("Received invalid screenshot error message:",f);break}const k=me.current.get(f.id);if(!k){R(`Received screenshot error for unknown or handled id: ${f.id}`);break}R(`Received screenshot error for id ${f.id}: ${f.message}`),k(new Error(f.message)),ge.current.delete(f.id),me.current.delete(f.id);break;case"cameraRequest":{const S=ve.current;if(!S)break;const Y=ei(f);if(!Y){R("Received invalid cameraRequest:",f);break}console.info("[RemoteControl] cameraRequest received:",Y.active,Y.facingMode),await yn(Y,n,S,i);break}case"microphoneRequest":{if(!tt.current)break;const S=f.active===!0;if(Ft.current=S,console.info("[RemoteControl] microphoneRequest received, active=",S),!S){xt.current||await St();break}if(ce.current){Rr(n);break}await Vt();break}case"microphoneStartResult":{if(Pe.current===null||f.id!==Pe.current)break;Pe.current=null,typeof f.error=="string"&&(console.warn("[RemoteControl] microphoneStart rejected by host:",f.error),St(f.error));break}case"terminateAppResult":if(typeof f.id!="string"){R("Received invalid terminateApp result message:",f);break}if(typeof f.error=="string"){const S=De.current.get(f.id);if(!S){R(`Received terminateApp error for unknown or handled id: ${f.id}`);break}R(`Received terminateApp error for id ${f.id}: ${f.error}`),S(new Error(f.error)),_e.current.delete(f.id),De.current.delete(f.id);break}const z=_e.current.get(f.id);if(!z){R(`Received terminateApp result for unknown or handled id: ${f.id}`);break}x(`Received terminateApp success for id ${f.id}`),z(),_e.current.delete(f.id),De.current.delete(f.id);break;default:R(`Received unhandled message type: ${f.type}`,f);break}},W.current===m){const v=await m.createOffer({offerToReceiveVideo:!0,offerToReceiveAudio:!1});if(!i()||W.current!==m||(await m.setLocalDescription(v),!i()||W.current!==m))return;i()&&T.current===n&&n.readyState===WebSocket.OPEN&&n.send(JSON.stringify({type:"offer",...C?{displayStreams:!0}:{},sdp:v.sdp,sessionId:oe})),K("Sent offer")}}catch(n){if(!i())return;const d=n instanceof Error?n.message:String(n);K("Error: "+d),je(d,o)}},jt=()=>{Ye.current=!1,or(!1),Mr(0)},Dn=()=>{ye.current+=1,mt.current=0,fe.current=!1,Rt(),ut(),Ve(),K("Stopped")},Tn=e=>{e.stopPropagation(),jt()};l.useEffect(()=>{qt()?Vt():St()},[le]),l.useEffect(()=>(kt(!1),jt(),document.hidden||_r(),document.addEventListener("visibilitychange",Ar),()=>{Dr(),Dn(),document.removeEventListener("visibilitychange",Ar)}),[t,s,a,y]);const br=()=>{const e=ct();if(!e){dr(null);return}const o={left:e.videoRect.left-e.containerRect.left+e.offsetX,top:e.videoRect.top-e.containerRect.top+e.offsetY,width:e.actualWidth,height:e.actualHeight};dr(i=>i&&i.left===o.left&&i.top===o.top&&i.width===o.width&&i.height===o.height?i:o)};l.useEffect(()=>{const e=F.current,o=Ne.current,i=de.current;if(!e)return;const n=()=>{if(!Ot||!o){cr({}),br();return}const h=o.clientWidth,E=o.clientHeight;if(h===0||E===0)return;const C=e.videoWidth>e.videoHeight;jr(C),Jr(ae==="android"&&yi(e.videoWidth,e.videoHeight));const m=C?$e.videoPosition.landscape:$e.videoPosition.portrait;let M={};m.heightMultiplier?(M.height=`${E*m.heightMultiplier}px`,M.width="auto"):m.widthMultiplier&&(M.width=`${h*m.widthMultiplier}px`,M.height="auto"),M.borderRadius=`${C?E*$e.videoBorderRadiusMultiplier:h*$e.videoBorderRadiusMultiplier}px`,cr(M),br()},d=new ResizeObserver(()=>{n()});o&&d.observe(o),d.observe(e),i&&d.observe(i),o&&o.addEventListener("load",n),e.addEventListener("loadedmetadata",n),e.addEventListener("resize",n);const u=()=>G.current?.bumpActivity();return e.addEventListener("resize",u),n(),()=>{d.disconnect(),e.removeEventListener("loadedmetadata",n),e.removeEventListener("resize",n),e.removeEventListener("resize",u),o&&o.removeEventListener("load",n)}},[$e,Ot]),l.useEffect(()=>{const e=G.current;ot?e?.start():(e?.stop(),lr(null),it(null),yt(null),fr(null),Le(null),vt.current=null,ne.current!==void 0&&(window.cancelAnimationFrame(ne.current),ne.current=void 0),L("onAxSnapshotChange",$t.current,null))},[ot]),l.useEffect(()=>()=>{ne.current!==void 0&&(window.cancelAnimationFrame(ne.current),ne.current=void 0)},[]),l.useEffect(()=>{if(!ot)return;const e=o=>{o.key==="Escape"&&(Ht||Wt)&&(yt(null),it(null),Le(null),L("onInspectSelectionChange",We.current,null))};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[ot,Ht,Wt]);const Rn=()=>{F.current&&F.current.focus()};l.useImperativeHandle(be,()=>({openUrl:e=>{if(!T.current||T.current.readyState!==WebSocket.OPEN){R("WebSocket not open, cannot send open_url command via ref.");return}try{const o=decodeURIComponent(e);K("Opening URL"),T.current.send(JSON.stringify({type:"openUrl",url:o,sessionId:oe}))}catch(o){R("Error decoding or sending URL via ref:",{error:o,url:e}),T.current.send(JSON.stringify({type:"openUrl",url:e,sessionId:oe}))}G.current?.bumpActivity()},sendKeyEvent:e=>{if(!P.current||P.current.readyState!=="open"){R("Data channel not ready for imperative key command:",P.current?.readyState);return}const o=Ur[e.code];if(!o){R(`Unknown event.code for imperative command: ${e.code}`);return}let i=c.META_NONE;e.shiftKey&&(i|=c.META_SHIFT_ON),e.altKey&&(i|=c.META_ALT_ON),e.ctrlKey&&(i|=c.META_CTRL_ON),e.metaKey&&(i|=c.META_META_ON);const n=e.type==="keydown"?c.ACTION_DOWN:c.ACTION_UP;x(`Sending Imperative Key Command: code=${e.code}, keycode=${o}, action=${n}, meta=${i}`);const d=lt(n,o,0,i);d&&se(d)},screenshot:e=>new Promise((o,i)=>{if(!T.current||T.current.readyState!==WebSocket.OPEN)return R("WebSocket not open, cannot send screenshot command."),i(new Error("WebSocket is not connected or connection is not open."));const n=`ui-ss-${Date.now()}-${Math.random().toString(36).substring(2,9)}`,d={type:e?"screenshotDisplay":"screenshot",...e?{display:e}:{},id:n};ge.current.set(n,o),me.current.set(n,i),x("Sending screenshot request:",d);try{T.current.send(JSON.stringify(d))}catch(u){R("Failed to send screenshot request immediately:",u),ge.current.delete(n),me.current.delete(n),i(u);return}setTimeout(()=>{ge.current.has(n)&&(R(`Screenshot request timed out for id ${n}`),me.current.get(n)?.(new Error("Screenshot request timed out")),ge.current.delete(n),me.current.delete(n))},3e4)}),terminateApp:e=>new Promise((o,i)=>{if(!T.current||T.current.readyState!==WebSocket.OPEN)return R("WebSocket not open, cannot send terminateApp command."),i(new Error("WebSocket is not connected or connection is not open."));const n=`ui-term-${Date.now()}-${Math.random().toString(36).substring(2,9)}`,d={type:"terminateApp",id:n,bundleId:e};_e.current.set(n,o),De.current.set(n,i),x("Sending terminateApp request:",d);try{T.current.send(JSON.stringify(d))}catch(u){R("Failed to send terminateApp request immediately:",u),_e.current.delete(n),De.current.delete(n),i(u);return}G.current?.bumpActivity(),setTimeout(()=>{_e.current.has(n)&&(R(`terminateApp request timed out for id ${n}`),De.current.get(n)?.(new Error("terminateApp request timed out")),_e.current.delete(n),De.current.delete(n))},3e4)}),reconnect:()=>jt(),refreshAxTree:async()=>{const e=G.current;if(!e)throw new Error("Inspect mode is not active");return e.refresh()},getAxSnapshot:()=>Fe.current,setInspectHighlight:e=>{it(e?.id??null)},setInspectSelection:e=>{yt(e?.id??null),Le(e?vt.current:null);const o=Fe.current;e&&o?L("onInspectSelectionChange",We.current,{element:e,snapshot:o}):L("onInspectSelectionChange",We.current,null)},getAxStatus:()=>G.current?.getStatus()??"idle"}));const wn=Qr&&Re!==null;return w.jsxs("div",{ref:de,className:Ae("rc-container",r),style:{touchAction:"none"},onMouseDown:Ce,onMouseMove:Ce,onMouseUp:Ce,onMouseLeave:Ce,onTouchStart:Ce,onTouchMove:Ce,onTouchEnd:Ce,onTouchCancel:Ce,children:[wn&&Re&&w.jsxs(w.Fragment,{children:[w.jsx("div",{className:"rc-touch-indicator",style:{left:`${Re.containerX}px`,top:`${Re.containerY}px`}}),w.jsx("div",{className:"rc-touch-indicator",style:{left:`${Re.mirrorContainerX}px`,top:`${Re.mirrorContainerY}px`}})]}),Ot&&w.jsx("img",{ref:Ne,src:gr,alt:"",className:ae==="ios"?Ae("rc-phone-frame","rc-phone-frame-ios"):"rc-phone-frame",draggable:!1}),w.jsx("video",{ref:F,className:Ae("rc-video",!Ot&&"rc-video-frameless",!Br&&"rc-video-loading"),style:{...zr,...ie?{opacity:0,width:1,height:1,pointerEvents:"none"}:{},...Cr?{backgroundImage:`url("${Cr}")`,backgroundRepeat:"no-repeat",backgroundPosition:"center",backgroundSize:$e.loadingLogoSize}:{}},autoPlay:!0,playsInline:!0,muted:!0,tabIndex:ie?-1:0,onKeyDown:Tt,onKeyUp:Tt,onClick:Rn,onLoadedData:mn,onFocus:()=>{F.current&&(F.current.style.outline="none")},onBlur:()=>{F.current&&(F.current.style.outline="none")}}),ie&&w.jsx("video",{ref:Je,autoPlay:!0,playsInline:!0,muted:!0,style:{position:"absolute",width:1,height:1,opacity:0,pointerEvents:"none"}}),ie&&tr&&w.jsx(l.Suspense,{fallback:w.jsx("div",{children:"Loading iPhone Duo…"}),children:w.jsx(hi,{showFrame:p,modelUrl:O,outer:F.current,inner:Je.current,state:tr,setAngle:e=>Kt("setHingeAngle",{angleDegrees:e}),setOrientation:e=>Kt("setDuoOrientation",{orientation:e}),button:(e,o)=>Kt("performActions",{actions:[{type:o?"buttonDown":"buttonUp",button:e}]}),touch:(e,o,i,n)=>{const d=P.current;d?.readyState==="open"&&d.send(Kn(e,o,i,n))},onKeyDown:Tt,onKeyUp:Tt})}),ie&&nr&&w.jsx("div",{role:"alert",className:"rc-duo-error",children:nr}),!ie&&ot&&w.jsx(fi,{snapshot:ur,geometry:en,highlightedId:Wt,selectedId:Ht,mode:nn,cursorPosition:tn,frozenCursorPosition:rn,onSelectChange:(e,o)=>{yt(e?.id??null),e&&o?Le(o):e||Le(null);const i=Fe.current;e&&i?L("onInspectSelectionChange",We.current,{element:e,snapshot:i}):L("onInspectSelectionChange",We.current,null)},onTapElement:(e,o)=>{if(o){vr(o.x,o.y);return}const i=Fe.current;i&&on(e,i)}}),Vr?w.jsxs("div",{className:"rc-terminated",role:"status",children:[w.jsx("div",{className:"rc-terminated-title",children:"Instance terminated"}),w.jsx("div",{className:"rc-terminated-message",children:"This instance no longer exists and can't be reconnected."})]}):qr&&w.jsx("button",{type:"button",className:"rc-retry-button",onClick:Tn,children:"Retry"})]})}),Di=r=>typeof r.message=="string"?r.message:typeof r.error=="string"?r.error:null,Ti=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;exports.AX_UNAVAILABLE_ERROR=Nt;exports.DUO_BUTTONS=Pn;exports.DUO_DIMENSIONS=Mn;exports.DuoButtonSender=Un;exports.HingeSender=kn;exports.RemoteControl=_i;exports.axElementAtPoint=Hr;exports.axElementSelectorExpression=$r;exports.axElementSummary=Qt;exports.axElementsEqual=Jt;exports.axSnapshotsEqual=zt;exports.clampAxFrameForScreen=Wr;exports.duoPointerMode=Yn;exports.flatDisplayTouch=bn;exports.normalizeAndroidTree=Fr;exports.normalizeIosTree=xr;exports.panelTouch=In;
|