@xenon-device-management/xenon 1.1.20 → 1.1.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/lib/package.json +1 -1
  2. package/lib/public/assets/{Layouts-7IT8aFLI.js → Layouts-DDyaq0x7.js} +1 -1
  3. package/lib/public/assets/{ai-settings-BbnfgdEx.js → ai-settings-C6IKGmmk.js} +1 -1
  4. package/lib/public/assets/{apps-CRMrI4_p.js → apps-BDRhNo4o.js} +1 -1
  5. package/lib/public/assets/{badge-CSvl5xIU.js → badge-BAasruTp.js} +1 -1
  6. package/lib/public/assets/{button-CvLaGFYj.js → button-Dj-mubV7.js} +1 -1
  7. package/lib/public/assets/{calendar-6w-D6Oaw.js → calendar-BymTqn8p.js} +1 -1
  8. package/lib/public/assets/{clock-DcdeWBPr.js → clock-BWbrY15X.js} +1 -1
  9. package/lib/public/assets/{cpu-DiSoXT9n.js → cpu-RQ95hEeI.js} +1 -1
  10. package/lib/public/assets/{device-explorer-CajM63OJ.js → device-explorer-C3LtXLHY.js} +14 -14
  11. package/lib/public/assets/{index-ByQwMN5T.js → index-CvgdoCl7.js} +2 -2
  12. package/lib/public/assets/{lock-B23ibZmo.js → lock-B7hcjD2m.js} +1 -1
  13. package/lib/public/assets/{maintenance-settings-CirzA6yG.js → maintenance-settings-75V2i60m.js} +1 -1
  14. package/lib/public/assets/{mouse-pointer-2-Cz76SHFb.js → mouse-pointer-2--4SDXR63.js} +1 -1
  15. package/lib/public/assets/{plus-BBwlIevt.js → plus-CspDy7t8.js} +1 -1
  16. package/lib/public/assets/{session-dashboard-HPDtwPOZ.js → session-dashboard-C5KwBUZv.js} +1 -1
  17. package/lib/public/assets/{settings-DrZsZwdc.js → settings-DRq6ku53.js} +1 -1
  18. package/lib/public/assets/{trash-2-DQpvzJec.js → trash-2-CVL2-wTB.js} +1 -1
  19. package/lib/public/assets/{useSocket-Dxsqae2a.js → useSocket-BGEh-0N6.js} +1 -1
  20. package/lib/public/assets/{webhook-settings-Cp-B4Nrw.js → webhook-settings-BEvfRZOy.js} +1 -1
  21. package/lib/public/assets/{zap-DovP6iow.js → zap-O1qTOCtS.js} +1 -1
  22. package/lib/public/index.html +1 -1
  23. package/lib/src/device-managers/ios/WDAClient.js +102 -80
  24. package/package.json +1 -1
package/lib/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xenon-device-management/xenon",
3
- "version": "1.1.20",
3
+ "version": "1.1.22",
4
4
  "description": "Xenon - Intelligent Mobile Infrastructure. A self-healing device orchestration platform for Appium.",
5
5
  "main": "./lib/src/index.js",
