@limrun/ui 0.20.0 → 0.20.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-BjfxfJc4.mjs → GLTFLoader-CEdCEYr6.mjs} +1 -1
- package/dist/{GLTFLoader-Ccp1cQVL.js → GLTFLoader-yqDaHF46.js} +1 -1
- package/dist/core-BqXmROsc.mjs +2162 -0
- package/dist/core-D7ODbXln.js +2 -0
- package/dist/core.cjs +1 -1
- package/dist/core.js +1 -1
- package/dist/{duo-frame-D9832t6H.js → duo-frame-BMVxq-Qi.js} +2 -2
- package/dist/{duo-frame-CMiDITQA.mjs → duo-frame-DCl_2GS3.mjs} +3 -3
- package/dist/{duo-view-tndcvbIi.mjs → duo-view-DhzmW9X6.mjs} +2 -2
- package/dist/{duo-view-Bhr7zyWr.js → duo-view-UZazbOh-.js} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +2 -2
- package/dist/lite.cjs +1 -1
- package/dist/lite.js +2 -2
- package/dist/remote-control-Cl8nEKUE.js +1 -0
- package/dist/{remote-control-BBgt4TkM.mjs → remote-control-aGoEKYFB.mjs} +388 -405
- package/package.json +1 -3
- package/dist/core-BhHpU_lr.mjs +0 -2113
- package/dist/core-DkhLItUD.js +0 -2
- package/dist/remote-control-GLVdY8Xa.js +0 -1
package/dist/core-DkhLItUD.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";const Ie={INJECT_KEYCODE:0,INJECT_TEXT:1,INJECT_TOUCH_EVENT:2,INJECT_TWO_FINGER_TOUCH_EVENT:18,INJECT_SCROLL_EVENT:3,BACK_OR_SCREEN_ON:4,EXPAND_NOTIFICATION_PANEL:5,EXPAND_SETTINGS_PANEL:6,COLLAPSE_PANELS:7,GET_CLIPBOARD:8,SET_CLIPBOARD:9,SET_DISPLAY_POWER:10,ROTATE_DEVICE:11},Ne={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},i={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_UNKNOWN:0,KEYCODE_SOFT_LEFT:1,KEYCODE_SOFT_RIGHT:2,KEYCODE_HOME:3,KEYCODE_BACK:4,KEYCODE_CALL:5,KEYCODE_ENDCALL:6,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,KEYCODE_STAR:17,KEYCODE_POUND:18,DPAD_UP:19,DPAD_DOWN:20,DPAD_LEFT:21,DPAD_RIGHT:22,KEYCODE_DPAD_CENTER:23,KEYCODE_VOLUME_UP:24,KEYCODE_VOLUME_DOWN:25,KEYCODE_POWER:26,KEYCODE_CAMERA:27,KEYCODE_CLEAR:28,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,KEYCODE_SYM:63,KEYCODE_EXPLORER:64,KEYCODE_ENVELOPE:65,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,KEYCODE_AT:77,KEYCODE_NUM:78,KEYCODE_HEADSETHOOK:79,KEYCODE_FOCUS:80,KEYCODE_PLUS:81,MENU:82,KEYCODE_NOTIFICATION:83,KEYCODE_SEARCH:84,KEYCODE_MEDIA_PLAY_PAUSE:85,KEYCODE_MEDIA_STOP:86,KEYCODE_MEDIA_NEXT:87,KEYCODE_MEDIA_PREVIOUS:88,KEYCODE_MEDIA_REWIND:89,KEYCODE_MEDIA_FAST_FORWARD:90,KEYCODE_MUTE:91,KEYCODE_PAGE_UP:92,KEYCODE_PAGE_DOWN:93,KEYCODE_PICTSYMBOLS:94,KEYCODE_SWITCH_CHARSET:95,KEYCODE_BUTTON_A:96,KEYCODE_BUTTON_B:97,KEYCODE_BUTTON_C:98,KEYCODE_BUTTON_X:99,KEYCODE_BUTTON_Y:100,KEYCODE_BUTTON_Z:101,KEYCODE_BUTTON_L1:102,KEYCODE_BUTTON_R1:103,KEYCODE_BUTTON_L2:104,KEYCODE_BUTTON_R2:105,KEYCODE_BUTTON_THUMBL:106,KEYCODE_BUTTON_THUMBR:107,KEYCODE_BUTTON_START:108,KEYCODE_BUTTON_SELECT:109,KEYCODE_BUTTON_MODE:110,KEYCODE_ESCAPE:111,FORWARD_DEL:112,KEYCODE_CTRL_LEFT:113,KEYCODE_CTRL_RIGHT:114,KEYCODE_CAPS_LOCK:115,KEYCODE_SCROLL_LOCK:116,KEYCODE_META_LEFT:117,KEYCODE_META_RIGHT:118,KEYCODE_FUNCTION:119,KEYCODE_SYSRQ:120,KEYCODE_BREAK:121,KEYCODE_MOVE_HOME:122,KEYCODE_MOVE_END:123,KEYCODE_INSERT:124,KEYCODE_FORWARD:125,KEYCODE_MEDIA_PLAY:126,KEYCODE_MEDIA_PAUSE:127,KEYCODE_MEDIA_CLOSE:128,KEYCODE_MEDIA_EJECT:129,KEYCODE_MEDIA_RECORD:130,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_NUM_LOCK:143,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,KEYCODE_NUMPAD_LEFT_PAREN:162,KEYCODE_NUMPAD_RIGHT_PAREN:163,KEYCODE_VOLUME_MUTE:164,KEYCODE_INFO:165,KEYCODE_CHANNEL_UP:166,KEYCODE_CHANNEL_DOWN:167,KEYCODE_ZOOM_IN:168,KEYCODE_ZOOM_OUT:169,KEYCODE_TV:170,KEYCODE_WINDOW:171,KEYCODE_GUIDE:172,KEYCODE_DVR:173,KEYCODE_BOOKMARK:174,KEYCODE_CAPTIONS:175,KEYCODE_SETTINGS:176,KEYCODE_TV_POWER:177,KEYCODE_TV_INPUT:178,KEYCODE_STB_POWER:179,KEYCODE_STB_INPUT:180,KEYCODE_AVR_POWER:181,KEYCODE_AVR_INPUT:182,KEYCODE_PROG_RED:183,KEYCODE_PROG_GREEN:184,KEYCODE_PROG_YELLOW:185,KEYCODE_PROG_BLUE:186,KEYCODE_APP_SWITCH:187,KEYCODE_LANGUAGE_SWITCH:204,KEYCODE_ASSIST:219,KEYCODE_BRIGHTNESS_DOWN:220,KEYCODE_BRIGHTNESS_UP:221,KEYCODE_SLEEP:223,KEYCODE_WAKEUP:224,KEYCODE_SOFT_SLEEP:276},vt={KeyA:i.KEYCODE_A,KeyB:i.KEYCODE_B,KeyC:i.KEYCODE_C,KeyD:i.KEYCODE_D,KeyE:i.KEYCODE_E,KeyF:i.KEYCODE_F,KeyG:i.KEYCODE_G,KeyH:i.KEYCODE_H,KeyI:i.KEYCODE_I,KeyJ:i.KEYCODE_J,KeyK:i.KEYCODE_K,KeyL:i.KEYCODE_L,KeyM:i.KEYCODE_M,KeyN:i.KEYCODE_N,KeyO:i.KEYCODE_O,KeyP:i.KEYCODE_P,KeyQ:i.KEYCODE_Q,KeyR:i.KEYCODE_R,KeyS:i.KEYCODE_S,KeyT:i.KEYCODE_T,KeyU:i.KEYCODE_U,KeyV:i.KEYCODE_V,KeyW:i.KEYCODE_W,KeyX:i.KEYCODE_X,KeyY:i.KEYCODE_Y,KeyZ:i.KEYCODE_Z,Digit0:i.KEYCODE_0,Digit1:i.KEYCODE_1,Digit2:i.KEYCODE_2,Digit3:i.KEYCODE_3,Digit4:i.KEYCODE_4,Digit5:i.KEYCODE_5,Digit6:i.KEYCODE_6,Digit7:i.KEYCODE_7,Digit8:i.KEYCODE_8,Digit9:i.KEYCODE_9,Backquote:i.KEYCODE_GRAVE,Minus:i.KEYCODE_MINUS,Equal:i.KEYCODE_EQUALS,BracketLeft:i.KEYCODE_LEFT_BRACKET,BracketRight:i.KEYCODE_RIGHT_BRACKET,Backslash:i.KEYCODE_BACKSLASH,Semicolon:i.KEYCODE_SEMICOLON,Quote:i.KEYCODE_APOSTROPHE,Comma:i.KEYCODE_COMMA,Period:i.KEYCODE_PERIOD,Slash:i.KEYCODE_SLASH,Space:i.KEYCODE_SPACE,Tab:i.KEYCODE_TAB,Escape:i.KEYCODE_ESCAPE,ArrowUp:i.DPAD_UP,ArrowDown:i.DPAD_DOWN,ArrowLeft:i.DPAD_LEFT,ArrowRight:i.DPAD_RIGHT,Enter:i.ENTER,Backspace:i.DEL,Delete:i.FORWARD_DEL,Home:i.KEYCODE_MOVE_HOME,End:i.KEYCODE_MOVE_END,PageUp:i.KEYCODE_PAGE_UP,PageDown:i.KEYCODE_PAGE_DOWN,Insert:i.KEYCODE_INSERT,F1:i.KEYCODE_F1,F2:i.KEYCODE_F2,F3:i.KEYCODE_F3,F4:i.KEYCODE_F4,F5:i.KEYCODE_F5,F6:i.KEYCODE_F6,F7:i.KEYCODE_F7,F8:i.KEYCODE_F8,F9:i.KEYCODE_F9,F10:i.KEYCODE_F10,F11:i.KEYCODE_F11,F12:i.KEYCODE_F12,ShiftLeft:i.KEYCODE_SHIFT_LEFT,ShiftRight:i.KEYCODE_SHIFT_RIGHT,ControlLeft:i.KEYCODE_CTRL_LEFT,ControlRight:i.KEYCODE_CTRL_RIGHT,AltLeft:i.KEYCODE_ALT_LEFT,AltRight:i.KEYCODE_ALT_RIGHT,MetaLeft:i.KEYCODE_META_LEFT,MetaRight:i.KEYCODE_META_RIGHT,ContextMenu:i.MENU,Numpad0:i.KEYCODE_NUMPAD_0,Numpad1:i.KEYCODE_NUMPAD_1,Numpad2:i.KEYCODE_NUMPAD_2,Numpad3:i.KEYCODE_NUMPAD_3,Numpad4:i.KEYCODE_NUMPAD_4,Numpad5:i.KEYCODE_NUMPAD_5,Numpad6:i.KEYCODE_NUMPAD_6,Numpad7:i.KEYCODE_NUMPAD_7,Numpad8:i.KEYCODE_NUMPAD_8,Numpad9:i.KEYCODE_NUMPAD_9,NumpadDivide:i.KEYCODE_NUMPAD_DIVIDE,NumpadMultiply:i.KEYCODE_NUMPAD_MULTIPLY,NumpadSubtract:i.KEYCODE_NUMPAD_SUBTRACT,NumpadAdd:i.KEYCODE_NUMPAD_ADD,NumpadDecimal:i.KEYCODE_NUMPAD_DOT,NumpadComma:i.KEYCODE_NUMPAD_COMMA,NumpadEnter:i.KEYCODE_NUMPAD_ENTER,NumpadEqual:i.KEYCODE_NUMPAD_EQUALS};function Kt(t,e,n,s,E,d,c=1,m=0,C=0){const p=new ArrayBuffer(32),v=new DataView(p);let w=0;v.setUint8(w,Ie.INJECT_TOUCH_EVENT),w+=1;const k=t===Ne.ACTION_POINTER_DOWN?Ne.ACTION_DOWN:t===Ne.ACTION_POINTER_UP?Ne.ACTION_UP:t;return v.setUint8(w,k),w+=1,v.setBigInt64(w,BigInt(e),!0),w+=8,v.setInt32(w,Math.round(E),!0),w+=4,v.setInt32(w,Math.round(d),!0),w+=4,v.setUint16(w,n,!0),w+=2,v.setUint16(w,s,!0),w+=2,v.setInt16(w,Math.round(c*65535),!0),w+=2,v.setInt32(w,m,!0),w+=4,v.setInt32(w,C,!0),p}function Zt(t,e,n,s,E,d,c){const m=new ArrayBuffer(24),C=new DataView(m);let p=0;return C.setUint8(p,Ie.INJECT_TWO_FINGER_TOUCH_EVENT),p+=1,C.setUint8(p,t),p+=1,C.setInt32(p,Math.round(s),!0),p+=4,C.setInt32(p,Math.round(E),!0),p+=4,C.setInt32(p,Math.round(d),!0),p+=4,C.setInt32(p,Math.round(c),!0),p+=4,C.setUint16(p,e,!0),p+=2,C.setUint16(p,n,!0),p+=2,C.setUint16(p,0,!0),m}function Mt(t,e=!0){const s=new TextEncoder().encode(t),E=new ArrayBuffer(14+s.length),d=new DataView(E);let c=0;return d.setUint8(c,Ie.SET_CLIPBOARD),c+=1,d.setBigInt64(c,BigInt(0),!1),c+=8,d.setUint8(c,e?1:0),c+=1,d.setUint32(c,s.length,!1),c+=4,new Uint8Array(E,c).set(s),E}function Je(t,e,n=0,s=0){const E=new ArrayBuffer(14),d=new DataView(E);let c=0;return d.setUint8(c,Ie.INJECT_KEYCODE),c+=1,d.setUint8(c,t),c+=1,d.setInt32(c,e,!0),c+=4,d.setInt32(c,n,!0),c+=4,d.setInt32(c,s,!0),E}const en={width:164.6,height:117.8,depth:5.2};function tn(t,e,n){return t=Math.max(0,Math.min(1,t)),e=Math.max(0,Math.min(1,e)),n===1?{x:e,y:1-t}:n===2?{x:1-t,y:1-e}:n===3?{x:1-e,y:t}:{x:t,y:e}}function nn(t){return Number.isFinite(t)&&t>=0&&t<=180}function rn(t,e){return{x:Math.max(0,Math.min(1,t)),y:Math.max(0,Math.min(1,1-e))}}function on(t,e,n){return e&&(t||!n)?"touch":t?"ignore":"orbit"}function wt(t,e,n,s){if(!Number.isInteger(t)||t<0||t>3||!Number.isInteger(e)||e<1||e>255||!Number.isFinite(n)||!Number.isFinite(s)||n<0||n>1||s<0||s>1)throw new RangeError("Invalid display touch coordinates");const E=new ArrayBuffer(12),d=new DataView(E);return d.setUint8(0,19),d.setUint8(1,t),d.setUint8(2,e),d.setFloat32(4,n,!0),d.setFloat32(8,s,!0),E}class an{constructor(e,n){this.send=e,this.failed=n}send;failed;latest;running=!1;stopped=!1;set(e){this.stopped||!nn(e)||(this.latest=e,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 e=this.latest;this.latest=void 0,await this.send(e)}}catch(e){this.latest=void 0,this.stopped||this.failed(e)}finally{this.running=!1}}}}const sn={side:"Sleep/Wake",volumeUp:"Volume Up",volumeDown:"Volume Down"};class cn{constructor(e,n){this.send=e,this.failed=n}send;failed;held;tail=Promise.resolve();timeout;press(e){this.held||(this.held=e,this.enqueue(e,!0),this.timeout=setTimeout(()=>this.release(),1e4))}release(){if(!this.held)return;clearTimeout(this.timeout);const e=this.held;this.held=void 0,this.enqueue(e,!1)}enqueue(e,n){this.tail=this.tail.then(()=>this.send(e,n)).catch(this.failed)}}const je="Accessibility unavailable on this device.",Xe=500,Yt=(t,e)=>Math.abs(t.x-e.x)<.5&&Math.abs(t.y-e.y)<.5&&Math.abs(t.width-e.width)<.5&&Math.abs(t.height-e.height)<.5,ln=t=>Math.max(0,t.width)*Math.max(0,t.height),dn=t=>{const e=t.find(n=>n.frame&&n.frame.width>0&&n.frame.height>0);return e?.frame?((Math.abs(e.frame.x)>.5||Math.abs(e.frame.y)>.5)&&console.warn(`[ax-tree] iOS root frame is not anchored at (0,0): (${e.frame.x},${e.frame.y}). Element positions may be slightly off from the rendered video.`),{x:0,y:0,width:e.frame.width,height:e.frame.height}):{x:0,y:0,width:1,height:1}},un=t=>{const e={};return typeof t.AXUniqueId=="string"&&t.AXUniqueId.length>0&&(e.AXUniqueId=t.AXUniqueId),typeof t.AXLabel=="string"&&t.AXLabel.length>0&&(e.AXLabel=t.AXLabel),typeof t.type=="string"&&t.type.length>0&&(e.className=t.type),e},En=t=>{const e={};for(const[n,s]of Object.entries(t))n!=="children"&&(e[n]=s);return e};function bt(t){const e=Array.isArray(t)?t:[t],n=dn(e),s=[],E=(d,c)=>{if(s.length>=Xe)return;const m=d.frame;if(m&&m.width>0&&m.height>0&&!Yt(m,n)){const p=d.role_description||d.role||"",v=(typeof d.AXLabel=="string"?d.AXLabel:"")||(typeof d.title=="string"?d.title:"")||"";s.push({id:typeof d.AXUniqueId=="string"&&d.AXUniqueId.length>0?d.AXUniqueId:c,path:c,label:v,value:typeof d.AXValue=="string"?d.AXValue:"",role:p,type:typeof d.type=="string"?d.type:"",enabled:d.enabled!==!1,focused:d.focused===!0,frame:{x:m.x,y:m.y,width:m.width,height:m.height},selectors:un(d),raw:En(d)})}const C=Array.isArray(d.children)?d.children:[];for(let p=0;p<C.length&&s.length<Xe;p++)E(C[p],`${c}.${p}`)};for(let d=0;d<e.length&&s.length<Xe;d++)E(e[d],String(d));return{platform:"ios",screen:{width:n.width,height:n.height},elements:s,capturedAt:Date.now()}}const fn=t=>{let e={x:0,y:0,width:1,height:1},n=0;for(const s of t){const E=s.parsedBounds;if(!E)continue;const d=E.right-E.left,c=E.bottom-E.top,m=Math.max(0,d)*Math.max(0,c);m>n&&(n=m,e={x:0,y:0,width:d,height:c})}return e},mn=t=>{const e={};return typeof t.resourceId=="string"&&t.resourceId.length>0&&(e.resourceId=t.resourceId),typeof t.contentDesc=="string"&&t.contentDesc.length>0&&(e.contentDesc=t.contentDesc),typeof t.text=="string"&&t.text.length>0&&(e.text=t.text),typeof t.className=="string"&&t.className.length>0&&(e.className=t.className),e};function Nt(t){const e=fn(t),n=[];for(let s=0;s<t.length&&n.length<Xe;s++){const E=t[s],d=E.parsedBounds;if(!d)continue;const c=Math.max(0,d.right-d.left),m=Math.max(0,d.bottom-d.top);if(c<=0||m<=0)continue;const C={x:d.left,y:d.top,width:c,height:m};if(Yt(C,{x:0,y:0,width:e.width,height:e.height}))continue;const p=E.contentDesc||E.text||"",v=E.className||"";n.push({id:E.resourceId&&E.resourceId.length>0?E.resourceId:E.contentDesc&&E.contentDesc.length>0?`cd:${E.contentDesc}`:String(s),path:String(s),label:p,value:typeof E.text=="string"?E.text:"",role:v,type:v,enabled:E.enabled!==!1,focused:E.focused===!0,frame:C,selectors:mn(E),raw:{...E}})}return{platform:"android",screen:{width:e.width,height:e.height},elements:n,capturedAt:Date.now()}}function hn(t,e){const n=Math.max(0,t.x),s=Math.max(0,t.y),E=Math.min(e.width,t.x+t.width),d=Math.min(e.height,t.y+t.height),c=Math.max(0,E-n),m=Math.max(0,d-s);return c>0&&m>0?{x:n,y:s,width:c,height:m}:null}function Rt(t,e){if(t===e)return!0;if(t.id!==e.id||t.path!==e.path||t.label!==e.label||t.value!==e.value||t.role!==e.role||t.type!==e.type||t.enabled!==e.enabled||t.focused!==e.focused)return!1;const n=t.frame,s=e.frame;return n.x===s.x&&n.y===s.y&&n.width===s.width&&n.height===s.height}function It(t,e){if(t===e)return!0;if(!t||!e||t.platform!==e.platform||t.screen.width!==e.screen.width||t.screen.height!==e.screen.height||t.elements.length!==e.elements.length)return!1;for(let n=0;n<t.elements.length;n++)if(!Rt(t.elements[n],e.elements[n]))return!1;return!0}function pn(t,e,n){let s=null,E=1/0;for(const d of t.elements){const c=d.frame;if(e<c.x||n<c.y||e>c.x+c.width||n>c.y+c.height)continue;const m=ln(c);m<E&&(E=m,s=d)}return s}function Cn(t,e){if(e==="ios"){if(t.selectors.AXUniqueId)return`client.tapElement({ AXUniqueId: ${JSON.stringify(t.selectors.AXUniqueId)} })`;if(t.selectors.AXLabel){const n=t.selectors.className?`, type: ${JSON.stringify(t.selectors.className)}`:"";return`client.tapElement({ AXLabel: ${JSON.stringify(t.selectors.AXLabel)}${n} })`}return null}return t.selectors.resourceId?`client.tap({ selector: { resourceId: ${JSON.stringify(t.selectors.resourceId)} } })`:t.selectors.contentDesc?`client.tap({ selector: { contentDesc: ${JSON.stringify(t.selectors.contentDesc)} } })`:t.selectors.text?`client.tap({ selector: { text: ${JSON.stringify(t.selectors.text)} } })`:null}function Ut(t){const e=t.role||t.type||"";if(!e)return"element";let n=e.replace(/^AX/,"");return n.includes(".")&&(n=n.split(".").pop()),n==="GenericElement"?"Element":(n=n.replace(/([a-z])([A-Z])/g,"$1 $2"),n)}const Dt=80;function On(t){const e=Ut(t),n=t.label||t.value||"";if(!n)return e;const s=n.length>Dt?n.slice(0,Dt).trimEnd()+"…":n;return`${e} · ${s}`}const _n=500,Dn=2e3,gt=5e3,gn=8e3,Tn=1200,Sn=250,yn=()=>`ax-rc-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;class An{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(e){this.platform=e.platform,this.send=e.send,this.onSnapshot=e.onSnapshot,this.onStatusChange=e.onStatusChange,this.baseIntervalMs=e.baseIntervalMs??_n,this.maxBackoffMs=e.maxBackoffMs??Dn,this.androidElementTreeOptions=e.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(e,n){if(this.status!==e&&(this.status=e,!!this.onStatusChange))try{this.onStatusChange(e,n)}catch(s){console.error("[AxFetcher] onStatusChange threw:",s)}}bumpActivity(){if(!this.running)return;const e=Date.now();this.boostUntilMs=e+Tn;const n=Math.max(150,Math.floor(this.baseIntervalMs/2));if(e-this.lastBumpAtMs<n){this.currentInterval=this.baseIntervalMs;return}this.lastBumpAtMs=e,this.currentInterval=this.baseIntervalMs,this.timer!==void 0&&(window.clearTimeout(this.timer),this.timer=void 0),this.inflight||this.runOnce()}async refresh(){const e=await this.requestOnce();return this.running&&this.deliver(e),e}getLatest(){return this.lastSnapshot}handleMessage(e){if(!e||typeof e.id!="string")return!1;const n=e.id;if(!this.pending.get(n))return!1;if(this.platform==="ios"){if(e.type!=="elementTreeResult")return!1;const m=typeof e.error=="string"?e.error:null;if(m)return this.settleReject(n,new Error(m)),!0;const C=typeof e.json=="string"?e.json:"";try{const p=JSON.parse(C),v=bt(p);this.settleResolve(n,v)}catch(p){this.settleReject(n,p instanceof Error?p:new Error(String(p)))}return!0}if(e.type!=="getElementTreeResult")return!1;const E=e.error;if(E&&typeof E=="object"){const m=typeof E.message=="string"?E.message:"getElementTree failed";return this.settleReject(n,new Error(m)),!0}const d=e.payload,c=Array.isArray(d?.nodes)?d.nodes:[];try{const m=Nt(c);this.settleResolve(n,m)}catch(m){this.settleReject(n,m instanceof Error?m:new Error(String(m)))}return!0}buildRequest(e){return this.platform==="ios"?{type:"elementTree",id:e}:{type:"getElementTree",id:e,...this.androidElementTreeOptions}}async requestOnce(){const e=yn();return new Promise((n,s)=>{const E=window.setTimeout(()=>{this.pending.delete(e),s(new Error("elementTree request timed out"))},gn+(this.androidElementTreeOptions?.waitForIdleTimeoutMs??0));this.pending.set(e,{resolve:n,reject:s,timer:E}),this.send(this.buildRequest(e))||(window.clearTimeout(E),this.pending.delete(e),s(new Error("elementTree send failed (WebSocket not open)")))})}async runOnce(){if(this.running&&!this.inflight){this.inflight=!0;try{const e=await this.requestOnce();if(!this.running)return;this.deliver(e)}catch(e){if(!this.running)return;const n=e instanceof Error?e.message:String(e),s=/unavailable|not (yet )?running|failed|timeout/i.test(n);this.currentInterval=s?gt:Math.min(this.currentInterval*2,this.maxBackoffMs),this.setStatus(s?"unavailable":"error",n)}finally{this.inflight=!1,this.scheduleNext()}}}deliver(e){const n=this.lastSnapshot;if(It(n,e)){this.currentInterval=Math.min(this.currentInterval*2,this.maxBackoffMs),this.lastSnapshot=e,e.errors?.includes(je)||this.setStatus("ready");return}this.lastSnapshot=e,this.currentInterval=this.baseIntervalMs,e.errors?.includes(je)?(this.currentInterval=gt,this.setStatus("unavailable",je)):this.setStatus("ready"),this.onSnapshot(e)}scheduleNext(){if(!this.running)return;this.timer!==void 0&&window.clearTimeout(this.timer);const e=Date.now()<this.boostUntilMs?Math.min(Sn,this.currentInterval):this.currentInterval;this.timer=window.setTimeout(()=>{this.timer=void 0,this.runOnce()},e)}settleResolve(e,n){const s=this.pending.get(e);s&&(window.clearTimeout(s.timer),this.pending.delete(e),s.resolve(n))}settleReject(e,n){const s=this.pending.get(e);s&&(window.clearTimeout(s.timer),this.pending.delete(e),s.reject(n))}failAllPending(e){for(const[n,s]of this.pending.entries())window.clearTimeout(s.timer),s.reject(new Error(e)),this.pending.delete(n)}}function Tt(t,e){if(e!=null&&(!Number.isFinite(e)||e<0||e>4e3)){console.warn("RemoteControl: jitterBufferTargetMs must be a finite number between 0 and 4000.");return}if(!("jitterBufferTarget"in t))return;const n=e??null;try{t.jitterBufferTarget!==n&&(t.jitterBufferTarget=n)}catch(s){console.warn("RemoteControl: could not set the jitter buffer target.",s)}}const kt=`(function(){"use strict";let e,t;self.onmessage=async({data:s})=>{s.type==="start"?(e=new AbortController,t=s.readable.pipeTo(s.writable,{signal:e.signal}).catch(o=>{e?.signal.aborted||self.postMessage({type:"error",message:String(o)})})):s.type==="stop"&&(e?.abort(),await t,self.postMessage({type:"stopped"}),self.close())}})();
|
|
2
|
-
`,St=typeof self<"u"&&self.Blob&&new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);",kt],{type:"text/javascript;charset=utf-8"});function vn(t){let e;try{if(e=St&&(self.URL||self.webkitURL).createObjectURL(St),!e)throw"";const n=new Worker(e,{name:t?.name});return n.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(e)}),n}catch{return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(kt),{name:t?.name})}}function Kn(t,e,n){const{MediaStreamTrackProcessor:s,MediaStreamTrackGenerator:E}=globalThis,d=e.getVideoTracks()[0];let c,m,C,p,v=!1;const w=()=>{v||(v=!0,c?.stop(),m?.stop(),C&&(C.postMessage({type:"stop"}),p=setTimeout(()=>C?.terminate(),1e3)))},k=b=>{t.srcObject=b,t.play().catch(()=>{})},T=b=>{v||(w(),n(b),k(e))};try{if(d&&s&&E){c=d.clone();const b=new s({track:c,maxBufferSize:1}),V=new E({kind:"video"});m=V,C=new vn,C.onmessage=({data:F})=>{F.type==="error"?T(new Error(F.message)):F.type==="stopped"&&(clearTimeout(p),C?.terminate())},C.onerror=F=>T(new Error(F.message)),C.postMessage({type:"start",readable:b.readable,writable:V.writable},[b.readable,V.writable]),k(new MediaStream(e.getTracks().map(F=>F===d?V:F)))}else k(e)}catch(b){T(b)}return w}function Re(t){return typeof t=="number"&&Number.isFinite(t)}function ge(t,e){if(!(!Re(t)||!Re(e)||t<e||e<0))return t-e}class Mn{previous=new Map;reset(){this.previous.clear()}read(e,n,s){const E={timestamp:0,video:[],audio:[]};s==null?E.requestedTargetMs=null:Re(s)&&s>=0&&s<=4e3&&(E.requestedTargetMs=s);const d=new Map;return e.forEach(c=>{if(c.type!=="inbound-rtp"||!Re(c.timestamp))return;const m=c.kind??c.mediaType;if(m!=="video"&&m!=="audio")return;const C=n.filter(Y=>Y.kind===m),p=c.trackIdentifier?C.find(Y=>Y.trackId===c.trackIdentifier):c.mid!=null?C.find(Y=>Y.mid===c.mid):C.length===1?C[0]:void 0;if(!p)return;const v=this.previous.get(c.id),k=v?.trackId===p.trackId&&v.stats.ssrc===c.ssrc?v.stats:void 0,T=k?c.timestamp-k.timestamp:void 0,b={id:c.id,trackId:p.trackId,timestamp:c.timestamp};if(T!==void 0&&T>0){b.intervalMs=T;const Y=ge(c.jitterBufferEmittedCount,k?.jitterBufferEmittedCount),L=ge(c.jitterBufferDelay,k?.jitterBufferDelay);Y!==void 0&&Y>0&&L!==void 0&&(b.bufferDelayMs=L/Y*1e3);const $=ge(c.bytesReceived,k?.bytesReceived);$!==void 0&&(b.bitrateBps=$*8e3/T)}if(m==="video"){const Y={...b,display:p.display??"primary"};if(b.intervalMs!==void 0){const L=ge(c.framesDecoded,k?.framesDecoded);L!==void 0&&(Y.fps=L*1e3/b.intervalMs),Y.droppedFrames=ge(c.framesDropped,k?.framesDropped),Y.freezes=ge(c.freezeCount,k?.freezeCount)}E.video.push(Y)}else E.audio.push(b);E.timestamp=Math.max(E.timestamp,c.timestamp),d.set(c.id,k&&c.timestamp<=k.timestamp?v:{stats:c,trackId:p.trackId});const V=c.transportId?e.get(c.transportId):void 0,F=V?.selectedCandidatePairId?e.get(V.selectedCandidatePairId):void 0;F?.state==="succeeded"&&Re(F.currentRoundTripTime)&&F.currentRoundTripTime>=0&&(E.rttMs=F.currentRoundTripTime*1e3)}),this.previous=d,E.video.length||E.audio.length?E:null}}const it=new WeakSet;function wn(t,e,n){const{peer:s,displays:E}=t,d=new Mn;let c,m=!1,C=!1,p=!1,v=0,w=!1,k=!1;const T=()=>!m&&!document.hidden&&s.connectionState==="connected",b=L=>{if(!(!L&&!w)){w=L!==null;try{e()?.(L)}catch($){console.error('[RemoteControl] customer callback "onPlaybackStats" threw:',$)}}},V=()=>{C=!1,v++,clearTimeout(c),d.reset(),b(null)},F=async()=>{if(p||!T())return;if(it.has(s)){c=setTimeout(()=>{F()},2e3);return}p=!0,it.add(s);const L=v;try{const $=await s.getStats();if(L!==v||!T())return;const B=s.getTransceivers().filter(J=>(J.currentDirection==="recvonly"||J.currentDirection==="sendrecv")&&J.receiver.track.readyState!=="ended").map(J=>({trackId:J.receiver.track.id,kind:J.receiver.track.kind,mid:J.mid,display:E.get(J.receiver)}));b(d.read($,B,n())),k=!1}catch($){if(L!==v||!T())return;k||console.warn("[RemoteControl] could not read playback stats:",$),k=!0,d.reset(),b(null)}finally{p=!1,it.delete(s),C&&T()&&(c=setTimeout(()=>{F()},L===v?2e3:0))}},Y=()=>{if(!T()){V();return}C||(C=!0,F())};return document.addEventListener("visibilitychange",Y),s.addEventListener("connectionstatechange",Y),Y(),()=>{m=!0,document.removeEventListener("visibilitychange",Y),s.removeEventListener("connectionstatechange",Y),V()}}function Yn(t,e){const n=t.createDataChannel("latency-trace-v1",{ordered:!0,negotiated:!0,id:2});let s=!1,E=!1,d=0;return n.onmessage=c=>{if(E)return;let m;try{m=JSON.parse(c.data)}catch(C){console.warn("Invalid latency trace message",C);return}m&&typeof m=="object"&&!Array.isArray(m)&&e(m)},n.onclose=()=>{E=!0,s=!1},{accept(c){s=!E&&c===1},wrap(c){if(!s||c.byteLength!==32)return c;const m=new DataView(c);if(m.getUint8(0)!==2||m.getUint8(1)>2)return c;const C=new ArrayBuffer(38),p=new DataView(C);return p.setUint8(0,240),p.setUint8(1,1),p.setUint32(2,++d,!0),new Uint8Array(C,6).set(new Uint8Array(c)),C},close(){E=!0,s=!1,n.onmessage=null,n.onclose=null,n.close()}}}class bn{generation=0;tail=Promise.resolve();get currentGeneration(){return this.generation}enqueue(e){const n=++this.generation;return this.append(n,e)}enqueueCurrent(e){return this.append(this.generation,e)}append(e,n){const s={generation:e,isCurrent:()=>e===this.generation},E=this.tail.then(()=>n(s));return this.tail=E.catch(()=>{}),E}invalidate(){++this.generation}}function Nn(t){if(!t||typeof t!="object")return null;const e=t;if(e.type!=="cameraRequest"||typeof e.active!="boolean")return null;const n={active:e.active};return(e.facingMode==="user"||e.facingMode==="environment")&&(n.facingMode=e.facingMode),n}function Rn(t){const e={frameRate:{ideal:30,max:30}};return t?.facingMode&&(e.facingMode={ideal:t.facingMode}),e}function In(t,e){return!t||t.facingMode!==e.facingMode}function Un(t){const e=t.getSettings();return{width:e.width,height:e.height,frameRate:e.frameRate,deviceId:e.deviceId,label:t.label||void 0,facingMode:e.facingMode}}function kn(t){return{type:"cameraResult",granted:!0,camera:Un(t)}}const ae=(...t)=>{window.debugRemoteControl&&console.log(...t)},S=(...t)=>{window.debugRemoteControl&&console.warn(...t)},P=(t,e,...n)=>{if(e)try{e(...n)}catch(s){console.error(`[RemoteControl] customer callback "${t}" threw:`,s)}},Pt=t=>t.includes("/android_")?"android":"ios",yt=(t,e)=>{const n=new URL(t);return n.searchParams.set("token",e),n.toString()},ot=3,Pn=1e3,Ln=15e3,Fn=3e3,Bn=4e3;function At(){const t=crypto.getRandomValues(new Uint8Array(16));t[6]=t[6]&15|64,t[8]=t[8]&63|128;const e=Array.from(t,n=>n.toString(16).padStart(2,"0")).join("");return`${e.slice(0,8)}-${e.slice(8,12)}-${e.slice(12,16)}-${e.slice(16,20)}-${e.slice(20)}`}function xn(t){let e={...t};const{url:n,token:s,deviceModel:E}=e,d=e.sessionId??At(),c=e.platform??Pt(n??"");let m={connection:"idle",videoReady:!1,controlReady:!1,duo:!1,duoState:null};const C=r=>{m={...m,...r},P("onStateChange",e.onStateChange,m)},p=r=>C({videoReady:r}),v=r=>C({duoState:r}),w=r=>C({duoError:r}),k=r=>C({duo:r}),T=r=>ae(r);let b=null,V;const F=()=>{V?.(),V=b&&e.onPlaybackStats?wn(b,()=>e.onPlaybackStats,()=>e.jitterBufferTargetMs):void 0},Y=new Map,L=new Set,$=new Set,B=new Map;let J=!1;const Ue=new Map,at=(r,u,a)=>{u.stop?.(),u.stop=Kn(r,a,l=>S("Video playback fallback:",l))},Lt=()=>{Ue.clear();for(const[r,u]of Y)u.clear?.(),u.stop?.(),u.stop=void 0,r.srcObject=null};let Ee=!1,Te=!1,ke=0,D=null,N=null,x=null,Pe=null,fe,Se,ye,Le,me,le=0,Fe=0,ne=!1,de=null,z=null,ue;const Qe=new bn;let Ae=null,Be=null,ze=e.microphoneEnabled??!1,Ze=!1,ve=null,te=null,xe=0,st=Promise.resolve(),he=null,Ke=!1,re=new Map,ee=new Map,se=new Map,ie=new Map,q=null,Me=null,ct=0;const We=r=>{if(r===null&&Me===null)return;Me=r;const u=++ct;queueMicrotask(()=>{u===ct&&P("onAxSnapshotChange",e.onAxSnapshotChange,r)})};let pe=null,Ce=new Map;const Ft=(r,u)=>new Promise((a,l)=>{const y=D;if(!y||y.readyState!==WebSocket.OPEN){l(new Error("Simulator disconnected"));return}const h=At(),O=setTimeout(()=>{Ce.delete(h),l(new Error("Device control timed out"))},5e3);Ce.set(h,{resolve:a,reject:l,timer:O}),y.send(JSON.stringify({type:r,id:h,...u}))}),Oe=r=>{pe!==r&&(pe=r,C({connection:r}),P("onConnectionStateChange",e.onConnectionStateChange,r))},ce=r=>{!x||x.readyState!=="open"||(x.send(Pe?.wrap(r)??r),q?.bumpActivity())},Bt=()=>{D&&D.readyState===WebSocket.OPEN&&D.send(JSON.stringify({type:"keepAlive",sessionId:d}))},lt=()=>{fe&&window.clearInterval(fe),fe=window.setInterval(Bt,1e4)},we=()=>{fe&&(window.clearInterval(fe),fe=void 0)},qe=()=>{Se&&(window.clearTimeout(Se),Se=void 0)},Ve=()=>{ye&&(window.clearTimeout(ye),ye=void 0)},Ye=()=>{Le&&(window.clearInterval(Le),Le=void 0)},be=()=>{me!==void 0&&(window.clearTimeout(me),me=void 0)},xt=()=>{Ke||(Ke=!0,Ye(),p(!0),Oe("connected"))},H=r=>{for(const u of r.getTracks())try{u.stop()}catch(a){S("track.stop() failed:",a)}},Wt=()=>{const r=z;r&&(z=null,H(r))},dt=r=>{const u=st.then(r).catch(a=>{S("microphone operation failed:",a)});return st=u,u},et=()=>ze||Ze,ut=r=>{const u=`ui-mic-${Date.now()}-${Math.random().toString(36).substring(2,9)}`;he=u,r.send(JSON.stringify({type:"microphoneStart",id:u}))},tt=()=>dt(()=>qt()),qt=async()=>{const r=xe,u=()=>r===xe&&et(),a=f=>{P("onMicrophoneStateChange",e.onMicrophoneStateChange,{active:!1,error:f})};if(!u())return;const l=D,y=ve;if(!l||l.readyState!==WebSocket.OPEN||!y||te)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)."),a("Microphone capture requires a secure context (https)");return}let h=null;try{h=await navigator.mediaDevices.getUserMedia({audio:!0,video:!1})}catch(f){console.warn("[RemoteControl] microphone getUserMedia denied/failed:",f)}if(!u()){h&&H(h);return}if(!h){a("Microphone permission denied or no device available");return}const O=h.getAudioTracks()[0]??null;if(!O){H(h),a("Captured stream has no audio track");return}try{await y.replaceTrack(O)}catch(f){S("replaceTrack(audioTrack) failed:",f),H(h),a("Failed to attach the microphone track to the connection");return}if(!u()){try{await y.replaceTrack(null)}catch(f){S("replaceTrack(null) on stale mic attach failed:",f)}H(h);return}te=h,O.onended=()=>{te===h&&$e("microphone capture ended by the browser")},ut(l),P("onMicrophoneStateChange",e.onMicrophoneStateChange,{active:!0,label:O.label||void 0})},$e=r=>(++xe,he=null,dt(async()=>{const u=ve,a=te;if(te=null,u&&a)try{await u.replaceTrack(null)}catch(y){S("replaceTrack(null) on mic detach failed:",y)}a&&H(a);const l=D;if(a&&l&&l.readyState===WebSocket.OPEN){const y=`ui-mic-${Date.now()}-${Math.random().toString(36).substring(2,9)}`;l.send(JSON.stringify({type:"microphoneStop",id:y}))}(a||r)&&P("onMicrophoneStateChange",e.onMicrophoneStateChange,{active:!1,...r!==void 0&&{error:r}})})),Et=(r,u)=>{let a;try{a=kn(u),console.info(`[RemoteControl] camera capture: ${a.camera?.width}x${a.camera?.height} @ ${a.camera?.frameRate??"?"}fps`+(a.camera?.label?` — ${a.camera.label}`:""))}catch(l){S("getSettings() on outbound camera track failed:",l),a={type:"cameraResult",granted:!0,camera:{label:u.label||void 0}}}r.send(JSON.stringify(a)),P("onCameraDemandChange",e.onCameraDemandChange,!0,!0,a.camera)},Vt=r=>{if(!r)return;const u=r.indexOf("/"),l=(u>=0?r.slice(u+1):r).toUpperCase();return l==="HEVC"?"H265":l},$t=async()=>{const r=de,u=e.onCameraStats;if(!r||!u)return;let a;try{a=await r.getStats()}catch{return}let l,y,h;if(a.forEach(R=>{R.type==="outbound-rtp"&&R.kind==="video"?l=R:R.type==="remote-inbound-rtp"&&R.kind==="video"&&(h=R)}),l?.codecId){const R=a.get(l.codecId);R&&(y=R.mimeType)}if(!l)return;const O=l.timestamp??Date.now(),f=Be;let j,U,X;if(f&&O>f.timestamp){const R=(O-f.timestamp)/1e3;if(typeof l.framesEncoded=="number"&&typeof f.framesEncoded=="number"&&(j=Math.max(0,(l.framesEncoded-f.framesEncoded)/R)),typeof l.bytesSent=="number"&&typeof f.bytesSent=="number"&&(U=Math.max(0,(l.bytesSent-f.bytesSent)*8/R)),typeof l.packetsSent=="number"&&typeof f.packetsSent=="number"&&h&&typeof h.packetsLost=="number"&&typeof f.packetsLost=="number"){const A=l.packetsSent-f.packetsSent,Ge=h.packetsLost-f.packetsLost;A>0&&(X=Math.max(0,Math.min(100,Ge/A*100)))}}Be={timestamp:O,framesEncoded:l.framesEncoded,bytesSent:l.bytesSent,packetsSent:l.packetsSent,packetsLost:h?.packetsLost};const M={codec:Vt(y),encoderImplementation:l.encoderImplementation,hardwareAccelerated:typeof l.powerEfficientEncoder=="boolean"?l.powerEfficientEncoder:void 0,framesPerSecond:j,framesEncoded:l.framesEncoded,bitrateBps:U,width:l.frameWidth,height:l.frameHeight,qualityLimitationReason:l.qualityLimitationReason,rttMs:typeof h?.roundTripTime=="number"?h.roundTripTime*1e3:void 0,packetsLostPct:X};P("onCameraStats",e.onCameraStats,M)},ft=()=>{Ae===null&&(Be=null,Ae=setInterval(()=>{$t()},1e3))},He=()=>{Ae!==null&&(clearInterval(Ae),Ae=null),Be=null,P("onCameraStats",e.onCameraStats,null)},Ht=(r,u,a,l)=>Qe.enqueue(async({isCurrent:y})=>{const h=()=>y()&&l()&&D===u&&de===a;if(!h())return;if(!r.active){const M=z;try{await a.replaceTrack(null)}catch(R){S("replaceTrack(null) on camera detach failed:",R)}if(z===M&&(z=null,ue=void 0,M&&H(M)),He(),!h())return;P("onCameraDemandChange",e.onCameraDemandChange,!1);return}P("onCameraDemandChange",e.onCameraDemandChange,!0);const O=z,f=O?.getVideoTracks()[0],j=ue;if(f?.readyState==="live"&&j&&!In(j,r)){ue=r,Et(u,f),ft();return}if(O){try{await a.replaceTrack(null)}catch(M){S("replaceTrack(null) before camera switch failed:",M)}if(z===O&&(z=null,ue=void 0,H(O)),He(),!h())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."),!h())return;u.send(JSON.stringify({type:"cameraResult",granted:!1})),P("onCameraDemandChange",e.onCameraDemandChange,!0,!1);return}let U=null;try{U=await navigator.mediaDevices.getUserMedia({video:Rn(r),audio:!1})}catch(M){console.warn("[RemoteControl] getUserMedia denied/failed:",M)}if(!h()){U&&H(U);return}if(!U){u.send(JSON.stringify({type:"cameraResult",granted:!1})),P("onCameraDemandChange",e.onCameraDemandChange,!0,!1);return}const X=U.getVideoTracks()[0]??null;if(!X){if(H(U),!h())return;u.send(JSON.stringify({type:"cameraResult",granted:!1})),P("onCameraDemandChange",e.onCameraDemandChange,!0,!1);return}try{X.contentHint="motion"}catch{}try{await a.replaceTrack(X)}catch(M){if(S("replaceTrack(videoTrack) failed:",M),H(U),!h())return;u.send(JSON.stringify({type:"cameraResult",granted:!1})),P("onCameraDemandChange",e.onCameraDemandChange,!0,!1);return}if(!h()){try{await a.replaceTrack(null)}catch(M){S("replaceTrack(null) for stale camera attach failed:",M)}H(U);return}try{const M=a.getParameters();(!M.encodings||M.encodings.length===0)&&(M.encodings=[{}]),M.encodings[0].maxBitrate=8e6,M.encodings[0].maxFramerate=30,M.degradationPreference="maintain-framerate",await a.setParameters(M)}catch(M){S("setParameters on outbound camera failed:",M)}if(!h()){try{await a.replaceTrack(null)}catch(M){S("replaceTrack(null) for stale camera finalize failed:",M)}H(U);return}z=U,ue=r,X.onended=()=>{z===U&&Qe.enqueueCurrent(async({isCurrent:M})=>{if(!(!M()||z!==U||!l()||D!==u||de!==a)){try{await a.replaceTrack(null)}catch(R){S("replaceTrack(null) after camera ended failed:",R)}!M()||z!==U||!l()||D!==u||de!==a||(z=null,ue=void 0,H(U),He(),u.send(JSON.stringify({type:"cameraResult",granted:!1})),P("onCameraDemandChange",e.onCameraDemandChange,!0,!1))}}).catch(M=>S("camera ended cleanup failed:",M))},h()&&(Et(u,X),ft())}),_e=()=>{for(const r of $)r();$.clear();for(const r of B.values())clearTimeout(r);B.clear();for(const r of ee.values())r(new Error("Simulator disconnected"));for(const r of ie.values())r(new Error("Simulator disconnected"));ee.clear(),re.clear(),ie.clear(),se.clear(),V?.(),V=void 0,Lt(),b=null;for(const r of Ce.values())clearTimeout(r.timer),r.reject(new Error("Simulator disconnected"));Ce.clear(),v(null),C({controlReady:!1,videoReady:!1}),Ve(),be(),Ye(),q&&(q.stop(),q=null),Me!==null&&We(null),Qe.invalidate(),He(),Wt(),ue=void 0,de=null,++xe,Ze=!1,he=null,te&&(H(te),te=null,P("onMicrophoneStateChange",e.onMicrophoneStateChange,{active:!1})),ve=null,D&&(D.onopen=null,D.onmessage=null,D.onerror=null,D.onclose=null,D.close(),D=null),Pe?.close(),Pe=null,N&&(N.onconnectionstatechange=null,N.oniceconnectionstatechange=null,N.ontrack=null,N.onicecandidate=null,N.close(),N=null),x&&(x.onopen=null,x.onclose=null,x.onerror=null,x.close(),x=null)},mt=()=>{document.hidden?we():lt()},Gt=async()=>{if(e.transport)return e.transport.isTerminated?.()??!1;if(typeof navigator<"u"&&navigator.onLine===!1)return!1;let r;try{const l=new URL(n);l.protocol=l.protocol==="wss:"?"https:":l.protocol==="ws:"?"http:":l.protocol,r=yt(l.toString(),s)}catch{return!1}const u=new AbortController,a=window.setTimeout(()=>u.abort(),Bn);try{return(await fetch(r,{method:"GET",cache:"no-store",signal:u.signal})).status===404}catch{return!1}finally{window.clearTimeout(a)}},Jt=()=>{Ee||(Ee=!0,le+=1,qe(),Ve(),be(),_e(),T("Instance terminated"),we(),Oe("terminated"),P("onTerminated",e.onTerminated))},jt=()=>{if(Ee||Te)return;Te=!0;const r=ke;Gt().catch(()=>!1).then(u=>{r===ke&&(Te=!1,u&&Jt())})},De=(r,u)=>{if(Ee||u!==le)return;if(jt(),ne){if(!e.autoReconnect){T(`Connection failed after it was established: ${r}`),we(),Oe("failed"),_e();return}T(`Reconnecting after established session dropped: ${r}`),ne=!1,Fe=-1}qe();const a=Fe+1;if(a>=ot){T(`Connection failed after ${ot} attempts: ${r}`),we(),Oe("failed"),_e();return}T(`Retrying connection (${a+1}/${ot})`),Oe("reconnecting"),_e(),Se=window.setTimeout(()=>{Se=void 0,u===le&&ht(a)},Pn)},ht=async(r=0)=>{const{openUrl:u,axPollIntervalMs:a,axMaxBackoffMs:l,androidElementTreeOptions:y}=e;if(Ee)return;const h=le+1;le=h,Fe=r,ne=!1,r===0&&pe!=="reconnecting"&&Oe("connecting"),qe(),Ve(),Ye(),Ke=!1,p(!1),_e();const O=()=>h===le;ye=window.setTimeout(()=>{ye=void 0,!(!O()||ne)&&De("Connection did not succeed within 15 seconds",h)},Ln);try{const f=e.transport?await e.transport.connect():new WebSocket(yt(n,s));if(!O()){f.close();return}if(D=f,await new Promise((_,o)=>{let I=!1;const W=()=>K(()=>o(new Error("Connection stopped")));$.add(W);const g=window.setTimeout(()=>K(()=>o(new Error("WebSocket connection timeout"))),3e4),K=Z=>{I||(I=!0,$.delete(W),window.clearTimeout(g),Z())};f.onopen=()=>{!O()||D!==f||K(_)},f.onerror=Z=>{!O()||D!==f||(T("WebSocket error: "+Z),K(()=>o(new Error("WebSocket connection failed"))))},f.onclose=()=>{!O()||D!==f||(T("WebSocket closed"),K(()=>o(new Error("WebSocket closed before connection was established"))))},f.readyState===WebSocket.OPEN?K(_):f.readyState!==WebSocket.CONNECTING&&K(()=>o(new Error("WebSocket is closed")))}),!O()||D!==f)return;f.onerror=_=>{!O()||D!==f||T("WebSocket error: "+_)},f.onclose=()=>{!O()||D!==f||T("WebSocket closed")};const j=new Promise((_,o)=>{let I=!1;const W=()=>g(()=>o(new Error("Connection stopped")));$.add(W);const g=G=>{I||(I=!0,$.delete(W),window.clearTimeout(K),f.removeEventListener("message",Z),G())},K=window.setTimeout(()=>g(()=>o(new Error("RTCConfiguration timeout"))),3e4),Z=G=>{if(!(!O()||D!==f))try{const Q=JSON.parse(G.data);if(Q.type==="signalingError"&&Q.requestType==="requestRtcConfiguration"&&Q.sessionId===d){const zt=typeof Q.error=="string"?Q.error:"Unable to load streaming configuration";g(()=>o(new Error(zt)))}else Q.type==="rtcConfiguration"&&g(()=>_({rtcConfiguration:Q.rtcConfiguration,cameraSupported:Q.cameraSupported===!0,foldSupported:Q.foldSupported===!0}))}catch(Q){console.error("Error handling RTC configuration:",Q),g(()=>o(Q))}};f.addEventListener("message",Z),f.send(JSON.stringify({type:"requestRtcConfiguration",sessionId:d}))}),{rtcConfiguration:U,cameraSupported:X,foldSupported:M}=await j;if(!O()||D!==f)return;const R=E==="iphone-duo"||M;k(R);const A=new RTCPeerConnection({...U,iceTransportPolicy:"relay"});N=A;const Ge={peer:A,displays:new Map};b=Ge,F(),A.addTransceiver("audio",{direction:"recvonly"});const Xt=A.addTransceiver("video",{direction:"recvonly"}),Qt=R?A.addTransceiver("video",{direction:"recvonly"}):null,_t=c==="ios"||X,nt=_t?A.addTransceiver("video",{direction:"sendonly"}):null;if(de=nt?.sender??null,ve=(_t?A.addTransceiver("audio",{direction:"sendonly"}):null)?.sender??null,RTCRtpReceiver.getCapabilities){const _=RTCRtpReceiver.getCapabilities("video");if(_&&_.codecs){const I=_.codecs.sort((W,g)=>{const K=Z=>{const G=Z.mimeType.toLowerCase();return G.includes("vp9")?1:G.includes("h265")||G.includes("hevc")?2:G.includes("h264")||G.includes("avc")?3:4};return K(W)-K(g)});Xt.setCodecPreferences(I),Qt?.setCodecPreferences(I),ae("Set codec preferences:",I.map(W=>W.mimeType).join(", "))}}if(nt&&RTCRtpSender.getCapabilities){const _=RTCRtpSender.getCapabilities("video");if(_&&_.codecs){const o=new Set(["42e01f","42e028","640c1f"]),I=g=>{const K=g.mimeType.toLowerCase(),G=(g.sdpFmtpLine||"").toLowerCase().match(/profile-level-id=([0-9a-f]{6})/),Q=G?G[1]:"";return K==="video/h265"||K==="video/hevc"?1:K==="video/h264"&&o.has(Q)?2:K==="video/h264"?3:K==="video/vp9"?4:K==="video/vp8"?5:K==="video/rtx"||K==="video/red"||K==="video/ulpfec"?0:6},W=[..._.codecs].sort((g,K)=>I(g)-I(K));try{nt.setCodecPreferences(W),ae("Outbound camera codec preferences:",W.map(g=>`${g.mimeType}${g.sdpFmtpLine?`[${g.sdpFmtpLine}]`:""}`).join(", "))}catch(g){S("Failed to set outbound camera codec preferences:",g)}}}const oe=A.createDataChannel("control",{ordered:!0,negotiated:!0,id:1});x=oe;const rt=!R&&e.onTrace?Yn(A,_=>{O()&&N===A&&P("onTrace",e.onTrace,_)}):null;if(Pe=rt,oe.onopen=()=>{if(!O()||x!==oe||D!==f)return;ne=!0,C({controlReady:!0}),Ve(),T("Control channel opened"),R&&f.send(JSON.stringify({type:"getFoldState",id:"duo-capabilities"})),q||(q=new An({platform:c,baseIntervalMs:a,maxBackoffMs:l,androidElementTreeOptions:y,send:o=>{if(!D||D.readyState!==WebSocket.OPEN)return!1;try{return D.send(JSON.stringify(o)),!0}catch{return!1}},onSnapshot:We,onStatusChange:(o,I)=>{P("onAxStatusChange",e.onAxStatusChange,o,I)}}),(e.inspectMode===!0||e.inspectMode==="hover-only")&&q.start());const _=()=>{!O()||Ke||x!==oe||D!==f||f.readyState!==WebSocket.OPEN||f.send(JSON.stringify({type:"requestFrame",sessionId:d}))};if(_(),Ye(),Le=window.setInterval(()=>{if(!O()||Ke||x!==oe||D!==f||f.readyState!==WebSocket.OPEN){Ye();return}_()},250),u){try{const o=decodeURIComponent(u);T("Opening URL"),f.send(JSON.stringify({type:"openUrl",url:o,sessionId:d}))}catch(o){console.error({error:o},"Error decoding URL, falling back to the original URL"),f.send(JSON.stringify({type:"openUrl",url:u,sessionId:d}))}q?.bumpActivity()}},oe.onclose=()=>{!O()||x!==oe||(C({controlReady:!1}),T("Control channel closed"))},oe.onerror=_=>{!O()||x!==oe||(console.error("Control channel error:",_),T("Control channel error: "+_))},A.onconnectionstatechange=()=>{!O()||N!==A||(T("Connection state: "+A.connectionState),A.connectionState==="failed"&&ne&&De("WebRTC connection entered failed state",h))},A.oniceconnectionstatechange=()=>{if(!O()||N!==A)return;const _=A.iceConnectionState;if(T("ICE state: "+_),_==="connected"||_==="completed"){be(),et()&&!te&&tt();return}if(_==="failed"){be(),ne&&De("ICE connection entered failed state",h);return}_==="disconnected"&&ne&&e.autoReconnect&&me===void 0&&(me=window.setTimeout(()=>{me=void 0,!(!O()||N!==A)&&A.iceConnectionState==="disconnected"&&De("ICE stayed disconnected past grace period",h)},Fn))},A.ontrack=_=>{if(!O()||N!==A)return;Tt(_.receiver,e.jitterBufferTargetMs);const o=_.track.id==="duo-inner"||_.streams.some(I=>I.id==="duo-inner");if(_.track.kind==="video"&&Ge.displays.set(_.receiver,o?"inner":"primary"),T("Received remote track: "+_.track.kind),_.track.kind==="video"){const I=o?"inner":"primary",W=R?new MediaStream([_.track]):_.streams[0]??new MediaStream([_.track]);Ue.set(I,W);for(const[g,K]of Y)K.display===I&&at(g,K,W)}},A.onicecandidate=_=>{if(!(!O()||N!==A||D!==f))if(_.candidate&&f.readyState===WebSocket.OPEN){const o={type:"candidate",candidate:_.candidate.candidate,sdpMid:_.candidate.sdpMid,sdpMLineIndex:_.candidate.sdpMLineIndex,sessionId:d};f.send(JSON.stringify(o)),T("Sent ICE candidate")}else T("ICE candidate gathering completed")},f.onmessage=async _=>{if(!O()||D!==f)return;let o;try{o=JSON.parse(_.data)}catch(I){S("Error parsing message:",I);return}if(!q?.handleMessage(o))switch(T("Received: "+o.type),o.type){case"performActionsResult":case"foldStateResult":case"foldStateChanged":{if(!R)break;o.state?(v(o.state),w(void 0)):o.id==="duo-capabilities"&&w(o.error||"This instance does not support native iPhone Duo displays.");const g=Ce.get(o.id);g&&(clearTimeout(g.timer),Ce.delete(o.id),o.error?g.reject(new Error(o.error)):g.resolve());break}case"signalingError":{if(o.requestType!=="offer"||o.sessionId!==d)break;const g=typeof o.error=="string"?o.error:"Unable to establish the streaming connection";T("Error: "+g),De(g,h);break}case"answer":if(!N||N!==A){T("No peer connection, skipping answer");break}if(rt?.accept(o.latencyTraceVersion),await A.setRemoteDescription(new RTCSessionDescription({type:"answer",sdp:o.sdp})),!O()||N!==A)return;T("Set remote description");break;case"candidate":if(!N||N!==A){T("No peer connection, skipping candidate");break}if(await A.addIceCandidate(new RTCIceCandidate({candidate:o.candidate,sdpMid:o.sdpMid,sdpMLineIndex:o.sdpMLineIndex})),!O()||N!==A)return;T("Added ICE candidate");break;case"screenshot":case"screenshotResult":{if(typeof o.id!="string"){S("Received invalid screenshot success message:",o);break}const g=Wn(o);if(g){const G=ee.get(o.id);if(typeof G!="function"){S(`Received screenshot error for unknown or handled id: ${o.id}`);break}S(`Received screenshot error for id ${o.id}: ${g}`),G(new Error(g)),re.delete(o.id),ee.delete(o.id),clearTimeout(B.get(o.id)),B.delete(o.id);break}const K=qn(o);if(!K){S("Received screenshot message without image data:",o);break}const Z=re.get(o.id);if(typeof Z!="function"){S(`Received screenshot data for unknown or handled id: ${o.id}`);break}ae(`Received screenshot data for id ${o.id}`),Z(K),re.delete(o.id),ee.delete(o.id),clearTimeout(B.get(o.id)),B.delete(o.id);break}case"screenshotError":if(typeof o.id!="string"||typeof o.message!="string"){S("Received invalid screenshot error message:",o);break}const I=ee.get(o.id);if(typeof I!="function"){S(`Received screenshot error for unknown or handled id: ${o.id}`);break}S(`Received screenshot error for id ${o.id}: ${o.message}`),I(new Error(o.message)),re.delete(o.id),ee.delete(o.id),clearTimeout(B.get(o.id)),B.delete(o.id);break;case"cameraRequest":{const g=de;if(!g)break;const K=Nn(o);if(!K){S("Received invalid cameraRequest:",o);break}console.info("[RemoteControl] cameraRequest received:",K.active,K.facingMode),await Ht(K,f,g,O);break}case"microphoneRequest":{if(!ve)break;const g=o.active===!0;if(Ze=g,console.info("[RemoteControl] microphoneRequest received, active=",g),!g){ze||await $e();break}if(te){ut(f);break}await tt();break}case"microphoneStartResult":{if(he===null||o.id!==he)break;he=null,typeof o.error=="string"&&(console.warn("[RemoteControl] microphoneStart rejected by host:",o.error),$e(o.error));break}case"terminateAppResult":if(typeof o.id!="string"){S("Received invalid terminateApp result message:",o);break}if(typeof o.error=="string"){const g=ie.get(o.id);if(typeof g!="function"){S(`Received terminateApp error for unknown or handled id: ${o.id}`);break}S(`Received terminateApp error for id ${o.id}: ${o.error}`),g(new Error(o.error)),se.delete(o.id),ie.delete(o.id),clearTimeout(B.get(o.id)),B.delete(o.id);break}const W=se.get(o.id);if(typeof W!="function"){S(`Received terminateApp result for unknown or handled id: ${o.id}`);break}ae(`Received terminateApp success for id ${o.id}`),W(),se.delete(o.id),ie.delete(o.id),clearTimeout(B.get(o.id)),B.delete(o.id);break;default:S(`Received unhandled message type: ${o.type}`,o);break}},N===A){const _=await A.createOffer({offerToReceiveVideo:!0,offerToReceiveAudio:!1});if(!O()||N!==A||(await A.setLocalDescription(_),!O()||N!==A))return;O()&&D===f&&f.readyState===WebSocket.OPEN&&f.send(JSON.stringify({type:"offer",...R?{displayStreams:!0}:{},...rt?{latencyTraceVersion:1}:{},sdp:_.sdp,sessionId:d})),T("Sent offer")}}catch(f){if(!O()||f instanceof Error&&f.message==="Connection stopped")return;const j=f instanceof Error?f.message:String(f);T("Error: "+j),De(j,h)}},pt=()=>{if(J)throw new Error("Device stream is disposed");ke++,Te=!1,We(null),pe!=="reconnecting"&&(pe=null),document.addEventListener("visibilitychange",mt),document.hidden||lt(),Ee=!1,ht(0)},Ct=()=>{ke++,Te=!1,we(),document.removeEventListener("visibilitychange",mt),le+=1,Fe=0,ne=!1,qe(),be(),_e(),pe=null,C({connection:"idle",videoReady:!1,controlReady:!1}),T("Stopped")},Ot=(r,u="primary")=>{if(J)throw new Error("Device stream is disposed");if(Y.has(r))throw new Error("Video element is already attached");const a={display:u};Y.set(r,a);const l=()=>{u==="primary"&&Ue.has(u)&&xt()};r.addEventListener("loadeddata",l);const y=Ue.get(u);y&&at(r,a,y);let h=!1;const O=()=>{h||(h=!0,L.delete(O),r.removeEventListener("loadeddata",l),a.stop?.(),Y.delete(r),r.srcObject=null)};return L.add(O),O};return{start:pt,stop:Ct,attachVideo:Ot,attachFrameSink:(r,u="primary")=>{const a=document.createElement("video");a.muted=!0,a.playsInline=!0,a.autoplay=!0;const l=Ot(a,u);let y=!1,h=0,O=0;const f=()=>{a.cancelVideoFrameCallback?.(h),cancelAnimationFrame(O)},j=()=>{y||!a.srcObject||(a.readyState>=2&&a.videoWidth>0&&P("present",(...M)=>r.present(...M),a,a.videoWidth,a.videoHeight,u),!(y||!a.srcObject)&&(a.requestVideoFrameCallback?h=a.requestVideoFrameCallback(j):O=requestAnimationFrame(j)))},U=()=>{f(),j()};Y.get(a).clear=f,a.addEventListener("loadeddata",U);const X=()=>{y||(y=!0,L.delete(X),f(),a.removeEventListener("loadeddata",U),l(),a.remove())};return L.delete(l),L.add(X),a.readyState>=2&&U(),X},dispose:()=>{if(!J){J=!0,Ct();for(const r of L)r();L.clear()}},getState:()=>m,updateOptions:r=>{if(J)throw new Error("Device stream is disposed");const u=e;if(e={...e,...r},u.jitterBufferTargetMs!==e.jitterBufferTargetMs)for(const a of N?.getTransceivers()??[])(a.currentDirection==="recvonly"||a.currentDirection==="sendrecv")&&Tt(a.receiver,e.jitterBufferTargetMs);!!u.onPlaybackStats!=!!e.onPlaybackStats&&F(),!!u.microphoneEnabled!=!!e.microphoneEnabled&&(ze=e.microphoneEnabled??!1,et()?tt():$e()),!!u.inspectMode!=!!e.inspectMode&&(e.inspectMode?q?.start():(q?.stop(),Me!==null&&We(null)))},sendControl:ce,sendTouch:(r,u,a,l,y,h=0)=>ce(Kt(r==="begin"?0:r==="end"?1:2,h,l,y,u,a,r==="end"?0:1)),sendText:r=>ce(Mt(r)),sendDisplayTouch:(r,u,a,l)=>ce(wt(r,u,a,l)),sendDuoControl:Ft,pressButton:r=>{const u={home:3,back:4,recents:187,power:26}[r];ce(Je(0,u,0,0)),ce(Je(1,u,0,0))},rotate:()=>ce(new Uint8Array([11]).buffer),bumpActivity:()=>q?.bumpActivity(),getAxStatus:()=>q?.getStatus()??"idle",openUrl:r=>{if(!D||D.readyState!==WebSocket.OPEN){S("WebSocket not open, cannot send open_url command.");return}try{const u=decodeURIComponent(r);T("Opening URL"),D.send(JSON.stringify({type:"openUrl",url:u,sessionId:d}))}catch(u){S("Error decoding or sending URL :",{error:u,url:r}),D.send(JSON.stringify({type:"openUrl",url:r,sessionId:d}))}q?.bumpActivity()},sendKeyEvent:r=>{if(!x||x.readyState!=="open"){S("Data channel not ready for imperative key command:",x?.readyState);return}const u=vt[r.code];if(!u){S(`Unknown event.code for imperative command: ${r.code}`);return}let a=i.META_NONE;r.shiftKey&&(a|=i.META_SHIFT_ON),r.altKey&&(a|=i.META_ALT_ON),r.ctrlKey&&(a|=i.META_CTRL_ON),r.metaKey&&(a|=i.META_META_ON);const l=r.type==="keydown"?i.ACTION_DOWN:i.ACTION_UP;ae(`Sending Imperative Key Command: code=${r.code}, keycode=${u}, action=${l}, meta=${a}`);const y=Je(l,u,0,a);y&&ce(y)},screenshot:r=>new Promise((u,a)=>{if(!D||D.readyState!==WebSocket.OPEN)return S("WebSocket not open, cannot send screenshot command."),a(new Error("WebSocket is not connected or connection is not open."));const l=`ui-ss-${Date.now()}-${Math.random().toString(36).substring(2,9)}`,y={type:r?"screenshotDisplay":"screenshot",...r?{display:r}:{},id:l};re.set(l,u),ee.set(l,a),ae("Sending screenshot request:",y);try{D.send(JSON.stringify(y))}catch(h){S("Failed to send screenshot request immediately:",h),re.delete(l),ee.delete(l),a(h);return}B.set(l,setTimeout(()=>{B.delete(l),re.has(l)&&(S(`Screenshot request timed out for id ${l}`),ee.get(l)?.(new Error("Screenshot request timed out")),re.delete(l),ee.delete(l))},3e4))}),terminateApp:r=>new Promise((u,a)=>{if(!D||D.readyState!==WebSocket.OPEN)return S("WebSocket not open, cannot send terminateApp command."),a(new Error("WebSocket is not connected or connection is not open."));const l=`ui-term-${Date.now()}-${Math.random().toString(36).substring(2,9)}`,y={type:"terminateApp",id:l,bundleId:r};se.set(l,u),ie.set(l,a),ae("Sending terminateApp request:",y);try{D.send(JSON.stringify(y))}catch(h){S("Failed to send terminateApp request immediately:",h),se.delete(l),ie.delete(l),a(h);return}q?.bumpActivity(),B.set(l,setTimeout(()=>{B.delete(l),se.has(l)&&(S(`terminateApp request timed out for id ${l}`),ie.get(l)?.(new Error("terminateApp request timed out")),se.delete(l),ie.delete(l))},3e4))}),reconnect:()=>pt(),refreshAxTree:async()=>{const r=q;if(!r)throw new Error("Inspect mode is not active");return r.refresh()},getAxSnapshot:()=>Me}}const Wn=t=>typeof t.message=="string"?t.message:typeof t.error=="string"?t.error:null,qn=t=>typeof t.dataUri=="string"?{dataUri:t.dataUri}:typeof t.base64=="string"?t.base64.startsWith("data:")?{dataUri:t.base64}:{dataUri:`data:${t.base64.startsWith("/9j/")?"image/jpeg":"image/png"};base64,${t.base64}`}:null;exports.AMOTION_EVENT=Ne;exports.ANDROID_KEYS=i;exports.AX_UNAVAILABLE_ERROR=je;exports.CONTROL_MSG_TYPE=Ie;exports.DUO_BUTTONS=sn;exports.DUO_DIMENSIONS=en;exports.DuoButtonSender=cn;exports.HingeSender=an;exports.axElementAtPoint=pn;exports.axElementRoleLabel=Ut;exports.axElementSelectorExpression=Cn;exports.axElementSummary=On;exports.axElementsEqual=Rt;exports.axSnapshotsEqual=It;exports.clampAxFrameForScreen=hn;exports.codeMap=vt;exports.createDeviceStream=xn;exports.createDisplayTouchMessage=wt;exports.createInjectKeycodeMessage=Je;exports.createSetClipboardMessage=Mt;exports.createTouchControlMessage=Kt;exports.createTwoFingerTouchControlMessage=Zt;exports.debugLog=ae;exports.debugWarn=S;exports.detectPlatform=Pt;exports.duoPointerMode=on;exports.flatDisplayTouch=tn;exports.normalizeAndroidTree=Nt;exports.normalizeIosTree=bt;exports.panelTouch=rn;exports.safeInvoke=P;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";require('./index.css');const g=require("react/jsx-runtime"),r=require("./core-DkhLItUD.js"),l=require("react"),Yt=require("react-dom");function ot(h){var i,m,f="";if(typeof h=="string"||typeof h=="number")f+=h;else if(typeof h=="object")if(Array.isArray(h)){var w=h.length;for(i=0;i<w;i++)h[i]&&(m=ot(h[i]))&&(f&&(f+=" "),f+=m)}else for(m in h)h[m]&&(f&&(f+=" "),f+=m);return f}function ie(){for(var h,i,m=0,f="",w=arguments.length;m<w;m++)(h=arguments[m])&&(i=ot(h))&&(f&&(f+=" "),f+=i);return f}const Pt=async h=>{if(!h)return!1;try{if(typeof navigator<"u"&&navigator.clipboard?.writeText)return await navigator.clipboard.writeText(h),!0}catch{}try{const i=document.createElement("textarea");i.value=h,i.style.position="fixed",i.style.opacity="0",document.body.appendChild(i),i.select();const m=document.execCommand("copy");return document.body.removeChild(i),m}catch{return!1}},kt=l.memo(function({element:i,screen:m,highlighted:f,selected:w,selectable:H,onClick:b}){const N=r.clampAxFrameForScreen(i.frame,m);if(!N)return null;const L=r.axElementSummary(i);return g.jsx("button",{type:"button",className:ie("rc-inspect-box",!i.enabled&&"rc-inspect-box-disabled"),"data-ax-id":i.id,"data-ax-path":i.path,"data-ax-label":i.label||void 0,"data-ax-role":i.role||void 0,"data-highlighted":f?"true":"false","data-selected":w?"true":"false","aria-label":L,onClick:P=>{H&&(P.preventDefault(),P.stopPropagation(),b(i,{x:P.clientX,y:P.clientY}))},style:{left:`${N.x/m.width*100}%`,top:`${N.y/m.height*100}%`,width:`${N.width/m.width*100}%`,height:`${N.height/m.height*100}%`}})},(h,i)=>h.highlighted===i.highlighted&&h.selected===i.selected&&h.selectable===i.selectable&&h.screen.width===i.screen.width&&h.screen.height===i.screen.height&&h.onClick===i.onClick&&r.axElementsEqual(h.element,i.element)),Lt=260,Xt=220,Wt=6,Ht=8,Vt=l.memo(function({element:i,platform:m,anchor:f,cursorAnchored:w,showActions:H,onTap:b}){const[N,L]=l.useState(null);l.useEffect(()=>{if(!N)return;const A=window.setTimeout(()=>L(null),1100);return()=>window.clearTimeout(A)},[N]);const P=l.useMemo(()=>{const A=Lt,X=Xt,D=Wt,v=Ht,U=typeof window<"u"?window.innerWidth:1024,Z=typeof window<"u"?window.innerHeight:768,z=f.x+D+A<=U-v,B=f.y-D-X>=v;let ce=z?f.x+D:f.x-D,me=B?f.y-D:f.y+D;const Ae=`translate(${z?"0":"-100%"}, ${B?"-100%":"0"})`;return ce=Math.max(v+(z?0:A),Math.min(U-v-(z?A:0),ce)),me=Math.max(v+(B?X:0),Math.min(Z-v-(B?0:X),me)),{left:`${ce}px`,top:`${me}px`,transform:Ae}},[f.x,f.y]),M=l.useMemo(()=>r.axElementSelectorExpression(i,m),[i,m]),k=m==="ios"?i.selectors.AXUniqueId:i.selectors.resourceId,j=m==="ios"?"AXUniqueId":"resourceId",F=l.useCallback(async(A,X)=>{if(!A)return;await Pt(A)&&L(X)},[]),C=r.axElementRoleLabel(i),ge=i.label||i.value||C,Q=r.axElementSummary(i);return Yt.createPortal(g.jsxs("div",{className:"rc-inspect-card","data-cursor-anchored":w?"true":"false",style:P,onClick:A=>A.stopPropagation(),onMouseDown:A=>A.stopPropagation(),onMouseMove:A=>A.stopPropagation(),children:[g.jsxs("div",{className:"rc-inspect-card-header",children:[g.jsx("span",{className:"rc-inspect-card-role",children:C}),!i.enabled&&g.jsx("span",{className:"rc-inspect-card-tag",children:"disabled"}),i.focused&&g.jsx("span",{className:"rc-inspect-card-tag rc-inspect-card-tag-blue",children:"focused"})]}),g.jsx("p",{className:"rc-inspect-card-title",title:Q,children:ge}),k&&g.jsxs("div",{className:"rc-inspect-card-row",children:[g.jsxs("span",{className:"rc-inspect-card-row-label",children:[j,":"]}),g.jsx("span",{className:"rc-inspect-card-row-value",children:k})]}),i.value&&i.value!==i.label&&g.jsxs("div",{className:"rc-inspect-card-row",children:[g.jsx("span",{className:"rc-inspect-card-row-label",children:"value:"}),g.jsx("span",{className:"rc-inspect-card-row-value",children:i.value})]}),g.jsxs("div",{className:"rc-inspect-card-row",children:[g.jsx("span",{className:"rc-inspect-card-row-label",children:"frame:"}),g.jsxs("span",{className:"rc-inspect-card-row-value",children:[Math.round(i.frame.width),"×",Math.round(i.frame.height)," @ ",Math.round(i.frame.x),",",Math.round(i.frame.y)]})]}),H&&g.jsxs("div",{className:"rc-inspect-card-actions",children:[g.jsx("button",{type:"button",className:"rc-inspect-card-btn rc-inspect-card-btn-primary",onClick:()=>b(i,f),children:"Tap"}),g.jsx("button",{type:"button",className:ie("rc-inspect-card-btn",N==="selector"&&"rc-inspect-card-btn-copied"),disabled:!M,title:M??"No usable selector for this element",onClick:()=>F(M??void 0,"selector"),children:N==="selector"?"Copied!":"Copy selector"}),g.jsx("button",{type:"button",className:ie("rc-inspect-card-btn",N==="id"&&"rc-inspect-card-btn-copied"),disabled:!k,title:k??`No ${j}`,onClick:()=>F(k,"id"),children:N==="id"?"Copied!":`Copy ${j}`})]})]}),document.body)}),jt=l.memo(function({snapshot:i,geometry:m,highlightedId:f,selectedId:w,mode:H,cursorPosition:b,frozenCursorPosition:N,onSelectChange:L,onTapElement:P}){const M=H==="select",k=M?f!==null&&f!==w:f!==null,j=M?f??w:f,F=l.useMemo(()=>{const v=new Map;if(!i)return v;for(const U of i.elements)v.set(U.id,U);return v},[i]),C=l.useMemo(()=>j?F.get(j)??null:null,[j,F]);if(!(!!i&&!!m&&i.screen.width>0&&i.screen.height>0&&i.elements.length>0))return null;const Q=k?b:N??b,A=k,X=M&&!k&&w!==null,D=v=>{M&&v.target===v.currentTarget&&L(null,null)};return g.jsxs(g.Fragment,{children:[g.jsx("div",{className:ie("rc-inspect-overlay",M&&"rc-inspect-overlay-select"),style:{left:`${m.left}px`,top:`${m.top}px`,width:`${m.width}px`,height:`${m.height}px`},onClick:D,children:i.elements.map(v=>g.jsx(kt,{element:v,screen:i.screen,highlighted:v.id===f,selected:v.id===w,selectable:M,onClick:L},v.id))}),C&&Q&&g.jsx(Vt,{element:C,platform:i.platform,anchor:Q,cursorAnchored:A,showActions:X,onTap:P})]})}),Kt=l.lazy(()=>Promise.resolve().then(()=>require("./duo-view-Bhr7zyWr.js")).then(h=>h.duoView)),Se=h=>Object.entries(r.AMOTION_EVENT).find(([m,f])=>m.startsWith("ACTION_")&&f===h)?.[0]??String(h),tt=1920,nt=1200,$t=(h,i)=>h===tt&&i===nt||h===nt&&i===tt,Ft={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 Ut(h){const i=h.code,m=r.codeMap[i];if(!m)return r.debugWarn(`Unknown event.code: ${i}, key: ${h.key}`),null;let f=r.ANDROID_KEYS.META_NONE;const w=i>="KeyA"&&i<="KeyZ",H=h.getModifierState("CapsLock"),b=h.shiftKey;let N=b;return w&&(N=b!==H),N&&(f|=r.ANDROID_KEYS.META_SHIFT_ON),h.ctrlKey&&(f|=r.ANDROID_KEYS.META_CTRL_ON),h.altKey&&(f|=r.ANDROID_KEYS.META_ALT_ON),h.metaKey&&(f|=r.ANDROID_KEYS.META_META_ON),{keycode:m,metaState:f}}const zt=l.forwardRef(({className:h,url:i,token:m,sessionId:f,openUrl:w,showFrame:H=!0,deviceModel:b,duoModelUrl:N,autoReconnect:L=!1,jitterBufferTargetMs:P,onPlaybackStats:M,onTerminated:k,assets:j,onConnectionStateChange:F,inspectMode:C,onAxSnapshotChange:ge,onInspectSelectionChange:Q,onAxStatusChange:A,axPollIntervalMs:X,axMaxBackoffMs:D,androidElementTreeOptions:v,onCameraDemandChange:U,onCameraStats:Z,onTrace:z,microphoneEnabled:B=!1,onMicrophoneStateChange:ce},me)=>{const pe=l.useRef(null),R=l.useRef(null),Ae=l.useRef(null),[rt,it]=l.useState(!1),W=b==="iphone-duo"||rt,we=l.useRef(null),[He,ct]=l.useState(null),[Ve,st]=l.useState(),[at,ut]=l.useState(!1),[lt,dt]=l.useState(!1),[ht,ft]=l.useState(!1),[je,Ke]=l.useState(!1),[gt,$e]=l.useState(!1),[mt,De]=l.useState({}),xe=l.useRef(null),_=l.useRef(new Map),J=l.useRef(!1),[pt,vt]=l.useState(!1),O=l.useRef(null),se=l.useRef(null),ve=l.useRef({handle:()=>{},end:()=>{}}),[ee,Oe]=l.useState(null),[Fe,Ye]=l.useState(null),[Pe,ye]=l.useState(null),[ke,Ie]=l.useState(null),[yt,Ue]=l.useState(null),[Et,ze]=l.useState(null),Re=l.useRef(null),K=l.useRef(void 0),Be=e=>{Re.current=e,K.current===void 0&&(K.current=window.requestAnimationFrame(()=>{K.current=void 0,ze(Re.current)}))},[Tt,ae]=l.useState(null),te=l.useRef(null);te.current=Fe;const ue=l.useRef(Q);ue.current=Q;const Ee=C===!0||C==="hover-only",Nt=C==="hover-only"?"hover-only":"select",q=l.useMemo(()=>r.detectPlatform(i),[i]),At=l.useMemo(()=>f||Array.from(crypto.getRandomValues(new Uint32Array(4)),e=>e.toString(36)).join(""),[f]),le=Ft[q],Te=j?.[q],qe=q==="android"&>?je?Te?.tabletFrameLandscape:Te?.tabletFrame:je?Te?.frameLandscape:Te?.frame,Ge=Te?.loadingLogo,be=!W&&H&&!!qe,y=l.useRef(null),V=e=>y.current?.sendControl(e),Le=(e,n)=>y.current?.sendDuoControl(e,n)??Promise.reject(new Error("Simulator disconnected")),Qe=-10,Ze=(e,n)=>{const o=Ne();if(!o)return;const t=he(o,e,n);if(!t)return;const{videoX:s,videoY:a,videoWidth:c,videoHeight:u}=t,d=r.createTouchControlMessage(r.AMOTION_EVENT.ACTION_DOWN,Qe,c,u,s,a,1,r.AMOTION_EVENT.BUTTON_PRIMARY,r.AMOTION_EVENT.BUTTON_PRIMARY);d&&V(d),window.setTimeout(()=>{const p=r.createTouchControlMessage(r.AMOTION_EVENT.ACTION_UP,Qe,c,u,s,a,0,r.AMOTION_EVENT.BUTTON_PRIMARY,r.AMOTION_EVENT.BUTTON_PRIMARY);p&&V(p)},60)},wt=(e,n)=>{const o=Ne();if(!o||n.screen.width<=0||n.screen.height<=0)return;const t=e.frame.x+e.frame.width/2,s=e.frame.y+e.frame.height/2,a=t/n.screen.width*o.actualWidth,c=s/n.screen.height*o.actualHeight,u=o.videoRect.left+o.offsetX+a,d=o.videoRect.top+o.offsetY+c;Ze(u,d)},Me=-1,_e=-2,ne=-3,de=(e,n,o,t,s,a)=>{const c=r.createTouchControlMessage(e,n,o,t,s,a,1,r.AMOTION_EVENT.BUTTON_PRIMARY,r.AMOTION_EVENT.BUTTON_PRIMARY);c&&(r.debugLog("[rc-touch] sendSingleTouch",{action:e,actionName:Se(e),pointerId:n,x:s,y:a,video:{width:o,height:t}}),V(c))},oe=(e,n,o)=>{if(!o)return;const{videoX:t,videoY:s,videoWidth:a,videoHeight:c}=o;let u=null,d=null,p=1;const I=r.AMOTION_EVENT.BUTTON_PRIMARY;switch(n){case"down":e!==ne&&ve.current.end(),u=_.current.size===0?r.AMOTION_EVENT.ACTION_DOWN:r.AMOTION_EVENT.ACTION_POINTER_DOWN,d={x:t,y:s},_.current.set(e,d),e===-1&&R.current?.focus();break;case"move":_.current.has(e)&&(u=r.AMOTION_EVENT.ACTION_MOVE,d={x:t,y:s},_.current.set(e,d));break;case"up":case"cancel":_.current.has(e)&&(d=_.current.get(e),_.current.delete(e),n==="cancel"?u=r.AMOTION_EVENT.ACTION_CANCEL:u=_.current.size===0?r.AMOTION_EVENT.ACTION_UP:r.AMOTION_EVENT.ACTION_POINTER_UP);break}if(u!==null&&d!==null){r.debugLog("[rc-touch][mouse->touch] sending",{pointerId:e,eventType:n,action:u,actionName:Se(u),positionToSend:d,video:{width:a,height:c},altHeld:J.current,activePointersAfter:Array.from(_.current.entries()).map(([S,T])=>({id:S,x:T.x,y:T.y}))});const E=r.createTouchControlMessage(u,e,a,c,d.x,d.y,p,I,I);E&&(r.debugLog("[rc-touch][mouse->touch] buffer",{pointerId:e,actionName:Se(u),byteLength:E.byteLength}),V(E))}else(n==="up"||n==="cancel")&&_.current.delete(e)},Xe=e=>{if(J.current!==e&&(J.current=e,vt(e),e||Oe(null),r.debugLog("[rc-touch][alt] updateAltHeld",{nextHeld:e,activePointerIds:Array.from(_.current.keys())}),q==="ios"&&y.current?.getState().controlReady)){const n=e?r.ANDROID_KEYS.ACTION_DOWN:r.ANDROID_KEYS.ACTION_UP,o=r.createInjectKeycodeMessage(n,r.ANDROID_KEYS.KEYCODE_ALT_LEFT,0,r.ANDROID_KEYS.META_NONE);r.debugLog("[rc-touch][alt] sending Indigo modifier keycode",{action:n,keycode:r.ANDROID_KEYS.KEYCODE_ALT_LEFT}),o&&V(o)}},Ne=()=>{const e=R.current,n=pe.current;if(!e||!n)return null;const o=e.videoWidth,t=e.videoHeight;if(!o||!t)return null;const s=e.getBoundingClientRect(),a=n.getBoundingClientRect(),c=s.width,u=s.height,d=o/t,p=c/u;let I=c,E=u;d>p?E=c/d:I=u*d;const S=(c-I)/2,T=(u-E)/2;return{videoWidth:o,videoHeight:t,videoRect:s,containerRect:a,actualWidth:I,actualHeight:E,offsetX:S,offsetY:T}},he=(e,n,o)=>{const t=n-e.videoRect.left-e.offsetX,s=o-e.videoRect.top-e.offsetY,a=Math.max(0,Math.min(e.actualWidth,t)),c=Math.max(0,Math.min(e.actualHeight,s)),u=Math.max(0,Math.min(e.videoWidth,a/e.actualWidth*e.videoWidth)),d=Math.max(0,Math.min(e.videoHeight,c/e.actualHeight*e.videoHeight));return{videoX:u,videoY:d,videoWidth:e.videoWidth,videoHeight:e.videoHeight}},Ot=(e,n,o)=>{const t=n-e.videoRect.left-e.offsetX,s=o-e.videoRect.top-e.offsetY,a=Math.max(0,Math.min(e.actualWidth,t)),c=Math.max(0,Math.min(e.actualHeight,s)),u=Math.max(0,Math.min(e.videoWidth,a/e.actualWidth*e.videoWidth)),d=Math.max(0,Math.min(e.videoHeight,c/e.actualHeight*e.videoHeight)),p=e.videoWidth-u,I=e.videoHeight-d,E=e.videoRect.left+e.offsetX,S=e.videoRect.top+e.offsetY,T=E-e.containerRect.left+a,$=S-e.containerRect.top+c,re=E-e.containerRect.left+(e.actualWidth-a),Y=S-e.containerRect.top+(e.actualHeight-c);return{containerX:T,containerY:$,mirrorContainerX:re,mirrorContainerY:Y,videoX:u,videoY:d,mirrorVideoX:p,mirrorVideoY:I,videoWidth:e.videoWidth,videoHeight:e.videoHeight}},It=(e,n,o,t,s,a,c)=>{const u=r.createTwoFingerTouchControlMessage(e,n,o,t,s,a,c);r.debugLog("[rc-touch2] sendTwoFingerMessage (iOS)",{actionName:Se(e),video:{width:n,height:o},p0:{x:t,y:s},p1:{x:a,y:c},byteLength:u.byteLength}),V(u)},fe=(e,n,o,t,s,a,c,u,d)=>{if(r.debugLog("[rc-touch2] applyTwoFingerEvent",{platform:q,eventType:e,video:{width:n,height:o},p0:{x:t,y:s,id:u},p1:{x:a,y:c,id:d}}),e==="down"&&ve.current.end(),q==="ios"){const p=e==="down"?r.AMOTION_EVENT.ACTION_DOWN:e==="move"?r.AMOTION_EVENT.ACTION_MOVE:r.AMOTION_EVENT.ACTION_UP;It(p,n,o,t,s,a,c)}else e==="down"?(de(r.AMOTION_EVENT.ACTION_DOWN,u,n,o,t,s),de(r.AMOTION_EVENT.ACTION_POINTER_DOWN,d,n,o,a,c)):e==="move"?(de(r.AMOTION_EVENT.ACTION_MOVE,u,n,o,t,s),de(r.AMOTION_EVENT.ACTION_MOVE,d,n,o,a,c)):(de(r.AMOTION_EVENT.ACTION_POINTER_UP,d,n,o,a,c),de(r.AMOTION_EVENT.ACTION_UP,u,n,o,t,s))},Rt=(e,n,o)=>{if(!J.current){ee!==null&&Oe(null);return}const t=Ot(e,n,o);Oe(t)},bt=(e,n,o)=>{const t=te.current;if(!t||t.screen.width<=0||t.screen.height<=0)return null;const s=n-e.videoRect.left-e.offsetX,a=o-e.videoRect.top-e.offsetY;if(s<0||a<0||s>e.actualWidth||a>e.actualHeight)return null;const c=s/e.actualWidth*t.screen.width,u=a/e.actualHeight*t.screen.height;return r.axElementAtPoint(t,c,u)},G=e=>{if(W)return;e.preventDefault(),e.stopPropagation();const n=Ne();if((C===!0||C==="hover-only")&&!("touches"in e))if(e.type==="mousemove"){if(Be({x:e.clientX,y:e.clientY}),n){const t=bt(n,e.clientX,e.clientY);ye(t?.id??null)}}else e.type==="mouseleave"&&(Be(null),ye(null));if(C!==!0&&(!("touches"in e)&&n&&(e.type==="mousemove"?Rt(n,e.clientX,e.clientY):e.type==="mouseleave"&&Oe(null)),!(!y.current?.getState().controlReady||!R.current||!n)))if("touches"in e){const t=e.touches,s=e.changedTouches;let a;switch(e.type){case"touchstart":a="down";break;case"touchmove":a="move";break;case"touchend":a="up";break;case"touchcancel":a="cancel";break;default:return}if(t.length===2){const c=t[0],u=t[1],d=he(n,c.clientX,c.clientY),p=he(n,u.clientX,u.clientY);if(!d||!p)return;O.current?O.current.source==="real-touch"&&(O.current.finger0={x:d.videoX,y:d.videoY},O.current.finger1={x:p.videoX,y:p.videoY},fe("move",d.videoWidth,d.videoHeight,d.videoX,d.videoY,p.videoX,p.videoY,O.current.pointerId0,O.current.pointerId1)):(O.current={finger0:{x:d.videoX,y:d.videoY},finger1:{x:p.videoX,y:p.videoY},videoSize:{width:d.videoWidth,height:d.videoHeight},source:"real-touch",pointerId0:c.identifier,pointerId1:u.identifier},fe("down",d.videoWidth,d.videoHeight,d.videoX,d.videoY,p.videoX,p.videoY,c.identifier,u.identifier))}else if(t.length<2&&O.current?.source==="real-touch"){const c=O.current;fe("up",c.videoSize.width,c.videoSize.height,c.finger0.x,c.finger0.y,c.finger1.x,c.finger1.y,c.pointerId0,c.pointerId1),O.current=null;return}else{if(t.length>2)return;{const c=s[0];if(c){const u=he(n,c.clientX,c.clientY);oe(c.identifier,a,u)}}}}else{let s=null;const a=O.current?.source==="alt-mouse";switch(e.type){case"mousedown":e.button===0&&(s="down");break;case"mousemove":(a||_.current.has(-1))&&(s="move");break;case"mouseup":e.button===0&&(s="up");break;case"mouseleave":(a||_.current.has(-1))&&(s="up");break}if(s){const c=he(n,e.clientX,e.clientY);if(!c)return;r.debugLog("[rc-touch][mouse] event",{domType:e.type,eventType:s,button:e.button,buttons:e.buttons,client:{x:e.clientX,y:e.clientY},altHeldRef:J.current,inTwoFingerMode:a,geometry:{videoX:c.videoX,videoY:c.videoY,videoWidth:c.videoWidth,videoHeight:c.videoHeight},activePointerIds:Array.from(_.current.keys())}),J.current||a?Mt(s,c):oe(-1,s,c)}}},Mt=(e,n)=>{const{videoX:o,videoY:t,videoWidth:s,videoHeight:a}=n,c=s-o,u=a-t;if(e==="down"){O.current={finger0:{x:o,y:t},finger1:{x:c,y:u},videoSize:{width:s,height:a},source:"alt-mouse",pointerId0:Me,pointerId1:_e},R.current?.focus(),fe("down",s,a,o,t,c,u,Me,_e);return}if(e==="move"){O.current?.source==="alt-mouse"&&(O.current.finger0={x:o,y:t},O.current.finger1={x:c,y:u},fe("move",s,a,o,t,c,u,Me,_e));return}if(e==="up"||e==="cancel"){const d=O.current;if(d?.source==="alt-mouse"){const{finger0:p,finger1:I,videoSize:E}=d;fe("up",E.width,E.height,p.x,p.y,I.x,I.y,Me,_e),O.current=null}return}},_t=150,Je=()=>{const e=se.current;e&&(window.clearTimeout(e.endTimer),oe(ne,"up",e.pos),se.current=null)},Ct=e=>{if(e.ctrlKey||J.current||O.current)return;const n=_.current.size;if(n>1||n===1&&!_.current.has(ne))return;const o=Ne();if(!o)return;const t=e.clientX-o.videoRect.left-o.offsetX,s=e.clientY-o.videoRect.top-o.offsetY;if(t<0||t>o.actualWidth||s<0||s>o.actualHeight)return;const a=he(o,e.clientX,e.clientY);if(!a)return;e.preventDefault();const c=(e.deltaMode===1?16:e.deltaMode===2?o.actualWidth:1)*(o.videoWidth/o.actualWidth),u=(e.deltaMode===1?16:e.deltaMode===2?o.actualHeight:1)*(o.videoHeight/o.actualHeight),d=-e.deltaX*c,p=-e.deltaY*u,I=Y=>{window.clearTimeout(Y.endTimer),Y.endTimer=window.setTimeout(Je,_t)};if(d===0&&p===0){se.current&&I(se.current);return}const E=()=>({videoWidth:a.videoWidth,videoHeight:a.videoHeight,videoX:Math.abs(d)>Math.abs(p)?Math.min(Math.max(a.videoX,a.videoWidth*.2),a.videoWidth*.8):a.videoX,videoY:Math.abs(p)>=Math.abs(d)?Math.min(Math.max(a.videoY,a.videoHeight*.2),a.videoHeight*.8):a.videoY}),S=Y=>({...Y,videoX:Math.min(Math.max(Y.videoX+d,0),Y.videoWidth),videoY:Math.min(Math.max(Y.videoY+p,0),Y.videoHeight)});let T=se.current;if(T)window.clearTimeout(T.endTimer);else{const Y=E();oe(ne,"down",Y),T={pos:Y,endTimer:0},se.current=T}let $=T.pos,re=S($);re.videoX===$.videoX&&re.videoY===$.videoY&&(oe(ne,"up",$),$=E(),oe(ne,"down",$),re=S($)),oe(ne,"move",re),T.pos=re,I(T)};l.useEffect(()=>{ve.current={handle:Ct,end:Je}}),l.useEffect(()=>{const e=pe.current;if(!e)return;const n=o=>ve.current.handle(o);return e.addEventListener("wheel",n,{passive:!1}),()=>{ve.current.end(),e.removeEventListener("wheel",n)}},[]),l.useEffect(()=>{const e=t=>{t.key==="Alt"&&Xe(!0)},n=t=>{t.key==="Alt"&&Xe(!1)},o=()=>{Xe(!1)};return window.addEventListener("keydown",e,!0),window.addEventListener("keyup",n,!0),window.addEventListener("blur",o),()=>{window.removeEventListener("keydown",e,!0),window.removeEventListener("keyup",n,!0),window.removeEventListener("blur",o)}},[]);const Ce=e=>{e.preventDefault(),e.stopPropagation();const n=document.activeElement===R.current||W&&document.activeElement===e.currentTarget;if(r.debugLog("Keyboard event:",{type:e.type,key:e.key,keyCode:e.keyCode,code:e.code,target:e.target.tagName,focused:n}),!n){r.debugWarn("Simulator input not focused, skipping keyboard event");return}if(!y.current?.getState().controlReady){r.debugWarn("Data channel not ready for keyboard event:",y.current?.getState().connection);return}if(e.type==="keydown"){if(e.key.toLowerCase()==="v"&&(e.metaKey||e.ctrlKey)){r.debugLog("Paste shortcut detected"),navigator.clipboard.readText().then(t=>{if(t){r.debugLog("Pasting text via SET_CLIPBOARD:",t.substring(0,20)+(t.length>20?"...":""));const s=r.createSetClipboardMessage(t,!0);V(s)}}).catch(t=>{console.error("Failed to read clipboard contents: ",t)});return}if(e.key.toLowerCase()==="m"&&(e.metaKey||e.ctrlKey)){r.debugLog("Menu shortcut detected");const t=r.createInjectKeycodeMessage(r.ANDROID_KEYS.ACTION_DOWN,r.ANDROID_KEYS.MENU,0,r.ANDROID_KEYS.META_NONE);V(t);const s=r.createInjectKeycodeMessage(r.ANDROID_KEYS.ACTION_UP,r.ANDROID_KEYS.MENU,0,r.ANDROID_KEYS.META_NONE);V(s);return}}const o=Ut(e);if(o){const{keycode:t,metaState:s}=o,a=e.type==="keydown"?r.ANDROID_KEYS.ACTION_DOWN:r.ANDROID_KEYS.ACTION_UP;r.debugLog(`Sending Keycode: key=${e.key}, code=${t}, action=${a}, meta=${s}`);const c=r.createInjectKeycodeMessage(a,t,0,s);V(c)}else r.debugLog(`Ignoring unhandled key event: type=${e.type}, key=${e.key}`)},St=e=>{e.stopPropagation(),y.current?.reconnect()},x=l.useRef({onAxSnapshotChange:ge,onAxStatusChange:A,onCameraDemandChange:U,onCameraStats:Z,onMicrophoneStateChange:ce,onTrace:z,onTerminated:k,onConnectionStateChange:F,onPlaybackStats:M});x.current={onAxSnapshotChange:ge,onAxStatusChange:A,onCameraDemandChange:U,onCameraStats:Z,onMicrophoneStateChange:ce,onTrace:z,onTerminated:k,onConnectionStateChange:F,onPlaybackStats:M};const We=!!z;l.useEffect(()=>{xe.current=null,Ke(!1),$e(!1),De({})},[i,b]),l.useEffect(()=>{let e=!0;te.current!==null&&(te.current=null,Ye(null),r.safeInvoke("onAxSnapshotChange",x.current.onAxSnapshotChange,null));const n=r.createDeviceStream({url:i,token:m,sessionId:At,deviceModel:b,autoReconnect:L,jitterBufferTargetMs:P,openUrl:w,inspectMode:C,axPollIntervalMs:X,axMaxBackoffMs:D,androidElementTreeOptions:v,microphoneEnabled:B,onStateChange:t=>{(t.videoReady||t.connection==="idle"||t.connection==="connecting"||t.connection==="reconnecting")&&ut(t.videoReady),dt(t.connection==="failed"),ft(t.connection==="terminated"),it(t.duo),ct(t.duoState),st(t.duoError)},onAxSnapshotChange:t=>{e&&(Ye(s=>r.axSnapshotsEqual(s,t)?s:t),x.current.onAxSnapshotChange?.(t))},onAxStatusChange:(...t)=>x.current.onAxStatusChange?.(...t),onCameraDemandChange:(...t)=>x.current.onCameraDemandChange?.(...t),onCameraStats:Z?(...t)=>x.current.onCameraStats?.(...t):void 0,onMicrophoneStateChange:(...t)=>x.current.onMicrophoneStateChange?.(...t),onTrace:We?(...t)=>x.current.onTrace?.(...t):void 0,onTerminated:()=>x.current.onTerminated?.(),onConnectionStateChange:(...t)=>x.current.onConnectionStateChange?.(...t),onPlaybackStats:M?(...t)=>x.current.onPlaybackStats?.(...t):void 0});y.current=n;const o=R.current?n.attachVideo(R.current):void 0;return n.start(),()=>{e=!1,n.dispose(),o?.(),y.current=null}},[i,m,f,b,We]),l.useEffect(()=>{if(W&&we.current)return y.current?.attachVideo(we.current,"inner")},[W,i,m,f,b,We]),l.useEffect(()=>{y.current?.updateOptions({openUrl:w,axPollIntervalMs:X,axMaxBackoffMs:D,androidElementTreeOptions:v,autoReconnect:L,jitterBufferTargetMs:P,microphoneEnabled:B,inspectMode:C,onPlaybackStats:M?(...e)=>x.current.onPlaybackStats?.(...e):void 0,onCameraStats:Z?(...e)=>x.current.onCameraStats?.(...e):void 0})},[L,P,B,C,!!M,!!Z,w,X,D,v]);const et=()=>{const e=Ne();if(!e){Ue(null);return}const n={left:e.videoRect.left-e.containerRect.left+e.offsetX,top:e.videoRect.top-e.containerRect.top+e.offsetY,width:e.actualWidth,height:e.actualHeight};Ue(o=>o&&o.left===n.left&&o.top===n.top&&o.width===n.width&&o.height===n.height?o:n)};l.useEffect(()=>{const e=R.current,n=Ae.current,o=pe.current;if(!e)return;const t=()=>{const c=e.videoWidth>0&&e.videoHeight>0;c&&(xe.current={width:e.videoWidth,height:e.videoHeight});const u=xe.current,d=u?`${u.width} / ${u.height}`:void 0;if(!be||!n){De(!c&&u?{aspectRatio:d,contain:"size",containIntrinsicSize:`${u.width}px ${u.height}px`}:{}),et();return}const p=n.clientWidth,I=n.clientHeight;if(p===0||I===0)return;const E=u?u.width>u.height:!1;Ke(E),$e(q==="android"&&!!u&&$t(u.width,u.height));const S=E?le.videoPosition.landscape:le.videoPosition.portrait;let T={aspectRatio:d};S.heightMultiplier?(T.height=`${I*S.heightMultiplier}px`,T.width="auto"):S.widthMultiplier&&(T.width=`${p*S.widthMultiplier}px`,T.height="auto"),T.borderRadius=`${E?I*le.videoBorderRadiusMultiplier:p*le.videoBorderRadiusMultiplier}px`,De(T),et()},s=new ResizeObserver(()=>{t()});n&&s.observe(n),s.observe(e),o&&s.observe(o),n&&n.addEventListener("load",t),e.addEventListener("loadedmetadata",t),e.addEventListener("resize",t);const a=()=>y.current?.bumpActivity();return e.addEventListener("resize",a),t(),()=>{s.disconnect(),e.removeEventListener("loadedmetadata",t),e.removeEventListener("resize",t),e.removeEventListener("resize",a),n&&n.removeEventListener("load",t)}},[le,be,i,b]),l.useEffect(()=>{Ee||(Ye(null),ye(null),Ie(null),ze(null),ae(null),Re.current=null,K.current!==void 0&&(window.cancelAnimationFrame(K.current),K.current=void 0))},[Ee]),l.useEffect(()=>()=>{K.current!==void 0&&(window.cancelAnimationFrame(K.current),K.current=void 0)},[]),l.useEffect(()=>{if(!Ee)return;const e=n=>{n.key==="Escape"&&(ke||Pe)&&(Ie(null),ye(null),ae(null),r.safeInvoke("onInspectSelectionChange",ue.current,null))};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[Ee,ke,Pe]);const Dt=()=>{R.current&&R.current.focus()};l.useImperativeHandle(me,()=>({openUrl:e=>y.current?.openUrl(e),sendKeyEvent:e=>y.current?.sendKeyEvent(e),screenshot:e=>y.current?.screenshot(e)??Promise.reject(new Error("Simulator disconnected")),terminateApp:e=>y.current?.terminateApp(e)??Promise.reject(new Error("Simulator disconnected")),reconnect:()=>y.current?.reconnect(),refreshAxTree:()=>y.current?.refreshAxTree()??Promise.reject(new Error("Simulator disconnected")),getAxSnapshot:()=>y.current?.getAxSnapshot()??null,setInspectHighlight:e=>{ye(e?.id??null)},setInspectSelection:e=>{Ie(e?.id??null),ae(e?Re.current:null);const n=te.current;e&&n?r.safeInvoke("onInspectSelectionChange",ue.current,{element:e,snapshot:n}):r.safeInvoke("onInspectSelectionChange",ue.current,null)},getAxStatus:()=>y.current?.getAxStatus()??"idle"}));const xt=pt&&ee!==null;return g.jsxs("div",{ref:pe,className:ie("rc-container",h),style:{touchAction:"none"},onMouseDown:G,onMouseMove:G,onMouseUp:G,onMouseLeave:G,onTouchStart:G,onTouchMove:G,onTouchEnd:G,onTouchCancel:G,children:[xt&&ee&&g.jsxs(g.Fragment,{children:[g.jsx("div",{className:"rc-touch-indicator",style:{left:`${ee.containerX}px`,top:`${ee.containerY}px`}}),g.jsx("div",{className:"rc-touch-indicator",style:{left:`${ee.mirrorContainerX}px`,top:`${ee.mirrorContainerY}px`}})]}),be&&g.jsx("img",{ref:Ae,src:qe,alt:"",className:q==="ios"?ie("rc-phone-frame","rc-phone-frame-ios"):"rc-phone-frame",draggable:!1}),g.jsx("video",{ref:R,className:ie("rc-video",!be&&"rc-video-frameless",!at&&"rc-video-loading"),style:{...mt,...W?{opacity:0,width:1,height:1,pointerEvents:"none"}:{},...Ge?{backgroundImage:`url("${Ge}")`,backgroundRepeat:"no-repeat",backgroundPosition:"center",backgroundSize:le.loadingLogoSize}:{}},autoPlay:!0,playsInline:!0,muted:!0,tabIndex:W?-1:0,onKeyDown:Ce,onKeyUp:Ce,onClick:Dt,onFocus:()=>{R.current&&(R.current.style.outline="none")},onBlur:()=>{R.current&&(R.current.style.outline="none")}}),W&&g.jsx("video",{ref:we,autoPlay:!0,playsInline:!0,muted:!0,style:{position:"absolute",width:1,height:1,opacity:0,pointerEvents:"none"}}),W&&He&&g.jsx(l.Suspense,{fallback:g.jsx("div",{children:"Loading iPhone Duo…"}),children:g.jsx(Kt,{showFrame:H,modelUrl:N,outer:R.current,inner:we.current,state:He,setAngle:e=>Le("setHingeAngle",{angleDegrees:e}),setOrientation:e=>Le("setDuoOrientation",{orientation:e}),button:(e,n)=>Le("performActions",{actions:[{type:n?"buttonDown":"buttonUp",button:e}]}),touch:(e,n,o,t)=>{y.current?.sendDisplayTouch(e,n,o,t)},onKeyDown:Ce,onKeyUp:Ce})}),W&&Ve&&g.jsx("div",{role:"alert",className:"rc-duo-error",children:Ve}),!W&&Ee&&g.jsx(jt,{snapshot:Fe,geometry:yt,highlightedId:Pe,selectedId:ke,mode:Nt,cursorPosition:Et,frozenCursorPosition:Tt,onSelectChange:(e,n)=>{Ie(e?.id??null),e&&n?ae(n):e||ae(null);const o=te.current;e&&o?r.safeInvoke("onInspectSelectionChange",ue.current,{element:e,snapshot:o}):r.safeInvoke("onInspectSelectionChange",ue.current,null)},onTapElement:(e,n)=>{if(n){Ze(n.x,n.y);return}const o=te.current;o&&wt(e,o)}}),ht?g.jsxs("div",{className:"rc-terminated",role:"status",children:[g.jsx("div",{className:"rc-terminated-title",children:"Instance terminated"}),g.jsx("div",{className:"rc-terminated-message",children:"This instance no longer exists and can't be reconnected."})]}):lt&&g.jsx("button",{type:"button",className:"rc-retry-button",onClick:St,children:"Retry"})]})});exports.RemoteControl=zt;
|