6
6
  "exports": {
@@ -1,4 +1,4 @@
1
- import{c,j as e,g as l}from"./index-ByQwMN5T.js";/**
1
+ import{c,j as e,g as l}from"./index-CvgdoCl7.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as j,r as l,j as e,B as u,d as f,g as C,i as A,T as z}from"./index-ByQwMN5T.js";import{X as x}from"./index-C1DBaoSh.js";import{A as P}from"./Layouts-7IT8aFLI.js";import{C as w}from"./cpu-DiSoXT9n.js";import{L as v}from"./lock-B23ibZmo.js";/**
1
+ import{c as j,r as l,j as e,B as u,d as f,g as C,i as A,T as z}from"./index-CvgdoCl7.js";import{X as x}from"./index-C1DBaoSh.js";import{A as P}from"./Layouts-DDyaq0x7.js";import{C as w}from"./cpu-RQ95hEeI.js";import{L as v}from"./lock-B7hcjD2m.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as g,u as X,r,j as e,S as z,g as q,X as V}from"./index-ByQwMN5T.js";import{X as c}from"./index-C1DBaoSh.js";import{S as H,B as S,D as K}from"./badge-CSvl5xIU.js";import{A as D,B as T,U as Z,C as J,a as Q,T as ee}from"./button-CvLaGFYj.js";import{Z as se}from"./zap-DovP6iow.js";import{T as ae}from"./trash-2-DQpvzJec.js";/**
1
+ import{c as g,u as X,r,j as e,S as z,g as q,X as V}from"./index-CvgdoCl7.js";import{X as c}from"./index-C1DBaoSh.js";import{S as H,B as S,D as K}from"./badge-BAasruTp.js";import{A as D,B as T,U as Z,C as J,a as Q,T as ee}from"./button-Dj-mubV7.js";import{Z as se}from"./zap-O1qTOCtS.js";import{T as ae}from"./trash-2-CVL2-wTB.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as ye,j as Ve}from"./index-ByQwMN5T.js";/**
1
+ import{c as ye,j as Ve}from"./index-CvgdoCl7.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as t,r as c,j as i}from"./index-ByQwMN5T.js";import{c as r,a as u}from"./badge-CSvl5xIU.js";/**
1
+ import{c as t,r as c,j as i}from"./index-CvgdoCl7.js";import{c as r,a as u}from"./badge-BAasruTp.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-ByQwMN5T.js";/**
1
+ import{c as e}from"./index-CvgdoCl7.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c}from"./index-ByQwMN5T.js";/**
1
+ import{c}from"./index-CvgdoCl7.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as h}from"./index-ByQwMN5T.js";/**
1
+ import{c as h}from"./index-CvgdoCl7.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as I,r,a as Cs,j as e,X as Ke,C as Ss,u as us,b as Qe,R as Fe,S as Je,d as Ze,e as ps,T as $s,f as vs,L as We,g as ss}from"./index-ByQwMN5T.js";import{p as ts,H as Ds,C as xs,a as Ve,u as As}from"./useSocket-Dxsqae2a.js";import{X as D}from"./index-C1DBaoSh.js";import{C as gs}from"./clock-DcdeWBPr.js";import{P as fs}from"./plus-BBwlIevt.js";import{A as ys,T as js,C as qe,a as Xe,U as Ls,B as Ge}from"./button-CvLaGFYj.js";import{M as Ts}from"./mouse-pointer-2-Cz76SHFb.js";import{S as es,D as Es,B as Me}from"./badge-CSvl5xIU.js";import{Z as zs}from"./zap-DovP6iow.js";import{L as Is}from"./lock-B23ibZmo.js";import{T as _e}from"./trash-2-DQpvzJec.js";/**
1
+ import{c as I,r,a as Cs,j as e,X as Ke,C as Ss,u as us,b as Qe,R as Fe,S as Je,d as Ze,e as ps,T as $s,f as vs,L as We,g as ss}from"./index-CvgdoCl7.js";import{p as ts,H as Ds,C as xs,a as Ve,u as As}from"./useSocket-BGEh-0N6.js";import{X as D}from"./index-C1DBaoSh.js";import{C as gs}from"./clock-BWbrY15X.js";import{P as fs}from"./plus-CspDy7t8.js";import{A as ys,T as js,C as qe,a as Xe,U as Ls,B as Ge}from"./button-Dj-mubV7.js";import{M as Ts}from"./mouse-pointer-2--4SDXR63.js";import{S as es,D as Es,B as Me}from"./badge-BAasruTp.js";import{Z as zs}from"./zap-O1qTOCtS.js";import{L as Is}from"./lock-B7hcjD2m.js";import{T as _e}from"./trash-2-CVL2-wTB.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -78,12 +78,12 @@ import{c as I,r,a as Cs,j as e,X as Ke,C as Ss,u as us,b as Qe,R as Fe,S as Je,d
78
78
  *
79
79
  * This source code is licensed under the ISC license.
80
80
  * See the LICENSE file in the root directory of this source tree.
81
- */const rt=[["path",{d:"M12 2v20",key:"t6zp3m"}],["path",{d:"m15 19-3 3-3-3",key:"11eu04"}],["path",{d:"m19 9 3 3-3 3",key:"1mg7y2"}],["path",{d:"M2 12h20",key:"9i4pu4"}],["path",{d:"m5 9-3 3 3 3",key:"j64kie"}],["path",{d:"m9 5 3-3 3 3",key:"l8vdw6"}]],ct=I("move",rt);/**
81
+ */const rt=[["path",{d:"M12 2v20",key:"t6zp3m"}],["path",{d:"m15 19-3 3-3-3",key:"11eu04"}],["path",{d:"m19 9 3 3-3 3",key:"1mg7y2"}],["path",{d:"M2 12h20",key:"9i4pu4"}],["path",{d:"m5 9-3 3 3 3",key:"j64kie"}],["path",{d:"m9 5 3-3 3 3",key:"l8vdw6"}]],lt=I("move",rt);/**
82
82
  * @license lucide-react v0.555.0 - ISC
83
83
  *
84
84
  * This source code is licensed under the ISC license.
85
85
  * See the LICENSE file in the root directory of this source tree.
86
- */const lt=[["path",{d:"M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z",key:"1a0edw"}],["path",{d:"M12 22V12",key:"d0xqtd"}],["polyline",{points:"3.29 7 12 12 20.71 7",key:"ousv84"}],["path",{d:"m7.5 4.27 9 5.15",key:"1c824w"}]],ot=I("package",lt);/**
86
+ */const ct=[["path",{d:"M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z",key:"1a0edw"}],["path",{d:"M12 22V12",key:"d0xqtd"}],["polyline",{points:"3.29 7 12 12 20.71 7",key:"ousv84"}],["path",{d:"m7.5 4.27 9 5.15",key:"1c824w"}]],ot=I("package",ct);/**
87
87
  * @license lucide-react v0.555.0 - ISC
88
88
  *
89
89
  * This source code is licensed under the ISC license.
@@ -103,7 +103,7 @@ import{c as I,r,a as Cs,j as e,X as Ke,C as Ss,u as us,b as Qe,R as Fe,S as Je,d
103
103
  *
104
104
  * This source code is licensed under the ISC license.
105
105
  * See the LICENSE file in the root directory of this source tree.
106
- */const pt=[["path",{d:"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z",key:"1s2grr"}],["path",{d:"M20 2v4",key:"1rf3ol"}],["path",{d:"M22 4h-4",key:"gwowj6"}],["circle",{cx:"4",cy:"20",r:"2",key:"6kqj1y"}]],cs=I("sparkles",pt);/**
106
+ */const pt=[["path",{d:"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z",key:"1s2grr"}],["path",{d:"M20 2v4",key:"1rf3ol"}],["path",{d:"M22 4h-4",key:"gwowj6"}],["circle",{cx:"4",cy:"20",r:"2",key:"6kqj1y"}]],ls=I("sparkles",pt);/**
107
107
  * @license lucide-react v0.555.0 - ISC
108
108
  *
109
109
  * This source code is licensed under the ISC license.
@@ -113,7 +113,7 @@ import{c as I,r,a as Cs,j as e,X as Ke,C as Ss,u as us,b as Qe,R as Fe,S as Je,d
113
113
  *
114
114
  * This source code is licensed under the ISC license.
115
115
  * See the LICENSE file in the root directory of this source tree.
116
- */const gt=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["circle",{cx:"12",cy:"12",r:"6",key:"1vlfrh"}],["circle",{cx:"12",cy:"12",r:"2",key:"1c9p78"}]],ls=I("target",gt);/**
116
+ */const gt=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["circle",{cx:"12",cy:"12",r:"6",key:"1vlfrh"}],["circle",{cx:"12",cy:"12",r:"2",key:"1c9p78"}]],cs=I("target",gt);/**
117
117
  * @license lucide-react v0.555.0 - ISC
118
118
  *
119
119
  * This source code is licensed under the ISC license.
@@ -138,7 +138,7 @@ import{c as I,r,a as Cs,j as e,X as Ke,C as Ss,u as us,b as Qe,R as Fe,S as Je,d
138
138
  *
139
139
  * This source code is licensed under the ISC license.
140
140
  * See the LICENSE file in the root directory of this source tree.
141
- */const Ct=[["path",{d:"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z",key:"1ngwbx"}]],St=I("wrench",Ct),$t=[{label:"1 Hour",value:"1h"},{label:"2 Hours",value:"2h"},{label:"4 Hours",value:"4h"},{label:"8 Hours",value:"8h"}],Dt=({device:n,onClose:s,onReserved:l})=>{const[u,p]=r.useState(""),[t,T]=r.useState("1h"),[v,x]=r.useState(""),[h,m]=r.useState(!1),[A,S]=r.useState(null),U=async()=>{if(!u.trim()){S("Please enter your name/ID");return}m(!0),S(null);try{const w=await D.reserveDevice(n.udid,n.host,u,t,v);w.success?(l(),s()):S(w.error||"Failed to reserve device")}catch(w){S(w.message||"An unexpected error occurred")}finally{m(!1)}};return Cs.createPortal(e.jsx("div",{className:"reservation-modal-overlay",onClick:s,children:e.jsxs("div",{className:"reservation-modal",onClick:w=>w.stopPropagation(),children:[e.jsx("div",{className:"scanline",style:{position:"absolute",inset:0,pointerEvents:"none",opacity:.05,zIndex:1001}}),e.jsxs("div",{className:"reservation-modal-header",children:[e.jsxs("div",{className:"reservation-modal-title",children:[e.jsx(bs,{size:18,className:"title-icon"}),"Reserve Device"]}),e.jsx("button",{className:"close-btn",onClick:s,children:e.jsx(Ke,{size:20})})]}),e.jsxs("div",{className:"reservation-modal-body",children:[e.jsxs("div",{className:"device-id-badge",children:[e.jsx("span",{className:"label",children:"Device:"}),e.jsx("span",{className:"value",children:n.udid})]}),e.jsxs("p",{children:["Reserve ",e.jsx("strong",{children:n.name||n.udid})," for exclusive use. This will prevent CI sessions from using this device."]}),e.jsxs("div",{className:"reservation-form-group",children:[e.jsxs("label",{children:[e.jsx(wt,{size:14,style:{marginRight:6,verticalAlign:"middle",color:"var(--color-primary)"}}),"Reserved By"]}),e.jsx("input",{type:"text",className:"reservation-input",placeholder:"Enter your name or ID",value:u,onChange:w=>p(w.target.value),disabled:h})]}),e.jsxs("div",{className:"reservation-form-group",children:[e.jsxs("label",{children:[e.jsx(gs,{size:14,style:{marginRight:6,verticalAlign:"middle",color:"var(--color-primary)"}}),"Duration"]}),e.jsx("div",{className:"duration-selector",children:$t.map(w=>e.jsx("div",{className:`duration-option ${t===w.value?"active":""}`,onClick:()=>T(w.value),children:w.label},w.value))})]}),e.jsxs("div",{className:"reservation-form-group",children:[e.jsxs("label",{children:[e.jsx(at,{size:14,style:{marginRight:6,verticalAlign:"middle",color:"var(--color-primary)"}}),"Reason (Optional)"]}),e.jsx("input",{type:"text",className:"reservation-input",placeholder:"e.g., Debugging flaky login test",value:v,onChange:w=>x(w.target.value),disabled:h})]}),A&&e.jsxs("div",{className:"error-message",children:[e.jsx(Ss,{size:14,style:{marginRight:6,verticalAlign:"middle"}}),A]})]}),e.jsxs("div",{className:"reservation-actions",children:[e.jsx("button",{className:"btn-cancel",onClick:s,disabled:h,children:"Cancel"}),e.jsx("button",{className:"btn-reserve",onClick:U,disabled:h||!u.trim(),children:h?"Reserving...":"Confirm Reservation"})]})]})}),document.body)},At=({device:n,onClose:s,onUpdated:l})=>{const{toast:u}=us(),[p,t]=r.useState(n.tags||[]),[T,v]=r.useState(""),[x,h]=r.useState(!1),m=r.useRef(null);r.useEffect(()=>{m.current&&m.current.focus()},[]);const A=()=>{const j=T.trim();j&&!p.includes(j)&&(t([...p,j]),v(""))},S=j=>{t(p.filter(E=>E!==j))},U=j=>{j.key==="Enter"?A():j.key==="Escape"&&s()},w=async()=>{h(!0);try{await D.updateDeviceTags(n.udid,n.host,p),l(),s()}catch(j){console.error("Failed to update tags",j),u("Error saving tags. Please try again.","error")}finally{h(!1)}};return e.jsx("div",{className:"tag-modal-overlay",onClick:s,children:e.jsxs("div",{className:"tag-modal-container",onClick:j=>j.stopPropagation(),children:[e.jsx("div",{className:"scanline",style:{position:"absolute",inset:0,pointerEvents:"none",opacity:.05,zIndex:1001}}),e.jsxs("div",{className:"tag-modal-header",children:[e.jsxs("div",{className:"tag-modal-title",children:[e.jsx(xt,{size:18,className:"title-icon"}),"Manage Device Tags"]}),e.jsx("button",{className:"close-btn",onClick:s,children:e.jsx(Ke,{size:20})})]}),e.jsxs("div",{className:"tag-modal-body",children:[e.jsxs("div",{className:"device-id-badge",children:[e.jsx("span",{className:"label",children:"Device:"}),e.jsx("span",{className:"value",children:n.udid})]}),e.jsxs("div",{className:"tag-input-section",children:[e.jsx("label",{htmlFor:"tag-input",children:"Add New Tag"}),e.jsxs("div",{className:"input-with-button",children:[e.jsx("input",{ref:m,id:"tag-input",type:"text",placeholder:"e.g. stable, team-a, ios-17",value:T,onChange:j=>v(j.target.value),onKeyDown:U}),e.jsx("button",{className:"add-inline-btn",onClick:A,disabled:!T.trim(),children:e.jsx(fs,{size:16})})]}),e.jsx("p",{className:"input-hint",children:"Press Enter to add multiple tags"})]}),e.jsxs("div",{className:"tags-display-section",children:[e.jsx("label",{children:"Current Tags"}),e.jsx("div",{className:"tags-list",children:p.length>0?p.map(j=>e.jsxs("div",{className:"tag-pill-editable",children:[j,e.jsx("button",{className:"remove-tag",onClick:()=>S(j),children:e.jsx(Ke,{size:12})})]},j)):e.jsx("div",{className:"empty-tags",children:"No tags assigned to this device."})})]})]}),e.jsxs("div",{className:"tag-modal-footer",children:[e.jsx("button",{className:"btn-cancel",onClick:s,children:"Cancel"}),e.jsx("button",{className:"btn-save",onClick:w,disabled:x,children:x?"Saving...":"Apply Changes"})]})]})})};class Lt extends Fe.Component{constructor(s){super(s),this.state={showReservation:!1,showTagManager:!1,showControl:!1}}getStatusClassName(){return this.props.device.offline?"disabled":this.props.device.busy?"busy":this.isReserved()?"reserved":""}getDeviceState(){return this.props.device.offline?"offline":this.props.device.userBlocked?"maintenance":this.props.device.busy?"busy":this.isReserved()?"reserved":"ready"}isReserved(){const{reservedUntil:s}=this.props.device;return s?Date.now()<s:!1}getRemainingReservationTime(){const{reservedUntil:s}=this.props.device;if(!s)return"";const l=s-Date.now();return l<=0?"":ts(l,{compact:!0})}async releaseReservation(s,l){await D.releaseReservation(s,l),this.props.reloadDevices()}async blockDevice(s,l){await D.blockDevice(s,l),this.props.reloadDevices()}async unblockDevice(s,l){await D.unblockDevice(s,l),this.props.reloadDevices()}async manageTags(){this.setState({showTagManager:!0})}render(){var H;const{name:s,sdk:l,deviceType:u,platform:p,udid:t,dashboard_link:T,total_session_count:v,host:x,totalUtilizationTimeMilliSec:h,userBlocked:m,busy:A,session_id:S,reservedBy:U,reservedUntil:w,reservationReason:j,batteryLevel:E,thermalStatus:O,storageFree:b,tags:k,sessionProgress:f,totalHealedCount:R}=this.props.device,M=this.getDeviceState();let _="";try{_=new URL(x).hostname}catch{_=x.split(":")[1].replace("//","")}const X=()=>A?null:this.isReserved()?e.jsx("button",{className:"tactical-btn reserved",onClick:()=>this.releaseReservation(t,x),title:`Reserved by ${U}${j?`: ${j}`:""}. Expires: ${w?new Date(w).toLocaleString():"Never"}`,children:e.jsx(Ns,{size:14,color:"#38bdf8"})}):m?e.jsx("button",{className:"tactical-btn exit-maintenance",onClick:()=>this.unblockDevice(t,x),title:"Exit Maintenance",children:e.jsx(Ze,{size:14})}):e.jsxs(e.Fragment,{children:[e.jsx("button",{className:"tactical-btn reserve",onClick:()=>this.setState({showReservation:!0}),title:"Reserve Device",children:e.jsx(bs,{size:14,color:"#38bdf8"})}),e.jsx("button",{className:"tactical-btn maintenance",onClick:()=>this.blockDevice(t,x),title:"Enter Maintenance",children:e.jsx(St,{size:14,color:"#fbbf24"})})]});return e.jsxs("div",{className:`device-info-card-container ${this.getStatusClassName()} group`,children:[e.jsx("div",{className:"scanline",style:{position:"absolute",inset:0,pointerEvents:"none",opacity:.1,zIndex:0}}),e.jsxs("div",{className:"card-header relative z-10",children:[e.jsxs("div",{className:"header-left",children:[e.jsx("div",{className:`platform-icon-wrapper ${p}`,children:["ios","tvos"].includes(p)?e.jsx(ys,{size:14}):e.jsx(Je,{size:14})}),e.jsx("div",{className:"device-id-mono",title:t,children:t})]}),e.jsx("div",{className:`device-status-badge ${M} ${M==="busy"&&f&&f!=="Session Active"?"pulse":""}`,children:M==="busy"&&f&&f!=="Session Active"?f:M})]}),e.jsxs("div",{className:"device-info-main relative z-10",children:[e.jsx("h3",{className:"device-name",title:s,children:s}),e.jsxs("p",{className:"device-subtext",children:[u.toUpperCase()," • ",l]}),this.props.device.tags&&this.props.device.tags.length>0&&e.jsxs("div",{className:"device-tags-inline",children:[this.props.device.tags.slice(0,3).map(se=>e.jsx("span",{className:"inline-tag",title:se,children:se},se)),this.props.device.tags.length>3&&e.jsxs("span",{className:"inline-tag-overflow",children:["+",this.props.device.tags.length-3]})]})]}),e.jsxs("div",{className:"metrics-grid relative z-10",children:[e.jsxs("div",{className:"metric-item",title:`Location: ${_}`,children:[e.jsx(ns,{size:10,className:"text-dim"}),e.jsx("span",{className:"truncate",children:_})]}),this.props.device.ip&&e.jsxs("div",{className:"metric-item",title:`IP: ${this.props.device.ip}`,children:[e.jsx(ws,{size:10,className:"text-dim"}),e.jsx("span",{className:"truncate",children:this.props.device.ip})]}),e.jsxs("div",{className:`metric-item health ${((H=this.props.device.healthStatus)==null?void 0:H.toLowerCase())||"healthy"}`,title:this.props.device.healthCheckError||"Device is healthy",children:[e.jsx("div",{className:"health-dot"}),e.jsx("span",{children:this.props.device.healthStatus||"Healthy"}),R&&R>0&&e.jsxs("span",{className:"heal-badge",children:[e.jsx(Ze,{size:8})," ",R]})]}),O&&O!=="Unknown"&&e.jsxs("div",{className:"metric-item thermal",title:`Thermal: ${O}`,children:[e.jsx(yt,{size:10,style:{color:O==="Nominal"?"var(--color-primary)":"var(--color-amber)"}}),e.jsx("span",{children:O})]}),E!==void 0&&e.jsxs("div",{className:"metric-item battery",title:`Battery: ${E}%`,children:[e.jsx("div",{className:`mini-battery ${E<20?"low":""}`,children:e.jsx("div",{className:"battery-fill",style:{width:`${E}%`}})}),e.jsxs("span",{children:[E,"%"]})]}),b&&b!=="Unknown"&&e.jsxs("div",{className:"metric-item storage",title:`Free Space: ${b}`,children:[e.jsx(Ds,{size:10,style:{color:"var(--color-sky)"}}),e.jsx("span",{children:b})]})]}),e.jsx("div",{className:"dynamic-data-layer relative z-10",children:this.isReserved()?e.jsxs("div",{className:"reservation-micro-banner",children:[e.jsx(gs,{size:10}),e.jsxs("span",{children:["RES: ",U||"Anon"," (",this.getRemainingReservationTime(),")"]})]}):S?e.jsxs("div",{className:"session-micro-banner",children:[e.jsx(js,{size:10}),e.jsxs("span",{children:["SID: ",S]})]}):e.jsx("div",{className:"utilization-micro-info",children:e.jsxs("span",{children:["UTIL: ",ts(h||0,{compact:!0})]})})}),e.jsxs("div",{className:"action-row relative z-10",children:[e.jsx("button",{className:"tactical-btn add-tag",onClick:()=>this.manageTags(),title:"Manage Tags",children:e.jsx(fs,{size:14})}),X(),e.jsxs("button",{className:`tactical-btn control-btn ${A&&S&&!S.toString().startsWith("manual_")?"disabled":""}`,onClick:()=>!(A&&S&&!S.toString().startsWith("manual_"))&&this.props.navigate(`/devices/${t}/control`),disabled:A&&!!S&&!S.toString().startsWith("manual_"),title:A&&S&&!S.toString().startsWith("manual_")?"Locked: Appium Session":"Take Control",children:[e.jsx(ns,{size:14}),e.jsx("span",{style:{fontSize:"10px",fontWeight:800,letterSpacing:"0.05em",fontFamily:"Outfit, sans-serif"},children:"CTRL"})]})]}),this.state.showReservation&&e.jsx(Dt,{device:this.props.device,onClose:()=>this.setState({showReservation:!1}),onReserved:()=>this.props.reloadDevices()}),this.state.showTagManager&&e.jsx(At,{device:this.props.device,onClose:()=>this.setState({showTagManager:!1}),onUpdated:()=>this.props.reloadDevices()})]})}}function Tt(n){const s=Qe();return e.jsx(Lt,{...n,navigate:s})}class Et extends Fe.Component{render(){return e.jsx("div",{className:"device-explorer-card-container",children:Fe.Children.toArray(this.props.devices.map(s=>e.jsx(Tt,{device:s,reloadDevices:this.props.reloadDevices})))})}}var Ue,zt=new Uint8Array(16);function It(){if(!Ue&&(Ue=typeof crypto<"u"&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||typeof msCrypto<"u"&&typeof msCrypto.getRandomValues=="function"&&msCrypto.getRandomValues.bind(msCrypto),!Ue))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return Ue(zt)}const Rt=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;function Mt(n){return typeof n=="string"&&Rt.test(n)}var Y=[];for(var Ye=0;Ye<256;++Ye)Y.push((Ye+256).toString(16).substr(1));function _t(n){var s=arguments.length>1&&arguments[1]!==void 0?arguments[1]:0,l=(Y[n[s+0]]+Y[n[s+1]]+Y[n[s+2]]+Y[n[s+3]]+"-"+Y[n[s+4]]+Y[n[s+5]]+"-"+Y[n[s+6]]+Y[n[s+7]]+"-"+Y[n[s+8]]+Y[n[s+9]]+"-"+Y[n[s+10]]+Y[n[s+11]]+Y[n[s+12]]+Y[n[s+13]]+Y[n[s+14]]+Y[n[s+15]]).toLowerCase();if(!Mt(l))throw TypeError("Stringified UUID is invalid");return l}function Ut(n,s,l){n=n||{};var u=n.random||(n.rng||It)();return u[6]=u[6]&15|64,u[8]=u[8]&63|128,_t(u)}const Ot=({onCommand:n,prompt:s="$",welcomeMessage:l="Interactive Shell (Restricted Mode)",platform:u})=>{const[p,t]=r.useState([{type:"system",content:l,timestamp:Date.now()},{type:"system",content:'Type "help" for allowed commands.',timestamp:Date.now()}]),[T,v]=r.useState(""),[x,h]=r.useState([]),[m,A]=r.useState(-1),[S,U]=r.useState(!1),w=r.useRef(null),j=r.useRef(null);r.useEffect(()=>{w.current&&(w.current.scrollTop=w.current.scrollHeight)},[p]);const E=b=>{const k=b.trim();if((k.startsWith("{")||k.startsWith("["))&&(k.endsWith("}")||k.endsWith("]")))try{const f=JSON.parse(k);return JSON.stringify(f,null,2)}catch{}return b},O=async b=>{if(b.key==="Enter"&&!S){const k=T.trim();if(!k)return;if(v(""),t(f=>[...f,{type:"command",content:`${s} ${k}`,timestamp:Date.now()}]),h(f=>[...f,k]),A(-1),U(!0),k==="clear"){t([]),U(!1);return}if(k==="help"){let f="";u==="android"?f=`
141
+ */const Ct=[["path",{d:"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z",key:"1ngwbx"}]],St=I("wrench",Ct),$t=[{label:"1 Hour",value:"1h"},{label:"2 Hours",value:"2h"},{label:"4 Hours",value:"4h"},{label:"8 Hours",value:"8h"}],Dt=({device:n,onClose:s,onReserved:c})=>{const[u,p]=r.useState(""),[t,T]=r.useState("1h"),[v,x]=r.useState(""),[h,m]=r.useState(!1),[A,$]=r.useState(null),U=async()=>{if(!u.trim()){$("Please enter your name/ID");return}m(!0),$(null);try{const w=await D.reserveDevice(n.udid,n.host,u,t,v);w.success?(c(),s()):$(w.error||"Failed to reserve device")}catch(w){$(w.message||"An unexpected error occurred")}finally{m(!1)}};return Cs.createPortal(e.jsx("div",{className:"reservation-modal-overlay",onClick:s,children:e.jsxs("div",{className:"reservation-modal",onClick:w=>w.stopPropagation(),children:[e.jsx("div",{className:"scanline",style:{position:"absolute",inset:0,pointerEvents:"none",opacity:.05,zIndex:1001}}),e.jsxs("div",{className:"reservation-modal-header",children:[e.jsxs("div",{className:"reservation-modal-title",children:[e.jsx(bs,{size:18,className:"title-icon"}),"Reserve Device"]}),e.jsx("button",{className:"close-btn",onClick:s,children:e.jsx(Ke,{size:20})})]}),e.jsxs("div",{className:"reservation-modal-body",children:[e.jsxs("div",{className:"device-id-badge",children:[e.jsx("span",{className:"label",children:"Device:"}),e.jsx("span",{className:"value",children:n.udid})]}),e.jsxs("p",{children:["Reserve ",e.jsx("strong",{children:n.name||n.udid})," for exclusive use. This will prevent CI sessions from using this device."]}),e.jsxs("div",{className:"reservation-form-group",children:[e.jsxs("label",{children:[e.jsx(wt,{size:14,style:{marginRight:6,verticalAlign:"middle",color:"var(--color-primary)"}}),"Reserved By"]}),e.jsx("input",{type:"text",className:"reservation-input",placeholder:"Enter your name or ID",value:u,onChange:w=>p(w.target.value),disabled:h})]}),e.jsxs("div",{className:"reservation-form-group",children:[e.jsxs("label",{children:[e.jsx(gs,{size:14,style:{marginRight:6,verticalAlign:"middle",color:"var(--color-primary)"}}),"Duration"]}),e.jsx("div",{className:"duration-selector",children:$t.map(w=>e.jsx("div",{className:`duration-option ${t===w.value?"active":""}`,onClick:()=>T(w.value),children:w.label},w.value))})]}),e.jsxs("div",{className:"reservation-form-group",children:[e.jsxs("label",{children:[e.jsx(at,{size:14,style:{marginRight:6,verticalAlign:"middle",color:"var(--color-primary)"}}),"Reason (Optional)"]}),e.jsx("input",{type:"text",className:"reservation-input",placeholder:"e.g., Debugging flaky login test",value:v,onChange:w=>x(w.target.value),disabled:h})]}),A&&e.jsxs("div",{className:"error-message",children:[e.jsx(Ss,{size:14,style:{marginRight:6,verticalAlign:"middle"}}),A]})]}),e.jsxs("div",{className:"reservation-actions",children:[e.jsx("button",{className:"btn-cancel",onClick:s,disabled:h,children:"Cancel"}),e.jsx("button",{className:"btn-reserve",onClick:U,disabled:h||!u.trim(),children:h?"Reserving...":"Confirm Reservation"})]})]})}),document.body)},At=({device:n,onClose:s,onUpdated:c})=>{const{toast:u}=us(),[p,t]=r.useState(n.tags||[]),[T,v]=r.useState(""),[x,h]=r.useState(!1),m=r.useRef(null);r.useEffect(()=>{m.current&&m.current.focus()},[]);const A=()=>{const j=T.trim();j&&!p.includes(j)&&(t([...p,j]),v(""))},$=j=>{t(p.filter(E=>E!==j))},U=j=>{j.key==="Enter"?A():j.key==="Escape"&&s()},w=async()=>{h(!0);try{await D.updateDeviceTags(n.udid,n.host,p),c(),s()}catch(j){console.error("Failed to update tags",j),u("Error saving tags. Please try again.","error")}finally{h(!1)}};return e.jsx("div",{className:"tag-modal-overlay",onClick:s,children:e.jsxs("div",{className:"tag-modal-container",onClick:j=>j.stopPropagation(),children:[e.jsx("div",{className:"scanline",style:{position:"absolute",inset:0,pointerEvents:"none",opacity:.05,zIndex:1001}}),e.jsxs("div",{className:"tag-modal-header",children:[e.jsxs("div",{className:"tag-modal-title",children:[e.jsx(xt,{size:18,className:"title-icon"}),"Manage Device Tags"]}),e.jsx("button",{className:"close-btn",onClick:s,children:e.jsx(Ke,{size:20})})]}),e.jsxs("div",{className:"tag-modal-body",children:[e.jsxs("div",{className:"device-id-badge",children:[e.jsx("span",{className:"label",children:"Device:"}),e.jsx("span",{className:"value",children:n.udid})]}),e.jsxs("div",{className:"tag-input-section",children:[e.jsx("label",{htmlFor:"tag-input",children:"Add New Tag"}),e.jsxs("div",{className:"input-with-button",children:[e.jsx("input",{ref:m,id:"tag-input",type:"text",placeholder:"e.g. stable, team-a, ios-17",value:T,onChange:j=>v(j.target.value),onKeyDown:U}),e.jsx("button",{className:"add-inline-btn",onClick:A,disabled:!T.trim(),children:e.jsx(fs,{size:16})})]}),e.jsx("p",{className:"input-hint",children:"Press Enter to add multiple tags"})]}),e.jsxs("div",{className:"tags-display-section",children:[e.jsx("label",{children:"Current Tags"}),e.jsx("div",{className:"tags-list",children:p.length>0?p.map(j=>e.jsxs("div",{className:"tag-pill-editable",children:[j,e.jsx("button",{className:"remove-tag",onClick:()=>$(j),children:e.jsx(Ke,{size:12})})]},j)):e.jsx("div",{className:"empty-tags",children:"No tags assigned to this device."})})]})]}),e.jsxs("div",{className:"tag-modal-footer",children:[e.jsx("button",{className:"btn-cancel",onClick:s,children:"Cancel"}),e.jsx("button",{className:"btn-save",onClick:w,disabled:x,children:x?"Saving...":"Apply Changes"})]})]})})};class Lt extends Fe.Component{constructor(s){super(s),this.state={showReservation:!1,showTagManager:!1,showControl:!1}}getStatusClassName(){return this.props.device.offline?"disabled":this.props.device.busy?"busy":this.isReserved()?"reserved":""}getDeviceState(){return this.props.device.offline?"offline":this.props.device.userBlocked?"maintenance":this.props.device.busy?"busy":this.isReserved()?"reserved":"ready"}isReserved(){const{reservedUntil:s}=this.props.device;return s?Date.now()<s:!1}getRemainingReservationTime(){const{reservedUntil:s}=this.props.device;if(!s)return"";const c=s-Date.now();return c<=0?"":ts(c,{compact:!0})}async releaseReservation(s,c){await D.releaseReservation(s,c),this.props.reloadDevices()}async blockDevice(s,c){await D.blockDevice(s,c),this.props.reloadDevices()}async unblockDevice(s,c){await D.unblockDevice(s,c),this.props.reloadDevices()}async manageTags(){this.setState({showTagManager:!0})}render(){var H;const{name:s,sdk:c,deviceType:u,platform:p,udid:t,dashboard_link:T,total_session_count:v,host:x,totalUtilizationTimeMilliSec:h,userBlocked:m,busy:A,session_id:$,reservedBy:U,reservedUntil:w,reservationReason:j,batteryLevel:E,thermalStatus:O,storageFree:b,tags:k,sessionProgress:f,totalHealedCount:R}=this.props.device,M=this.getDeviceState();let _="";try{_=new URL(x).hostname}catch{_=x.split(":")[1].replace("//","")}const X=()=>A?null:this.isReserved()?e.jsx("button",{className:"tactical-btn reserved",onClick:()=>this.releaseReservation(t,x),title:`Reserved by ${U}${j?`: ${j}`:""}. Expires: ${w?new Date(w).toLocaleString():"Never"}`,children:e.jsx(Ns,{size:14,color:"#38bdf8"})}):m?e.jsx("button",{className:"tactical-btn exit-maintenance",onClick:()=>this.unblockDevice(t,x),title:"Exit Maintenance",children:e.jsx(Ze,{size:14})}):e.jsxs(e.Fragment,{children:[e.jsx("button",{className:"tactical-btn reserve",onClick:()=>this.setState({showReservation:!0}),title:"Reserve Device",children:e.jsx(bs,{size:14,color:"#38bdf8"})}),e.jsx("button",{className:"tactical-btn maintenance",onClick:()=>this.blockDevice(t,x),title:"Enter Maintenance",children:e.jsx(St,{size:14,color:"#fbbf24"})})]});return e.jsxs("div",{className:`device-info-card-container ${this.getStatusClassName()} group`,children:[e.jsx("div",{className:"scanline",style:{position:"absolute",inset:0,pointerEvents:"none",opacity:.1,zIndex:0}}),e.jsxs("div",{className:"card-header relative z-10",children:[e.jsxs("div",{className:"header-left",children:[e.jsx("div",{className:`platform-icon-wrapper ${p}`,children:["ios","tvos"].includes(p)?e.jsx(ys,{size:14}):e.jsx(Je,{size:14})}),e.jsx("div",{className:"device-id-mono",title:t,children:t})]}),e.jsx("div",{className:`device-status-badge ${M} ${M==="busy"&&f&&f!=="Session Active"?"pulse":""}`,children:M==="busy"&&f&&f!=="Session Active"?f:M})]}),e.jsxs("div",{className:"device-info-main relative z-10",children:[e.jsx("h3",{className:"device-name",title:s,children:s}),e.jsxs("p",{className:"device-subtext",children:[u.toUpperCase()," • ",c]}),this.props.device.tags&&this.props.device.tags.length>0&&e.jsxs("div",{className:"device-tags-inline",children:[this.props.device.tags.slice(0,3).map(ee=>e.jsx("span",{className:"inline-tag",title:ee,children:ee},ee)),this.props.device.tags.length>3&&e.jsxs("span",{className:"inline-tag-overflow",children:["+",this.props.device.tags.length-3]})]})]}),e.jsxs("div",{className:"metrics-grid relative z-10",children:[e.jsxs("div",{className:"metric-item",title:`Location: ${_}`,children:[e.jsx(ns,{size:10,className:"text-dim"}),e.jsx("span",{className:"truncate",children:_})]}),this.props.device.ip&&e.jsxs("div",{className:"metric-item",title:`IP: ${this.props.device.ip}`,children:[e.jsx(ws,{size:10,className:"text-dim"}),e.jsx("span",{className:"truncate",children:this.props.device.ip})]}),e.jsxs("div",{className:`metric-item health ${((H=this.props.device.healthStatus)==null?void 0:H.toLowerCase())||"healthy"}`,title:this.props.device.healthCheckError||"Device is healthy",children:[e.jsx("div",{className:"health-dot"}),e.jsx("span",{children:this.props.device.healthStatus||"Healthy"}),R&&R>0&&e.jsxs("span",{className:"heal-badge",children:[e.jsx(Ze,{size:8})," ",R]})]}),O&&O!=="Unknown"&&e.jsxs("div",{className:"metric-item thermal",title:`Thermal: ${O}`,children:[e.jsx(yt,{size:10,style:{color:O==="Nominal"?"var(--color-primary)":"var(--color-amber)"}}),e.jsx("span",{children:O})]}),E!==void 0&&e.jsxs("div",{className:"metric-item battery",title:`Battery: ${E}%`,children:[e.jsx("div",{className:`mini-battery ${E<20?"low":""}`,children:e.jsx("div",{className:"battery-fill",style:{width:`${E}%`}})}),e.jsxs("span",{children:[E,"%"]})]}),b&&b!=="Unknown"&&e.jsxs("div",{className:"metric-item storage",title:`Free Space: ${b}`,children:[e.jsx(Ds,{size:10,style:{color:"var(--color-sky)"}}),e.jsx("span",{children:b})]})]}),e.jsx("div",{className:"dynamic-data-layer relative z-10",children:this.isReserved()?e.jsxs("div",{className:"reservation-micro-banner",children:[e.jsx(gs,{size:10}),e.jsxs("span",{children:["RES: ",U||"Anon"," (",this.getRemainingReservationTime(),")"]})]}):$?e.jsxs("div",{className:"session-micro-banner",children:[e.jsx(js,{size:10}),e.jsxs("span",{children:["SID: ",$]})]}):e.jsx("div",{className:"utilization-micro-info",children:e.jsxs("span",{children:["UTIL: ",ts(h||0,{compact:!0})]})})}),e.jsxs("div",{className:"action-row relative z-10",children:[e.jsx("button",{className:"tactical-btn add-tag",onClick:()=>this.manageTags(),title:"Manage Tags",children:e.jsx(fs,{size:14})}),X(),e.jsxs("button",{className:`tactical-btn control-btn ${A&&$&&!$.toString().startsWith("manual_")?"disabled":""}`,onClick:()=>!(A&&$&&!$.toString().startsWith("manual_"))&&this.props.navigate(`/devices/${t}/control`),disabled:A&&!!$&&!$.toString().startsWith("manual_"),title:A&&$&&!$.toString().startsWith("manual_")?"Locked: Appium Session":"Take Control",children:[e.jsx(ns,{size:14}),e.jsx("span",{style:{fontSize:"10px",fontWeight:800,letterSpacing:"0.05em",fontFamily:"Outfit, sans-serif"},children:"CTRL"})]})]}),this.state.showReservation&&e.jsx(Dt,{device:this.props.device,onClose:()=>this.setState({showReservation:!1}),onReserved:()=>this.props.reloadDevices()}),this.state.showTagManager&&e.jsx(At,{device:this.props.device,onClose:()=>this.setState({showTagManager:!1}),onUpdated:()=>this.props.reloadDevices()})]})}}function Tt(n){const s=Qe();return e.jsx(Lt,{...n,navigate:s})}class Et extends Fe.Component{render(){return e.jsx("div",{className:"device-explorer-card-container",children:Fe.Children.toArray(this.props.devices.map(s=>e.jsx(Tt,{device:s,reloadDevices:this.props.reloadDevices})))})}}var Ue,zt=new Uint8Array(16);function It(){if(!Ue&&(Ue=typeof crypto<"u"&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||typeof msCrypto<"u"&&typeof msCrypto.getRandomValues=="function"&&msCrypto.getRandomValues.bind(msCrypto),!Ue))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return Ue(zt)}const Rt=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;function Mt(n){return typeof n=="string"&&Rt.test(n)}var Y=[];for(var Ye=0;Ye<256;++Ye)Y.push((Ye+256).toString(16).substr(1));function _t(n){var s=arguments.length>1&&arguments[1]!==void 0?arguments[1]:0,c=(Y[n[s+0]]+Y[n[s+1]]+Y[n[s+2]]+Y[n[s+3]]+"-"+Y[n[s+4]]+Y[n[s+5]]+"-"+Y[n[s+6]]+Y[n[s+7]]+"-"+Y[n[s+8]]+Y[n[s+9]]+"-"+Y[n[s+10]]+Y[n[s+11]]+Y[n[s+12]]+Y[n[s+13]]+Y[n[s+14]]+Y[n[s+15]]).toLowerCase();if(!Mt(c))throw TypeError("Stringified UUID is invalid");return c}function Ut(n,s,c){n=n||{};var u=n.random||(n.rng||It)();return u[6]=u[6]&15|64,u[8]=u[8]&63|128,_t(u)}const Ot=({onCommand:n,prompt:s="$",welcomeMessage:c="Interactive Shell (Restricted Mode)",platform:u})=>{const[p,t]=r.useState([{type:"system",content:c,timestamp:Date.now()},{type:"system",content:'Type "help" for allowed commands.',timestamp:Date.now()}]),[T,v]=r.useState(""),[x,h]=r.useState([]),[m,A]=r.useState(-1),[$,U]=r.useState(!1),w=r.useRef(null),j=r.useRef(null);r.useEffect(()=>{w.current&&(w.current.scrollTop=w.current.scrollHeight)},[p]);const E=b=>{const k=b.trim();if((k.startsWith("{")||k.startsWith("["))&&(k.endsWith("}")||k.endsWith("]")))try{const f=JSON.parse(k);return JSON.stringify(f,null,2)}catch{}return b},O=async b=>{if(b.key==="Enter"&&!$){const k=T.trim();if(!k)return;if(v(""),t(f=>[...f,{type:"command",content:`${s} ${k}`,timestamp:Date.now()}]),h(f=>[...f,k]),A(-1),U(!0),k==="clear"){t([]),U(!1);return}if(k==="help"){let f="";u==="android"?f=`
142
142
  Android Allowed Commands:
143
143
  • System Info: getprop, ip addr, date, uptime, cat /proc/meminfo, cat /proc/cpuinfo
144
144
  • Process Mgmt: ps, top
@@ -151,9 +151,9 @@ iOS Allowed Commands:
151
151
  listapps, get_app_container, list, getenv
152
152
  • Real Device (go-ios):
153
153
  apps, info, syslog, list
154
- `),t(R=>[...R,{type:"output",content:f.trim(),timestamp:Date.now()}]),U(!1);return}try{const f=await n(k),R=E(f||"(No output)");t(M=>[...M,{type:"output",content:R,timestamp:Date.now()}])}catch(f){t(R=>[...R,{type:"error",content:f.message||"Unknown error",timestamp:Date.now()}])}finally{U(!1),setTimeout(()=>{var f;return(f=j.current)==null?void 0:f.focus()},10)}}else if(b.key==="ArrowUp"){if(b.preventDefault(),x.length>0){const k=m===-1?x.length-1:Math.max(0,m-1);A(k),v(x[k])}}else if(b.key==="ArrowDown"&&(b.preventDefault(),m!==-1)){const k=m+1;k>=x.length?(A(-1),v("")):(A(k),v(x[k]))}};return e.jsxs("div",{className:"terminal-container",children:[e.jsx("div",{className:"scanline",style:{position:"absolute",inset:0,pointerEvents:"none",opacity:.05,zIndex:1001}}),e.jsxs("header",{className:"terminal-header",children:[e.jsxs("div",{className:"terminal-controls",children:[e.jsx("div",{className:"dot red"}),e.jsx("div",{className:"dot yellow"}),e.jsx("div",{className:"dot green"})]}),e.jsxs("div",{className:"terminal-title",children:[u.toUpperCase()," INTERNAL SHELL"]}),e.jsx("div",{className:"terminal-actions",children:e.jsx("button",{className:"terminal-action-btn",onClick:()=>t([]),title:"Clear Terminal",children:"CLEAR"})})]}),e.jsxs("div",{className:"terminal-history",ref:w,onClick:()=>{var b;return(b=j.current)==null?void 0:b.focus()},children:[p.map((b,k)=>e.jsx("div",{className:`terminal-line ${b.type}`,children:b.content},k)),S&&e.jsx("div",{className:"terminal-line system animate-pulse",children:"Executing command..."})]}),e.jsxs("div",{className:"terminal-input-area",children:[e.jsx("span",{className:"terminal-prompt",children:s}),e.jsx("input",{ref:j,className:"terminal-input",value:T,onChange:b=>v(b.target.value),onKeyDown:O,disabled:S,autoFocus:!0,spellCheck:!1,autoComplete:"off",placeholder:"Type a command..."})]})]})};function os(n,s){const l=n.toLowerCase();if(l==="accessibility id")return/[0-9a-f]{8}-[0-9a-f]{4}/i.test(s)?{level:"fragile",reason:"UUID in accessibility ID — dynamically generated, unreliable"}:{level:"stable",reason:"#1 recommended by Appium — portable across Android & iOS"};if(l==="id")return/[0-9a-f]{8}-[0-9a-f]{4}/i.test(s)?{level:"fragile",reason:"UUID in resource ID — dynamically generated"}:/\d{6,}/.test(s)&&!s.includes(":id/")?{level:"moderate",reason:"Long numeric ID without package prefix — may not be unique"}:/^[a-z][a-z0-9.]+:id\//.test(s)?{level:"stable",reason:"Android resource-id with package prefix — #2 by Appium priority"}:{level:"stable",reason:"Element ID — #2 by Appium 2.x recommended priority"};if(l==="xpath"){if(s.startsWith("/hierarchy")||s.startsWith("/")&&!s.startsWith("//"))return{level:"very-fragile",reason:"ABSOLUTE XPath — breaks on any layout change. Avoid entirely"};if(/\[\d+\]/.test(s))return{level:"very-fragile",reason:"Index-based XPath [n] — breaks when element order changes"};const u=(s.match(/\//g)||[]).length;return u>7?{level:"fragile",reason:`${u}-level deep XPath — brittle to layout changes, 10x slower on iOS`}:s.includes("@content-desc")||s.includes("@resource-id")||s.includes("@text")?{level:"moderate",reason:"XPath with semantic attribute — more stable, but still prefer ID/accessibility id"}:{level:"fragile",reason:"XPath is a LAST RESORT per Appium docs — 10x slower on iOS, breaks on UI changes"}}return l==="-ios predicate string"?{level:"stable",reason:"iOS NSPredicate — native engine, excellent performance on iOS"}:l==="-ios class chain"?{level:"stable",reason:"iOS Class Chain — native iOS, faster than XPath"}:l==="-android uiautomator"?s.includes("resourceId")||s.includes("description")?{level:"stable",reason:"UIAutomator2 with resourceId/description — Android native, very reliable"}:s.includes("textContains")||s.includes("text(")?{level:"moderate",reason:"UIAutomator2 with text matching — breaks if copy changes"}:{level:"stable",reason:"UIAutomator2 — Android native engine, preferred over XPath on Android"}:l==="class name"?{level:"fragile",reason:"Class name alone is almost never unique — use with explicit index or prefer accessibility id"}:l==="name"?{level:"fragile",reason:"⚠️ Deprecated in Appium 2.x — replace with accessibility id or id"}:l==="link text"?{level:"moderate",reason:"Text-based locator — breaks if copy/label changes"}:{level:"moderate",reason:"Verify reliability for your target platform"}}function ds(n,s,l,u){var b,k,f,R,M,_,X;const{strategy:p,value:t}=u,T=(n.text||n.name||((b=n.type)==null?void 0:b.split(".").pop())||"element").replace(/[^a-zA-Z0-9]/g,"_").replace(/^_+/,"").slice(0,24)||"element",v=T.charAt(0).toLowerCase()+T.slice(1),x=((k=n.type)==null?void 0:k.toLowerCase().includes("edit"))||((f=n.type)==null?void 0:f.toLowerCase().includes("input"))||((R=n.type)==null?void 0:R.toLowerCase().includes("field"))||((M=n.type)==null?void 0:M.toLowerCase().includes("textfield")),h=((_=n.attributes)==null?void 0:_.scrollable)==="true"||((X=n.attributes)==null?void 0:X.scrollable)===!0,m=p.toLowerCase().startsWith("-ios")&&s!=="ios"?`// ⚠️ -ios predicate/class chain ONLY work with XCUITest (iOS)
154
+ `),t(R=>[...R,{type:"output",content:f.trim(),timestamp:Date.now()}]),U(!1);return}try{const f=await n(k),R=E(f||"(No output)");t(M=>[...M,{type:"output",content:R,timestamp:Date.now()}])}catch(f){t(R=>[...R,{type:"error",content:f.message||"Unknown error",timestamp:Date.now()}])}finally{U(!1),setTimeout(()=>{var f;return(f=j.current)==null?void 0:f.focus()},10)}}else if(b.key==="ArrowUp"){if(b.preventDefault(),x.length>0){const k=m===-1?x.length-1:Math.max(0,m-1);A(k),v(x[k])}}else if(b.key==="ArrowDown"&&(b.preventDefault(),m!==-1)){const k=m+1;k>=x.length?(A(-1),v("")):(A(k),v(x[k]))}};return e.jsxs("div",{className:"terminal-container",children:[e.jsx("div",{className:"scanline",style:{position:"absolute",inset:0,pointerEvents:"none",opacity:.05,zIndex:1001}}),e.jsxs("header",{className:"terminal-header",children:[e.jsxs("div",{className:"terminal-controls",children:[e.jsx("div",{className:"dot red"}),e.jsx("div",{className:"dot yellow"}),e.jsx("div",{className:"dot green"})]}),e.jsxs("div",{className:"terminal-title",children:[u.toUpperCase()," INTERNAL SHELL"]}),e.jsx("div",{className:"terminal-actions",children:e.jsx("button",{className:"terminal-action-btn",onClick:()=>t([]),title:"Clear Terminal",children:"CLEAR"})})]}),e.jsxs("div",{className:"terminal-history",ref:w,onClick:()=>{var b;return(b=j.current)==null?void 0:b.focus()},children:[p.map((b,k)=>e.jsx("div",{className:`terminal-line ${b.type}`,children:b.content},k)),$&&e.jsx("div",{className:"terminal-line system animate-pulse",children:"Executing command..."})]}),e.jsxs("div",{className:"terminal-input-area",children:[e.jsx("span",{className:"terminal-prompt",children:s}),e.jsx("input",{ref:j,className:"terminal-input",value:T,onChange:b=>v(b.target.value),onKeyDown:O,disabled:$,autoFocus:!0,spellCheck:!1,autoComplete:"off",placeholder:"Type a command..."})]})]})};function os(n,s){const c=n.toLowerCase();if(c==="accessibility id")return/[0-9a-f]{8}-[0-9a-f]{4}/i.test(s)?{level:"fragile",reason:"UUID in accessibility ID — dynamically generated, unreliable"}:{level:"stable",reason:"#1 recommended by Appium — portable across Android & iOS"};if(c==="id")return/[0-9a-f]{8}-[0-9a-f]{4}/i.test(s)?{level:"fragile",reason:"UUID in resource ID — dynamically generated"}:/\d{6,}/.test(s)&&!s.includes(":id/")?{level:"moderate",reason:"Long numeric ID without package prefix — may not be unique"}:/^[a-z][a-z0-9.]+:id\//.test(s)?{level:"stable",reason:"Android resource-id with package prefix — #2 by Appium priority"}:{level:"stable",reason:"Element ID — #2 by Appium 2.x recommended priority"};if(c==="xpath"){if(s.startsWith("/hierarchy")||s.startsWith("/")&&!s.startsWith("//"))return{level:"very-fragile",reason:"ABSOLUTE XPath — breaks on any layout change. Avoid entirely"};if(/\[\d+\]/.test(s))return{level:"very-fragile",reason:"Index-based XPath [n] — breaks when element order changes"};const u=(s.match(/\//g)||[]).length;return u>7?{level:"fragile",reason:`${u}-level deep XPath — brittle to layout changes, 10x slower on iOS`}:s.includes("@content-desc")||s.includes("@resource-id")||s.includes("@text")?{level:"moderate",reason:"XPath with semantic attribute — more stable, but still prefer ID/accessibility id"}:{level:"fragile",reason:"XPath is a LAST RESORT per Appium docs — 10x slower on iOS, breaks on UI changes"}}return c==="-ios predicate string"?{level:"stable",reason:"iOS NSPredicate — native engine, excellent performance on iOS"}:c==="-ios class chain"?{level:"stable",reason:"iOS Class Chain — native iOS, faster than XPath"}:c==="-android uiautomator"?s.includes("resourceId")||s.includes("description")?{level:"stable",reason:"UIAutomator2 with resourceId/description — Android native, very reliable"}:s.includes("textContains")||s.includes("text(")?{level:"moderate",reason:"UIAutomator2 with text matching — breaks if copy changes"}:{level:"stable",reason:"UIAutomator2 — Android native engine, preferred over XPath on Android"}:c==="class name"?{level:"fragile",reason:"Class name alone is almost never unique — use with explicit index or prefer accessibility id"}:c==="name"?{level:"fragile",reason:"⚠️ Deprecated in Appium 2.x — replace with accessibility id or id"}:c==="link text"?{level:"moderate",reason:"Text-based locator — breaks if copy/label changes"}:{level:"moderate",reason:"Verify reliability for your target platform"}}function ds(n,s,c,u){var b,k,f,R,M,_,X;const{strategy:p,value:t}=u,T=(n.text||n.name||((b=n.type)==null?void 0:b.split(".").pop())||"element").replace(/[^a-zA-Z0-9]/g,"_").replace(/^_+/,"").slice(0,24)||"element",v=T.charAt(0).toLowerCase()+T.slice(1),x=((k=n.type)==null?void 0:k.toLowerCase().includes("edit"))||((f=n.type)==null?void 0:f.toLowerCase().includes("input"))||((R=n.type)==null?void 0:R.toLowerCase().includes("field"))||((M=n.type)==null?void 0:M.toLowerCase().includes("textfield")),h=((_=n.attributes)==null?void 0:_.scrollable)==="true"||((X=n.attributes)==null?void 0:X.scrollable)===!0,m=p.toLowerCase().startsWith("-ios")&&s!=="ios"?`// ⚠️ -ios predicate/class chain ONLY work with XCUITest (iOS)
155
155
  `:p.toLowerCase().startsWith("-android")&&s!=="android"?`// ⚠️ -android uiautomator ONLY works with UIAutomator2 (Android)
156
- `:"",A={"accessibility id":`~${t}`,id:s==="ios"?`-ios predicate string:label == "${t}"`:`android=new UiSelector().resourceId("${t}")`,xpath:`${t}`,"-ios predicate string":`-ios predicate string:${t}`,"-ios class chain":`-ios class chain:${t}`,"-android uiautomator":`android=${t}`},S={"accessibility id":`AppiumBy.accessibilityId("${t}")`,id:`AppiumBy.id("${t}")`,xpath:`AppiumBy.xpath("${t}")`,"-ios predicate string":`AppiumBy.iOSNsPredicateString("${t}")`,"-ios class chain":`AppiumBy.iOSClassChain("${t}")`,"-android uiautomator":`AppiumBy.androidUIAutomator("${t}")`,"class name":`AppiumBy.className("${t}")`},U={"accessibility id":`AppiumBy.ACCESSIBILITY_ID, "${t}"`,id:`AppiumBy.ID, "${t}"`,xpath:`AppiumBy.XPATH, "${t}"`,"-ios predicate string":`AppiumBy.IOS_PREDICATE, "${t}"`,"-ios class chain":`AppiumBy.IOS_CLASS_CHAIN, "${t}"`,"-android uiautomator":`AppiumBy.ANDROID_UIAUTOMATOR, '${t}'`,"class name":`AppiumBy.CLASS_NAME, "${t}"`},w=S[p.toLowerCase()],j=U[p.toLowerCase()],E=A[p.toLowerCase()];return l==="java"?w?`${m}// Appium Java Client 9.x + Selenium 4 + TestNG
156
+ `:"",A={"accessibility id":`~${t}`,id:s==="ios"?`-ios predicate string:label == "${t}"`:`android=new UiSelector().resourceId("${t}")`,xpath:`${t}`,"-ios predicate string":`-ios predicate string:${t}`,"-ios class chain":`-ios class chain:${t}`,"-android uiautomator":`android=${t}`},$={"accessibility id":`AppiumBy.accessibilityId("${t}")`,id:`AppiumBy.id("${t}")`,xpath:`AppiumBy.xpath("${t}")`,"-ios predicate string":`AppiumBy.iOSNsPredicateString("${t}")`,"-ios class chain":`AppiumBy.iOSClassChain("${t}")`,"-android uiautomator":`AppiumBy.androidUIAutomator("${t}")`,"class name":`AppiumBy.className("${t}")`},U={"accessibility id":`AppiumBy.ACCESSIBILITY_ID, "${t}"`,id:`AppiumBy.ID, "${t}"`,xpath:`AppiumBy.XPATH, "${t}"`,"-ios predicate string":`AppiumBy.IOS_PREDICATE, "${t}"`,"-ios class chain":`AppiumBy.IOS_CLASS_CHAIN, "${t}"`,"-android uiautomator":`AppiumBy.ANDROID_UIAUTOMATOR, '${t}'`,"class name":`AppiumBy.CLASS_NAME, "${t}"`},w=$[p.toLowerCase()],j=U[p.toLowerCase()],E=A[p.toLowerCase()];return c==="java"?w?`${m}// Appium Java Client 9.x + Selenium 4 + TestNG
157
157
  import io.appium.java_client.AppiumBy;
158
158
  import io.appium.java_client.${s==="android"?"AndroidDriver":s==="ios"?"IOSDriver":"AppiumDriver"};
159
159
  import org.openqa.selenium.WebElement;
@@ -165,7 +165,7 @@ public void test_${v}() {
165
165
  ${h?'((Scrollable) element).scrollTo("target text");':x?`element.clear();
166
166
  element.sendKeys("your text here");`:"element.click();"}
167
167
  // Add assertions here via TestNG Assert or Hamcrest
168
- }`:`// Strategy "${p}" not supported in Appium Java Client`:l==="python"?j?`${m}# Appium Python Client 4.x + pytest
168
+ }`:`// Strategy "${p}" not supported in Appium Java Client`:c==="python"?j?`${m}# Appium Python Client 4.x + pytest
169
169
  from appium.webdriver.common.appiumby import AppiumBy
170
170
  import pytest
171
171
 
@@ -173,7 +173,7 @@ def test_${v}(self):
173
173
  element = self.driver.find_element(${j})
174
174
  ${x?`element.clear()
175
175
  element.send_keys("your text here")`:"element.click()"}
176
- # Add assertions here via assert or pytest.assert`:`# Strategy "${p}" not supported in Appium Python Client`:l==="javascript"?E?`${m}// WebdriverIO 9.x + @wdio/appium-service
176
+ # Add assertions here via assert or pytest.assert`:`# Strategy "${p}" not supported in Appium Python Client`:c==="javascript"?E?`${m}// WebdriverIO 9.x + @wdio/appium-service
177
177
  describe('${v} test', () => {
178
178
  it('should interact with ${v}', async () => {
179
179
  const element = await $('${E}');
@@ -187,7 +187,7 @@ const element = await driver.$('${E}');
187
187
  await element.waitForExist({ timeout: 5000 });
188
188
  ${x?`await driver.$('target').clearValue();
189
189
  await element.addValue("your text here");`:"await element.click();"}
190
- // Assert with expect(element).toBeDisplayed()`:`// Strategy "${p}" not supported in WebdriverIO mobile`}function Ft(n){var U,w,j,E,O,b,k,f,R,M,_;const s=(n.type||"").toLowerCase(),l=((U=n.attributes)==null?void 0:U.clickable)==="true"||((w=n.attributes)==null?void 0:w.clickable)===!0,u=((j=n.attributes)==null?void 0:j.enabled)!=="false"&&((E=n.attributes)==null?void 0:E.enabled)!==!1,p=((O=n.attributes)==null?void 0:O.scrollable)==="true"||((b=n.attributes)==null?void 0:b.scrollable)===!0,t=n.text||n.label||n.value||"",T=((k=n.children)==null?void 0:k.length)||0;let v="Element",x="📦";s.includes("button")||s.includes("btn")||l&&T===0?(v="Button",x="🔘"):s.includes("edit")||s.includes("input")||s.includes("field")?(v="Text Input",x="✏️"):s.includes("image")||s.includes("img")||s.includes("imageview")?(v="Image",x="🖼️"):s.includes("scroll")||s.includes("recyclerview")||s.includes("listview")||p?(v="Scrollable List",x="📜"):s.includes("text")||s.includes("label")?(v="Text Label",x="📝"):s.includes("switch")||s.includes("toggle")||s.includes("checkbox")?(v="Toggle / Checkbox",x="☑️"):s.includes("nav")||s.includes("toolbar")||s.includes("tabbar")?(v="Navigation Bar",x="🧭"):T>0&&(v=`Container (${T} children)`,x="🗂️");const h=((f=n.suggestedLocators)==null?void 0:f.find(X=>X.strategy==="accessibility id"||X.strategy==="id"))||((R=n.suggestedLocators)==null?void 0:R[0]),m=u?((M=n.rect)==null?void 0:M.width)===0||((_=n.rect)==null?void 0:_.height)===0?"⚠️ Zero-size element — may not be interactable":void 0:"⚠️ Element is disabled",A=t?` with text "${t.slice(0,30)}"`:"",S=`This is a ${v.toLowerCase()}${A}. ${l?"It can be tapped/clicked.":p?"It supports scrolling.":"It is a visual container."}${T>0?` Contains ${T} child element${T>1?"s":""}.`:""}`;return{role:v,description:S,interactable:l||u,bestLocator:h,warning:m,emoji:x}}function hs(n,s){if(!s)return!0;const l=s.toLowerCase().trim(),u={button:["button","btn","clickable","tapable"],input:["edittext","input","field","textfield","textinput","edit"],image:["image","imageview","img","picture","photo","icon"],text:["textview","label","text","statictext"],list:["listview","recyclerview","scrollview","tableview","collectionview","scroll"],toggle:["switch","checkbox","toggle","radiobutton"],nav:["toolbar","navigationbar","tabbar","actionbar","navbar"]},p=(n.type||"").toLowerCase(),t=(n.text||n.label||n.value||"").toLowerCase(),T=(n.name||"").toLowerCase(),v=Object.values(n.attributes||{}).join(" ").toLowerCase();for(const[x,h]of Object.entries(u))if(l.includes(x)&&h.some(m=>p.includes(m)))return!0;return p.includes(l)||t.includes(l)||T.includes(l)||v.includes(l)}const Ht=({sessionId:n,udid:s,streamUrl:l})=>{var pe,Se,ze,$e,ve,De,Ie;const[u,p]=r.useState(!0),[t,T]=r.useState(null),[v,x]=r.useState(null),[h,m]=r.useState(null),[A,S]=r.useState(null),[U,w]=r.useState(new Set(["/"])),[j,E]=r.useState(""),[O,b]=r.useState(null),[k,f]=r.useState("info"),[R,M]=r.useState("java"),[_,X]=r.useState(null),[H,se]=r.useState({width:0,height:0}),[be,xe]=r.useState({width:0,height:0}),[He,d]=r.useState(!1),[J,Ae]=r.useState("inspect"),Ne=r.useRef(null),ge=r.useRef(null),fe=r.useRef(null),oe=r.useRef(null),de=r.useCallback(()=>{var z,G,Q;if(!Ne.current)return;const i=Ne.current.getBoundingClientRect(),o=i.width,y=i.height,C=(z=t==null?void 0:t.hierarchy)==null?void 0:z.rect;let F=((G=t==null?void 0:t.metadata)==null?void 0:G.screenWidth)||H.width||1,W=((Q=t==null?void 0:t.metadata)==null?void 0:Q.screenHeight)||H.height||1;C&&C.width>0&&C.height>0&&(F=C.width,W=C.height);const V=F/W;let P,q;o/y>V?(q=y,P=q*V):(P=o,q=P/V),xe({width:P,height:q})},[t,H]);r.useEffect(()=>(de(),window.addEventListener("resize",de),()=>window.removeEventListener("resize",de)),[de]),r.useEffect(()=>{s&&re()},[s]),r.useEffect(()=>{var i;if((i=h==null?void 0:h.suggestedLocators)!=null&&i.length){const o=h.suggestedLocators.find(y=>y.strategy==="accessibility id"||y.strategy==="id")||h.suggestedLocators[0];X(o)}else X(null)},[h]);const re=async()=>{if(s){p(!0),x(null);try{const i=await D.getInspectorSnapshot(s);T(i);const o=new Set(["/"]),y=(C,F)=>{var W;F<2&&(o.add(C.xpath),(W=C.children)==null||W.forEach(V=>y(V,F+1)))};i.hierarchy&&y(i.hierarchy,0),w(o)}catch(i){x(i.message||"Failed to capture snapshot")}finally{p(!1)}}},Le=i=>{const{naturalWidth:o,naturalHeight:y}=i.currentTarget;se({width:o,height:y})},ce=()=>d(!0),Te=i=>{d(!1);const{naturalWidth:o,naturalHeight:y}=i.currentTarget;o>0&&y>0&&se({width:o,height:y})},Z=l&&!He,Ee=i=>{if(J!=="interact"||!s)return;const o=i.currentTarget.getBoundingClientRect();oe.current={x:i.clientX-o.left,y:i.clientY-o.top,time:Date.now()}},ye=async i=>{var c,g,$;if(J!=="interact"||!s||!oe.current)return;const o=oe.current,y=i.currentTarget.getBoundingClientRect(),C=i.clientX-y.left,F=i.clientY-y.top,W=Date.now()-o.time,V=be.width,P=be.height,q=(c=t==null?void 0:t.hierarchy)==null?void 0:c.rect;let z=((g=t==null?void 0:t.metadata)==null?void 0:g.screenWidth)||H.width,G=(($=t==null?void 0:t.metadata)==null?void 0:$.screenHeight)||H.height;if(q&&q.width>0&&q.height>0&&(z=q.width,G=q.height),!z||!G||V===0||P===0)return;const Q=(N,L)=>({x:Math.round(N/V*z),y:Math.round(L/P*G),px:N/V,py:L/P}),K=Q(o.x,o.y),le=Q(C,F),a=Math.sqrt(Math.pow(C-o.x,2)+Math.pow(F-o.y,2));if(!(K.px<0||K.px>1||K.py<0||K.py>1)){try{W<500&&a<10?await D.tap(s,K.x,K.y):W>=500&&a<10?await D.touchAndHold(s,K.x,K.y,W):a>=10&&await D.swipe(s,K.x,K.y,le.x,le.y)}catch(N){console.error("Interaction failed:",N)}oe.current=null}},Pe=i=>{const o=new Set(U);o.has(i)?o.delete(i):o.add(i),w(o)},je=()=>{const i=new Set,o=y=>{var C;i.add(y.xpath),(C=y.children)==null||C.forEach(o)};t!=null&&t.hierarchy&&o(t.hierarchy),w(i)},te=()=>w(new Set(["/"])),he=(i,o)=>{navigator.clipboard.writeText(i),b(o),setTimeout(()=>b(null),2e3)},we=i=>{var y;let o=1;return(y=i.children)==null||y.forEach(C=>o+=we(C)),o},Be=i=>i.xpath.split("/").filter(Boolean).slice(-3),me=(i,o=0)=>{var q;if(!i)return null;const y=U.has(i.xpath),C=((q=i.children)==null?void 0:q.length)>0,F=(h==null?void 0:h.xpath)===i.xpath,W=(A==null?void 0:A.xpath)===i.xpath,V=i.name||i.type.split(".").pop()||"Element",P=!j||hs(i,j);if(!P&&!C)return null;if(j&&!P){const z=G=>{var Q;return hs(G,j)?!0:((Q=G.children)==null?void 0:Q.some(z))||!1};if(!z(i))return null}return e.jsxs("div",{className:"tree-node",children:[e.jsxs("div",{className:`tree-item ${F?"selected":""} ${W&&!F?"hovered":""}`,onClick:()=>{m(i),f("info")},onMouseEnter:()=>S(i),onMouseLeave:()=>S(null),children:[e.jsx("div",{className:"tree-item-indent",style:{width:`${o*14}px`}}),C?e.jsx("button",{onClick:z=>{z.stopPropagation(),Pe(i.xpath)},className:"tree-toggle",children:y?e.jsx(ps,{size:11}):e.jsx(xs,{size:11})}):e.jsx("span",{className:"tree-toggle-spacer"}),e.jsx(Ms,{size:11,className:"tree-icon"}),e.jsx("span",{className:"tree-label",children:V}),i.text&&e.jsxs("span",{className:"tree-text-preview",children:['"',i.text.slice(0,20),'"']}),C&&e.jsx("span",{className:"tree-badge",children:i.children.length})]}),y&&C&&e.jsx("div",{className:"tree-children",children:i.children.map(z=>me(z,o+1))})]},i.xpath)},ke=i=>{var V,P,q;if(!H.width)return[];const o=[],y=(V=t==null?void 0:t.hierarchy)==null?void 0:V.rect;let C=((P=t==null?void 0:t.metadata)==null?void 0:P.screenWidth)||H.width,F=((q=t==null?void 0:t.metadata)==null?void 0:q.screenHeight)||H.height;y&&y.width>0&&y.height>0&&(C=y.width,F=y.height);const W=(z,G)=>{var K,le,a;const Q=!z.children||z.children.length===0;((K=z.rect)==null?void 0:K.width)>0&&((le=z.rect)==null?void 0:le.height)>0&&Q&&o.push(e.jsx("div",{className:"omni-hit-area",style:{left:`${z.rect.x/C*100}%`,top:`${z.rect.y/F*100}%`,width:`${z.rect.width/C*100}%`,height:`${z.rect.height/F*100}%`,zIndex:G},onClick:c=>{c.stopPropagation(),m(z),f("info")},onMouseEnter:()=>S(z),onMouseLeave:()=>S(null)},z.xpath)),(a=z.children)==null||a.forEach(c=>W(c,G+1))};return t!=null&&t.hierarchy&&W(t.hierarchy,1),o},ue=(i,o)=>{var W,V,P;if(!(i!=null&&i.rect)||!H.width)return null;const y=(W=t==null?void 0:t.hierarchy)==null?void 0:W.rect;let C=((V=t==null?void 0:t.metadata)==null?void 0:V.screenWidth)||H.width,F=((P=t==null?void 0:t.metadata)==null?void 0:P.screenHeight)||H.height;return y&&y.width>0&&y.height>0&&(C=y.width,F=y.height),e.jsx("div",{className:`omni-frame-${o}`,style:{left:`${i.rect.x/C*100}%`,top:`${i.rect.y/F*100}%`,width:`${i.rect.width/C*100}%`,height:`${i.rect.height/F*100}%`}})},ae=t!=null&&t.hierarchy?we(t.hierarchy):0,B=h?Ft(h):null,Ce={stable:{icon:e.jsx(Ze,{size:10}),cls:"stable"},moderate:{icon:e.jsx($s,{size:10}),cls:"moderate"},fragile:{icon:e.jsx(rs,{size:10}),cls:"fragile"},"very-fragile":{icon:e.jsx(rs,{size:10}),cls:"very-fragile"}};return e.jsx("div",{className:"omni-inspector-container",children:e.jsxs("div",{className:"omni-main-content",children:[e.jsxs("div",{className:"omni-screenshot-panel",children:[e.jsxs("div",{className:"omni-screenshot-header",children:[e.jsxs("div",{className:"omni-header-left",children:[e.jsx("span",{className:"omni-screenshot-title",children:"Device Preview"}),e.jsxs("div",{className:"omni-mode-toggle",children:[e.jsxs("button",{className:`omni-mode-btn ${J==="inspect"?"active":""}`,onClick:()=>Ae("inspect"),title:"Inspection Mode (Highlight Elements)",children:[e.jsx(Ts,{size:12}),e.jsx("span",{children:"Inspect"})]}),e.jsxs("button",{className:`omni-mode-btn ${J==="interact"?"active":""}`,onClick:()=>Ae("interact"),title:"Interaction Mode (Direct Control)",children:[e.jsx(bt,{size:12}),e.jsx("span",{children:"Interact"})]})]})]}),e.jsxs("button",{className:"omni-refresh-btn",onClick:re,disabled:u,children:[e.jsx(Oe,{size:12,className:u?"animate-spin":""}),u?"Capturing...":"Refresh"]})]}),e.jsxs("div",{className:"omni-screenshot-container",ref:Ne,children:[u&&!Z&&e.jsxs("div",{className:"omni-loading-overlay",children:[e.jsx("div",{className:"omni-spinner"}),e.jsx("span",{children:"Capturing screen..."})]}),!t&&!u&&!Z&&e.jsxs("div",{className:"omni-empty-state",children:[e.jsx(ls,{size:40}),e.jsx("span",{children:"Click Refresh to capture"})]}),Z&&e.jsxs("div",{className:`omni-screenshot-wrapper ${J==="interact"?"interactable":""}`,onMouseDown:Ee,onMouseUp:ye,children:[e.jsx("img",{ref:fe,src:l,onLoad:Te,onError:ce,className:"omni-screenshot-img",style:J==="interact"?{pointerEvents:"none"}:{},draggable:!1,alt:"Live Device Stream"}),(t==null?void 0:t.hierarchy)&&J==="inspect"&&e.jsxs("div",{className:"omni-overlay",children:[ke(t.hierarchy),ue(A,"hover"),ue(h,"select")]})]}),!Z&&(t==null?void 0:t.screenshot)&&e.jsxs("div",{className:`omni-screenshot-wrapper ${J==="interact"?"interactable":""}`,onMouseDown:Ee,onMouseUp:ye,children:[e.jsx("img",{ref:ge,src:`data:image/png;base64,${t.screenshot}`,onLoad:Le,className:"omni-screenshot-img",style:J==="interact"?{pointerEvents:"none"}:{},draggable:!1}),J==="inspect"&&e.jsxs("div",{className:"omni-overlay",children:[ke(t.hierarchy),ue(A,"hover"),ue(h,"select")]})]})]})]}),e.jsxs("div",{className:"omni-tree-panel",children:[e.jsxs("div",{className:"omni-tree-header",children:[e.jsxs("div",{className:"omni-tree-title",children:[e.jsx(Js,{size:14}),e.jsx("span",{children:"Source"}),ae>0&&e.jsxs("span",{className:"omni-count-badge",children:[ae," elements"]})]}),e.jsxs("div",{className:"omni-tree-actions",children:[e.jsx("button",{onClick:je,className:"omni-action-btn",title:"Expand All",children:e.jsx(Xs,{size:12})}),e.jsx("button",{onClick:te,className:"omni-action-btn",title:"Collapse All",children:e.jsx(ht,{size:12})})]})]}),e.jsxs("div",{className:"omni-tree-search",children:[e.jsx(es,{size:14}),e.jsx("input",{type:"text",placeholder:"Search elements... (try 'login button' or 'text field')",value:j,onChange:i=>E(i.target.value)}),j&&e.jsx("button",{onClick:()=>E(""),className:"omni-clear-btn",children:"×"})]}),j&&e.jsxs("div",{className:"omni-search-hint",children:[e.jsx(cs,{size:10}),' Smart search active — try "button", "input", "image"']}),e.jsx("div",{className:"omni-tree-content",children:t!=null&&t.hierarchy?me(t.hierarchy):e.jsx("div",{className:"omni-empty-state small",children:e.jsx("span",{children:"No hierarchy loaded"})})})]}),e.jsxs("div",{className:"omni-details-panel",children:[e.jsxs("div",{className:"omni-details-tabs",children:[e.jsxs("button",{className:`omni-details-tab ${k==="info"?"active":""}`,onClick:()=>f("info"),children:[e.jsx(tt,{size:12})," Info"]}),e.jsxs("button",{className:`omni-details-tab ${k==="insight"?"active":""}`,onClick:()=>f("insight"),disabled:!h,title:"AI Element Analysis",children:[e.jsx(Qs,{size:12})," AI Insight"]}),e.jsxs("button",{className:`omni-details-tab ${k==="code"?"active":""}`,onClick:()=>f("code"),disabled:!h,title:"Generate Test Code",children:[e.jsx(as,{size:12})," Code Gen"]})]}),e.jsx("div",{className:"omni-details-content",children:h?e.jsxs(e.Fragment,{children:[k==="info"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"omni-section",children:[e.jsx("div",{className:"omni-section-header",children:"Element Info"}),e.jsxs("div",{className:"omni-info-table",children:[e.jsxs("div",{className:"omni-info-row",children:[e.jsx("span",{className:"omni-info-key",children:"Type"}),e.jsx("span",{className:"omni-info-value mono",children:h.type})]}),h.text&&e.jsxs("div",{className:"omni-info-row",children:[e.jsx("span",{className:"omni-info-key",children:"Text"}),e.jsx("span",{className:"omni-info-value",children:h.text})]}),e.jsxs("div",{className:"omni-info-row",children:[e.jsx("span",{className:"omni-info-key",children:"Path"}),e.jsx("span",{className:"omni-info-value mono small",children:Be(h).join(" › ")})]})]})]}),e.jsxs("div",{className:"omni-section",children:[e.jsx("div",{className:"omni-section-header",children:"Layout"}),e.jsx("div",{className:"omni-layout-grid",children:["x","y","width","height"].map(i=>e.jsxs("div",{className:"omni-layout-item",children:[e.jsx("span",{className:"omni-layout-label",children:i.toUpperCase()}),e.jsx("span",{className:"omni-layout-value",children:h.rect[i]})]},i))})]}),e.jsxs("div",{className:"omni-section",children:[e.jsxs("div",{className:"omni-section-header",children:["Locators",e.jsx("span",{className:"omni-section-badge",children:"Stability Scored"})]}),e.jsx("div",{className:"omni-locators-list",children:(pe=h.suggestedLocators)==null?void 0:pe.map(i=>{const o=os(i.strategy,i.value),y=Ce[o.level];return e.jsxs("div",{className:`omni-locator-row ${(_==null?void 0:_.strategy)===i.strategy?"selected-for-code":""}`,onClick:()=>X(i),title:"Click to use in Code Generator",children:[e.jsxs("div",{className:"omni-locator-left",children:[e.jsxs("div",{className:"omni-locator-top",children:[e.jsx("span",{className:"omni-locator-strategy",children:i.strategy}),e.jsxs("span",{className:`omni-stability-badge ${y.cls}`,title:o.reason,children:[y.icon,o.level]})]}),e.jsx("code",{className:"omni-locator-value",children:i.value}),e.jsx("span",{className:"omni-stability-reason",children:o.reason})]}),e.jsx("button",{onClick:C=>{C.stopPropagation(),he(i.value,i.strategy)},className:`omni-copy-btn ${O===i.strategy?"copied":""}`,children:O===i.strategy?e.jsx(qe,{size:12}):e.jsx(Xe,{size:12})})]},i.strategy)})})]}),e.jsxs("div",{className:"omni-section",children:[e.jsx("div",{className:"omni-section-header",children:"Attributes"}),e.jsx("div",{className:"omni-attributes-table",children:Object.entries(h.attributes||{}).filter(([i,o])=>o!=null&&o!=="").map(([i,o])=>e.jsxs("div",{className:"omni-attr-row",children:[e.jsx("span",{className:"omni-attr-key",children:i}),e.jsx("span",{className:"omni-attr-value",children:String(o)})]},i))})]})]}),k==="insight"&&B&&e.jsxs("div",{className:"omni-insight-panel",children:[e.jsxs("div",{className:"omni-insight-role",children:[e.jsx("span",{className:"omni-insight-emoji",children:B.emoji}),e.jsxs("div",{children:[e.jsx("div",{className:"omni-insight-role-name",children:B.role}),e.jsx("div",{className:"omni-insight-interactable",children:B.interactable?e.jsxs("span",{className:"omni-badge-green",children:[e.jsx(zs,{size:10})," Interactable"]}):e.jsx("span",{className:"omni-badge-gray",children:"Visual Only"})})]})]}),B.warning&&e.jsx("div",{className:"omni-insight-warning",children:B.warning}),e.jsxs("div",{className:"omni-insight-description",children:[e.jsx(cs,{size:12,className:"omni-insight-icon"}),e.jsx("p",{children:B.description})]}),B.bestLocator&&e.jsxs("div",{className:"omni-insight-best-locator",children:[e.jsx("div",{className:"omni-section-header",children:"Recommended Locator"}),e.jsxs("div",{className:"omni-locator-row",children:[e.jsxs("div",{className:"omni-locator-left",children:[e.jsx("span",{className:"omni-locator-strategy",children:B.bestLocator.strategy}),e.jsx("code",{className:"omni-locator-value",children:B.bestLocator.value})]}),e.jsx("button",{onClick:()=>he(B.bestLocator.value,"best"),className:`omni-copy-btn ${O==="best"?"copied":""}`,children:O==="best"?e.jsx(qe,{size:12}):e.jsx(Xe,{size:12})})]})]}),e.jsxs("div",{className:"omni-insight-attributes",children:[e.jsx("div",{className:"omni-section-header",children:"Quick Facts"}),e.jsx("div",{className:"omni-quick-facts",children:[{label:"Clickable",value:(Se=h.attributes)==null?void 0:Se.clickable},{label:"Enabled",value:(ze=h.attributes)==null?void 0:ze.enabled},{label:"Scrollable",value:($e=h.attributes)==null?void 0:$e.scrollable},{label:"Focusable",value:(ve=h.attributes)==null?void 0:ve.focusable},{label:"Children",value:((De=h.children)==null?void 0:De.length)||0}].map(({label:i,value:o})=>e.jsxs("div",{className:"omni-quick-fact-row",children:[e.jsx("span",{className:"omni-quick-fact-label",children:i}),e.jsx("span",{className:`omni-quick-fact-value ${o==="true"||o===!0?"true":""}`,children:String(o??"—")})]},i))})]})]}),k==="code"&&e.jsxs("div",{className:"omni-codegen-panel",children:[e.jsx("div",{className:"omni-codegen-frameworks",children:["java","python","javascript","wdio"].map(i=>e.jsx("button",{className:`omni-fw-btn ${R===i?"active":""}`,onClick:()=>M(i),children:i==="java"?"☕ Java":i==="python"?"🐍 Python":i==="javascript"?"🟨 JS":"🔷 WD.io"},i))}),_?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"omni-codegen-locator-selector",children:[e.jsx("span",{className:"omni-codegen-label",children:"Locator:"}),e.jsx("select",{value:_.strategy,onChange:i=>{var y;const o=(y=h.suggestedLocators)==null?void 0:y.find(C=>C.strategy===i.target.value);o&&X(o)},className:"omni-fw-select",children:(Ie=h.suggestedLocators)==null?void 0:Ie.map(i=>e.jsxs("option",{value:i.strategy,children:[i.strategy," — ",os(i.strategy,i.value).level]},i.strategy))})]}),e.jsxs("div",{className:"omni-codegen-output",children:[e.jsxs("div",{className:"omni-codegen-header",children:[e.jsx("span",{className:"omni-codegen-lang",children:R==="java"?"Java / TestNG":R==="python"?"Python / unittest":R==="javascript"?"JavaScript / Mocha":"WebdriverIO"}),e.jsx("button",{className:"omni-copy-btn",onClick:()=>he(ds(h,(t==null?void 0:t.platform)==="android"?"android":(t==null?void 0:t.platform)==="ios"?"ios":"unknown",R,_),"code"),children:O==="code"?e.jsx(qe,{size:12}):e.jsx(Xe,{size:12})})]}),e.jsx("pre",{className:"omni-codegen-pre",children:e.jsx("code",{children:ds(h,(t==null?void 0:t.platform)==="android"?"android":(t==null?void 0:t.platform)==="ios"?"ios":"unknown",R,_)})})]})]}):e.jsxs("div",{className:"omni-empty-state small",children:[e.jsx(as,{size:24}),e.jsx("span",{children:"No locators available for this element"})]})]})]}):e.jsxs("div",{className:"omni-empty-state",children:[e.jsx(ls,{size:32}),e.jsx("span",{children:"Select an element from the tree or screenshot"})]})})]})]})})};function Pt({device:n,onClose:s}){var le;const{toast:l,removeToast:u}=us(),p=Qe(),{tab:t}=vs(),T=r.useRef(null),v=r.useRef(null),[x,h]=r.useState({width:0,height:0}),[m,A]=r.useState(t||"actions"),[S,U]=r.useState(""),[w,j]=r.useState(""),[E,O]=r.useState(""),[b,k]=r.useState(!0),[f,R]=r.useState([]),[M,_]=r.useState(null),[X,H]=r.useState(!1),[se,be]=r.useState(!1),[xe,He]=r.useState(0),[d,J]=r.useState(n),[Ae,Ne]=r.useState([]),[ge,fe]=r.useState(!1),[oe,de]=r.useState(!1),[re,Le]=r.useState(null),[ce,Te]=r.useState([]),[Z,Ee]=r.useState(!0),[ye,Pe]=r.useState(""),je=r.useRef(""),te=r.useRef(null),[he,we]=r.useState(!1);r.useEffect(()=>{m&&(!t||t!==m)&&p(`/devices/${n.udid}/control/${m}`,{replace:!0})},[m,t,n.udid,p]),r.useEffect(()=>{let a;if(m==="logs"){const c=async()=>{try{const g=await D.getLogs(d.udid);if(g&&g.logs){const $=g.logs.replace(/\\u[0-9a-fA-F]{4}/g,N=>JSON.parse(`"${N}"`)).replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,"").split(`
191
- `).filter(N=>N.trim().length>0);Te(N=>{const L=N.slice(-20),ee=$.filter(ne=>!L.includes(ne));return[...N,...ee].slice(-1e3)})}}catch(g){console.error("Failed to fetch logs:",g)}};c(),a=setInterval(c,2e3)}return()=>clearInterval(a)},[m,d.udid]);const Be=()=>ce.length===0?e.jsx("div",{className:"log-line log-debug",children:e.jsx("span",{className:"log-content",children:"Establishing technical link... Waiting for heartbeat."})}):ce.filter(c=>!ye||c.toLowerCase().includes(ye.toLowerCase())).map((c,g)=>{let $="log-debug";const N=c.toLowerCase();return N.includes("error")||N.includes("fail")?$="log-error":N.includes("warning")||N.includes("warn")?$="log-warn":(N.includes("notice")||N.includes("info"))&&($="log-notice"),e.jsxs("div",{className:`log-line ${$}`,children:[e.jsx("span",{className:"log-index",children:g+1}),e.jsx("span",{className:"log-content",children:c})]},`${g}-${c.substring(0,10)}`)});r.useEffect(()=>{m==="logs"&&Z&&v.current&&(v.current.scrollTop=v.current.scrollHeight)},[ce,m,Z]),r.useEffect(()=>((async()=>{try{be(!0),await D.startStream(d.udid);const g=(await D.getDevices()).find($=>$.udid===d.udid);g&&J(g)}catch(c){console.error("Auto-start stream failed:",c)}finally{be(!1)}})(),()=>{D.stopStream(d.udid).catch(()=>{})}),[n.udid]);const me=r.useCallback(async()=>{try{fe(!0);const a=await D.listApps(d.udid);Array.isArray(a)&&Ne(a)}catch(a){console.error("Failed to load apps:",a)}finally{fe(!1)}},[d.udid]);r.useEffect(()=>{m==="actions"&&me()},[m,me]);const ke=parseInt(d.screenWidth||"1080",10),ue=parseInt(d.screenHeight||"1920",10),ae=Math.min(ke,ue),B=Math.max(ke,ue),Ce=ae/B,pe=r.useCallback(()=>{const a=!b,c=a?window.innerHeight*.55:window.innerHeight*.7,g=a?window.innerWidth*.8:window.innerWidth*.45,$=b?Ce:1/Ce;let N,L;b?(N=c,L=N*$,L>g&&(L=g,N=L/$)):(L=g,N=L/$,N>c&&(N=c,L=N*$)),h({width:L,height:N})},[Ce,b]);r.useEffect(()=>(pe(),window.addEventListener("resize",pe),()=>window.removeEventListener("resize",pe)),[pe]),r.useEffect(()=>{const a=async()=>{if(je.current.length>0){const g=je.current;je.current="";try{await D.typeText(d.udid,g)}catch($){console.error("Keyboard buffering flush failed:",$)}}},c=g=>{const $=document.activeElement;if($&&($.tagName==="INPUT"||$.tagName==="TEXTAREA"||$.isContentEditable)||!he&&m!=="terminal")return;const L=g.key;L==="Enter"?(te.current&&clearTimeout(te.current),a(),D.pressKey(d.udid,d.platform==="android"?66:"enter")):L==="Backspace"?(te.current&&clearTimeout(te.current),a(),D.pressKey(d.udid,d.platform==="android"?67:"backspace")):L.length===1&&(je.current+=L,te.current&&clearTimeout(te.current),te.current=setTimeout(()=>{a()},50))};return window.addEventListener("keydown",c),()=>{window.removeEventListener("keydown",c),te.current&&clearTimeout(te.current)}},[d.udid,d.platform,he,m]);const[Se,ze]=r.useState(Date.now()),$e=()=>{const a=xe>0?`r=${xe}&`:"";return d.session_id&&!String(d.session_id).startsWith("manual_")?`/xenon/api/session/${d.session_id}/live_video?${a}t=${Se}`:`/xenon/api/control/${d.udid}/stream?${a}t=${Se}`};r.useEffect(()=>{xe>0&&ze(Date.now())},[xe]);const ve=r.useRef(null),De=a=>{const c=a.currentTarget.getBoundingClientRect();return{x:a.clientX-c.left,y:a.clientY-c.top}},Ie=a=>{const c=De(a);ve.current={x:c.x,y:c.y,time:Date.now()}},i=async a=>{if(!ve.current)return;const c=ve.current,g=De(a),$=Date.now()-c.time;let N,L,ee,ie;b?(N=c.x/x.width*ae,L=c.y/x.height*B,ee=g.x/x.width*ae,ie=g.y/x.height*B):(N=c.x/x.width*B,L=c.y/x.height*ae,ee=g.x/x.width*B,ie=g.y/x.height*ae);const ne=Math.abs(ee-N),Re=Math.abs(ie-L);try{$<500&&ne<10&&Re<10?await D.tap(d.udid,Math.round(N),Math.round(L)):$>=500&&ne<10&&Re<10?await D.touchAndHold(d.udid,Math.round(N),Math.round(L),$):await D.swipe(d.udid,Math.round(N),Math.round(L),Math.round(ee),Math.round(ie))}catch(ks){console.error("Action failed:",ks)}ve.current=null},o=()=>D.pressKey(d.udid,d.platform==="android"?3:"home"),y=()=>D.lock(d.udid),C=()=>D.unlock(d.udid),F=async()=>{S.trim()&&(await D.typeText(d.udid,S),U(""))},W=async()=>{try{j("Fetching...");const a=await D.getClipboard(d.udid);a&&a.content!==void 0?j(a.content||"(Clipboard is empty)"):j("No content received")}catch{j("Error: Check Appium Settings app")}},V=async()=>{H(!0);try{const a=await D.getScreenshot(d.udid);if(a!=null&&a.screenshot){const c={id:Ut(),base64:a.screenshot,timestamp:Date.now()};R(g=>[c,...g]),_(0)}}catch(a){console.error("Failed to take screenshot:",a)}finally{H(!1)}},P=a=>{R(c=>{const g=c.filter($=>$.id!==a);return g.length===0?_(null):M!==null&&M>=g.length&&_(0),g})},q=()=>{R([]),_(null),l("Cleared all captured evidence.","success")},z=a=>{const c=document.createElement("a");c.href=`data:image/png;base64,${a}`,c.download=`screenshot-${d.udid}-${Date.now()}.png`,c.click()},G=async a=>{const c=ae/2,g=B/2,$=ae*.4,N=B*.4;let L,ee,ie,ne;switch(a){case"left":L=c+$,ee=g,ie=c-$,ne=g;break;case"right":L=c-$,ee=g,ie=c+$,ne=g;break;case"up":L=c,ee=g+N,ie=c,ne=g-N;break;case"down":L=c,ee=g-N,ie=c,ne=g+N;break}try{await D.swipe(d.udid,Math.round(L),Math.round(ee),Math.round(ie),Math.round(ne))}catch(Re){console.error(`Quick swipe ${a} failed:`,Re)}},Q=async()=>{if(E.trim()){const a=l(`Uninstalling ${E}...`,"loading",0);try{fe(!0),await D.uninstallApp(d.udid,E),O(""),l(`Request sent for ${E}`,"success"),setTimeout(me,3e3)}catch{l("Uninstall failed. Check logs.","error")}finally{fe(!1),u(a)}}},K=async()=>{if(!re)return;let a;try{de(!0),a=l(`Installing app to ${d.udid}...`,"loading",0);const c=await D.uploadAndInstallApp(d.udid,re);c.success?(l(c.message||"App installed successfully","success"),Le(null),setTimeout(me,5e3)):l("Installation failed: "+(c.error||"Unknown error"),"error")}catch(c){l("Installation failed: "+c.message,"error")}finally{a&&u(a),de(!1)}};return e.jsxs("div",{className:"device-control-view",children:[e.jsx("div",{className:"scanline",style:{position:"absolute",inset:0,pointerEvents:"none",opacity:.05,zIndex:1001}}),e.jsxs("header",{className:"control-view-top-bar",children:[e.jsxs("button",{className:"back-to-devices-btn",onClick:s,children:[e.jsx(is,{size:18})," DEVICES"]}),e.jsxs("div",{className:"device-info-mini",children:[e.jsx("span",{className:`device-pill platform-pill ${d.platform}`,children:d.platform==="ios"?"Apple":"Android"}),e.jsxs("span",{className:"device-pill version-pill",children:["v",d.sdk]}),d.reservedUntil&&Date.now()<d.reservedUntil&&e.jsxs("span",{className:"device-pill reserved-pill",title:`Reserved by ${d.reservedBy}${d.reservationReason?`: ${d.reservationReason}`:""}`,children:["RESERVED BY ",((le=d.reservedBy)==null?void 0:le.toUpperCase())||"ANONYMOUS"]}),e.jsx("h2",{className:"device-name-text",children:d.name}),e.jsx("span",{className:"code-font",style:{opacity:.5},children:d.udid})]})]}),e.jsxs("div",{className:`control-view-main ${b?"":"is-landscape"} ${m==="omni"?"omni-mode":""}`,children:[e.jsxs("div",{className:"device-preview-column",children:[e.jsx("div",{className:"device-screen-wrapper",children:e.jsxs("div",{ref:T,className:`device-stream-canvas ${b?"":"landscape"} ${he?"focused":""}`,style:{width:x.width,height:x.height,background:"#000"},tabIndex:0,onFocus:()=>we(!0),onBlur:()=>we(!1),onMouseDown:Ie,onMouseUp:i,children:[se&&e.jsxs("div",{className:"device-stream-placeholder",style:{position:"absolute",zIndex:10},children:[e.jsx(Oe,{size:40,className:"animate-spin",color:"var(--primary)"}),e.jsx("p",{style:{marginTop:16},children:"ESTABLISHING TRACE..."})]}),e.jsx("img",{src:$e(),alt:"Device Stream",className:"device-stream-image",style:{width:"100%",height:"100%",objectFit:"contain"},onError:()=>{console.warn("Stream failed to load, retrying..."),setTimeout(()=>He(a=>a+1),2e3)}})]})}),e.jsxs("aside",{className:"device-footer-actions",children:[e.jsxs("button",{className:`footer-action-btn ${b?"active":""}`,onClick:()=>k(!0),children:[e.jsx(Oe,{size:14,style:{transform:b?"none":"rotate(-90deg)"}})," ","PORTRAIT"]}),e.jsxs("button",{className:`footer-action-btn ${b?"":"active"}`,onClick:()=>k(!1),children:[e.jsx(Oe,{size:14,style:{transform:"rotate(90deg)"}})," LANDSCAPE"]}),e.jsx("div",{className:"footer-divider"}),e.jsxs("button",{className:"footer-action-btn",onClick:o,children:[e.jsx(Ys,{size:20})," HOME"]}),e.jsx("button",{className:"footer-action-btn",onClick:y,title:"Lock Device",children:e.jsx(Is,{size:20})}),e.jsx("button",{className:"footer-action-btn",onClick:C,title:"Unlock Device",children:e.jsx(Ns,{size:20})})]})]}),e.jsxs("div",{className:"device-interactions-column",children:[e.jsxs("div",{className:"interaction-tabs",children:[e.jsx("button",{className:`tab-btn ${m==="actions"?"active":""}`,onClick:()=>A("actions"),children:"ACTIONS"}),e.jsx("button",{className:`tab-btn ${m==="screenshot"?"active":""}`,onClick:()=>A("screenshot"),children:"SCREENSHOT"}),e.jsx("button",{className:`tab-btn ${m==="logs"?"active":""}`,onClick:()=>A("logs"),children:"DEBUG LOGS"}),e.jsxs("button",{className:`tab-btn ${m==="terminal"?"active":""}`,onClick:()=>A("terminal"),children:[e.jsx(js,{size:14,style:{marginRight:6}})," SHELL"]}),e.jsx("button",{className:`tab-btn ${m==="omni"?"active":""}`,onClick:()=>A("omni"),children:"OMNI-VISION"})]}),e.jsx("div",{className:`interactions-scroll-area ${m==="terminal"?"terminal-mode":""} ${m==="screenshot"||m==="logs"?"screenshot-mode":""}`,children:e.jsxs("div",{className:"tab-content",children:[m==="omni"&&e.jsx("div",{className:"omni-inspector-tab-wrapper animate-fade-in",style:{height:"calc(100vh - 266px)"},children:e.jsx(Ht,{sessionId:d.session_id?String(d.session_id):null,udid:d.udid,streamUrl:$e()})}),m==="actions"&&e.jsxs("div",{className:"actions-grid",children:[e.jsxs("div",{className:"action-card",children:[e.jsxs("h4",{className:"action-card-title",children:[e.jsx(ct,{size:18,color:"var(--primary)"})," Directional Gestures"]}),e.jsxs("div",{className:"gestures-grid-container",children:[e.jsxs("div",{className:"gestures-dpad",children:[e.jsx("div",{}),e.jsx("button",{className:"dpad-btn",onClick:()=>G("up"),children:e.jsx(Fs,{size:24})}),e.jsx("div",{}),e.jsx("button",{className:"dpad-btn",onClick:()=>G("left"),children:e.jsx(is,{size:24})}),e.jsx("div",{className:"dpad-center"}),e.jsx("button",{className:"dpad-btn",onClick:()=>G("right"),children:e.jsx(xs,{size:24})}),e.jsx("div",{}),e.jsx("button",{className:"dpad-btn",onClick:()=>G("down"),children:e.jsx(ps,{size:24})}),e.jsx("div",{})]}),e.jsx("p",{className:"compact-label",style:{opacity:.5},children:"Directional Glide"})]})]}),e.jsxs("div",{className:"action-card",children:[e.jsxs("h4",{className:"action-card-title",children:[e.jsx(Vs,{size:18,color:"var(--primary)"})," Smart Input"]}),e.jsx("input",{type:"text",className:"type-input-field compact",placeholder:"Relay keystrokes...",value:S,onChange:a=>U(a.target.value),onKeyDown:a=>a.key==="Enter"&&F()})]}),e.jsxs("div",{className:"action-card full-width",children:[e.jsxs("h4",{className:"action-card-title",children:[e.jsx(ot,{size:18,color:"var(--primary)"})," App Management"]}),e.jsxs("div",{className:"app-mgmt-content",children:[e.jsxs("div",{className:"install-section",children:[e.jsx("p",{className:"compact-label",children:"Install Package (.apk, .ipa, .app)"}),e.jsxs("div",{className:"upload-box-row",children:[e.jsxs("label",{className:"file-upload-launcher",children:[e.jsx(Ls,{size:14}),e.jsx("span",{children:re?re.name:"Select File"}),e.jsx("input",{type:"file",accept:".apk,.ipa,.app",onChange:a=>{var c;return Le(((c=a.target.files)==null?void 0:c[0])||null)},hidden:!0})]}),e.jsx("button",{className:"btn-premium btn-sm",disabled:!re||oe,onClick:K,children:oe?e.jsx(We,{className:"animate-spin",size:14}):"INSTALL"})]})]}),e.jsx("div",{className:"divider-v"}),e.jsxs("div",{className:"uninstall-section",children:[e.jsx("p",{className:"compact-label",children:"Quick Uninstall"}),e.jsxs("div",{className:"uninstall-controls-row",children:[e.jsxs("div",{className:"select-wrapper",children:[e.jsxs("select",{className:"app-select-dropdown compact",value:E,onChange:a=>O(a.target.value),disabled:ge,children:[e.jsx("option",{value:"",children:ge?"Loading apps...":"-- Select App to Remove --"}),Ae.map(a=>e.jsx("option",{value:a,children:a},a))]}),ge&&e.jsx(We,{className:"animate-spin select-loader",size:12})]}),e.jsxs("button",{className:"btn-destructive btn-sm",onClick:Q,disabled:!E||ge,children:[e.jsx(_e,{size:14})," UNINSTALL"]})]}),e.jsxs("div",{className:"manual-input-box",children:[e.jsx("p",{className:"hint-text",children:"Or enter manually:"}),e.jsx("input",{type:"text",className:"type-input-field tiny",placeholder:"com.example.app",value:E,onChange:a=>O(a.target.value)})]})]})]})]}),e.jsxs("div",{className:"action-card full-width",children:[e.jsxs("h4",{className:"action-card-title",children:[e.jsx(Ps,{size:18,color:"var(--primary)"})," Clipboard"]}),e.jsxs("div",{style:{display:"flex",gap:"12px",alignItems:"flex-start"},children:[e.jsx("button",{className:"btn-premium btn-sm",style:{width:"140px",flexShrink:0},onClick:W,children:"FETCH VALUE"}),e.jsx("div",{className:"clipboard-display compact",style:{marginTop:0,flex:1},children:w})]})]})]}),m==="screenshot"&&e.jsxs("div",{className:"action-card screenshot-card",children:[e.jsxs("header",{className:"action-card-header",children:[e.jsxs("div",{className:"title-group",children:[e.jsxs("h4",{className:"action-card-title",children:[e.jsx(Ve,{size:20,color:"var(--primary)"})," Captured Evidence"]}),e.jsx("p",{className:"hint-text",children:"Relay screenshots from device to host."})]}),f.length>0&&e.jsx("button",{className:"btn-text-only",onClick:q,children:"CLEAR ALL"})]}),e.jsxs("div",{className:"screenshot-workspace",children:[e.jsxs("div",{className:"screenshot-gallery-sidebar",children:[e.jsxs("button",{className:"btn-premium take-screenshot-btn",onClick:V,disabled:X,children:[X?e.jsx(We,{className:"animate-spin",size:16}):e.jsx(Ve,{size:16}),e.jsx("span",{children:X?"CAPTURING...":"NEW CAPTURE"})]}),e.jsxs("div",{className:"screenshot-thumbnails-list",children:[f.length===0&&!X&&e.jsx("div",{className:"empty-gallery-state",children:e.jsx("p",{children:"No captures yet"})}),f.map((a,c)=>e.jsxs("div",{className:`screenshot-thumb-item ${M===c?"active":""}`,onClick:()=>_(c),children:[e.jsx("img",{src:`data:image/png;base64,${a.base64}`,alt:"Thumb"}),e.jsx("span",{className:"thumb-time",children:new Date(a.timestamp).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"})}),e.jsx("button",{className:"thumb-delete-btn",onClick:g=>{g.stopPropagation(),P(a.id)},children:e.jsx(_e,{size:12})})]},a.id))]})]}),e.jsx("div",{className:"screenshot-main-preview",children:M!==null&&f[M]?e.jsxs("div",{className:"preview-container",children:[e.jsx("div",{className:"preview-image-wrapper",children:e.jsx("img",{src:`data:image/png;base64,${f[M].base64}`,alt:"Selected Evidence"})}),e.jsxs("footer",{className:"preview-footer",children:[e.jsxs("div",{className:"preview-meta",children:[e.jsx("span",{className:"meta-label",children:"ID:"}),e.jsx("span",{className:"meta-value",children:f[M].id.substring(0,8)}),e.jsx("span",{className:"meta-divider",children:"|"}),e.jsx("span",{className:"meta-value",children:new Date(f[M].timestamp).toLocaleString()})]}),e.jsxs("div",{className:"preview-actions",children:[e.jsx("button",{className:"btn-premium btn-sm",onClick:()=>z(f[M].base64),children:"DOWNLOAD PNG"}),e.jsxs("button",{className:"btn-destructive btn-sm",onClick:()=>P(f[M].id),children:[e.jsx(_e,{size:14})," DELETE"]})]})]})]}):e.jsxs("div",{className:"preview-empty-placeholder",children:[e.jsx(Ve,{size:48,style:{opacity:.1,marginBottom:16}}),e.jsx("p",{children:"Capture a screenshot to begin analysis"})]})})]})]}),m==="logs"&&e.jsxs("div",{className:"action-card screenshot-card",style:{padding:0,gap:0},children:[e.jsxs("div",{className:"log-toolbar",children:[e.jsxs("div",{className:"log-filter-group",children:[e.jsx("div",{className:"log-stat-pill",children:"LIVE"}),e.jsxs("div",{className:"log-stat-pill",style:{opacity:.6},children:[ce.length," LINES"]}),e.jsxs("div",{className:"log-search-box",children:[e.jsx(es,{size:14,className:"search-icon-inline"}),e.jsx("input",{type:"text",className:"type-input-field tiny",placeholder:"Filter trace...",value:ye,onChange:a=>Pe(a.target.value)})]})]}),e.jsxs("div",{className:"log-actions-group",children:[e.jsxs("button",{className:`btn-secondary btn-sm ${Z?"active":""}`,onClick:()=>Ee(!Z),title:Z?"Freeze Logs":"Follow Logs",children:[e.jsx(ws,{size:14,className:Z?"animate-pulse":""}),Z?"FREEZE":"FOLLOW"]}),e.jsxs("button",{className:"btn-premium btn-sm",onClick:()=>{const a=new Blob([ce.join(`
192
- `)],{type:"text/plain"}),c=URL.createObjectURL(a),g=document.createElement("a");g.href=c,g.download=`logs-${d.udid}-${Date.now()}.txt`,g.click(),URL.revokeObjectURL(c)},disabled:ce.length===0,children:[e.jsx(Es,{size:14}),"EXPORT"]}),e.jsxs("button",{className:"btn-secondary btn-sm",onClick:()=>Te([]),title:"Clear Logs",children:[e.jsx(_e,{size:14}),"CLEAR"]})]})]}),e.jsx("div",{className:"log-display-area",ref:v,style:{flex:1},children:Be()})]}),m==="terminal"&&e.jsx("div",{className:"action-card full-height",children:e.jsx(Ot,{platform:(d.platform||"").toLowerCase(),prompt:`${(d.platform||"").toLowerCase()==="ios"?"ios":"adb"} $`,welcomeMessage:`Connected to ${d.name} (${d.udid}).
193
- Internal Shell Environment.`,onCommand:async a=>{const c=await D.executeShell(d.udid,a);if(c.error)throw new Error(c.error);return c.output}})})]})})]})]})]})}const ms={platform:{ios:!0,android:!0},state:{ready:!0,offline:!0,busy:!0},name:""};class Bt extends Fe.Component{constructor(s){super(s),this.socketCleanups=[],this.refreshTimeout=null,this.state={devices:[],activeSessionsCount:0,pendingSessionsCount:0,queueSummary:null,filter:ms}}componentDidMount(){this.fetchDevices(),this.devicePolling=setInterval(()=>{this.fetchDevices()},1e4);const s=this.props.onSocketEvent("device_unblocked",()=>{console.info("Real-time: Device unblocked, triggering debounced refresh"),this.fetchDevicesDebounced()}),l=this.props.onSocketEvent("device_blocked",()=>{console.info("Real-time: Device blocked, triggering debounced refresh"),this.fetchDevicesDebounced()});this.socketCleanups.push(s,l)}componentWillUnmount(){this.devicePolling&&(clearInterval(this.devicePolling),this.devicePolling=void 0),this.refreshTimeout&&(clearTimeout(this.refreshTimeout),this.refreshTimeout=null),this.socketCleanups.forEach(s=>s())}fetchDevicesDebounced(){this.refreshTimeout&&clearTimeout(this.refreshTimeout),this.refreshTimeout=setTimeout(()=>{this.refreshTimeout=null,this.fetchDevices()},500)}getBusyDevicesCount(s){return[u=>u.busy].reduce((u,p)=>u.filter(p),s).length}async fetchDevices(){try{const s=await D.getDevices(),l=this.getBusyDevicesCount(s),u=await D.getPendingSessionsCount(),p=await D.getQueueSummary();console.log(s),this.setState({devices:s,activeSessionsCount:l,pendingSessionsCount:u,queueSummary:p})}catch(s){console.log(s)}}getFilteredDevice(){const{ready:s,busy:l,offline:u}=this.state.filter.state,{ios:p,android:t}=this.state.filter.platform,T=[v=>p&&(v.platform=="ios"||v.platform=="tvos")||t&&v.platform=="android",v=>s&&!v.busy&&!v.offline||l&&v.busy||u&&v.offline];return this.state.filter.name!=""&&T.push(v=>v.name.toLowerCase().includes(this.state.filter.name.toLowerCase())||v.udid.toLowerCase().includes(this.state.filter.name.toLowerCase())),T.reduce((v,x)=>v.filter(x),this.state.devices)}setFilter(s){this.setState({filter:{...this.state.filter,...s}})}getPlatformFilterComponent(){const{ios:s,android:l}=this.state.filter.platform;return e.jsxs("div",{className:"device-explorer-header-value",children:[e.jsxs("button",{className:`device-explorer-header__platform-btn ${l&&"selected"}`,onClick:()=>this.setFilter({platform:{...this.state.filter.platform,android:!this.state.filter.platform.android}}),children:[e.jsx(Je,{size:20,color:"currentColor"}),"Android"]}),e.jsxs("button",{className:`device-explorer-header__platform-btn ${s&&"selected"}`,onClick:()=>this.setFilter({platform:{...this.state.filter.platform,ios:!this.state.filter.platform.ios}}),children:[e.jsx(ys,{size:20,color:"currentColor"}),"iOS"]})]})}getDeviceStateFilterComponent(){const{ready:s,busy:l,offline:u}=this.state.filter.state;return e.jsxs("div",{className:"device-explorer-header-value",children:[e.jsx("div",{className:`device-explorer-header__device-state ready ${s&&"selected"}`,onClick:()=>this.setFilter({state:{...this.state.filter.state,ready:!this.state.filter.state.ready}}),children:"Ready"}),e.jsx("div",{className:`device-explorer-header__device-state busy ${l&&"selected"}`,onClick:()=>this.setFilter({state:{...this.state.filter.state,busy:!this.state.filter.state.busy}}),children:"Busy"}),e.jsx("div",{className:`device-explorer-header__device-state offline ${u&&"selected"}`,onClick:()=>this.setFilter({state:{...this.state.filter.state,offline:!this.state.filter.state.offline}}),children:"Offline"})]})}render(){const s=this.getFilteredDevice(),{udid:l}=this.props.params,u=l?this.state.devices.find(p=>p.udid===l):null;return e.jsxs("div",{className:"device-explorer-container",children:[e.jsxs("div",{className:"device-explorer-header-container",children:[e.jsxs("div",{className:"device-explorer-header-left-container",children:[e.jsxs("div",{className:"device-explorer-header-entry",children:[e.jsx("div",{className:"device-explorer-header-entry-header",children:"Platform"}),this.getPlatformFilterComponent()]}),e.jsxs("div",{className:"device-explorer-header-entry",children:[e.jsx("div",{className:"device-explorer-header-entry-header",children:"Device state"}),this.getDeviceStateFilterComponent()]}),e.jsxs("div",{className:"device-explorer-header-entry search-entry",children:[e.jsx("div",{className:"device-explorer-header-entry-header",children:"Search by name or udid"}),e.jsx("div",{className:"device-explorer-header-value",children:e.jsxs("div",{className:"device-explorer-search-wrapper",children:[e.jsx(es,{size:16,color:"#94a3b8",className:"device-explorer-search-icon"}),e.jsx("input",{type:"text",className:"device-explorer-header-text-filter",placeholder:"Search devices...",onChange:p=>{this.setState({filter:{...this.state.filter,name:p.target.value}})}})]})})]})]}),e.jsx("div",{className:"device-explorer-header-filter-count",children:e.jsxs(Me,{variant:"secondary",children:[e.jsx("span",{className:"font-bold",children:s.length})," of"," ",e.jsx("span",{className:"font-bold",children:this.state.devices.length})," ",this.state.devices.length===1?"device":"devices"]})}),e.jsxs("div",{className:"device-explorer-header-right-container",children:[this.state.queueSummary&&this.state.pendingSessionsCount>0&&e.jsxs(Me,{variant:"secondary",className:"mr-2",children:[e.jsx("span",{className:"font-bold",children:"Queue Insights:"})," ",Object.entries(this.state.queueSummary.byPlatform).map(([p,t])=>e.jsxs("span",{className:"ml-1",children:[p==="any"?"Mixed":p.toUpperCase(),":"," ",Math.ceil(t.avgDurationMs/6e4),"m ETA"]},p))]}),e.jsxs(Me,{variant:"success",children:[e.jsx("span",{className:"font-bold",children:this.state.activeSessionsCount})," Active session",this.state.activeSessionsCount!==1?"s":""]}),e.jsxs(Me,{variant:"warning",children:[e.jsx("span",{className:"font-bold",children:this.state.pendingSessionsCount})," Pending session",this.state.pendingSessionsCount!==1?"s":""]}),e.jsxs(Ge,{size:"sm",variant:"default",onClick:()=>this.fetchDevices(),children:[e.jsx(ss,{size:14,color:"currentColor",className:"mr-1"}),"Refresh"]})]})]}),s.length>0?e.jsx(Et,{devices:s,reloadDevices:()=>this.fetchDevices()}):e.jsxs("div",{className:"device-explorer-empty stagger-1",children:[e.jsx("div",{className:"device-explorer-empty-icon",children:e.jsx(Je,{size:32})}),this.state.devices.length===0?e.jsxs(e.Fragment,{children:[e.jsx("h3",{className:"brand-font",children:"Global Device Registry Empty"}),e.jsx("p",{children:"Xenon hasn't detected any active device nodes in your infrastructure. Ensure your device farm is connected and heartbeat signals are active."}),e.jsxs(Ge,{variant:"default",onClick:()=>this.fetchDevices(),children:[e.jsx(ss,{size:14,className:"mr-2"}),"Manual Sync"]})]}):e.jsxs(e.Fragment,{children:[e.jsx("h3",{className:"brand-font",children:"No Devices Found"}),e.jsx("p",{children:"Deployment configuration mismatch. Adjust your platform or state filters to find the appropriate testing target."}),e.jsx(Ge,{variant:"outline",onClick:()=>this.setState({filter:ms}),children:"Reset All Filters"})]})]}),u&&e.jsx("div",{className:"device-control-modal-overlay",children:e.jsx("div",{className:"device-control-modal",children:e.jsx(Pt,{device:u,onClose:()=>this.props.navigate("/devices")})})})]})}}function si(){const n=vs(),s=Qe(),{on:l}=As();return e.jsx(Bt,{params:n,navigate:s,onSocketEvent:l})}export{Bt as DeviceExplorer,si as default};
190
+ // Assert with expect(element).toBeDisplayed()`:`// Strategy "${p}" not supported in WebdriverIO mobile`}function Ft(n){var U,w,j,E,O,b,k,f,R,M,_;const s=(n.type||"").toLowerCase(),c=((U=n.attributes)==null?void 0:U.clickable)==="true"||((w=n.attributes)==null?void 0:w.clickable)===!0,u=((j=n.attributes)==null?void 0:j.enabled)!=="false"&&((E=n.attributes)==null?void 0:E.enabled)!==!1,p=((O=n.attributes)==null?void 0:O.scrollable)==="true"||((b=n.attributes)==null?void 0:b.scrollable)===!0,t=n.text||n.label||n.value||"",T=((k=n.children)==null?void 0:k.length)||0;let v="Element",x="📦";s.includes("button")||s.includes("btn")||c&&T===0?(v="Button",x="🔘"):s.includes("edit")||s.includes("input")||s.includes("field")?(v="Text Input",x="✏️"):s.includes("image")||s.includes("img")||s.includes("imageview")?(v="Image",x="🖼️"):s.includes("scroll")||s.includes("recyclerview")||s.includes("listview")||p?(v="Scrollable List",x="📜"):s.includes("text")||s.includes("label")?(v="Text Label",x="📝"):s.includes("switch")||s.includes("toggle")||s.includes("checkbox")?(v="Toggle / Checkbox",x="☑️"):s.includes("nav")||s.includes("toolbar")||s.includes("tabbar")?(v="Navigation Bar",x="🧭"):T>0&&(v=`Container (${T} children)`,x="🗂️");const h=((f=n.suggestedLocators)==null?void 0:f.find(X=>X.strategy==="accessibility id"||X.strategy==="id"))||((R=n.suggestedLocators)==null?void 0:R[0]),m=u?((M=n.rect)==null?void 0:M.width)===0||((_=n.rect)==null?void 0:_.height)===0?"⚠️ Zero-size element — may not be interactable":void 0:"⚠️ Element is disabled",A=t?` with text "${t.slice(0,30)}"`:"",$=`This is a ${v.toLowerCase()}${A}. ${c?"It can be tapped/clicked.":p?"It supports scrolling.":"It is a visual container."}${T>0?` Contains ${T} child element${T>1?"s":""}.`:""}`;return{role:v,description:$,interactable:c||u,bestLocator:h,warning:m,emoji:x}}function hs(n,s){if(!s)return!0;const c=s.toLowerCase().trim(),u={button:["button","btn","clickable","tapable"],input:["edittext","input","field","textfield","textinput","edit"],image:["image","imageview","img","picture","photo","icon"],text:["textview","label","text","statictext"],list:["listview","recyclerview","scrollview","tableview","collectionview","scroll"],toggle:["switch","checkbox","toggle","radiobutton"],nav:["toolbar","navigationbar","tabbar","actionbar","navbar"]},p=(n.type||"").toLowerCase(),t=(n.text||n.label||n.value||"").toLowerCase(),T=(n.name||"").toLowerCase(),v=Object.values(n.attributes||{}).join(" ").toLowerCase();for(const[x,h]of Object.entries(u))if(c.includes(x)&&h.some(m=>p.includes(m)))return!0;return p.includes(c)||t.includes(c)||T.includes(c)||v.includes(c)}const Ht=({sessionId:n,udid:s,streamUrl:c})=>{var pe,Se,ze,$e,ve,De,Ie;const[u,p]=r.useState(!0),[t,T]=r.useState(null),[v,x]=r.useState(null),[h,m]=r.useState(null),[A,$]=r.useState(null),[U,w]=r.useState(new Set(["/"])),[j,E]=r.useState(""),[O,b]=r.useState(null),[k,f]=r.useState("info"),[R,M]=r.useState("java"),[_,X]=r.useState(null),[H,ee]=r.useState({width:0,height:0}),[be,xe]=r.useState({width:0,height:0}),[He,d]=r.useState(!1),[J,Ae]=r.useState("inspect"),Ne=r.useRef(null),ge=r.useRef(null),fe=r.useRef(null),oe=r.useRef(null),de=r.useCallback(()=>{var z,G,Q;if(!Ne.current)return;const i=Ne.current.getBoundingClientRect(),o=i.width,y=i.height,C=(z=t==null?void 0:t.hierarchy)==null?void 0:z.rect;let F=((G=t==null?void 0:t.metadata)==null?void 0:G.screenWidth)||H.width||1,W=((Q=t==null?void 0:t.metadata)==null?void 0:Q.screenHeight)||H.height||1;C&&C.width>0&&C.height>0&&(F=C.width,W=C.height);const V=F/W;let P,q;o/y>V?(q=y,P=q*V):(P=o,q=P/V),xe({width:P,height:q})},[t,H]);r.useEffect(()=>(de(),window.addEventListener("resize",de),()=>window.removeEventListener("resize",de)),[de]),r.useEffect(()=>{s&&ne()},[s]),r.useEffect(()=>{var i;if((i=h==null?void 0:h.suggestedLocators)!=null&&i.length){const o=h.suggestedLocators.find(y=>y.strategy==="accessibility id"||y.strategy==="id")||h.suggestedLocators[0];X(o)}else X(null)},[h]);const ne=async()=>{if(s){p(!0),x(null);try{const i=await D.getInspectorSnapshot(s);T(i);const o=new Set(["/"]),y=(C,F)=>{var W;F<2&&(o.add(C.xpath),(W=C.children)==null||W.forEach(V=>y(V,F+1)))};i.hierarchy&&y(i.hierarchy,0),w(o)}catch(i){x(i.message||"Failed to capture snapshot")}finally{p(!1)}}},Le=i=>{const{naturalWidth:o,naturalHeight:y}=i.currentTarget;ee({width:o,height:y})},re=()=>d(!0),Te=i=>{d(!1);const{naturalWidth:o,naturalHeight:y}=i.currentTarget;o>0&&y>0&&ee({width:o,height:y})},Z=c&&!He,Ee=i=>{if(J!=="interact"||!s)return;const o=i.currentTarget.getBoundingClientRect();oe.current={x:i.clientX-o.left,y:i.clientY-o.top,time:Date.now()}},ye=async i=>{var l,g,S;if(J!=="interact"||!s||!oe.current)return;const o=oe.current,y=i.currentTarget.getBoundingClientRect(),C=i.clientX-y.left,F=i.clientY-y.top,W=Date.now()-o.time,V=be.width,P=be.height,q=(l=t==null?void 0:t.hierarchy)==null?void 0:l.rect;let z=((g=t==null?void 0:t.metadata)==null?void 0:g.screenWidth)||H.width,G=((S=t==null?void 0:t.metadata)==null?void 0:S.screenHeight)||H.height;if(q&&q.width>0&&q.height>0&&(z=q.width,G=q.height),!z||!G||V===0||P===0)return;const Q=(N,L)=>({x:Math.round(N/V*z),y:Math.round(L/P*G),px:N/V,py:L/P}),K=Q(o.x,o.y),le=Q(C,F),a=Math.sqrt(Math.pow(C-o.x,2)+Math.pow(F-o.y,2));if(!(K.px<0||K.px>1||K.py<0||K.py>1)){try{W<500&&a<10?await D.tap(s,K.x,K.y):W>=500&&a<10?await D.touchAndHold(s,K.x,K.y,W):a>=10&&await D.swipe(s,K.x,K.y,le.x,le.y)}catch(N){console.error("Interaction failed:",N)}oe.current=null}},Pe=i=>{const o=new Set(U);o.has(i)?o.delete(i):o.add(i),w(o)},je=()=>{const i=new Set,o=y=>{var C;i.add(y.xpath),(C=y.children)==null||C.forEach(o)};t!=null&&t.hierarchy&&o(t.hierarchy),w(i)},se=()=>w(new Set(["/"])),he=(i,o)=>{navigator.clipboard.writeText(i),b(o),setTimeout(()=>b(null),2e3)},we=i=>{var y;let o=1;return(y=i.children)==null||y.forEach(C=>o+=we(C)),o},Be=i=>i.xpath.split("/").filter(Boolean).slice(-3),me=(i,o=0)=>{var q;if(!i)return null;const y=U.has(i.xpath),C=((q=i.children)==null?void 0:q.length)>0,F=(h==null?void 0:h.xpath)===i.xpath,W=(A==null?void 0:A.xpath)===i.xpath,V=i.name||i.type.split(".").pop()||"Element",P=!j||hs(i,j);if(!P&&!C)return null;if(j&&!P){const z=G=>{var Q;return hs(G,j)?!0:((Q=G.children)==null?void 0:Q.some(z))||!1};if(!z(i))return null}return e.jsxs("div",{className:"tree-node",children:[e.jsxs("div",{className:`tree-item ${F?"selected":""} ${W&&!F?"hovered":""}`,onClick:()=>{m(i),f("info")},onMouseEnter:()=>$(i),onMouseLeave:()=>$(null),children:[e.jsx("div",{className:"tree-item-indent",style:{width:`${o*14}px`}}),C?e.jsx("button",{onClick:z=>{z.stopPropagation(),Pe(i.xpath)},className:"tree-toggle",children:y?e.jsx(ps,{size:11}):e.jsx(xs,{size:11})}):e.jsx("span",{className:"tree-toggle-spacer"}),e.jsx(Ms,{size:11,className:"tree-icon"}),e.jsx("span",{className:"tree-label",children:V}),i.text&&e.jsxs("span",{className:"tree-text-preview",children:['"',i.text.slice(0,20),'"']}),C&&e.jsx("span",{className:"tree-badge",children:i.children.length})]}),y&&C&&e.jsx("div",{className:"tree-children",children:i.children.map(z=>me(z,o+1))})]},i.xpath)},ke=i=>{var V,P,q;if(!H.width)return[];const o=[],y=(V=t==null?void 0:t.hierarchy)==null?void 0:V.rect;let C=((P=t==null?void 0:t.metadata)==null?void 0:P.screenWidth)||H.width,F=((q=t==null?void 0:t.metadata)==null?void 0:q.screenHeight)||H.height;y&&y.width>0&&y.height>0&&(C=y.width,F=y.height);const W=(z,G)=>{var K,le,a;const Q=!z.children||z.children.length===0;((K=z.rect)==null?void 0:K.width)>0&&((le=z.rect)==null?void 0:le.height)>0&&Q&&o.push(e.jsx("div",{className:"omni-hit-area",style:{left:`${z.rect.x/C*100}%`,top:`${z.rect.y/F*100}%`,width:`${z.rect.width/C*100}%`,height:`${z.rect.height/F*100}%`,zIndex:G},onClick:l=>{l.stopPropagation(),m(z),f("info")},onMouseEnter:()=>$(z),onMouseLeave:()=>$(null)},z.xpath)),(a=z.children)==null||a.forEach(l=>W(l,G+1))};return t!=null&&t.hierarchy&&W(t.hierarchy,1),o},ue=(i,o)=>{var W,V,P;if(!(i!=null&&i.rect)||!H.width)return null;const y=(W=t==null?void 0:t.hierarchy)==null?void 0:W.rect;let C=((V=t==null?void 0:t.metadata)==null?void 0:V.screenWidth)||H.width,F=((P=t==null?void 0:t.metadata)==null?void 0:P.screenHeight)||H.height;return y&&y.width>0&&y.height>0&&(C=y.width,F=y.height),e.jsx("div",{className:`omni-frame-${o}`,style:{left:`${i.rect.x/C*100}%`,top:`${i.rect.y/F*100}%`,width:`${i.rect.width/C*100}%`,height:`${i.rect.height/F*100}%`}})},te=t!=null&&t.hierarchy?we(t.hierarchy):0,B=h?Ft(h):null,Ce={stable:{icon:e.jsx(Ze,{size:10}),cls:"stable"},moderate:{icon:e.jsx($s,{size:10}),cls:"moderate"},fragile:{icon:e.jsx(rs,{size:10}),cls:"fragile"},"very-fragile":{icon:e.jsx(rs,{size:10}),cls:"very-fragile"}};return e.jsx("div",{className:"omni-inspector-container",children:e.jsxs("div",{className:"omni-main-content",children:[e.jsxs("div",{className:"omni-screenshot-panel",children:[e.jsxs("div",{className:"omni-screenshot-header",children:[e.jsxs("div",{className:"omni-header-left",children:[e.jsx("span",{className:"omni-screenshot-title",children:"Device Preview"}),e.jsxs("div",{className:"omni-mode-toggle",children:[e.jsxs("button",{className:`omni-mode-btn ${J==="inspect"?"active":""}`,onClick:()=>Ae("inspect"),title:"Inspection Mode (Highlight Elements)",children:[e.jsx(Ts,{size:12}),e.jsx("span",{children:"Inspect"})]}),e.jsxs("button",{className:`omni-mode-btn ${J==="interact"?"active":""}`,onClick:()=>Ae("interact"),title:"Interaction Mode (Direct Control)",children:[e.jsx(bt,{size:12}),e.jsx("span",{children:"Interact"})]})]})]}),e.jsxs("button",{className:"omni-refresh-btn",onClick:ne,disabled:u,children:[e.jsx(Oe,{size:12,className:u?"animate-spin":""}),u?"Capturing...":"Refresh"]})]}),e.jsxs("div",{className:"omni-screenshot-container",ref:Ne,children:[u&&!Z&&e.jsxs("div",{className:"omni-loading-overlay",children:[e.jsx("div",{className:"omni-spinner"}),e.jsx("span",{children:"Capturing screen..."})]}),!t&&!u&&!Z&&e.jsxs("div",{className:"omni-empty-state",children:[e.jsx(cs,{size:40}),e.jsx("span",{children:"Click Refresh to capture"})]}),Z&&e.jsxs("div",{className:`omni-screenshot-wrapper ${J==="interact"?"interactable":""}`,onMouseDown:Ee,onMouseUp:ye,children:[e.jsx("img",{ref:fe,src:c,onLoad:Te,onError:re,className:"omni-screenshot-img",style:J==="interact"?{pointerEvents:"none"}:{},draggable:!1,alt:"Live Device Stream"}),(t==null?void 0:t.hierarchy)&&J==="inspect"&&e.jsxs("div",{className:"omni-overlay",children:[ke(t.hierarchy),ue(A,"hover"),ue(h,"select")]})]}),!Z&&(t==null?void 0:t.screenshot)&&e.jsxs("div",{className:`omni-screenshot-wrapper ${J==="interact"?"interactable":""}`,onMouseDown:Ee,onMouseUp:ye,children:[e.jsx("img",{ref:ge,src:`data:image/png;base64,${t.screenshot}`,onLoad:Le,className:"omni-screenshot-img",style:J==="interact"?{pointerEvents:"none"}:{},draggable:!1}),J==="inspect"&&e.jsxs("div",{className:"omni-overlay",children:[ke(t.hierarchy),ue(A,"hover"),ue(h,"select")]})]})]})]}),e.jsxs("div",{className:"omni-tree-panel",children:[e.jsxs("div",{className:"omni-tree-header",children:[e.jsxs("div",{className:"omni-tree-title",children:[e.jsx(Js,{size:14}),e.jsx("span",{children:"Source"}),te>0&&e.jsxs("span",{className:"omni-count-badge",children:[te," elements"]})]}),e.jsxs("div",{className:"omni-tree-actions",children:[e.jsx("button",{onClick:je,className:"omni-action-btn",title:"Expand All",children:e.jsx(Xs,{size:12})}),e.jsx("button",{onClick:se,className:"omni-action-btn",title:"Collapse All",children:e.jsx(ht,{size:12})})]})]}),e.jsxs("div",{className:"omni-tree-search",children:[e.jsx(es,{size:14}),e.jsx("input",{type:"text",placeholder:"Search elements... (try 'login button' or 'text field')",value:j,onChange:i=>E(i.target.value)}),j&&e.jsx("button",{onClick:()=>E(""),className:"omni-clear-btn",children:"×"})]}),j&&e.jsxs("div",{className:"omni-search-hint",children:[e.jsx(ls,{size:10}),' Smart search active — try "button", "input", "image"']}),e.jsx("div",{className:"omni-tree-content",children:t!=null&&t.hierarchy?me(t.hierarchy):e.jsx("div",{className:"omni-empty-state small",children:e.jsx("span",{children:"No hierarchy loaded"})})})]}),e.jsxs("div",{className:"omni-details-panel",children:[e.jsxs("div",{className:"omni-details-tabs",children:[e.jsxs("button",{className:`omni-details-tab ${k==="info"?"active":""}`,onClick:()=>f("info"),children:[e.jsx(tt,{size:12})," Info"]}),e.jsxs("button",{className:`omni-details-tab ${k==="insight"?"active":""}`,onClick:()=>f("insight"),disabled:!h,title:"AI Element Analysis",children:[e.jsx(Qs,{size:12})," AI Insight"]}),e.jsxs("button",{className:`omni-details-tab ${k==="code"?"active":""}`,onClick:()=>f("code"),disabled:!h,title:"Generate Test Code",children:[e.jsx(as,{size:12})," Code Gen"]})]}),e.jsx("div",{className:"omni-details-content",children:h?e.jsxs(e.Fragment,{children:[k==="info"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"omni-section",children:[e.jsx("div",{className:"omni-section-header",children:"Element Info"}),e.jsxs("div",{className:"omni-info-table",children:[e.jsxs("div",{className:"omni-info-row",children:[e.jsx("span",{className:"omni-info-key",children:"Type"}),e.jsx("span",{className:"omni-info-value mono",children:h.type})]}),h.text&&e.jsxs("div",{className:"omni-info-row",children:[e.jsx("span",{className:"omni-info-key",children:"Text"}),e.jsx("span",{className:"omni-info-value",children:h.text})]}),e.jsxs("div",{className:"omni-info-row",children:[e.jsx("span",{className:"omni-info-key",children:"Path"}),e.jsx("span",{className:"omni-info-value mono small",children:Be(h).join(" › ")})]})]})]}),e.jsxs("div",{className:"omni-section",children:[e.jsx("div",{className:"omni-section-header",children:"Layout"}),e.jsx("div",{className:"omni-layout-grid",children:["x","y","width","height"].map(i=>e.jsxs("div",{className:"omni-layout-item",children:[e.jsx("span",{className:"omni-layout-label",children:i.toUpperCase()}),e.jsx("span",{className:"omni-layout-value",children:h.rect[i]})]},i))})]}),e.jsxs("div",{className:"omni-section",children:[e.jsxs("div",{className:"omni-section-header",children:["Locators",e.jsx("span",{className:"omni-section-badge",children:"Stability Scored"})]}),e.jsx("div",{className:"omni-locators-list",children:(pe=h.suggestedLocators)==null?void 0:pe.map(i=>{const o=os(i.strategy,i.value),y=Ce[o.level];return e.jsxs("div",{className:`omni-locator-row ${(_==null?void 0:_.strategy)===i.strategy?"selected-for-code":""}`,onClick:()=>X(i),title:"Click to use in Code Generator",children:[e.jsxs("div",{className:"omni-locator-left",children:[e.jsxs("div",{className:"omni-locator-top",children:[e.jsx("span",{className:"omni-locator-strategy",children:i.strategy}),e.jsxs("span",{className:`omni-stability-badge ${y.cls}`,title:o.reason,children:[y.icon,o.level]})]}),e.jsx("code",{className:"omni-locator-value",children:i.value}),e.jsx("span",{className:"omni-stability-reason",children:o.reason})]}),e.jsx("button",{onClick:C=>{C.stopPropagation(),he(i.value,i.strategy)},className:`omni-copy-btn ${O===i.strategy?"copied":""}`,children:O===i.strategy?e.jsx(qe,{size:12}):e.jsx(Xe,{size:12})})]},i.strategy)})})]}),e.jsxs("div",{className:"omni-section",children:[e.jsx("div",{className:"omni-section-header",children:"Attributes"}),e.jsx("div",{className:"omni-attributes-table",children:Object.entries(h.attributes||{}).filter(([i,o])=>o!=null&&o!=="").map(([i,o])=>e.jsxs("div",{className:"omni-attr-row",children:[e.jsx("span",{className:"omni-attr-key",children:i}),e.jsx("span",{className:"omni-attr-value",children:String(o)})]},i))})]})]}),k==="insight"&&B&&e.jsxs("div",{className:"omni-insight-panel",children:[e.jsxs("div",{className:"omni-insight-role",children:[e.jsx("span",{className:"omni-insight-emoji",children:B.emoji}),e.jsxs("div",{children:[e.jsx("div",{className:"omni-insight-role-name",children:B.role}),e.jsx("div",{className:"omni-insight-interactable",children:B.interactable?e.jsxs("span",{className:"omni-badge-green",children:[e.jsx(zs,{size:10})," Interactable"]}):e.jsx("span",{className:"omni-badge-gray",children:"Visual Only"})})]})]}),B.warning&&e.jsx("div",{className:"omni-insight-warning",children:B.warning}),e.jsxs("div",{className:"omni-insight-description",children:[e.jsx(ls,{size:12,className:"omni-insight-icon"}),e.jsx("p",{children:B.description})]}),B.bestLocator&&e.jsxs("div",{className:"omni-insight-best-locator",children:[e.jsx("div",{className:"omni-section-header",children:"Recommended Locator"}),e.jsxs("div",{className:"omni-locator-row",children:[e.jsxs("div",{className:"omni-locator-left",children:[e.jsx("span",{className:"omni-locator-strategy",children:B.bestLocator.strategy}),e.jsx("code",{className:"omni-locator-value",children:B.bestLocator.value})]}),e.jsx("button",{onClick:()=>he(B.bestLocator.value,"best"),className:`omni-copy-btn ${O==="best"?"copied":""}`,children:O==="best"?e.jsx(qe,{size:12}):e.jsx(Xe,{size:12})})]})]}),e.jsxs("div",{className:"omni-insight-attributes",children:[e.jsx("div",{className:"omni-section-header",children:"Quick Facts"}),e.jsx("div",{className:"omni-quick-facts",children:[{label:"Clickable",value:(Se=h.attributes)==null?void 0:Se.clickable},{label:"Enabled",value:(ze=h.attributes)==null?void 0:ze.enabled},{label:"Scrollable",value:($e=h.attributes)==null?void 0:$e.scrollable},{label:"Focusable",value:(ve=h.attributes)==null?void 0:ve.focusable},{label:"Children",value:((De=h.children)==null?void 0:De.length)||0}].map(({label:i,value:o})=>e.jsxs("div",{className:"omni-quick-fact-row",children:[e.jsx("span",{className:"omni-quick-fact-label",children:i}),e.jsx("span",{className:`omni-quick-fact-value ${o==="true"||o===!0?"true":""}`,children:String(o??"—")})]},i))})]})]}),k==="code"&&e.jsxs("div",{className:"omni-codegen-panel",children:[e.jsx("div",{className:"omni-codegen-frameworks",children:["java","python","javascript","wdio"].map(i=>e.jsx("button",{className:`omni-fw-btn ${R===i?"active":""}`,onClick:()=>M(i),children:i==="java"?"☕ Java":i==="python"?"🐍 Python":i==="javascript"?"🟨 JS":"🔷 WD.io"},i))}),_?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"omni-codegen-locator-selector",children:[e.jsx("span",{className:"omni-codegen-label",children:"Locator:"}),e.jsx("select",{value:_.strategy,onChange:i=>{var y;const o=(y=h.suggestedLocators)==null?void 0:y.find(C=>C.strategy===i.target.value);o&&X(o)},className:"omni-fw-select",children:(Ie=h.suggestedLocators)==null?void 0:Ie.map(i=>e.jsxs("option",{value:i.strategy,children:[i.strategy," — ",os(i.strategy,i.value).level]},i.strategy))})]}),e.jsxs("div",{className:"omni-codegen-output",children:[e.jsxs("div",{className:"omni-codegen-header",children:[e.jsx("span",{className:"omni-codegen-lang",children:R==="java"?"Java / TestNG":R==="python"?"Python / unittest":R==="javascript"?"JavaScript / Mocha":"WebdriverIO"}),e.jsx("button",{className:"omni-copy-btn",onClick:()=>he(ds(h,(t==null?void 0:t.platform)==="android"?"android":(t==null?void 0:t.platform)==="ios"?"ios":"unknown",R,_),"code"),children:O==="code"?e.jsx(qe,{size:12}):e.jsx(Xe,{size:12})})]}),e.jsx("pre",{className:"omni-codegen-pre",children:e.jsx("code",{children:ds(h,(t==null?void 0:t.platform)==="android"?"android":(t==null?void 0:t.platform)==="ios"?"ios":"unknown",R,_)})})]})]}):e.jsxs("div",{className:"omni-empty-state small",children:[e.jsx(as,{size:24}),e.jsx("span",{children:"No locators available for this element"})]})]})]}):e.jsxs("div",{className:"omni-empty-state",children:[e.jsx(cs,{size:32}),e.jsx("span",{children:"Select an element from the tree or screenshot"})]})})]})]})})};function Pt({device:n,onClose:s}){var le;const{toast:c,removeToast:u}=us(),p=Qe(),{tab:t}=vs(),T=r.useRef(null),v=r.useRef(null),[x,h]=r.useState({width:0,height:0}),[m,A]=r.useState(t||"actions"),[$,U]=r.useState(""),[w,j]=r.useState(""),[E,O]=r.useState(""),[b,k]=r.useState(!0),[f,R]=r.useState([]),[M,_]=r.useState(null),[X,H]=r.useState(!1),[ee,be]=r.useState(!1),[xe,He]=r.useState(0),[d,J]=r.useState(n),[Ae,Ne]=r.useState([]),[ge,fe]=r.useState(!1),[oe,de]=r.useState(!1),[ne,Le]=r.useState(null),[re,Te]=r.useState([]),[Z,Ee]=r.useState(!0),[ye,Pe]=r.useState(""),je=r.useRef(""),se=r.useRef(null),[he,we]=r.useState(!1);r.useEffect(()=>{m&&(!t||t!==m)&&p(`/devices/${n.udid}/control/${m}`,{replace:!0})},[m,t,n.udid,p]),r.useEffect(()=>{let a;if(m==="logs"){const l=async()=>{try{const g=await D.getLogs(d.udid);if(g&&g.logs&&g.logs.trim().length>0){const S=g.logs.replace(/\\u[0-9a-fA-F]{4}/g,N=>JSON.parse(`"${N}"`)).replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,"").split(`
191
+ `).filter(N=>N.trim().length>0);S.length>0&&Te(N=>[...N,...S].slice(-1e3))}}catch(g){console.error("Failed to fetch logs:",g)}};l(),a=setInterval(l,3e3)}return()=>clearInterval(a)},[m,d.udid]);const Be=()=>re.length===0?e.jsx("div",{className:"log-line log-debug",children:e.jsx("span",{className:"log-content",children:"Establishing technical link... Waiting for heartbeat."})}):re.filter(l=>!ye||l.toLowerCase().includes(ye.toLowerCase())).map((l,g)=>{let S="log-debug";const N=l.toLowerCase();return N.includes("error")||N.includes("fail")?S="log-error":N.includes("warning")||N.includes("warn")?S="log-warn":(N.includes("notice")||N.includes("info"))&&(S="log-notice"),e.jsxs("div",{className:`log-line ${S}`,children:[e.jsx("span",{className:"log-index",children:g+1}),e.jsx("span",{className:"log-content",children:l})]},`${g}-${l.substring(0,10)}`)});r.useEffect(()=>{m==="logs"&&Z&&v.current&&(v.current.scrollTop=v.current.scrollHeight)},[re,m,Z]),r.useEffect(()=>((async()=>{try{be(!0),await D.startStream(d.udid);const g=(await D.getDevices()).find(S=>S.udid===d.udid);g&&J(g)}catch(l){console.error("Auto-start stream failed:",l)}finally{be(!1)}})(),()=>{D.stopStream(d.udid).catch(()=>{})}),[n.udid]);const me=r.useCallback(async()=>{try{fe(!0);const a=await D.listApps(d.udid);Array.isArray(a)&&Ne(a)}catch(a){console.error("Failed to load apps:",a)}finally{fe(!1)}},[d.udid]);r.useEffect(()=>{m==="actions"&&me()},[m,me]);const ke=parseInt(d.screenWidth||"1080",10),ue=parseInt(d.screenHeight||"1920",10),te=Math.min(ke,ue),B=Math.max(ke,ue),Ce=te/B,pe=r.useCallback(()=>{const a=!b,l=a?window.innerHeight*.55:window.innerHeight*.7,g=a?window.innerWidth*.8:window.innerWidth*.45,S=b?Ce:1/Ce;let N,L;b?(N=l,L=N*S,L>g&&(L=g,N=L/S)):(L=g,N=L/S,N>l&&(N=l,L=N*S)),h({width:L,height:N})},[Ce,b]);r.useEffect(()=>(pe(),window.addEventListener("resize",pe),()=>window.removeEventListener("resize",pe)),[pe]),r.useEffect(()=>{const a=async()=>{if(je.current.length>0){const g=je.current;je.current="";try{await D.typeText(d.udid,g)}catch(S){console.error("Keyboard buffering flush failed:",S)}}},l=g=>{const S=document.activeElement;if(S&&(S.tagName==="INPUT"||S.tagName==="TEXTAREA"||S.isContentEditable)||!he&&m!=="terminal")return;const L=g.key;L==="Enter"?(se.current&&clearTimeout(se.current),a(),D.pressKey(d.udid,d.platform==="android"?66:"enter")):L==="Backspace"?(se.current&&clearTimeout(se.current),a(),D.pressKey(d.udid,d.platform==="android"?67:"backspace")):L.length===1&&(je.current+=L,se.current&&clearTimeout(se.current),se.current=setTimeout(()=>{a()},50))};return window.addEventListener("keydown",l),()=>{window.removeEventListener("keydown",l),se.current&&clearTimeout(se.current)}},[d.udid,d.platform,he,m]);const[Se,ze]=r.useState(Date.now()),$e=()=>{const a=xe>0?`r=${xe}&`:"";return d.session_id&&!String(d.session_id).startsWith("manual_")?`/xenon/api/session/${d.session_id}/live_video?${a}t=${Se}`:`/xenon/api/control/${d.udid}/stream?${a}t=${Se}`};r.useEffect(()=>{xe>0&&ze(Date.now())},[xe]);const ve=r.useRef(null),De=a=>{const l=a.currentTarget.getBoundingClientRect();return{x:a.clientX-l.left,y:a.clientY-l.top}},Ie=a=>{const l=De(a);ve.current={x:l.x,y:l.y,time:Date.now()}},i=async a=>{if(!ve.current)return;const l=ve.current,g=De(a),S=Date.now()-l.time;let N,L,ie,ae;b?(N=l.x/x.width*te,L=l.y/x.height*B,ie=g.x/x.width*te,ae=g.y/x.height*B):(N=l.x/x.width*B,L=l.y/x.height*te,ie=g.x/x.width*B,ae=g.y/x.height*te);const ce=Math.abs(ie-N),Re=Math.abs(ae-L);try{S<500&&ce<10&&Re<10?await D.tap(d.udid,Math.round(N),Math.round(L)):S>=500&&ce<10&&Re<10?await D.touchAndHold(d.udid,Math.round(N),Math.round(L),S):await D.swipe(d.udid,Math.round(N),Math.round(L),Math.round(ie),Math.round(ae))}catch(ks){console.error("Action failed:",ks)}ve.current=null},o=()=>D.pressKey(d.udid,d.platform==="android"?3:"home"),y=()=>D.lock(d.udid),C=()=>D.unlock(d.udid),F=async()=>{$.trim()&&(await D.typeText(d.udid,$),U(""))},W=async()=>{try{j("Fetching...");const a=await D.getClipboard(d.udid);a&&a.content!==void 0?j(a.content||"(Clipboard is empty)"):j("No content received")}catch{j("Error: Check Appium Settings app")}},V=async()=>{H(!0);try{const a=await D.getScreenshot(d.udid);if(a!=null&&a.screenshot){const l={id:Ut(),base64:a.screenshot,timestamp:Date.now()};R(g=>[l,...g]),_(0)}}catch(a){console.error("Failed to take screenshot:",a)}finally{H(!1)}},P=a=>{R(l=>{const g=l.filter(S=>S.id!==a);return g.length===0?_(null):M!==null&&M>=g.length&&_(0),g})},q=()=>{R([]),_(null),c("Cleared all captured evidence.","success")},z=a=>{const l=document.createElement("a");l.href=`data:image/png;base64,${a}`,l.download=`screenshot-${d.udid}-${Date.now()}.png`,l.click()},G=async a=>{const l=te/2,g=B/2,S=te*.4,N=B*.4;let L,ie,ae,ce;switch(a){case"left":L=l+S,ie=g,ae=l-S,ce=g;break;case"right":L=l-S,ie=g,ae=l+S,ce=g;break;case"up":L=l,ie=g+N,ae=l,ce=g-N;break;case"down":L=l,ie=g-N,ae=l,ce=g+N;break}try{await D.swipe(d.udid,Math.round(L),Math.round(ie),Math.round(ae),Math.round(ce))}catch(Re){console.error(`Quick swipe ${a} failed:`,Re)}},Q=async()=>{if(E.trim()){const a=c(`Uninstalling ${E}...`,"loading",0);try{fe(!0),await D.uninstallApp(d.udid,E),O(""),c(`Request sent for ${E}`,"success"),setTimeout(me,3e3)}catch{c("Uninstall failed. Check logs.","error")}finally{fe(!1),u(a)}}},K=async()=>{if(!ne)return;let a;try{de(!0),a=c(`Installing app to ${d.udid}...`,"loading",0);const l=await D.uploadAndInstallApp(d.udid,ne);l.success?(c(l.message||"App installed successfully","success"),Le(null),setTimeout(me,5e3)):c("Installation failed: "+(l.error||"Unknown error"),"error")}catch(l){c("Installation failed: "+l.message,"error")}finally{a&&u(a),de(!1)}};return e.jsxs("div",{className:"device-control-view",children:[e.jsx("div",{className:"scanline",style:{position:"absolute",inset:0,pointerEvents:"none",opacity:.05,zIndex:1001}}),e.jsxs("header",{className:"control-view-top-bar",children:[e.jsxs("button",{className:"back-to-devices-btn",onClick:s,children:[e.jsx(is,{size:18})," DEVICES"]}),e.jsxs("div",{className:"device-info-mini",children:[e.jsx("span",{className:`device-pill platform-pill ${d.platform}`,children:d.platform==="ios"?"Apple":"Android"}),e.jsxs("span",{className:"device-pill version-pill",children:["v",d.sdk]}),d.reservedUntil&&Date.now()<d.reservedUntil&&e.jsxs("span",{className:"device-pill reserved-pill",title:`Reserved by ${d.reservedBy}${d.reservationReason?`: ${d.reservationReason}`:""}`,children:["RESERVED BY ",((le=d.reservedBy)==null?void 0:le.toUpperCase())||"ANONYMOUS"]}),e.jsx("h2",{className:"device-name-text",children:d.name}),e.jsx("span",{className:"code-font",style:{opacity:.5},children:d.udid})]})]}),e.jsxs("div",{className:`control-view-main ${b?"":"is-landscape"} ${m==="omni"?"omni-mode":""}`,children:[e.jsxs("div",{className:"device-preview-column",children:[e.jsx("div",{className:"device-screen-wrapper",children:e.jsxs("div",{ref:T,className:`device-stream-canvas ${b?"":"landscape"} ${he?"focused":""}`,style:{width:x.width,height:x.height,background:"#000"},tabIndex:0,onFocus:()=>we(!0),onBlur:()=>we(!1),onMouseDown:Ie,onMouseUp:i,children:[ee&&e.jsxs("div",{className:"device-stream-placeholder",style:{position:"absolute",zIndex:10},children:[e.jsx(Oe,{size:40,className:"animate-spin",color:"var(--primary)"}),e.jsx("p",{style:{marginTop:16},children:"ESTABLISHING TRACE..."})]}),e.jsx("img",{src:$e(),alt:"Device Stream",className:"device-stream-image",style:{width:"100%",height:"100%",objectFit:"contain"},onError:()=>{console.warn("Stream failed to load, retrying..."),setTimeout(()=>He(a=>a+1),2e3)}})]})}),e.jsxs("aside",{className:"device-footer-actions",children:[e.jsxs("button",{className:`footer-action-btn ${b?"active":""}`,onClick:()=>k(!0),children:[e.jsx(Oe,{size:14,style:{transform:b?"none":"rotate(-90deg)"}})," ","PORTRAIT"]}),e.jsxs("button",{className:`footer-action-btn ${b?"":"active"}`,onClick:()=>k(!1),children:[e.jsx(Oe,{size:14,style:{transform:"rotate(90deg)"}})," LANDSCAPE"]}),e.jsx("div",{className:"footer-divider"}),e.jsxs("button",{className:"footer-action-btn",onClick:o,children:[e.jsx(Ys,{size:20})," HOME"]}),e.jsx("button",{className:"footer-action-btn",onClick:y,title:"Lock Device",children:e.jsx(Is,{size:20})}),e.jsx("button",{className:"footer-action-btn",onClick:C,title:"Unlock Device",children:e.jsx(Ns,{size:20})})]})]}),e.jsxs("div",{className:"device-interactions-column",children:[e.jsxs("div",{className:"interaction-tabs",children:[e.jsx("button",{className:`tab-btn ${m==="actions"?"active":""}`,onClick:()=>A("actions"),children:"ACTIONS"}),e.jsx("button",{className:`tab-btn ${m==="screenshot"?"active":""}`,onClick:()=>A("screenshot"),children:"SCREENSHOT"}),e.jsx("button",{className:`tab-btn ${m==="logs"?"active":""}`,onClick:()=>A("logs"),children:"DEBUG LOGS"}),e.jsxs("button",{className:`tab-btn ${m==="terminal"?"active":""}`,onClick:()=>A("terminal"),children:[e.jsx(js,{size:14,style:{marginRight:6}})," SHELL"]}),e.jsx("button",{className:`tab-btn ${m==="omni"?"active":""}`,onClick:()=>A("omni"),children:"OMNI-VISION"})]}),e.jsx("div",{className:`interactions-scroll-area ${m==="terminal"?"terminal-mode":""} ${m==="screenshot"||m==="logs"?"screenshot-mode":""}`,children:e.jsxs("div",{className:"tab-content",children:[m==="omni"&&e.jsx("div",{className:"omni-inspector-tab-wrapper animate-fade-in",style:{height:"calc(100vh - 266px)"},children:e.jsx(Ht,{sessionId:d.session_id?String(d.session_id):null,udid:d.udid,streamUrl:$e()})}),m==="actions"&&e.jsxs("div",{className:"actions-grid",children:[e.jsxs("div",{className:"action-card",children:[e.jsxs("h4",{className:"action-card-title",children:[e.jsx(lt,{size:18,color:"var(--primary)"})," Directional Gestures"]}),e.jsxs("div",{className:"gestures-grid-container",children:[e.jsxs("div",{className:"gestures-dpad",children:[e.jsx("div",{}),e.jsx("button",{className:"dpad-btn",onClick:()=>G("up"),children:e.jsx(Fs,{size:24})}),e.jsx("div",{}),e.jsx("button",{className:"dpad-btn",onClick:()=>G("left"),children:e.jsx(is,{size:24})}),e.jsx("div",{className:"dpad-center"}),e.jsx("button",{className:"dpad-btn",onClick:()=>G("right"),children:e.jsx(xs,{size:24})}),e.jsx("div",{}),e.jsx("button",{className:"dpad-btn",onClick:()=>G("down"),children:e.jsx(ps,{size:24})}),e.jsx("div",{})]}),e.jsx("p",{className:"compact-label",style:{opacity:.5},children:"Directional Glide"})]})]}),e.jsxs("div",{className:"action-card",children:[e.jsxs("h4",{className:"action-card-title",children:[e.jsx(Vs,{size:18,color:"var(--primary)"})," Smart Input"]}),e.jsx("input",{type:"text",className:"type-input-field compact",placeholder:"Relay keystrokes...",value:$,onChange:a=>U(a.target.value),onKeyDown:a=>a.key==="Enter"&&F()})]}),e.jsxs("div",{className:"action-card full-width",children:[e.jsxs("h4",{className:"action-card-title",children:[e.jsx(ot,{size:18,color:"var(--primary)"})," App Management"]}),e.jsxs("div",{className:"app-mgmt-content",children:[e.jsxs("div",{className:"install-section",children:[e.jsx("p",{className:"compact-label",children:"Install Package (.apk, .ipa, .app)"}),e.jsxs("div",{className:"upload-box-row",children:[e.jsxs("label",{className:"file-upload-launcher",children:[e.jsx(Ls,{size:14}),e.jsx("span",{children:ne?ne.name:"Select File"}),e.jsx("input",{type:"file",accept:".apk,.ipa,.app",onChange:a=>{var l;return Le(((l=a.target.files)==null?void 0:l[0])||null)},hidden:!0})]}),e.jsx("button",{className:"btn-premium btn-sm",disabled:!ne||oe,onClick:K,children:oe?e.jsx(We,{className:"animate-spin",size:14}):"INSTALL"})]})]}),e.jsx("div",{className:"divider-v"}),e.jsxs("div",{className:"uninstall-section",children:[e.jsx("p",{className:"compact-label",children:"Quick Uninstall"}),e.jsxs("div",{className:"uninstall-controls-row",children:[e.jsxs("div",{className:"select-wrapper",children:[e.jsxs("select",{className:"app-select-dropdown compact",value:E,onChange:a=>O(a.target.value),disabled:ge,children:[e.jsx("option",{value:"",children:ge?"Loading apps...":"-- Select App to Remove --"}),Ae.map(a=>e.jsx("option",{value:a,children:a},a))]}),ge&&e.jsx(We,{className:"animate-spin select-loader",size:12})]}),e.jsxs("button",{className:"btn-destructive btn-sm",onClick:Q,disabled:!E||ge,children:[e.jsx(_e,{size:14})," UNINSTALL"]})]}),e.jsxs("div",{className:"manual-input-box",children:[e.jsx("p",{className:"hint-text",children:"Or enter manually:"}),e.jsx("input",{type:"text",className:"type-input-field tiny",placeholder:"com.example.app",value:E,onChange:a=>O(a.target.value)})]})]})]})]}),e.jsxs("div",{className:"action-card full-width",children:[e.jsxs("h4",{className:"action-card-title",children:[e.jsx(Ps,{size:18,color:"var(--primary)"})," Clipboard"]}),e.jsxs("div",{style:{display:"flex",gap:"12px",alignItems:"flex-start"},children:[e.jsx("button",{className:"btn-premium btn-sm",style:{width:"140px",flexShrink:0},onClick:W,children:"FETCH VALUE"}),e.jsx("div",{className:"clipboard-display compact",style:{marginTop:0,flex:1},children:w})]})]})]}),m==="screenshot"&&e.jsxs("div",{className:"action-card screenshot-card",children:[e.jsxs("header",{className:"action-card-header",children:[e.jsxs("div",{className:"title-group",children:[e.jsxs("h4",{className:"action-card-title",children:[e.jsx(Ve,{size:20,color:"var(--primary)"})," Captured Evidence"]}),e.jsx("p",{className:"hint-text",children:"Relay screenshots from device to host."})]}),f.length>0&&e.jsx("button",{className:"btn-text-only",onClick:q,children:"CLEAR ALL"})]}),e.jsxs("div",{className:"screenshot-workspace",children:[e.jsxs("div",{className:"screenshot-gallery-sidebar",children:[e.jsxs("button",{className:"btn-premium take-screenshot-btn",onClick:V,disabled:X,children:[X?e.jsx(We,{className:"animate-spin",size:16}):e.jsx(Ve,{size:16}),e.jsx("span",{children:X?"CAPTURING...":"NEW CAPTURE"})]}),e.jsxs("div",{className:"screenshot-thumbnails-list",children:[f.length===0&&!X&&e.jsx("div",{className:"empty-gallery-state",children:e.jsx("p",{children:"No captures yet"})}),f.map((a,l)=>e.jsxs("div",{className:`screenshot-thumb-item ${M===l?"active":""}`,onClick:()=>_(l),children:[e.jsx("img",{src:`data:image/png;base64,${a.base64}`,alt:"Thumb"}),e.jsx("span",{className:"thumb-time",children:new Date(a.timestamp).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"})}),e.jsx("button",{className:"thumb-delete-btn",onClick:g=>{g.stopPropagation(),P(a.id)},children:e.jsx(_e,{size:12})})]},a.id))]})]}),e.jsx("div",{className:"screenshot-main-preview",children:M!==null&&f[M]?e.jsxs("div",{className:"preview-container",children:[e.jsx("div",{className:"preview-image-wrapper",children:e.jsx("img",{src:`data:image/png;base64,${f[M].base64}`,alt:"Selected Evidence"})}),e.jsxs("footer",{className:"preview-footer",children:[e.jsxs("div",{className:"preview-meta",children:[e.jsx("span",{className:"meta-label",children:"ID:"}),e.jsx("span",{className:"meta-value",children:f[M].id.substring(0,8)}),e.jsx("span",{className:"meta-divider",children:"|"}),e.jsx("span",{className:"meta-value",children:new Date(f[M].timestamp).toLocaleString()})]}),e.jsxs("div",{className:"preview-actions",children:[e.jsx("button",{className:"btn-premium btn-sm",onClick:()=>z(f[M].base64),children:"DOWNLOAD PNG"}),e.jsxs("button",{className:"btn-destructive btn-sm",onClick:()=>P(f[M].id),children:[e.jsx(_e,{size:14})," DELETE"]})]})]})]}):e.jsxs("div",{className:"preview-empty-placeholder",children:[e.jsx(Ve,{size:48,style:{opacity:.1,marginBottom:16}}),e.jsx("p",{children:"Capture a screenshot to begin analysis"})]})})]})]}),m==="logs"&&e.jsxs("div",{className:"action-card screenshot-card",style:{padding:0,gap:0},children:[e.jsxs("div",{className:"log-toolbar",children:[e.jsxs("div",{className:"log-filter-group",children:[e.jsx("div",{className:"log-stat-pill",children:"LIVE"}),e.jsxs("div",{className:"log-stat-pill",style:{opacity:.6},children:[re.length," LINES"]}),e.jsxs("div",{className:"log-search-box",children:[e.jsx(es,{size:14,className:"search-icon-inline"}),e.jsx("input",{type:"text",className:"type-input-field tiny",placeholder:"Filter trace...",value:ye,onChange:a=>Pe(a.target.value)})]})]}),e.jsxs("div",{className:"log-actions-group",children:[e.jsxs("button",{className:`btn-secondary btn-sm ${Z?"active":""}`,onClick:()=>Ee(!Z),title:Z?"Freeze Logs":"Follow Logs",children:[e.jsx(ws,{size:14,className:Z?"animate-pulse":""}),Z?"FREEZE":"FOLLOW"]}),e.jsxs("button",{className:"btn-premium btn-sm",onClick:()=>{const a=new Blob([re.join(`
192
+ `)],{type:"text/plain"}),l=URL.createObjectURL(a),g=document.createElement("a");g.href=l,g.download=`logs-${d.udid}-${Date.now()}.txt`,g.click(),URL.revokeObjectURL(l)},disabled:re.length===0,children:[e.jsx(Es,{size:14}),"EXPORT"]}),e.jsxs("button",{className:"btn-secondary btn-sm",onClick:()=>Te([]),title:"Clear Logs",children:[e.jsx(_e,{size:14}),"CLEAR"]})]})]}),e.jsx("div",{className:"log-display-area",ref:v,style:{flex:1},children:Be()})]}),m==="terminal"&&e.jsx("div",{className:"action-card full-height",children:e.jsx(Ot,{platform:(d.platform||"").toLowerCase(),prompt:`${(d.platform||"").toLowerCase()==="ios"?"ios":"adb"} $`,welcomeMessage:`Connected to ${d.name} (${d.udid}).
193
+ Internal Shell Environment.`,onCommand:async a=>{const l=await D.executeShell(d.udid,a);if(l.error)throw new Error(l.error);return l.output}})})]})})]})]})]})}const ms={platform:{ios:!0,android:!0},state:{ready:!0,offline:!0,busy:!0},name:""};class Bt extends Fe.Component{constructor(s){super(s),this.socketCleanups=[],this.refreshTimeout=null,this.state={devices:[],activeSessionsCount:0,pendingSessionsCount:0,queueSummary:null,filter:ms}}componentDidMount(){this.fetchDevices(),this.devicePolling=setInterval(()=>{this.fetchDevices()},1e4);const s=this.props.onSocketEvent("device_unblocked",()=>{console.info("Real-time: Device unblocked, triggering debounced refresh"),this.fetchDevicesDebounced()}),c=this.props.onSocketEvent("device_blocked",()=>{console.info("Real-time: Device blocked, triggering debounced refresh"),this.fetchDevicesDebounced()});this.socketCleanups.push(s,c)}componentWillUnmount(){this.devicePolling&&(clearInterval(this.devicePolling),this.devicePolling=void 0),this.refreshTimeout&&(clearTimeout(this.refreshTimeout),this.refreshTimeout=null),this.socketCleanups.forEach(s=>s())}fetchDevicesDebounced(){this.refreshTimeout&&clearTimeout(this.refreshTimeout),this.refreshTimeout=setTimeout(()=>{this.refreshTimeout=null,this.fetchDevices()},500)}getBusyDevicesCount(s){return[u=>u.busy].reduce((u,p)=>u.filter(p),s).length}async fetchDevices(){try{const s=await D.getDevices(),c=this.getBusyDevicesCount(s),u=await D.getPendingSessionsCount(),p=await D.getQueueSummary();console.log(s),this.setState({devices:s,activeSessionsCount:c,pendingSessionsCount:u,queueSummary:p})}catch(s){console.log(s)}}getFilteredDevice(){const{ready:s,busy:c,offline:u}=this.state.filter.state,{ios:p,android:t}=this.state.filter.platform,T=[v=>p&&(v.platform=="ios"||v.platform=="tvos")||t&&v.platform=="android",v=>s&&!v.busy&&!v.offline||c&&v.busy||u&&v.offline];return this.state.filter.name!=""&&T.push(v=>v.name.toLowerCase().includes(this.state.filter.name.toLowerCase())||v.udid.toLowerCase().includes(this.state.filter.name.toLowerCase())),T.reduce((v,x)=>v.filter(x),this.state.devices)}setFilter(s){this.setState({filter:{...this.state.filter,...s}})}getPlatformFilterComponent(){const{ios:s,android:c}=this.state.filter.platform;return e.jsxs("div",{className:"device-explorer-header-value",children:[e.jsxs("button",{className:`device-explorer-header__platform-btn ${c&&"selected"}`,onClick:()=>this.setFilter({platform:{...this.state.filter.platform,android:!this.state.filter.platform.android}}),children:[e.jsx(Je,{size:20,color:"currentColor"}),"Android"]}),e.jsxs("button",{className:`device-explorer-header__platform-btn ${s&&"selected"}`,onClick:()=>this.setFilter({platform:{...this.state.filter.platform,ios:!this.state.filter.platform.ios}}),children:[e.jsx(ys,{size:20,color:"currentColor"}),"iOS"]})]})}getDeviceStateFilterComponent(){const{ready:s,busy:c,offline:u}=this.state.filter.state;return e.jsxs("div",{className:"device-explorer-header-value",children:[e.jsx("div",{className:`device-explorer-header__device-state ready ${s&&"selected"}`,onClick:()=>this.setFilter({state:{...this.state.filter.state,ready:!this.state.filter.state.ready}}),children:"Ready"}),e.jsx("div",{className:`device-explorer-header__device-state busy ${c&&"selected"}`,onClick:()=>this.setFilter({state:{...this.state.filter.state,busy:!this.state.filter.state.busy}}),children:"Busy"}),e.jsx("div",{className:`device-explorer-header__device-state offline ${u&&"selected"}`,onClick:()=>this.setFilter({state:{...this.state.filter.state,offline:!this.state.filter.state.offline}}),children:"Offline"})]})}render(){const s=this.getFilteredDevice(),{udid:c}=this.props.params,u=c?this.state.devices.find(p=>p.udid===c):null;return e.jsxs("div",{className:"device-explorer-container",children:[e.jsxs("div",{className:"device-explorer-header-container",children:[e.jsxs("div",{className:"device-explorer-header-left-container",children:[e.jsxs("div",{className:"device-explorer-header-entry",children:[e.jsx("div",{className:"device-explorer-header-entry-header",children:"Platform"}),this.getPlatformFilterComponent()]}),e.jsxs("div",{className:"device-explorer-header-entry",children:[e.jsx("div",{className:"device-explorer-header-entry-header",children:"Device state"}),this.getDeviceStateFilterComponent()]}),e.jsxs("div",{className:"device-explorer-header-entry search-entry",children:[e.jsx("div",{className:"device-explorer-header-entry-header",children:"Search by name or udid"}),e.jsx("div",{className:"device-explorer-header-value",children:e.jsxs("div",{className:"device-explorer-search-wrapper",children:[e.jsx(es,{size:16,color:"#94a3b8",className:"device-explorer-search-icon"}),e.jsx("input",{type:"text",className:"device-explorer-header-text-filter",placeholder:"Search devices...",onChange:p=>{this.setState({filter:{...this.state.filter,name:p.target.value}})}})]})})]})]}),e.jsx("div",{className:"device-explorer-header-filter-count",children:e.jsxs(Me,{variant:"secondary",children:[e.jsx("span",{className:"font-bold",children:s.length})," of"," ",e.jsx("span",{className:"font-bold",children:this.state.devices.length})," ",this.state.devices.length===1?"device":"devices"]})}),e.jsxs("div",{className:"device-explorer-header-right-container",children:[this.state.queueSummary&&this.state.pendingSessionsCount>0&&e.jsxs(Me,{variant:"secondary",className:"mr-2",children:[e.jsx("span",{className:"font-bold",children:"Queue Insights:"})," ",Object.entries(this.state.queueSummary.byPlatform).map(([p,t])=>e.jsxs("span",{className:"ml-1",children:[p==="any"?"Mixed":p.toUpperCase(),":"," ",Math.ceil(t.avgDurationMs/6e4),"m ETA"]},p))]}),e.jsxs(Me,{variant:"success",children:[e.jsx("span",{className:"font-bold",children:this.state.activeSessionsCount})," Active session",this.state.activeSessionsCount!==1?"s":""]}),e.jsxs(Me,{variant:"warning",children:[e.jsx("span",{className:"font-bold",children:this.state.pendingSessionsCount})," Pending session",this.state.pendingSessionsCount!==1?"s":""]}),e.jsxs(Ge,{size:"sm",variant:"default",onClick:()=>this.fetchDevices(),children:[e.jsx(ss,{size:14,color:"currentColor",className:"mr-1"}),"Refresh"]})]})]}),s.length>0?e.jsx(Et,{devices:s,reloadDevices:()=>this.fetchDevices()}):e.jsxs("div",{className:"device-explorer-empty stagger-1",children:[e.jsx("div",{className:"device-explorer-empty-icon",children:e.jsx(Je,{size:32})}),this.state.devices.length===0?e.jsxs(e.Fragment,{children:[e.jsx("h3",{className:"brand-font",children:"Global Device Registry Empty"}),e.jsx("p",{children:"Xenon hasn't detected any active device nodes in your infrastructure. Ensure your device farm is connected and heartbeat signals are active."}),e.jsxs(Ge,{variant:"default",onClick:()=>this.fetchDevices(),children:[e.jsx(ss,{size:14,className:"mr-2"}),"Manual Sync"]})]}):e.jsxs(e.Fragment,{children:[e.jsx("h3",{className:"brand-font",children:"No Devices Found"}),e.jsx("p",{children:"Deployment configuration mismatch. Adjust your platform or state filters to find the appropriate testing target."}),e.jsx(Ge,{variant:"outline",onClick:()=>this.setState({filter:ms}),children:"Reset All Filters"})]})]}),u&&e.jsx("div",{className:"device-control-modal-overlay",children:e.jsx("div",{className:"device-control-modal",children:e.jsx(Pt,{device:u,onClose:()=>this.props.navigate("/devices")})})})]})}}function si(){const n=vs(),s=Qe(),{on:c}=As();return e.jsx(Bt,{params:n,navigate:s,onSocketEvent:c})}export{Bt as DeviceExplorer,si as default};
@@ -1,4 +1,4 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/device-explorer-CajM63OJ.js","assets/useSocket-Dxsqae2a.js","assets/index-C1DBaoSh.js","assets/clock-DcdeWBPr.js","assets/plus-BBwlIevt.js","assets/button-CvLaGFYj.js","assets/badge-CSvl5xIU.js","assets/badge-B1nKs8zj.css","assets/button-CJlKn4PZ.css","assets/mouse-pointer-2-Cz76SHFb.js","assets/zap-DovP6iow.js","assets/lock-B23ibZmo.js","assets/trash-2-DQpvzJec.js","assets/device-explorer-CxdUAoTL.css","assets/session-dashboard-HPDtwPOZ.js","assets/cpu-DiSoXT9n.js","assets/session-dashboard-C2k7FFv_.css","assets/apps-CRMrI4_p.js","assets/apps-CcM77dgg.css","assets/webhook-settings-Cp-B4Nrw.js","assets/webhook-settings-CDPgsgkb.css","assets/settings-DrZsZwdc.js","assets/Layouts-7IT8aFLI.js","assets/Layouts-DPMls9vh.css","assets/calendar-6w-D6Oaw.js","assets/ai-settings-BbnfgdEx.js","assets/maintenance-settings-CirzA6yG.js"])))=>i.map(i=>d[i]);
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/device-explorer-C3LtXLHY.js","assets/useSocket-BGEh-0N6.js","assets/index-C1DBaoSh.js","assets/clock-BWbrY15X.js","assets/plus-CspDy7t8.js","assets/button-Dj-mubV7.js","assets/badge-BAasruTp.js","assets/badge-B1nKs8zj.css","assets/button-CJlKn4PZ.css","assets/mouse-pointer-2--4SDXR63.js","assets/zap-O1qTOCtS.js","assets/lock-B7hcjD2m.js","assets/trash-2-CVL2-wTB.js","assets/device-explorer-CxdUAoTL.css","assets/session-dashboard-C5KwBUZv.js","assets/cpu-RQ95hEeI.js","assets/session-dashboard-C2k7FFv_.css","assets/apps-BDRhNo4o.js","assets/apps-CcM77dgg.css","assets/webhook-settings-BEvfRZOy.js","assets/webhook-settings-CDPgsgkb.css","assets/settings-DRq6ku53.js","assets/Layouts-DDyaq0x7.js","assets/Layouts-DPMls9vh.css","assets/calendar-BymTqn8p.js","assets/ai-settings-C6IKGmmk.js","assets/maintenance-settings-75V2i60m.js"])))=>i.map(i=>d[i]);
2
2
  function Ec(e,t){for(var n=0;n<t.length;n++){const r=t[n];if(typeof r!="string"&&!Array.isArray(r)){for(const l in r)if(l!=="default"&&!(l in e)){const o=Object.getOwnPropertyDescriptor(r,l);o&&Object.defineProperty(e,l,o.get?o:{enumerable:!0,get:()=>r[l]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const l of document.querySelectorAll('link[rel="modulepreload"]'))r(l);new MutationObserver(l=>{for(const o of l)if(o.type==="childList")for(const i of o.addedNodes)i.tagName==="LINK"&&i.rel==="modulepreload"&&r(i)}).observe(document,{childList:!0,subtree:!0});function n(l){const o={};return l.integrity&&(o.integrity=l.integrity),l.referrerPolicy&&(o.referrerPolicy=l.referrerPolicy),l.crossOrigin==="use-credentials"?o.credentials="include":l.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function r(l){if(l.ep)return;l.ep=!0;const o=n(l);fetch(l.href,o)}})();function kc(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var ss={exports:{}},Zn={};/*
3
3
  object-assign
4
4
  (c) Sindre Sorhus
@@ -171,4 +171,4 @@ Add a <Suspense fallback=...> component higher in the tree to provide a loading
171
171
  *
172
172
  * This source code is licensed under the ISC license.
173
173
  * See the LICENSE file in the root directory of this source tree.
174
- */const ch=[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]],fh=q("x",ch),dh=[{id:"devices",label:"Devices",icon:v.jsx(uh,{size:18,color:"currentColor"}),path:"/devices",enabled:!0},{id:"builds",label:"Builds",icon:v.jsx(Zp,{size:18,color:"currentColor"}),path:"/builds",enabled:!0},{id:"apps",label:"Apps",icon:v.jsx(Dp,{size:18,color:"currentColor"}),path:"/apps",enabled:!0},{id:"notifications",label:"Notifications",icon:v.jsx(Up,{size:18,color:"currentColor"}),path:"/notifications",enabled:!0},{id:"settings",label:"Settings",icon:v.jsx(yc,{size:18,color:"currentColor"}),path:"/settings",enabled:!1}],gc=()=>dh.filter(e=>e.enabled),ph=()=>{const e=Ti();or(),gc();const[t,n]=x.useState(!1),r=x.useRef(null);return x.useEffect(()=>{const l=o=>{r.current&&!r.current.contains(o.target)&&n(!1)};return document.addEventListener("mousedown",l),()=>document.removeEventListener("mousedown",l)},[]),v.jsxs("div",{className:"header-container",children:[v.jsx("div",{className:"header-left",children:v.jsx("div",{className:"header-logo-container",onClick:()=>e("/"),children:v.jsx("img",{src:"logo.svg",alt:"Xenon Logo",className:"header-logo-image"})})}),v.jsxs("div",{className:"header-right",children:[v.jsx("div",{className:"header-actions",children:v.jsxs("div",{className:"header-status-pill",children:[v.jsx("div",{className:"status-dot"}),v.jsx("span",{children:"System Online"})]})}),v.jsxs("div",{className:"profile-dropdown-container",ref:r,children:[v.jsxs("button",{className:`profile-trigger ${t?"open":""}`,onClick:()=>n(!t),children:[v.jsx("div",{className:"avatar-preview",children:v.jsx(oh,{size:16})}),v.jsxs("div",{className:"profile-info-compact",children:[v.jsx("span",{className:"profile-name",children:"Administrator"}),v.jsx("span",{className:"profile-role",children:"Root Node"})]}),v.jsx(Hp,{size:14,className:`chevron-icon ${t?"rotate":""}`})]}),t&&v.jsxs("div",{className:"profile-dropdown animate-slide-up",children:[v.jsxs("div",{className:"dropdown-group",children:[v.jsxs("div",{className:"dropdown-section-header",children:[v.jsx(mc,{size:12}),v.jsx("span",{children:"Workspace Context"})]}),v.jsxs("div",{className:"dropdown-context-item",children:[v.jsx("p",{className:"context-label",children:"Current Registry"}),v.jsx("p",{className:"context-value",children:"Xenon Default Registry"})]}),v.jsxs("div",{className:"dropdown-context-item",children:[v.jsx("p",{className:"context-label",children:"Active Node"}),v.jsx("p",{className:"context-value",children:"Root Node • Primary"})]})]}),v.jsx("div",{className:"dropdown-divider"}),v.jsxs("div",{className:"dropdown-system-info",children:[v.jsxs("div",{className:"status-indicator",children:[v.jsx("div",{className:"status-dot online"}),v.jsx("span",{children:"Node: Stable"})]}),v.jsx("span",{className:"version-label",children:"v1.2.4-stable"})]})]})]})]})]})},hh="modulepreload",mh=function(e){return"/xenon/"+e},is={},kt=function(t,n,r){let l=Promise.resolve();if(n&&n.length>0){document.getElementsByTagName("link");const i=document.querySelector("meta[property=csp-nonce]"),u=(i==null?void 0:i.nonce)||(i==null?void 0:i.getAttribute("nonce"));l=Promise.allSettled(n.map(s=>{if(s=mh(s),s in is)return;is[s]=!0;const f=s.endsWith(".css"),m=f?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${s}"]${m}`))return;const g=document.createElement("link");if(g.rel=f?"stylesheet":hh,f||(g.as="script"),g.crossOrigin="",g.href=s,u&&g.setAttribute("nonce",u),document.head.appendChild(g),f)return new Promise((p,E)=>{g.addEventListener("load",p),g.addEventListener("error",()=>E(new Error(`Unable to preload CSS for ${s}`)))})}))}function o(i){const u=new Event("vite:preloadError",{cancelable:!0});if(u.payload=i,window.dispatchEvent(u),!u.defaultPrevented)throw i}return l.then(i=>{for(const u of i||[])u.status==="rejected"&&o(u.reason);return t().catch(o)})};class vh extends x.Component{constructor(){super(...arguments),this.state={hasError:!1},this.handleReset=()=>{this.setState({hasError:!1}),window.location.reload()}}static getDerivedStateFromError(t){return{hasError:!0,error:t}}componentDidCatch(t,n){console.error("Uncaught error:",t,n)}render(){return this.state.hasError?this.props.fallback||v.jsxs("div",{className:"error-boundary-container",style:{padding:"4rem 2rem",textAlign:"center",display:"flex",flexDirection:"column",alignItems:"center",gap:"1.5rem",color:"var(--text-main)",background:"var(--bg-main)",minHeight:"100vh"},children:[v.jsx("div",{style:{color:"var(--accent-red)",filter:"drop-shadow(0 0 10px rgba(239, 68, 68, 0.3))"},children:v.jsx(ah,{size:64})}),v.jsx("h2",{style:{fontSize:"2rem",fontWeight:700,margin:0},children:"Component Exception Detected"}),v.jsx("p",{style:{color:"var(--text-muted)",maxWidth:"500px",lineHeight:1.6},children:"An unexpected error occurred while rendering this section. Xenon's isolation engine has contained the fault to prevent a total system crash."}),this.state.error&&v.jsx("pre",{style:{background:"rgba(0,0,0,0.3)",padding:"1rem",borderRadius:"8px",fontSize:"0.8rem",color:"var(--accent-red)",maxWidth:"80%",overflowX:"auto"},children:this.state.error.message}),v.jsxs("button",{onClick:this.handleReset,style:{background:"var(--primary)",color:"var(--secondary)",border:"none",padding:"0.75rem 2rem",borderRadius:"8px",fontWeight:700,cursor:"pointer",display:"flex",alignItems:"center",gap:"0.5rem",transition:"all 0.2s"},onMouseOver:t=>t.currentTarget.style.transform="translateY(-2px)",onMouseOut:t=>t.currentTarget.style.transform="translateY(0)",children:[v.jsx(vc,{size:18}),"Reload Application"]})]}):this.props.children}}const us=x.lazy(()=>kt(()=>import("./device-explorer-CajM63OJ.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13]))),yh=x.lazy(()=>kt(()=>import("./session-dashboard-HPDtwPOZ.js"),__vite__mapDeps([14,1,2,6,7,3,15,16]))),gh=x.lazy(()=>kt(()=>import("./apps-CRMrI4_p.js"),__vite__mapDeps([17,2,6,7,5,8,10,12,18]))),wh=x.lazy(()=>kt(()=>import("./webhook-settings-Cp-B4Nrw.js"),__vite__mapDeps([19,2,12,10,4,20])).then(e=>({default:e.WebhookSettings}))),xh=x.lazy(()=>kt(()=>import("./settings-DrZsZwdc.js"),__vite__mapDeps([21,2,22,23,3,24,9])).then(e=>({default:e.Settings}))),Eh=x.lazy(()=>kt(()=>import("./ai-settings-BbnfgdEx.js"),__vite__mapDeps([25,2,22,23,15,11])).then(e=>({default:e.AISettings}))),kh=x.lazy(()=>kt(()=>import("./maintenance-settings-CirzA6yG.js"),__vite__mapDeps([26,2,22,23,12,24])).then(e=>({default:e.MaintenanceSettings}))),Sh=()=>v.jsxs("div",{className:"settings-loading",style:{height:"calc(100vh - 72px)"},children:[v.jsx(vc,{className:"animate-spin",size:32}),v.jsx("span",{children:"Hydrating View..."})]}),_h=()=>v.jsx(vh,{children:v.jsx(x.Suspense,{fallback:v.jsx(Sh,{}),children:v.jsxs(Np,{children:[v.jsx(xe,{path:"/",element:v.jsx(ts,{to:"/devices",replace:!0})}),v.jsx(xe,{path:"/devices",element:v.jsx("div",{className:"app-body-container devices-view",children:v.jsx(us,{})})}),v.jsx(xe,{path:"/devices/:udid/control/:tab?",element:v.jsx("div",{className:"app-body-container devices-view",children:v.jsx(us,{})})}),v.jsx(xe,{path:"/apps",element:v.jsx("div",{className:"app-body-container apps-view",children:v.jsx(gh,{})})}),v.jsx(xe,{path:"/builds",element:v.jsx("div",{className:"app-body-container sessions-view",children:v.jsx(yh,{})})}),v.jsx(xe,{path:"/notifications",element:v.jsx("div",{className:"app-body-container settings-view",style:{height:"calc(100vh - 72px)",overflow:"hidden",display:"flex",flexDirection:"column"},children:v.jsx(wh,{})})}),v.jsx(xe,{path:"/settings",element:v.jsx("div",{className:"app-body-container settings-view",children:v.jsx(xh,{})})}),v.jsx(xe,{path:"/ai-settings",element:v.jsx("div",{className:"app-body-container settings-view",children:v.jsx(Eh,{})})}),v.jsx(xe,{path:"/maintenance",element:v.jsx("div",{className:"app-body-container settings-view",children:v.jsx(kh,{})})}),v.jsx(xe,{path:"*",element:v.jsx(ts,{to:"/devices",replace:!0})})]})})}),wc=x.createContext(void 0),Lh=()=>{const e=x.useContext(wc);if(!e)throw new Error("useToast must be used within a ToastProvider");return e},Ch=({children:e})=>{const[t,n]=x.useState([]),r=x.useCallback(o=>{n(i=>i.filter(u=>u.id!==o))},[]),l=x.useCallback((o,i="info",u=4e3)=>{const s=Math.random().toString(36).substring(2,9);return n(f=>[...f,{id:s,message:o,type:i,duration:u}]),i!=="loading"&&u>0&&setTimeout(()=>{r(s)},u),s},[r]);return v.jsxs(wc.Provider,{value:{toast:l,removeToast:r},children:[e,v.jsx("div",{className:"toast-container","aria-live":"polite","aria-atomic":"true",role:"status",children:t.map(o=>v.jsxs("div",{className:`toast-item toast-${o.type} animate-slide-in`,children:[v.jsxs("div",{className:"toast-icon",children:[o.type==="success"&&v.jsx(Kp,{size:18}),o.type==="error"&&v.jsx(Yp,{size:18}),o.type==="info"&&v.jsx(mc,{size:18}),o.type==="loading"&&v.jsx(bp,{size:18,className:"animate-spin"})]}),v.jsx("div",{className:"toast-message",children:o.message}),v.jsx("button",{className:"toast-close",onClick:()=>r(o.id),"aria-label":`Close ${o.type} notification`,children:v.jsx(fh,{size:14})})]},o.id))})]})},vn=({icon:e,label:t,path:n,active:r,onClick:l})=>v.jsxs("div",{className:"sidebar-item-wrapper group",onClick:l,children:[r&&v.jsx("div",{className:"sidebar-active-indicator"}),v.jsx("div",{className:`sidebar-icon-container ${r?"active":""}`,children:e}),v.jsx("div",{className:"sidebar-tooltip",children:t})]}),Nh=()=>{const e=Ti(),t=or(),n=gc(),r=l=>t.pathname===l;return v.jsxs("aside",{className:"app-sidebar",children:[v.jsx("div",{className:"sidebar-nav",children:n.map(l=>v.jsx(vn,{icon:l.icon,label:l.label,path:l.path,active:r(l.path),onClick:()=>e(l.path)},l.id))}),v.jsxs("div",{className:"sidebar-footer",children:[v.jsx(vn,{icon:v.jsx(yc,{size:18}),label:"Settings",path:"/settings",active:r("/settings"),onClick:()=>e("/settings")}),v.jsx(vn,{icon:v.jsx(Vp,{size:18}),label:"AI Engine",path:"/ai-settings",active:r("/ai-settings"),onClick:()=>e("/ai-settings")}),v.jsx(vn,{icon:v.jsx(rh,{size:18}),label:"Maintenance",path:"/maintenance",active:r("/maintenance"),onClick:()=>e("/maintenance")}),v.jsx(vn,{icon:v.jsx(Bp,{size:18}),label:"API Docs",path:"/xenon/api-docs",active:!1,onClick:()=>window.open(window.location.origin+"/xenon/api-docs","_blank")})]})]})};function Ph(){return v.jsx(Ch,{children:v.jsx(Lp,{basename:"/xenon",children:v.jsxs("div",{className:"app-layout",children:[v.jsx(ph,{}),v.jsxs("div",{className:"app-main-container",children:[v.jsx(Nh,{}),v.jsx("main",{className:"app-content",children:v.jsx(_h,{})})]})]})})})}Id.render(v.jsx(x.StrictMode,{children:v.jsx(Ph,{})}),document.getElementById("root"));export{Vp as B,Yp as C,mc as I,bp as L,Oc as R,uh as S,ah as T,fh as X,Id as a,Ti as b,q as c,rh as d,Hp as e,jh as f,vc as g,kc as h,Kp as i,v as j,Up as k,oh as l,x as r,Lh as u};
174
+ */const ch=[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]],fh=q("x",ch),dh=[{id:"devices",label:"Devices",icon:v.jsx(uh,{size:18,color:"currentColor"}),path:"/devices",enabled:!0},{id:"builds",label:"Builds",icon:v.jsx(Zp,{size:18,color:"currentColor"}),path:"/builds",enabled:!0},{id:"apps",label:"Apps",icon:v.jsx(Dp,{size:18,color:"currentColor"}),path:"/apps",enabled:!0},{id:"notifications",label:"Notifications",icon:v.jsx(Up,{size:18,color:"currentColor"}),path:"/notifications",enabled:!0},{id:"settings",label:"Settings",icon:v.jsx(yc,{size:18,color:"currentColor"}),path:"/settings",enabled:!1}],gc=()=>dh.filter(e=>e.enabled),ph=()=>{const e=Ti();or(),gc();const[t,n]=x.useState(!1),r=x.useRef(null);return x.useEffect(()=>{const l=o=>{r.current&&!r.current.contains(o.target)&&n(!1)};return document.addEventListener("mousedown",l),()=>document.removeEventListener("mousedown",l)},[]),v.jsxs("div",{className:"header-container",children:[v.jsx("div",{className:"header-left",children:v.jsx("div",{className:"header-logo-container",onClick:()=>e("/"),children:v.jsx("img",{src:"logo.svg",alt:"Xenon Logo",className:"header-logo-image"})})}),v.jsxs("div",{className:"header-right",children:[v.jsx("div",{className:"header-actions",children:v.jsxs("div",{className:"header-status-pill",children:[v.jsx("div",{className:"status-dot"}),v.jsx("span",{children:"System Online"})]})}),v.jsxs("div",{className:"profile-dropdown-container",ref:r,children:[v.jsxs("button",{className:`profile-trigger ${t?"open":""}`,onClick:()=>n(!t),children:[v.jsx("div",{className:"avatar-preview",children:v.jsx(oh,{size:16})}),v.jsxs("div",{className:"profile-info-compact",children:[v.jsx("span",{className:"profile-name",children:"Administrator"}),v.jsx("span",{className:"profile-role",children:"Root Node"})]}),v.jsx(Hp,{size:14,className:`chevron-icon ${t?"rotate":""}`})]}),t&&v.jsxs("div",{className:"profile-dropdown animate-slide-up",children:[v.jsxs("div",{className:"dropdown-group",children:[v.jsxs("div",{className:"dropdown-section-header",children:[v.jsx(mc,{size:12}),v.jsx("span",{children:"Workspace Context"})]}),v.jsxs("div",{className:"dropdown-context-item",children:[v.jsx("p",{className:"context-label",children:"Current Registry"}),v.jsx("p",{className:"context-value",children:"Xenon Default Registry"})]}),v.jsxs("div",{className:"dropdown-context-item",children:[v.jsx("p",{className:"context-label",children:"Active Node"}),v.jsx("p",{className:"context-value",children:"Root Node • Primary"})]})]}),v.jsx("div",{className:"dropdown-divider"}),v.jsxs("div",{className:"dropdown-system-info",children:[v.jsxs("div",{className:"status-indicator",children:[v.jsx("div",{className:"status-dot online"}),v.jsx("span",{children:"Node: Stable"})]}),v.jsx("span",{className:"version-label",children:"v1.2.4-stable"})]})]})]})]})]})},hh="modulepreload",mh=function(e){return"/xenon/"+e},is={},kt=function(t,n,r){let l=Promise.resolve();if(n&&n.length>0){document.getElementsByTagName("link");const i=document.querySelector("meta[property=csp-nonce]"),u=(i==null?void 0:i.nonce)||(i==null?void 0:i.getAttribute("nonce"));l=Promise.allSettled(n.map(s=>{if(s=mh(s),s in is)return;is[s]=!0;const f=s.endsWith(".css"),m=f?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${s}"]${m}`))return;const g=document.createElement("link");if(g.rel=f?"stylesheet":hh,f||(g.as="script"),g.crossOrigin="",g.href=s,u&&g.setAttribute("nonce",u),document.head.appendChild(g),f)return new Promise((p,E)=>{g.addEventListener("load",p),g.addEventListener("error",()=>E(new Error(`Unable to preload CSS for ${s}`)))})}))}function o(i){const u=new Event("vite:preloadError",{cancelable:!0});if(u.payload=i,window.dispatchEvent(u),!u.defaultPrevented)throw i}return l.then(i=>{for(const u of i||[])u.status==="rejected"&&o(u.reason);return t().catch(o)})};class vh extends x.Component{constructor(){super(...arguments),this.state={hasError:!1},this.handleReset=()=>{this.setState({hasError:!1}),window.location.reload()}}static getDerivedStateFromError(t){return{hasError:!0,error:t}}componentDidCatch(t,n){console.error("Uncaught error:",t,n)}render(){return this.state.hasError?this.props.fallback||v.jsxs("div",{className:"error-boundary-container",style:{padding:"4rem 2rem",textAlign:"center",display:"flex",flexDirection:"column",alignItems:"center",gap:"1.5rem",color:"var(--text-main)",background:"var(--bg-main)",minHeight:"100vh"},children:[v.jsx("div",{style:{color:"var(--accent-red)",filter:"drop-shadow(0 0 10px rgba(239, 68, 68, 0.3))"},children:v.jsx(ah,{size:64})}),v.jsx("h2",{style:{fontSize:"2rem",fontWeight:700,margin:0},children:"Component Exception Detected"}),v.jsx("p",{style:{color:"var(--text-muted)",maxWidth:"500px",lineHeight:1.6},children:"An unexpected error occurred while rendering this section. Xenon's isolation engine has contained the fault to prevent a total system crash."}),this.state.error&&v.jsx("pre",{style:{background:"rgba(0,0,0,0.3)",padding:"1rem",borderRadius:"8px",fontSize:"0.8rem",color:"var(--accent-red)",maxWidth:"80%",overflowX:"auto"},children:this.state.error.message}),v.jsxs("button",{onClick:this.handleReset,style:{background:"var(--primary)",color:"var(--secondary)",border:"none",padding:"0.75rem 2rem",borderRadius:"8px",fontWeight:700,cursor:"pointer",display:"flex",alignItems:"center",gap:"0.5rem",transition:"all 0.2s"},onMouseOver:t=>t.currentTarget.style.transform="translateY(-2px)",onMouseOut:t=>t.currentTarget.style.transform="translateY(0)",children:[v.jsx(vc,{size:18}),"Reload Application"]})]}):this.props.children}}const us=x.lazy(()=>kt(()=>import("./device-explorer-C3LtXLHY.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13]))),yh=x.lazy(()=>kt(()=>import("./session-dashboard-C5KwBUZv.js"),__vite__mapDeps([14,1,2,6,7,3,15,16]))),gh=x.lazy(()=>kt(()=>import("./apps-BDRhNo4o.js"),__vite__mapDeps([17,2,6,7,5,8,10,12,18]))),wh=x.lazy(()=>kt(()=>import("./webhook-settings-BEvfRZOy.js"),__vite__mapDeps([19,2,12,10,4,20])).then(e=>({default:e.WebhookSettings}))),xh=x.lazy(()=>kt(()=>import("./settings-DRq6ku53.js"),__vite__mapDeps([21,2,22,23,3,24,9])).then(e=>({default:e.Settings}))),Eh=x.lazy(()=>kt(()=>import("./ai-settings-C6IKGmmk.js"),__vite__mapDeps([25,2,22,23,15,11])).then(e=>({default:e.AISettings}))),kh=x.lazy(()=>kt(()=>import("./maintenance-settings-75V2i60m.js"),__vite__mapDeps([26,2,22,23,12,24])).then(e=>({default:e.MaintenanceSettings}))),Sh=()=>v.jsxs("div",{className:"settings-loading",style:{height:"calc(100vh - 72px)"},children:[v.jsx(vc,{className:"animate-spin",size:32}),v.jsx("span",{children:"Hydrating View..."})]}),_h=()=>v.jsx(vh,{children:v.jsx(x.Suspense,{fallback:v.jsx(Sh,{}),children:v.jsxs(Np,{children:[v.jsx(xe,{path:"/",element:v.jsx(ts,{to:"/devices",replace:!0})}),v.jsx(xe,{path:"/devices",element:v.jsx("div",{className:"app-body-container devices-view",children:v.jsx(us,{})})}),v.jsx(xe,{path:"/devices/:udid/control/:tab?",element:v.jsx("div",{className:"app-body-container devices-view",children:v.jsx(us,{})})}),v.jsx(xe,{path:"/apps",element:v.jsx("div",{className:"app-body-container apps-view",children:v.jsx(gh,{})})}),v.jsx(xe,{path:"/builds",element:v.jsx("div",{className:"app-body-container sessions-view",children:v.jsx(yh,{})})}),v.jsx(xe,{path:"/notifications",element:v.jsx("div",{className:"app-body-container settings-view",style:{height:"calc(100vh - 72px)",overflow:"hidden",display:"flex",flexDirection:"column"},children:v.jsx(wh,{})})}),v.jsx(xe,{path:"/settings",element:v.jsx("div",{className:"app-body-container settings-view",children:v.jsx(xh,{})})}),v.jsx(xe,{path:"/ai-settings",element:v.jsx("div",{className:"app-body-container settings-view",children:v.jsx(Eh,{})})}),v.jsx(xe,{path:"/maintenance",element:v.jsx("div",{className:"app-body-container settings-view",children:v.jsx(kh,{})})}),v.jsx(xe,{path:"*",element:v.jsx(ts,{to:"/devices",replace:!0})})]})})}),wc=x.createContext(void 0),Lh=()=>{const e=x.useContext(wc);if(!e)throw new Error("useToast must be used within a ToastProvider");return e},Ch=({children:e})=>{const[t,n]=x.useState([]),r=x.useCallback(o=>{n(i=>i.filter(u=>u.id!==o))},[]),l=x.useCallback((o,i="info",u=4e3)=>{const s=Math.random().toString(36).substring(2,9);return n(f=>[...f,{id:s,message:o,type:i,duration:u}]),i!=="loading"&&u>0&&setTimeout(()=>{r(s)},u),s},[r]);return v.jsxs(wc.Provider,{value:{toast:l,removeToast:r},children:[e,v.jsx("div",{className:"toast-container","aria-live":"polite","aria-atomic":"true",role:"status",children:t.map(o=>v.jsxs("div",{className:`toast-item toast-${o.type} animate-slide-in`,children:[v.jsxs("div",{className:"toast-icon",children:[o.type==="success"&&v.jsx(Kp,{size:18}),o.type==="error"&&v.jsx(Yp,{size:18}),o.type==="info"&&v.jsx(mc,{size:18}),o.type==="loading"&&v.jsx(bp,{size:18,className:"animate-spin"})]}),v.jsx("div",{className:"toast-message",children:o.message}),v.jsx("button",{className:"toast-close",onClick:()=>r(o.id),"aria-label":`Close ${o.type} notification`,children:v.jsx(fh,{size:14})})]},o.id))})]})},vn=({icon:e,label:t,path:n,active:r,onClick:l})=>v.jsxs("div",{className:"sidebar-item-wrapper group",onClick:l,children:[r&&v.jsx("div",{className:"sidebar-active-indicator"}),v.jsx("div",{className:`sidebar-icon-container ${r?"active":""}`,children:e}),v.jsx("div",{className:"sidebar-tooltip",children:t})]}),Nh=()=>{const e=Ti(),t=or(),n=gc(),r=l=>t.pathname===l;return v.jsxs("aside",{className:"app-sidebar",children:[v.jsx("div",{className:"sidebar-nav",children:n.map(l=>v.jsx(vn,{icon:l.icon,label:l.label,path:l.path,active:r(l.path),onClick:()=>e(l.path)},l.id))}),v.jsxs("div",{className:"sidebar-footer",children:[v.jsx(vn,{icon:v.jsx(yc,{size:18}),label:"Settings",path:"/settings",active:r("/settings"),onClick:()=>e("/settings")}),v.jsx(vn,{icon:v.jsx(Vp,{size:18}),label:"AI Engine",path:"/ai-settings",active:r("/ai-settings"),onClick:()=>e("/ai-settings")}),v.jsx(vn,{icon:v.jsx(rh,{size:18}),label:"Maintenance",path:"/maintenance",active:r("/maintenance"),onClick:()=>e("/maintenance")}),v.jsx(vn,{icon:v.jsx(Bp,{size:18}),label:"API Docs",path:"/xenon/api-docs",active:!1,onClick:()=>window.open(window.location.origin+"/xenon/api-docs","_blank")})]})]})};function Ph(){return v.jsx(Ch,{children:v.jsx(Lp,{basename:"/xenon",children:v.jsxs("div",{className:"app-layout",children:[v.jsx(ph,{}),v.jsxs("div",{className:"app-main-container",children:[v.jsx(Nh,{}),v.jsx("main",{className:"app-content",children:v.jsx(_h,{})})]})]})})})}Id.render(v.jsx(x.StrictMode,{children:v.jsx(Ph,{})}),document.getElementById("root"));export{Vp as B,Yp as C,mc as I,bp as L,Oc as R,uh as S,ah as T,fh as X,Id as a,Ti as b,q as c,rh as d,Hp as e,jh as f,vc as g,kc as h,Kp as i,v as j,Up as k,oh as l,x as r,Lh as u};
@@ -1,4 +1,4 @@
1
- import{c}from"./index-ByQwMN5T.js";/**
1
+ import{c}from"./index-CvgdoCl7.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as x,r as n,j as e,g as j,l as v,d as b,I as y,i as C,T as f}from"./index-ByQwMN5T.js";import{X as u}from"./index-C1DBaoSh.js";import{A as N}from"./Layouts-7IT8aFLI.js";import{T as S}from"./trash-2-DQpvzJec.js";import{C as M}from"./calendar-6w-D6Oaw.js";/**
1
+ import{c as x,r as n,j as e,g as j,l as v,d as b,I as y,i as C,T as f}from"./index-CvgdoCl7.js";import{X as u}from"./index-C1DBaoSh.js";import{A as N}from"./Layouts-DDyaq0x7.js";import{T as S}from"./trash-2-CVL2-wTB.js";import{C as M}from"./calendar-BymTqn8p.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-ByQwMN5T.js";/**
1
+ import{c as e}from"./index-CvgdoCl7.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-ByQwMN5T.js";/**
1
+ import{c as e}from"./index-CvgdoCl7.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as Me,h as tn,R as U,r as ve,j as s,i as qr,C as Wr,e as Xr,B as ut,S as Qr}from"./index-ByQwMN5T.js";import{H as Kr,a as Yr,p as er,u as Gr,C as nr}from"./useSocket-Dxsqae2a.js";import{X as ce}from"./index-C1DBaoSh.js";import{c as Jr,D as tr,S as ct,B as De}from"./badge-CSvl5xIU.js";import{C as Gn}from"./clock-DcdeWBPr.js";import{C as Zr}from"./cpu-DiSoXT9n.js";/**
1
+ import{c as Me,h as tn,R as U,r as ve,j as s,i as qr,C as Wr,e as Xr,B as ut,S as Qr}from"./index-CvgdoCl7.js";import{H as Kr,a as Yr,p as er,u as Gr,C as nr}from"./useSocket-BGEh-0N6.js";import{X as ce}from"./index-C1DBaoSh.js";import{c as Jr,D as tr,S as ct,B as De}from"./badge-BAasruTp.js";import{C as Gn}from"./clock-BWbrY15X.js";import{C as Zr}from"./cpu-RQ95hEeI.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1 +1 @@
1
- import{r as i,j as e,g as j,l as S,B as C,i as y,T as N}from"./index-ByQwMN5T.js";import{X as c}from"./index-C1DBaoSh.js";import{A as b}from"./Layouts-7IT8aFLI.js";import{C as k}from"./clock-DcdeWBPr.js";import{C as I}from"./calendar-6w-D6Oaw.js";import{M}from"./mouse-pointer-2-Cz76SHFb.js";const B=()=>{const[a,t]=i.useState({healthCheckIntervalMs:3e4,healthCheckSchedule:"",enableSelfHealing:!0}),[g,d]=i.useState(!0),[m,h]=i.useState(!1),[l,n]=i.useState(null);i.useEffect(()=>{o()},[]);const o=async()=>{d(!0);try{const s=await c.getGlobalConfig();t({healthCheckIntervalMs:s.healthCheckIntervalMs||3e4,healthCheckSchedule:s.healthCheckSchedule||"",enableSelfHealing:s.enableSelfHealing!==void 0?s.enableSelfHealing:!0})}catch(s){console.error("Failed to load settings",s),n({type:"error",message:"Failed to access infrastructure parameters."})}finally{d(!1)}},u=async(s=a)=>{h(!0),n(null);try{await c.updateGlobalConfig(s),n({type:"success",message:"Infrastructure parameters synchronized across fleet."}),setTimeout(()=>n(null),5e3)}catch(r){console.error("Failed to save settings",r),n({type:"error",message:"Synchronization failed. Check network integrity."})}finally{h(!1)}},v=async()=>{const s={healthCheckIntervalMs:3e4,healthCheckSchedule:"",enableSelfHealing:!0};t(s),await u(s);try{await c.resetMetrics()}catch(r){console.error("Failed to reset metrics",r)}},p=[{label:"Battery Saver (2 AM)",value:"0 2 * * *"},{label:"Standard (Hourly)",value:"0 * * * *"},{label:"Operational Coverage (30m)",value:"*/30 * * * *"},{label:"High Performance (10m)",value:"*/10 * * * *"},{label:"Disable Schedule",value:""}],f=s=>s?s.split(" ").filter(x=>x!=="").length!==5?"Invalid Cron format (needs 5 parts)":s==="0 2 * * *"?"Quiet hours: Daily at 2:00 AM":s==="0 * * * *"?"Standard rotation: Start of every hour":s==="*/30 * * * *"?"Balanced: Every 30 minutes":s==="*/10 * * * *"?"Intensive: Every 10 minutes":`Custom orchestration: ${s}`:"Using Idle Health Frequency (Continuous/Passive mode).";return g?e.jsxs("div",{className:"settings-loading",children:[e.jsx(j,{className:"animate-spin",size:32}),e.jsx("span",{children:"Synchronizing Global Infrastructure..."})]}):e.jsxs("div",{className:"settings-container mesh-gradient-infra",children:[e.jsx("div",{className:"scanline",style:{position:"absolute",inset:0,pointerEvents:"none",opacity:.05,zIndex:1001}}),e.jsxs("div",{className:"settings-header",children:[e.jsxs("div",{className:"settings-title-group",children:[e.jsx(S,{className:"settings-icon infra-icon",size:28}),e.jsx("h2",{children:"Infrastructure Control"})]}),e.jsx("p",{className:"settings-subtitle",children:"Manage core farm parameters, heartbeat frequency, and maintenance orchestrations across the global registry."})]}),e.jsxs("div",{className:"settings-content",children:[e.jsxs("div",{className:"settings-grid",children:[e.jsxs("div",{className:"setting-card stagger-1",children:[e.jsxs("div",{className:"setting-card-header",children:[e.jsx(k,{size:16}),e.jsx("h4",{children:"Idle Health Frequency"})]}),e.jsx("p",{className:"section-description-dense",children:"Frequency of passive health pings when the system is in idle state."}),e.jsx("div",{className:"setting-field",children:e.jsxs("div",{className:"input-group",children:[e.jsx("input",{type:"number",value:a.healthCheckIntervalMs,onChange:s=>t({...a,healthCheckIntervalMs:parseInt(s.target.value)}),min:5e3,step:5e3}),e.jsx("span",{className:"code-font",children:"MS"})]})}),e.jsx("div",{className:"setting-hint-clean",children:"Minimum safe value: 5000ms. Note: This frequency is overridden when a schedule is active."})]}),e.jsxs("div",{className:"setting-card stagger-2",children:[e.jsxs("div",{className:"setting-card-header",children:[e.jsx(I,{size:16}),e.jsx("h4",{children:"Deep Diagnostic Schedule"})]}),e.jsx("p",{className:"section-description-dense",children:"Execute intensive reliability bursts (WDA restarts, Cache purges) using standardized Cron syntax."}),e.jsx("div",{className:"setting-field",children:e.jsx("div",{className:"setting-input-wrapper",children:e.jsx("input",{type:"text",placeholder:"e.g. 0 * * * * (At internal min 0)",value:a.healthCheckSchedule,onChange:s=>t({...a,healthCheckSchedule:s.target.value})})})}),e.jsxs("div",{className:"cron-preview",children:[e.jsx("span",{className:"preview-label",children:"Active Logic:"}),e.jsx("span",{className:"preview-value",children:f(a.healthCheckSchedule)})]}),e.jsxs("div",{className:"cron-presets",children:[e.jsxs("div",{className:"presets-label",children:[e.jsx(M,{size:12}),e.jsx("span",{children:"Intent-Based Presets:"})]}),e.jsx("div",{className:"presets-grid",children:p.map(s=>e.jsx("button",{className:`preset-chip ${a.healthCheckSchedule===s.value?"active":""}`,onClick:()=>t({...a,healthCheckSchedule:s.value}),children:s.label},s.label))})]})]}),e.jsxs("div",{className:"setting-card stagger-3",children:[e.jsxs("div",{className:"setting-card-header",children:[e.jsx(C,{size:16}),e.jsx("h4",{children:"AI Self-Healing"})]}),e.jsx("p",{className:"section-description-dense",children:"Automatically intercept and recover from failing locators using Xenon's 5-tier strategy."}),e.jsxs("div",{className:"toggle-group",children:[e.jsxs("label",{className:"switch",children:[e.jsx("input",{type:"checkbox",checked:a.enableSelfHealing,onChange:s=>t({...a,enableSelfHealing:s.target.checked})}),e.jsx("span",{className:"slider round"})]}),e.jsx("span",{className:"toggle-label",children:a.enableSelfHealing?"ENABLED":"DISABLED"})]}),e.jsx("div",{className:"setting-hint-clean",children:"When enabled, Xenon will attempt to find elements via Fuzzy XML, OCR, Visual AI, and LLM before failing a test."})]})]}),l&&e.jsxs("div",{className:`status-banner ${l.type}`,children:[l.type==="success"?e.jsx(y,{size:18}):e.jsx(N,{size:18}),e.jsx("span",{children:l.message})]})]}),e.jsx(b,{onSave:u,onDiscard:o,onRestoreDefaults:v,isSaving:m,saveLabel:"Save Configuration"})]})};export{B as Settings};
1
+ import{r as i,j as e,g as j,l as S,B as C,i as y,T as N}from"./index-CvgdoCl7.js";import{X as c}from"./index-C1DBaoSh.js";import{A as b}from"./Layouts-DDyaq0x7.js";import{C as k}from"./clock-BWbrY15X.js";import{C as I}from"./calendar-BymTqn8p.js";import{M}from"./mouse-pointer-2--4SDXR63.js";const B=()=>{const[a,t]=i.useState({healthCheckIntervalMs:3e4,healthCheckSchedule:"",enableSelfHealing:!0}),[g,d]=i.useState(!0),[m,h]=i.useState(!1),[l,n]=i.useState(null);i.useEffect(()=>{o()},[]);const o=async()=>{d(!0);try{const s=await c.getGlobalConfig();t({healthCheckIntervalMs:s.healthCheckIntervalMs||3e4,healthCheckSchedule:s.healthCheckSchedule||"",enableSelfHealing:s.enableSelfHealing!==void 0?s.enableSelfHealing:!0})}catch(s){console.error("Failed to load settings",s),n({type:"error",message:"Failed to access infrastructure parameters."})}finally{d(!1)}},u=async(s=a)=>{h(!0),n(null);try{await c.updateGlobalConfig(s),n({type:"success",message:"Infrastructure parameters synchronized across fleet."}),setTimeout(()=>n(null),5e3)}catch(r){console.error("Failed to save settings",r),n({type:"error",message:"Synchronization failed. Check network integrity."})}finally{h(!1)}},v=async()=>{const s={healthCheckIntervalMs:3e4,healthCheckSchedule:"",enableSelfHealing:!0};t(s),await u(s);try{await c.resetMetrics()}catch(r){console.error("Failed to reset metrics",r)}},p=[{label:"Battery Saver (2 AM)",value:"0 2 * * *"},{label:"Standard (Hourly)",value:"0 * * * *"},{label:"Operational Coverage (30m)",value:"*/30 * * * *"},{label:"High Performance (10m)",value:"*/10 * * * *"},{label:"Disable Schedule",value:""}],f=s=>s?s.split(" ").filter(x=>x!=="").length!==5?"Invalid Cron format (needs 5 parts)":s==="0 2 * * *"?"Quiet hours: Daily at 2:00 AM":s==="0 * * * *"?"Standard rotation: Start of every hour":s==="*/30 * * * *"?"Balanced: Every 30 minutes":s==="*/10 * * * *"?"Intensive: Every 10 minutes":`Custom orchestration: ${s}`:"Using Idle Health Frequency (Continuous/Passive mode).";return g?e.jsxs("div",{className:"settings-loading",children:[e.jsx(j,{className:"animate-spin",size:32}),e.jsx("span",{children:"Synchronizing Global Infrastructure..."})]}):e.jsxs("div",{className:"settings-container mesh-gradient-infra",children:[e.jsx("div",{className:"scanline",style:{position:"absolute",inset:0,pointerEvents:"none",opacity:.05,zIndex:1001}}),e.jsxs("div",{className:"settings-header",children:[e.jsxs("div",{className:"settings-title-group",children:[e.jsx(S,{className:"settings-icon infra-icon",size:28}),e.jsx("h2",{children:"Infrastructure Control"})]}),e.jsx("p",{className:"settings-subtitle",children:"Manage core farm parameters, heartbeat frequency, and maintenance orchestrations across the global registry."})]}),e.jsxs("div",{className:"settings-content",children:[e.jsxs("div",{className:"settings-grid",children:[e.jsxs("div",{className:"setting-card stagger-1",children:[e.jsxs("div",{className:"setting-card-header",children:[e.jsx(k,{size:16}),e.jsx("h4",{children:"Idle Health Frequency"})]}),e.jsx("p",{className:"section-description-dense",children:"Frequency of passive health pings when the system is in idle state."}),e.jsx("div",{className:"setting-field",children:e.jsxs("div",{className:"input-group",children:[e.jsx("input",{type:"number",value:a.healthCheckIntervalMs,onChange:s=>t({...a,healthCheckIntervalMs:parseInt(s.target.value)}),min:5e3,step:5e3}),e.jsx("span",{className:"code-font",children:"MS"})]})}),e.jsx("div",{className:"setting-hint-clean",children:"Minimum safe value: 5000ms. Note: This frequency is overridden when a schedule is active."})]}),e.jsxs("div",{className:"setting-card stagger-2",children:[e.jsxs("div",{className:"setting-card-header",children:[e.jsx(I,{size:16}),e.jsx("h4",{children:"Deep Diagnostic Schedule"})]}),e.jsx("p",{className:"section-description-dense",children:"Execute intensive reliability bursts (WDA restarts, Cache purges) using standardized Cron syntax."}),e.jsx("div",{className:"setting-field",children:e.jsx("div",{className:"setting-input-wrapper",children:e.jsx("input",{type:"text",placeholder:"e.g. 0 * * * * (At internal min 0)",value:a.healthCheckSchedule,onChange:s=>t({...a,healthCheckSchedule:s.target.value})})})}),e.jsxs("div",{className:"cron-preview",children:[e.jsx("span",{className:"preview-label",children:"Active Logic:"}),e.jsx("span",{className:"preview-value",children:f(a.healthCheckSchedule)})]}),e.jsxs("div",{className:"cron-presets",children:[e.jsxs("div",{className:"presets-label",children:[e.jsx(M,{size:12}),e.jsx("span",{children:"Intent-Based Presets:"})]}),e.jsx("div",{className:"presets-grid",children:p.map(s=>e.jsx("button",{className:`preset-chip ${a.healthCheckSchedule===s.value?"active":""}`,onClick:()=>t({...a,healthCheckSchedule:s.value}),children:s.label},s.label))})]})]}),e.jsxs("div",{className:"setting-card stagger-3",children:[e.jsxs("div",{className:"setting-card-header",children:[e.jsx(C,{size:16}),e.jsx("h4",{children:"AI Self-Healing"})]}),e.jsx("p",{className:"section-description-dense",children:"Automatically intercept and recover from failing locators using Xenon's 5-tier strategy."}),e.jsxs("div",{className:"toggle-group",children:[e.jsxs("label",{className:"switch",children:[e.jsx("input",{type:"checkbox",checked:a.enableSelfHealing,onChange:s=>t({...a,enableSelfHealing:s.target.checked})}),e.jsx("span",{className:"slider round"})]}),e.jsx("span",{className:"toggle-label",children:a.enableSelfHealing?"ENABLED":"DISABLED"})]}),e.jsx("div",{className:"setting-hint-clean",children:"When enabled, Xenon will attempt to find elements via Fuzzy XML, OCR, Visual AI, and LLM before failing a test."})]})]}),l&&e.jsxs("div",{className:`status-banner ${l.type}`,children:[l.type==="success"?e.jsx(y,{size:18}):e.jsx(N,{size:18}),e.jsx("span",{children:l.message})]})]}),e.jsx(b,{onSave:u,onDiscard:o,onRestoreDefaults:v,isSaving:m,saveLabel:"Save Configuration"})]})};export{B as Settings};
@@ -1,4 +1,4 @@
1
- import{c as a}from"./index-ByQwMN5T.js";/**
1
+ import{c as a}from"./index-CvgdoCl7.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as V,r as E}from"./index-ByQwMN5T.js";/**
1
+ import{c as V,r as E}from"./index-CvgdoCl7.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1 +1 @@
1
- import{r as i,j as e,k,i as A,C as _}from"./index-ByQwMN5T.js";import{X as n}from"./index-C1DBaoSh.js";import{T as g}from"./trash-2-DQpvzJec.js";import{Z as W}from"./zap-DovP6iow.js";import{P as O}from"./plus-BBwlIevt.js";const v=[{id:"device_offline",label:"Device Offline",icon:e.jsx(_,{size:14,className:"text-red-400"})},{id:"device_new",label:"New Device",icon:e.jsx(O,{size:14,className:"text-green-400"})},{id:"session_failed",label:"Session Failed",icon:e.jsx(g,{size:14,className:"text-orange-400"})}],J=()=>{const[x,w]=i.useState([]),[t,p]=i.useState(""),[r,j]=i.useState(["device_offline","session_failed"]),[N,u]=i.useState(!1),[d,o]=i.useState("idle"),[c,b]=i.useState(!1),[f,h]=i.useState("");i.useEffect(()=>{m()},[]);const m=async()=>{try{const s=await n.getWebhookConfigs();w(s||[])}catch(s){console.error("Failed to load webhook configs",s)}},y=async()=>{if(t){u(!0);try{await n.addWebhookConfig(t,r,"slack",f||void 0),p(""),h(""),b(!1),j(["device_offline","session_failed"]),await m()}catch(s){console.error("Failed to add webhook",s)}finally{u(!1)}}},S=async s=>{try{await n.deleteWebhookConfig(s),await m()}catch(a){console.error("Failed to delete webhook",a)}},C=async()=>{if(t){o("idle");try{await n.testWebhook(t,"slack"),o("success"),setTimeout(()=>o("idle"),3e3)}catch{o("error"),setTimeout(()=>o("idle"),3e3)}}},T=s=>{j(a=>a.includes(s)?a.filter(l=>l!==s):[...a,s])},E=s=>{h(a=>a+`{{${s}}} `)};return e.jsxs("div",{className:"webhook-settings-container",children:[e.jsx("div",{className:"scanline",style:{position:"absolute",inset:0,pointerEvents:"none",opacity:.05,zIndex:1001}}),e.jsxs("div",{className:"webhook-header",children:[e.jsxs("div",{className:"webhook-title",children:[e.jsx(k,{className:"webhook-icon",size:20}),e.jsx("h2",{children:"Notification Webhooks"})]}),e.jsx("p",{className:"webhook-subtitle",children:"Configure Slack or generic webhooks to receive alerts for critical infrastructure events."})]}),e.jsxs("div",{className:"webhook-list",children:[x.map(s=>e.jsxs("div",{className:"webhook-card",children:[e.jsxs("div",{className:"webhook-card-header",children:[e.jsxs("div",{className:"webhook-url-display",children:[e.jsx("span",{className:"platform-tag",children:s.payloadTemplate?"CUSTOM":"SLACK"}),e.jsx("span",{className:"url-text",children:s.url})]}),e.jsx("button",{className:"delete-btn",onClick:()=>S(s.id),children:e.jsx(g,{size:16})})]}),e.jsx("div",{className:"webhook-events-list",children:JSON.parse(s.events).map(a=>{const l=v.find(z=>z.id===a);return e.jsxs("span",{className:"event-pill",children:[l==null?void 0:l.icon,(l==null?void 0:l.label)||a]},a)})})]},s.id)),x.length===0&&e.jsxs("div",{className:"empty-webhook-state",children:[e.jsx(k,{size:48,className:"empty-icon"}),e.jsx("p",{children:"No webhooks configured yet."})]})]}),e.jsxs("div",{className:"add-webhook-form",children:[e.jsxs("div",{className:"form-scrollable-content",children:[e.jsx("h3",{children:"Add New Webhook"}),e.jsx("div",{className:"form-group",children:e.jsx("input",{type:"text",className:"webhook-input",placeholder:"https://hooks.slack.com/services/...",value:t,onChange:s=>p(s.target.value)})}),e.jsxs("div",{className:"events-selection",children:[e.jsx("label",{children:"Trigger Events:"}),e.jsx("div",{className:"events-grid",children:v.map(s=>e.jsxs("div",{className:`event-checkbox ${r.includes(s.id)?"selected":""}`,onClick:()=>T(s.id),children:[s.icon,e.jsx("span",{children:s.label}),r.includes(s.id)&&e.jsx(A,{size:14,className:"check-icon"})]},s.id))})]}),e.jsxs("div",{className:"template-section",children:[e.jsxs("div",{className:"template-header",onClick:()=>b(!c),children:[e.jsxs("div",{className:"template-toggle",children:[e.jsx(W,{size:16,className:c?"text-yellow-400":"text-gray-400"}),e.jsx("span",{children:"Use Custom Payload (Optional)"})]}),e.jsx("span",{className:"toggle-indicator",children:c?"−":"+"})]}),c&&e.jsxs("div",{className:"template-editor",children:[e.jsxs("p",{className:"template-hint",children:["Define a JSON or text template. Use variables like ",e.jsx("code",{children:"{{udid}}"})," to insert dynamic data."]}),e.jsx("div",{className:"variable-chips",children:["udid","host","name","sessionId","failureReason","eventType","platform"].map(s=>e.jsx("span",{className:"variable-chip",onClick:()=>E(s),children:s},s))}),e.jsx("textarea",{className:"template-textarea",placeholder:'Example JSON: { "text": "Alert: Device {{udid}} is offline!" }',value:f,onChange:s=>h(s.target.value),rows:3})]})]})]}),e.jsxs("div",{className:"form-actions",children:[e.jsx("button",{className:`test-btn ${d}`,onClick:C,disabled:!t,children:d==="success"?"Sent!":d==="error"?"Failed":"Test Payload"}),e.jsx("button",{className:"add-btn",onClick:y,disabled:!t||N,children:N?"Saving...":"Save Configuration"})]})]})]})};export{J as WebhookSettings};
1
+ import{r as i,j as e,k,i as A,C as _}from"./index-CvgdoCl7.js";import{X as n}from"./index-C1DBaoSh.js";import{T as g}from"./trash-2-CVL2-wTB.js";import{Z as W}from"./zap-O1qTOCtS.js";import{P as O}from"./plus-CspDy7t8.js";const v=[{id:"device_offline",label:"Device Offline",icon:e.jsx(_,{size:14,className:"text-red-400"})},{id:"device_new",label:"New Device",icon:e.jsx(O,{size:14,className:"text-green-400"})},{id:"session_failed",label:"Session Failed",icon:e.jsx(g,{size:14,className:"text-orange-400"})}],J=()=>{const[x,w]=i.useState([]),[t,p]=i.useState(""),[r,j]=i.useState(["device_offline","session_failed"]),[N,u]=i.useState(!1),[d,o]=i.useState("idle"),[c,b]=i.useState(!1),[f,h]=i.useState("");i.useEffect(()=>{m()},[]);const m=async()=>{try{const s=await n.getWebhookConfigs();w(s||[])}catch(s){console.error("Failed to load webhook configs",s)}},y=async()=>{if(t){u(!0);try{await n.addWebhookConfig(t,r,"slack",f||void 0),p(""),h(""),b(!1),j(["device_offline","session_failed"]),await m()}catch(s){console.error("Failed to add webhook",s)}finally{u(!1)}}},S=async s=>{try{await n.deleteWebhookConfig(s),await m()}catch(a){console.error("Failed to delete webhook",a)}},C=async()=>{if(t){o("idle");try{await n.testWebhook(t,"slack"),o("success"),setTimeout(()=>o("idle"),3e3)}catch{o("error"),setTimeout(()=>o("idle"),3e3)}}},T=s=>{j(a=>a.includes(s)?a.filter(l=>l!==s):[...a,s])},E=s=>{h(a=>a+`{{${s}}} `)};return e.jsxs("div",{className:"webhook-settings-container",children:[e.jsx("div",{className:"scanline",style:{position:"absolute",inset:0,pointerEvents:"none",opacity:.05,zIndex:1001}}),e.jsxs("div",{className:"webhook-header",children:[e.jsxs("div",{className:"webhook-title",children:[e.jsx(k,{className:"webhook-icon",size:20}),e.jsx("h2",{children:"Notification Webhooks"})]}),e.jsx("p",{className:"webhook-subtitle",children:"Configure Slack or generic webhooks to receive alerts for critical infrastructure events."})]}),e.jsxs("div",{className:"webhook-list",children:[x.map(s=>e.jsxs("div",{className:"webhook-card",children:[e.jsxs("div",{className:"webhook-card-header",children:[e.jsxs("div",{className:"webhook-url-display",children:[e.jsx("span",{className:"platform-tag",children:s.payloadTemplate?"CUSTOM":"SLACK"}),e.jsx("span",{className:"url-text",children:s.url})]}),e.jsx("button",{className:"delete-btn",onClick:()=>S(s.id),children:e.jsx(g,{size:16})})]}),e.jsx("div",{className:"webhook-events-list",children:JSON.parse(s.events).map(a=>{const l=v.find(z=>z.id===a);return e.jsxs("span",{className:"event-pill",children:[l==null?void 0:l.icon,(l==null?void 0:l.label)||a]},a)})})]},s.id)),x.length===0&&e.jsxs("div",{className:"empty-webhook-state",children:[e.jsx(k,{size:48,className:"empty-icon"}),e.jsx("p",{children:"No webhooks configured yet."})]})]}),e.jsxs("div",{className:"add-webhook-form",children:[e.jsxs("div",{className:"form-scrollable-content",children:[e.jsx("h3",{children:"Add New Webhook"}),e.jsx("div",{className:"form-group",children:e.jsx("input",{type:"text",className:"webhook-input",placeholder:"https://hooks.slack.com/services/...",value:t,onChange:s=>p(s.target.value)})}),e.jsxs("div",{className:"events-selection",children:[e.jsx("label",{children:"Trigger Events:"}),e.jsx("div",{className:"events-grid",children:v.map(s=>e.jsxs("div",{className:`event-checkbox ${r.includes(s.id)?"selected":""}`,onClick:()=>T(s.id),children:[s.icon,e.jsx("span",{children:s.label}),r.includes(s.id)&&e.jsx(A,{size:14,className:"check-icon"})]},s.id))})]}),e.jsxs("div",{className:"template-section",children:[e.jsxs("div",{className:"template-header",onClick:()=>b(!c),children:[e.jsxs("div",{className:"template-toggle",children:[e.jsx(W,{size:16,className:c?"text-yellow-400":"text-gray-400"}),e.jsx("span",{children:"Use Custom Payload (Optional)"})]}),e.jsx("span",{className:"toggle-indicator",children:c?"−":"+"})]}),c&&e.jsxs("div",{className:"template-editor",children:[e.jsxs("p",{className:"template-hint",children:["Define a JSON or text template. Use variables like ",e.jsx("code",{children:"{{udid}}"})," to insert dynamic data."]}),e.jsx("div",{className:"variable-chips",children:["udid","host","name","sessionId","failureReason","eventType","platform"].map(s=>e.jsx("span",{className:"variable-chip",onClick:()=>E(s),children:s},s))}),e.jsx("textarea",{className:"template-textarea",placeholder:'Example JSON: { "text": "Alert: Device {{udid}} is offline!" }',value:f,onChange:s=>h(s.target.value),rows:3})]})]})]}),e.jsxs("div",{className:"form-actions",children:[e.jsx("button",{className:`test-btn ${d}`,onClick:C,disabled:!t,children:d==="success"?"Sent!":d==="error"?"Failed":"Test Payload"}),e.jsx("button",{className:"add-btn",onClick:y,disabled:!t||N,children:N?"Saving...":"Save Configuration"})]})]})]})};export{J as WebhookSettings};
@@ -1,4 +1,4 @@
1
- import{c as a}from"./index-ByQwMN5T.js";/**
1
+ import{c as a}from"./index-CvgdoCl7.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -24,7 +24,7 @@
24
24
  Learn how to configure a non-root public URL by running `npm run build`.
25
25
  -->
26
26
  <title>Xenon</title>
27
- <script type="module" crossorigin src="/xenon/assets/index-ByQwMN5T.js"></script>
27
+ <script type="module" crossorigin src="/xenon/assets/index-CvgdoCl7.js"></script>
28
28
  <link rel="stylesheet" crossorigin href="/xenon/assets/index-qzCez_kk.css">
29
29
  </head>
30
30
 
@@ -17,6 +17,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
17
17
  var __importDefault = (this && this.__importDefault) || function (mod) {
18
18
  return (mod && mod.__esModule) ? mod : { "default": mod };
19
19
  };
20
+ var WDAClient_1;
20
21
  Object.defineProperty(exports, "__esModule", { value: true });
21
22
  exports.WDAClient = void 0;
22
23
  const axios_1 = __importDefault(require("axios"));
@@ -33,13 +34,15 @@ const os_1 = __importDefault(require("os"));
33
34
  const fs_extra_1 = __importDefault(require("fs-extra"));
34
35
  const execFilePromise = (0, util_1.promisify)(child_process_1.execFile);
35
36
  const execPromise = (0, util_1.promisify)(child_process_1.exec);
36
- let WDAClient = class WDAClient {
37
+ let WDAClient = WDAClient_1 = class WDAClient {
37
38
  constructor() {
38
39
  this.log = logger_1.default.scope('WDAClient');
39
40
  this.wdaConnectionCache = new Map();
40
41
  this.commandQueues = new Map();
41
42
  this.ideviceinstallerVersion = null;
42
43
  this.typeBuffers = new Map();
44
+ // Persistent log streams: one background syslog process per device
45
+ this.logStreams = new Map();
43
46
  }
44
47
  executeSerializedCommand(udid, action) {
45
48
  return __awaiter(this, void 0, void 0, function* () {
@@ -108,7 +111,7 @@ let WDAClient = class WDAClient {
108
111
  for (const prefix of prefixes) {
109
112
  try {
110
113
  const isSessionless = !(options === null || options === void 0 ? void 0 : options.useSessionPath) &&
111
- (['/status', '/health'].includes(endpoint) || endpoint.startsWith('/wda/'));
114
+ (['/status', '/health', '/wda/healthcheck'].includes(endpoint));
112
115
  const url = `http://${targetHost}:${targetPort}${isSessionless ? '' : prefix}${endpoint}`;
113
116
  // Principal Stability: Screenshots, activation, and script execution need longer timeouts.
114
117
  // Heartbeats and Status checks should be snappy to fail-over quickly.
@@ -712,97 +715,114 @@ let WDAClient = class WDAClient {
712
715
  }
713
716
  });
714
717
  }
718
+ startLogStream(udid, command, args, goIOSPath) {
719
+ var _a;
720
+ // Already running?
721
+ const existing = this.logStreams.get(udid);
722
+ if (existing && existing.proc && !existing.proc.killed) {
723
+ existing.lastAccess = Date.now();
724
+ return;
725
+ }
726
+ this.log.info(`[LogStream] Starting persistent syslog for ${udid}: ${command} ${args.join(' ')}`);
727
+ const proc = (0, child_process_1.spawn)(command, args, {
728
+ env: Object.assign(Object.assign({}, process.env), { ENABLE_GO_IOS_AGENT: 'yes' }),
729
+ stdio: ['ignore', 'pipe', 'pipe'],
730
+ });
731
+ const entry = {
732
+ proc,
733
+ buffer: [],
734
+ lastAccess: Date.now(),
735
+ idleTimer: null,
736
+ goIOSPath,
737
+ };
738
+ if (proc.stdout) {
739
+ const rl = readline_1.default.createInterface({ input: proc.stdout, terminal: false });
740
+ rl.on('line', (line) => {
741
+ if (!line.trim())
742
+ return;
743
+ let parsed = line;
744
+ if (command === goIOSPath) {
745
+ try {
746
+ const obj = JSON.parse(line);
747
+ parsed = obj.msg || line;
748
+ }
749
+ catch (e) {
750
+ // Use raw line
751
+ }
752
+ }
753
+ entry.buffer.push(parsed);
754
+ // Ring buffer: drop oldest lines
755
+ if (entry.buffer.length > WDAClient_1.LOG_BUFFER_MAX) {
756
+ entry.buffer.splice(0, entry.buffer.length - WDAClient_1.LOG_BUFFER_MAX);
757
+ }
758
+ });
759
+ }
760
+ // Suppress stderr noise (go-ios tunnel messages)
761
+ (_a = proc.stderr) === null || _a === void 0 ? void 0 : _a.on('data', () => { });
762
+ proc.on('error', (err) => {
763
+ this.log.debug(`[LogStream] Process error for ${udid}: ${err.message}`);
764
+ this.logStreams.delete(udid);
765
+ });
766
+ proc.on('exit', (code) => {
767
+ this.log.debug(`[LogStream] Process exited for ${udid} with code ${code}`);
768
+ this.logStreams.delete(udid);
769
+ });
770
+ this.logStreams.set(udid, entry);
771
+ }
772
+ stopLogStream(udid) {
773
+ const entry = this.logStreams.get(udid);
774
+ if (entry) {
775
+ if (entry.idleTimer)
776
+ clearTimeout(entry.idleTimer);
777
+ if (entry.proc && !entry.proc.killed) {
778
+ entry.proc.kill('SIGKILL');
779
+ }
780
+ this.logStreams.delete(udid);
781
+ this.log.debug(`[LogStream] Stopped persistent syslog for ${udid}`);
782
+ }
783
+ }
715
784
  getLogs(udid) {
716
785
  return __awaiter(this, void 0, void 0, function* () {
717
786
  const s = typedi_1.Container.get(IOSStreamService_1.default);
718
- // Find device to check if it's a simulator
719
787
  const device = yield device_store_1.DeviceStoreFactory.getStore().findDevice({ udid });
720
788
  const isSimulator = device && !device.realDevice;
721
789
  let command = 'idevicesyslog';
722
790
  let args = ['-u', udid];
723
791
  if (isSimulator) {
792
+ // Simulators: Use one-shot log show (no persistent stream needed)
724
793
  command = 'xcrun';
725
794
  args = ['simctl', 'spawn', udid, 'log', 'show', '--last', '10s', '--style', 'compact'];
795
+ return new Promise((resolve) => {
796
+ var _a;
797
+ const proc = (0, child_process_1.spawn)(command, args);
798
+ let output = '';
799
+ (_a = proc.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (data) => { output += data.toString(); });
800
+ proc.on('close', () => resolve(output));
801
+ setTimeout(() => { if (!proc.killed)
802
+ proc.kill('SIGKILL'); resolve(output); }, 5000);
803
+ });
726
804
  }
727
- else if (yield s.isGoIOSAvailable()) {
805
+ if (yield s.isGoIOSAvailable()) {
728
806
  command = s.goIOSPath;
729
807
  args = ['syslog', '--udid', udid];
730
808
  }
731
- this.log.debug(`Fetching logs for ${udid} (Simulator: ${isSimulator}) using ${command} ${args.join(' ')}`);
732
- return new Promise((resolve) => {
733
- var _a;
734
- const proc = (0, child_process_1.spawn)(command, args, {
735
- env: Object.assign(Object.assign({}, process.env), { ENABLE_GO_IOS_AGENT: 'yes' }),
736
- });
737
- let output = '';
738
- let resolved = false;
739
- if (!proc.stdout) {
740
- resolved = true;
741
- this.log.error(`Failed to capture logs for ${udid}: stdout stream is missing`);
742
- proc.kill('SIGKILL');
743
- resolve(output);
744
- return;
745
- }
746
- const rl = readline_1.default.createInterface({
747
- input: proc.stdout,
748
- terminal: false,
749
- });
750
- let timer;
751
- const resetInactivityTimeout = () => {
752
- if (timer)
753
- clearTimeout(timer);
754
- timer = setTimeout(() => {
755
- if (!resolved) {
756
- resolved = true;
757
- rl.close();
758
- proc.kill('SIGKILL');
759
- this.log.debug(`getLogs snapshot completed (inactivity timeout) for ${udid}`);
760
- resolve(output);
761
- }
762
- }, 2000);
763
- };
764
- // Initial timer start
765
- resetInactivityTimeout();
766
- rl.on('line', (line) => {
767
- resetInactivityTimeout();
768
- if (!line.trim())
769
- return;
770
- if (command === s.goIOSPath) {
771
- try {
772
- const parsed = JSON.parse(line);
773
- output += (parsed.msg || line) + '\n';
774
- }
775
- catch (e) {
776
- output += line + '\n';
777
- }
778
- }
779
- else {
780
- output += line + '\n';
781
- }
782
- });
783
- (_a = proc.stderr) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
784
- resetInactivityTimeout();
785
- this.log.debug(`[getLogs][stderr] ${data.toString()}`);
786
- });
787
- proc.on('error', (err) => {
788
- if (!resolved) {
789
- resolved = true;
790
- rl.close();
791
- this.log.debug(`getLogs failed for ${udid}: ${err.message}`);
792
- clearTimeout(timer);
793
- resolve(output);
794
- }
795
- });
796
- proc.on('exit', (code) => {
797
- if (!resolved) {
798
- resolved = true;
799
- rl.close();
800
- clearTimeout(timer);
801
- this.log.debug(`getLogs process exited with code ${code} for ${udid}`);
802
- resolve(output);
803
- }
804
- });
805
- });
809
+ // Ensure persistent stream is running
810
+ this.startLogStream(udid, command, args, s.goIOSPath);
811
+ const entry = this.logStreams.get(udid);
812
+ if (!entry) {
813
+ return '';
814
+ }
815
+ // Mark access and reset idle timer
816
+ entry.lastAccess = Date.now();
817
+ if (entry.idleTimer)
818
+ clearTimeout(entry.idleTimer);
819
+ entry.idleTimer = setTimeout(() => {
820
+ this.log.info(`[LogStream] Idle timeout for ${udid}, stopping persistent syslog`);
821
+ this.stopLogStream(udid);
822
+ }, WDAClient_1.LOG_IDLE_TIMEOUT_MS);
823
+ // Return buffered lines and clear (so next poll gets only new lines)
824
+ const lines = entry.buffer.splice(0, entry.buffer.length);
825
+ return lines.join('\n');
806
826
  });
807
827
  }
808
828
  verifyWDAStatus(udid) {
@@ -861,6 +881,8 @@ let WDAClient = class WDAClient {
861
881
  }
862
882
  };
863
883
  exports.WDAClient = WDAClient;
864
- exports.WDAClient = WDAClient = __decorate([
884
+ WDAClient.LOG_BUFFER_MAX = 500; // Ring buffer size
885
+ WDAClient.LOG_IDLE_TIMEOUT_MS = 60000; // Kill after 60s of no polling
886
+ exports.WDAClient = WDAClient = WDAClient_1 = __decorate([
865
887
  (0, typedi_1.Service)()
866
888
  ], WDAClient);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xenon-device-management/xenon",
3
- "version": "1.1.20",
3
+ "version": "1.1.22",
4
4
  "description": "Xenon - Intelligent Mobile Infrastructure. A self-healing device orchestration platform for Appium.",
5
5
  "main": "./lib/src/index.js",
6
6
  "exports": {