@xenon-device-management/xenon 1.27.0 → 1.28.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/lib/package.json +1 -1
  2. package/lib/public/assets/{ApiKeyGate-CdwAz8U0.js → ApiKeyGate-C1flnFDX.js} +1 -1
  3. package/lib/public/assets/{BugReportButton-BRpZbizS.js → BugReportButton-B0FVUoM9.js} +1 -1
  4. package/lib/public/assets/{DeviceMosaicView-DIliYF7k.js → DeviceMosaicView-DExNbxhJ.js} +2 -2
  5. package/lib/public/assets/{EmptyState-DdGslmm0.js → EmptyState-CQ8QKCDQ.js} +1 -1
  6. package/lib/public/assets/{FieldGroup-Bb3NBVy1.js → FieldGroup-BNgWZuEO.js} +1 -1
  7. package/lib/public/assets/{Modal-B1wiaZoC.js → Modal-BgHBR90U.js} +1 -1
  8. package/lib/public/assets/{SegmentedControl-CSSdDwVG.js → SegmentedControl-Dv49e2ww.js} +1 -1
  9. package/lib/public/assets/{SettingCard-B5QGLufn.js → SettingCard-WgZ0tJaW.js} +1 -1
  10. package/lib/public/assets/{Table-CaLvNt65.js → Table-D4yRFXBB.js} +1 -1
  11. package/lib/public/assets/{activity-BKpt4jQ5.js → activity-BPmKT1-Z.js} +1 -1
  12. package/lib/public/assets/{ai-settings-DXab66Uw.js → ai-settings-D3aY4Qnp.js} +2 -2
  13. package/lib/public/assets/{api-keys-BKOBEq40.js → api-keys-BgF4grSL.js} +1 -1
  14. package/lib/public/assets/{apps-h1-WF2M3.js → apps-D77xxhJm.js} +2 -2
  15. package/lib/public/assets/{arrow-left-CsL4cGlx.js → arrow-left-6r6Ky3gZ.js} +1 -1
  16. package/lib/public/assets/{arrow-right-ms3VXPTM.js → arrow-right-D89pOZ-E.js} +1 -1
  17. package/lib/public/assets/{arrow-up-right-DsPkHtnY.js → arrow-up-right-CyK-2OUL.js} +1 -1
  18. package/lib/public/assets/{auth-shell-Di20xJer.js → auth-shell-DIc2eQJF.js} +2 -2
  19. package/lib/public/assets/{builds-page-B7Ykr6Y7.js → builds-page-BmWHa-ao.js} +1 -1
  20. package/lib/public/assets/{button-B4yBI9rz.js → button-DltzrxJt.js} +1 -1
  21. package/lib/public/assets/{calendar-CDhdbn6g.js → calendar-DlZbz8st.js} +1 -1
  22. package/lib/public/assets/{check-CQ6W-pr3.js → check-BS_iDiCm.js} +1 -1
  23. package/lib/public/assets/{chevron-left-Brw18ZbJ.js → chevron-left-DfBtWaTB.js} +1 -1
  24. package/lib/public/assets/{chevron-right-_5hhohkO.js → chevron-right-D_ce1lFZ.js} +1 -1
  25. package/lib/public/assets/{circle-check-DFS84uuw.js → circle-check-CY1FVKEM.js} +1 -1
  26. package/lib/public/assets/{circle-x--eZQbJ-L.js → circle-x-BUc9Nbjp.js} +1 -1
  27. package/lib/public/assets/{clock-BKQop8v4.js → clock-C3HFHOjc.js} +1 -1
  28. package/lib/public/assets/{copy-C6MtTTlz.js → copy-B_nF93V0.js} +1 -1
  29. package/lib/public/assets/{device-explorer-ISQgiqG9.css → device-explorer-CLvcu3ZP.css} +1 -1
  30. package/lib/public/assets/device-explorer-DzKpulyk.js +277 -0
  31. package/lib/public/assets/{download-CJQADlfa.js → download-eLe3MTlf.js} +1 -1
  32. package/lib/public/assets/{forgot-password-BDwj629H.js → forgot-password-C8Df90UG.js} +1 -1
  33. package/lib/public/assets/{funnel-DZ7jzsbh.js → funnel-BUtUuHdr.js} +1 -1
  34. package/lib/public/assets/{index-BpueX0rJ.js → index-CbC9kGzR.js} +42 -42
  35. package/lib/public/assets/{input-CjSO5fIy.js → input-DWZrPTa0.js} +1 -1
  36. package/lib/public/assets/{keycodes-DX_YyhNk.js → keycodes-DwpzQkCL.js} +1 -1
  37. package/lib/public/assets/{layers-DeJ98GnJ.js → layers-C5Ie6pKP.js} +1 -1
  38. package/lib/public/assets/{lock-D7AfKT4W.js → lock-CP7rT2zw.js} +1 -1
  39. package/lib/public/assets/{login-DzvYxcU2.js → login-I9MEyL3z.js} +1 -1
  40. package/lib/public/assets/{maintenance-settings-CI8PjeAD.js → maintenance-settings-BaUIPa6P.js} +2 -2
  41. package/lib/public/assets/{monitor-COjPL4Nw.js → monitor-BPOD4miY.js} +1 -1
  42. package/lib/public/assets/{mouse-pointer-2-JHGsHIlv.js → mouse-pointer-2-FC5NkA3b.js} +1 -1
  43. package/lib/public/assets/{network-CHdKReD2.js → network-byVYMhG6.js} +1 -1
  44. package/lib/public/assets/{overview-BFi5MYtk.js → overview-DPsyLt0p.js} +1 -1
  45. package/lib/public/assets/{page-header-Dlf-n7I6.js → page-header-DNv41R4K.js} +1 -1
  46. package/lib/public/assets/{plus-BO31f8er.js → plus-CUw6PQEq.js} +1 -1
  47. package/lib/public/assets/{profile-page-C2mhKOSp.js → profile-page-q3_je-fg.js} +2 -2
  48. package/lib/public/assets/{reset-password-D2-nKd2R.js → reset-password-CXBKmL7E.js} +1 -1
  49. package/lib/public/assets/{runbook-page-Dua237ld.js → runbook-page-C4_BNJyE.js} +1 -1
  50. package/lib/public/assets/{select-r2t6ViSf.js → select-Cr2iHnZS.js} +1 -1
  51. package/lib/public/assets/{selector-detail-page-BADJhfZc.js → selector-detail-page-D3VX9poK.js} +1 -1
  52. package/lib/public/assets/{selector-health-3LaUwIOS.js → selector-health-eEVbocTY.js} +1 -1
  53. package/lib/public/assets/{selector-health-page-hCruYbXz.js → selector-health-page-BmwOWPwo.js} +2 -2
  54. package/lib/public/assets/{session-detail-page-ovBT1YRs.js → session-detail-page-bU0UqDHG.js} +1 -1
  55. package/lib/public/assets/{settings-CIK56OMn.js → settings-DVnMtUD4.js} +2 -2
  56. package/lib/public/assets/{status-pill-outline-CG_1PTcd.js → status-pill-outline-BiW2dT9V.js} +1 -1
  57. package/lib/public/assets/{tablet-mcews5C3.js → tablet-CtMP3El1.js} +1 -1
  58. package/lib/public/assets/{teams-Cf8a8-Uo.js → teams-Ci7oAHO1.js} +1 -1
  59. package/lib/public/assets/{trash-2-CsJaXAJF.js → trash-2--73YRWvy.js} +1 -1
  60. package/lib/public/assets/{upload-CL1XK43J.js → upload-DLH0SpN3.js} +1 -1
  61. package/lib/public/assets/{use-password-reset-mode-gRcAFXVy.js → use-password-reset-mode-GyXnzO4L.js} +1 -1
  62. package/lib/public/assets/{users-24eVEQFo.js → users-C8eFBsHD.js} +1 -1
  63. package/lib/public/assets/{users-CgxBmVs9.js → users-CSByb3Y_.js} +3 -3
  64. package/lib/public/assets/{video-off-LUd5fEht.js → video-off-Dhb4hlQJ.js} +1 -1
  65. package/lib/public/assets/{webhook-settings-KzrG-pNv.js → webhook-settings-CCKFvTiR.js} +1 -1
  66. package/lib/public/assets/{zap-BA1OUWAL.js → zap-EAMj2mbO.js} +1 -1
  67. package/lib/public/index.html +1 -1
  68. package/lib/src/app/routers/control.js +94 -23
  69. package/lib/src/app/routers/streamLeave.js +75 -0
  70. package/lib/src/device-managers/HealthMonitorService.js +10 -6
  71. package/lib/src/device-managers/android/AndroidH264StreamService.js +6 -1
  72. package/lib/src/device-managers/android/AndroidStreamService.js +9 -18
  73. package/lib/src/device-managers/android/previewHold.js +72 -0
  74. package/lib/src/device-managers/ios/IOSStreamService.js +58 -15
  75. package/lib/src/middleware/deviceAccessGuard.js +1 -0
  76. package/lib/test/unit/android-preview-hold.spec.js +179 -0
  77. package/lib/test/unit/device-access-guard.spec.js +3 -2
  78. package/lib/test/unit/health-monitor-stream-lookup.spec.js +107 -0
  79. package/lib/test/unit/ios-idle-hold.spec.js +133 -0
  80. package/lib/test/unit/stream-leave-route.spec.js +178 -0
  81. package/lib/test/unit/stream-leave.spec.js +98 -0
  82. package/lib/tsconfig.tsbuildinfo +1 -1
  83. package/package.json +1 -1
  84. package/lib/public/assets/device-explorer-DTHiUDlu.js +0 -246
package/lib/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xenon-device-management/xenon",
3
- "version": "1.27.0",
3
+ "version": "1.28.1",
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 +1 @@
1
- import{r as n,j as e,o as h}from"./index-BpueX0rJ.js";function y({children:c}){const[i,s]=n.useState(null),[o,l]=n.useState(""),[a,r]=n.useState(null);if(n.useEffect(()=>{fetch("/xenon/api/health").then(()=>fetch("/xenon/api/sessions",{credentials:"include"})).then(t=>s(t.status!==401)).catch(()=>s(!1))},[]),i===null)return e.jsx("div",{style:{padding:40},children:"Loading…"});if(i)return e.jsx(e.Fragment,{children:c});async function u(t){t.preventDefault(),r(null);const d=await fetch("/xenon/api/auth/dashboard-session",{method:"POST",headers:{"Content-Type":"application/json",...h},credentials:"include",body:JSON.stringify({apiKey:o.trim()})});if(d.ok)s(!0);else{const p=await d.json().catch(()=>({}));r(p.error||"Invalid key")}}return e.jsxs("div",{style:{maxWidth:420,margin:"120px auto",padding:24},children:[e.jsx("h2",{children:"Sign in to Xenon"}),e.jsxs("p",{children:["Paste an API key. First-time setup: the bootstrap key is in"," ",e.jsx("code",{children:"~/.cache/xenon/bootstrap-key.txt"})," on the server."]}),e.jsxs("form",{onSubmit:u,children:[e.jsx("input",{type:"password",value:o,onChange:t=>l(t.target.value),placeholder:"API key",style:{width:"100%",padding:8,boxSizing:"border-box"},autoFocus:!0}),e.jsx("button",{type:"submit",style:{marginTop:12,padding:"8px 16px"},children:"Continue"})]}),a&&e.jsx("p",{style:{color:"crimson",marginTop:12},children:a})]})}export{y as ApiKeyGate};
1
+ import{r as n,j as e,o as h}from"./index-CbC9kGzR.js";function y({children:c}){const[i,s]=n.useState(null),[o,l]=n.useState(""),[a,r]=n.useState(null);if(n.useEffect(()=>{fetch("/xenon/api/health").then(()=>fetch("/xenon/api/sessions",{credentials:"include"})).then(t=>s(t.status!==401)).catch(()=>s(!1))},[]),i===null)return e.jsx("div",{style:{padding:40},children:"Loading…"});if(i)return e.jsx(e.Fragment,{children:c});async function u(t){t.preventDefault(),r(null);const d=await fetch("/xenon/api/auth/dashboard-session",{method:"POST",headers:{"Content-Type":"application/json",...h},credentials:"include",body:JSON.stringify({apiKey:o.trim()})});if(d.ok)s(!0);else{const p=await d.json().catch(()=>({}));r(p.error||"Invalid key")}}return e.jsxs("div",{style:{maxWidth:420,margin:"120px auto",padding:24},children:[e.jsx("h2",{children:"Sign in to Xenon"}),e.jsxs("p",{children:["Paste an API key. First-time setup: the bootstrap key is in"," ",e.jsx("code",{children:"~/.cache/xenon/bootstrap-key.txt"})," on the server."]}),e.jsxs("form",{onSubmit:u,children:[e.jsx("input",{type:"password",value:o,onChange:t=>l(t.target.value),placeholder:"API key",style:{width:"100%",padding:8,boxSizing:"border-box"},autoFocus:!0}),e.jsx("button",{type:"submit",style:{marginTop:12,padding:"8px 16px"},children:"Continue"})]}),a&&e.jsx("p",{style:{color:"crimson",marginTop:12},children:a})]})}export{y as ApiKeyGate};
@@ -1,4 +1,4 @@
1
- import{c as m,j as o,r as f,x as g,f as b}from"./index-BpueX0rJ.js";/**
1
+ import{c as m,j as o,r as f,x as g,f as b}from"./index-CbC9kGzR.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,2 +1,2 @@
1
- import{r as u,j as n,z as Ye,B as Xe,X as O,y as Ve,T as Fe,Y as Ge}from"./index-BpueX0rJ.js";import{p as Ke}from"./labels-C21SA4JG.js";import{C as We}from"./circle-check-DFS84uuw.js";import{C as Re,A as te,H as He,S as Ne,a as Je,I as qe}from"./keycodes-DX_YyhNk.js";import{V as Ze}from"./video-off-LUd5fEht.js";import{C as Qe}from"./chevron-left-Brw18ZbJ.js";import{P as et}from"./plus-BO31f8er.js";import{S as tt}from"./SegmentedControl-CSSdDwVG.js";import{D as ie}from"./download-CJQADlfa.js";import{B as fe}from"./button-B4yBI9rz.js";import{C as rt}from"./clock-BKQop8v4.js";import{a as nt}from"./page-header-Dlf-n7I6.js";import"./utils-CDN07tui.js";function ot(e,t){return e!=="auto"?e:t<=1?"1":t===2?"2x1":t<=4?"2x2":"3x2"}const st={selected:new Set,layout:"auto",tiles:[],groupId:null,compositeEnabled:!1,downloadableVideoCount:0,recordingPhase:"idle",recording:!1,startedAt:null,annotateMode:!1,shape:"RECT",color:"#ff3333",overlayAnnotations:{},errorBanner:null,banner:null};function it(e,t){var r;switch(t.type){case"SET_LAYOUT":return{...e,layout:t.layout};case"TOGGLE_SELECTED":{const o=new Set(e.selected);return o.has(t.udid)?o.delete(t.udid):o.add(t.udid),{...e,selected:o}}case"CLEAR_SELECTED":return{...e,selected:new Set};case"SET_TILES":return{...e,tiles:t.tiles};case"ADD_TILE":return e.tiles.some(o=>o.udid===t.tile.udid)?e:{...e,tiles:[...e.tiles,t.tile]};case"PATCH_TILE_DIMS":{let o=!1;const s=e.tiles.map(h=>h.udid!==t.udid||h.screenWidth&&h.screenHeight?h:(o=!0,{...h,screenWidth:t.screenWidth,screenHeight:t.screenHeight,aspect:t.aspect??h.aspect}));return o?{...e,tiles:s}:e}case"REMOVE_TILE":return e.recordingPhase!=="idle"?e:{...e,tiles:e.tiles.filter(o=>o.udid!==t.udid)};case"BIND_RECORDING_IDS":{const o=e.tiles.map(s=>({...s,recordingId:t.map[s.udid]??s.recordingId}));return{...e,tiles:o}}case"SET_RECORDING_PHASE":{const o=t.phase;return{...e,recordingPhase:o,recording:o==="recording"||o==="stopping"}}case"START_RECORDING":{const o=e.tiles.map(s=>({...s,recordingId:t.tileIds[s.udid]??s.recordingId}));return{...e,groupId:t.groupId,compositeEnabled:t.compositeEnabled===!0,downloadableVideoCount:0,recordingPhase:"recording",recording:!0,annotateMode:!1,startedAt:t.startedAt,overlayAnnotations:{},tiles:o}}case"REHYDRATE_RECORDING":{const o=e.tiles.map(s=>({...s,recordingId:t.tileIds[s.udid]??s.recordingId}));return{...e,groupId:t.groupId,compositeEnabled:t.compositeEnabled,downloadableVideoCount:0,recordingPhase:"recording",recording:!0,annotateMode:!1,startedAt:t.startedAt,overlayAnnotations:t.overlayAnnotations,tiles:o}}case"STOP_RECORDING":{const o=e.tiles.map(s=>({...s,recordingId:void 0}));return{...e,recording:!1,recordingPhase:"idle",annotateMode:!1,overlayAnnotations:{},downloadableVideoCount:t.downloadableVideoCount??e.downloadableVideoCount,compositeEnabled:t.compositeEnabled!==void 0?t.compositeEnabled:e.compositeEnabled,tiles:o}}case"SET_ANNOTATE_MODE":return{...e,annotateMode:t.enabled};case"SET_SHAPE":return{...e,shape:t.shape};case"SET_COLOR":return{...e,color:t.color};case"SET_OVERLAY_ANNOTATIONS":return{...e,overlayAnnotations:{...e.overlayAnnotations,[t.recordingId]:t.annotations}};case"CLEAR_OVERLAY_ANNOTATIONS":return{...e,overlayAnnotations:{}};case"SET_ERROR_BANNER":return{...e,errorBanner:t.message,banner:t.message?{tone:"error",message:t.message}:null};case"SET_BANNER":return{...e,banner:t.banner,errorBanner:((r=t.banner)==null?void 0:r.tone)==="error"?t.banner.message:null};default:return e}}const Se=u.createContext(null);function at(){const e=u.useContext(Se);if(!e)throw new Error("useMosaic must be used inside <MosaicContext.Provider>");return e}function ct(){return u.useReducer(it,st)}function lt(e){const t=Math.max(0,Math.floor(e/1e3)),r=Math.floor(t/3600),o=Math.floor(t%3600/60),s=t%60;return r>0?`${r}:${String(o).padStart(2,"0")}:${String(s).padStart(2,"0")}`:`${o}:${String(s).padStart(2,"0")}`}function dt(e){switch(e){case"automation":return"In automation";case"manual_other":return"Manual control by another user";case"manual_self":return"On your grid";case"recording_other_group":return"Recording in another group";default:return e?"Busy":null}}const he=[{id:"ios",label:"iOS",match:e=>e==="ios"},{id:"android",label:"Android",match:e=>e==="android"},{id:"tvos",label:"tvOS",match:e=>e==="tvos"},{id:"androidtv",label:"Android TV",match:e=>e==="androidtv"||e==="android-tv"},{id:"other",label:"Other",match:()=>!0}],W={available:"bg-[var(--color-success)]",inUse:"bg-[var(--color-warning)]",offline:"bg-[rgb(var(--rgb-offline))]"},ut=[["available",W.available],["in use",W.inUse],["offline",W.offline]];function pe(e){return Ke(e)}function ft({devices:e,inMosaic:t,onToggle:r,status:o="ready"}){const[s,h]=u.useState(""),[a,b]=u.useState({}),v=u.useMemo(()=>{const f=s.trim().toLowerCase();return f?e.filter(y=>y.udid.toLowerCase().includes(f)||(y.name??"").toLowerCase().includes(f)||(y.altName??"").toLowerCase().includes(f)||(y.platform??"").toLowerCase().includes(f)):e},[e,s]),g=u.useMemo(()=>{const f=he.map(c=>({id:c.id,label:c.label,rows:[]})),y=c=>f.find((S,m)=>he[m].match(c))??f[f.length-1];for(const c of v)y((c.platform??"").toLowerCase()).rows.push(c);return f.filter(c=>c.rows.length>0)},[v]);if(e.length===0){const f=o==="loading"?"Loading devices…":o==="error"?"Couldn’t load devices. Retrying…":"No devices online.";return n.jsx("div",{role:"status",className:"text-xs text-[var(--text-dim)] p-3",children:f})}return n.jsxs("div",{className:"flex flex-col gap-2",children:[n.jsxs("div",{className:"relative",children:[n.jsx(Ye,{"aria-hidden":!0,size:12,className:"absolute left-2 top-1/2 -translate-y-1/2 text-[var(--text-dim)]"}),n.jsx("input",{type:"text",value:s,placeholder:"Filter devices...",onChange:f=>h(f.target.value),className:"w-full pl-7 pr-2 py-1.5 text-xs rounded border border-[var(--border)] bg-transparent placeholder:text-[var(--text-dim)] focus:outline-none focus:border-[var(--color-info)]"})]}),g.map(f=>{const y=a[f.id];return n.jsxs("section",{className:"flex flex-col gap-1",children:[n.jsxs("button",{type:"button","aria-expanded":!y,onClick:()=>b(c=>({...c,[f.id]:!c[f.id]})),className:"flex items-center justify-between w-full text-[11px] text-[var(--text-dim)] hover:text-[rgb(var(--rgb-fg))] px-1 py-0.5",children:[n.jsxs("span",{className:"flex items-center gap-1.5",children:[n.jsx(Xe,{"aria-hidden":!0,size:12,className:`transition-transform ${y?"-rotate-90":"rotate-0"}`}),f.label]}),n.jsx("span",{children:f.rows.length})]}),!y&&n.jsx("ul",{className:"flex flex-col gap-1 text-sm",children:f.rows.map(c=>{const S=c.busyReason==="manual_self",m=t.has(c.udid),x=!!c.busy&&!S&&!m||!!c.offline,j=c.offline?"Offline":dt(c.busyReason),I=!x,D=[c.name??c.udid,c.platform&&pe(c.platform)].concat(x&&j?[j]:[]).filter(Boolean).join(", ");return n.jsx("li",{children:n.jsxs("button",{type:"button",disabled:x,draggable:!x,onDragStart:T=>{T.dataTransfer.effectAllowed="copy",T.dataTransfer.setData("application/x-xenon-udid",c.udid),T.dataTransfer.setData("text/plain",c.udid)},onClick:()=>r(c.udid),"aria-label":D,"aria-pressed":m,className:`w-full flex items-center gap-2 px-2 py-1.5 rounded text-left border transition-colors ${x?"opacity-60 cursor-not-allowed border-transparent":m?"border-[rgb(var(--rgb-accent)/0.4)] bg-[rgb(var(--rgb-accent)/0.05)] hover:bg-[rgb(var(--rgb-accent)/0.1)]":"border-transparent hover:border-[var(--border)] hover:bg-[var(--surface-2)]"}`,title:x?`${j} — release first`:m?"Click to remove from the grid":"Click to add to the grid (or drag to a cell)",children:[m?n.jsx(We,{"aria-hidden":!0,size:14,className:"shrink-0 text-[var(--color-accent-soft)]"}):n.jsx(Re,{"aria-hidden":!0,size:14,className:"shrink-0 text-[var(--text-dim)]"}),n.jsx("span",{"aria-hidden":!0,className:`inline-block w-1.5 h-1.5 rounded-full ${c.offline?W.offline:I?W.available:W.inUse}`}),n.jsx("span",{className:"font-medium flex-1 truncate text-[13px]",children:c.name??c.udid}),c.platform&&n.jsx("span",{className:"text-[11px] px-1.5 py-0.5 rounded bg-[var(--surface-2)] text-[var(--text-dim)]",children:pe(c.platform)})]})},c.udid)})})]},f.id)}),s&&g.length===0&&n.jsxs("div",{className:"text-xs text-[var(--text-dim)] px-1 py-2",children:['No devices match "',s,'".']}),n.jsx("div",{className:"text-[10px] text-[var(--text-dim)] px-1 pt-2 flex items-center gap-3",children:ut.map(([f,y])=>n.jsxs("span",{className:"inline-flex items-center gap-1",children:[n.jsx("span",{className:`w-1.5 h-1.5 rounded-full inline-block ${y}`}),f]},f))})]})}const ht=[{id:"1",label:"1",icon:n.jsx(mt,{})},{id:"2x1",label:"2×1",icon:n.jsx(gt,{})},{id:"2x2",label:"2×2",icon:n.jsx(xt,{})},{id:"3x2",label:"3×2",icon:n.jsx(bt,{})},{id:"auto",label:"Auto",icon:n.jsx(vt,{})}];function pt({value:e,onChange:t}){return n.jsx("div",{role:"tablist",className:"inline-flex border border-[var(--border)] rounded-md overflow-hidden text-xs bg-[rgb(var(--rgb-white)/0.02)]",children:ht.map(r=>{const o=e===r.id;return n.jsxs("button",{role:"tab","aria-selected":o,onClick:()=>t(r.id),className:`flex items-center gap-1.5 px-2.5 py-1.5 border-r border-[var(--border)] last:border-r-0 transition-colors ${o?"bg-[var(--surface-2)] text-[rgb(var(--rgb-fg))]":"text-[var(--text-dim)] hover:bg-[var(--surface-2)] hover:text-[rgb(var(--rgb-fg))]"}`,title:`Layout: ${r.label}`,children:[n.jsx("span",{className:"w-3.5 h-3.5 inline-flex items-center justify-center",children:r.icon}),n.jsx("span",{children:r.label})]},r.id)})})}function V(e){return n.jsx("rect",{rx:1.2,ry:1.2,fill:"currentColor",...e})}function mt(){return n.jsx("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",children:V({x:2,y:2,width:10,height:10})})}function gt(){return n.jsxs("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",children:[V({x:1.5,y:3,width:5,height:8}),V({x:7.5,y:3,width:5,height:8})]})}function xt(){return n.jsxs("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",children:[V({x:1.5,y:1.5,width:5,height:5}),V({x:7.5,y:1.5,width:5,height:5}),V({x:1.5,y:7.5,width:5,height:5}),V({x:7.5,y:7.5,width:5,height:5})]})}function bt(){return n.jsxs("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",children:[V({x:1,y:1.5,width:3.3,height:5}),V({x:5.35,y:1.5,width:3.3,height:5}),V({x:9.7,y:1.5,width:3.3,height:5}),V({x:1,y:7.5,width:3.3,height:5}),V({x:5.35,y:7.5,width:3.3,height:5}),V({x:9.7,y:7.5,width:3.3,height:5})]})}function vt(){return n.jsxs("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",fill:"none",stroke:"currentColor",strokeWidth:"1.4",children:[n.jsx("rect",{x:"2",y:"2",width:"10",height:"10",rx:"1.5"}),n.jsx("circle",{cx:"7",cy:"7",r:"1.5",fill:"currentColor",stroke:"none"})]})}const yt=1600;function wt(e,t){const r=yt/Math.max(e,t);return{w:Math.round(e*r),h:Math.round(t*r)}}function Et(e,t,r,o=document){if(t<=0||r<=0)return null;const{w:s,h}=wt(t,r),a=o.createElement("canvas");a.width=s,a.height=h;const b=a.getContext("2d");if(!b)return null;b.scale(s/t,h/r),ce(b,t,r,e);try{return a.toDataURL("image/png")}catch{return null}}function Te(e,t,r){const o={left:0,top:0,width:e,height:t};if(!r||!(r>0)||e<=0||t<=0)return o;const s=e/t;if(Math.abs(s-r)<1e-6)return o;if(r>s){const a=e/r;return{left:0,top:(t-a)/2,width:e,height:a}}const h=t*r;return{left:(e-h)/2,top:0,width:h,height:t}}const Rt=(e,t)=>e===t||!!e&&!!t&&e.left===t.left&&e.top===t.top&&e.width===t.width&&e.height===t.height,Nt=2,St=2e3;function me(e,t,r){if(e.length>=St)return e;const o=e[e.length-1];return o&&Math.hypot(t-o[0],r-o[1])<Nt?e:[...e,[t,r]]}function ge(e,t){const r=(e||"#ff3333").trim();if(/^#[0-9a-fA-F]{6}$/.test(r)){const o=parseInt(r.slice(1,3),16),s=parseInt(r.slice(3,5),16),h=parseInt(r.slice(5,7),16);return`rgba(${o},${s},${h},${t})`}return r}function ce(e,t,r,o){var y;const s=o.geometry,h=o.color||"#ff3333",a=Math.max(4,Math.round(Math.min(t,r)*.008));if(e.lineCap="round",e.lineJoin="round",o.shape==="CIRCLE"){const c=(s.x??0)*t,S=(s.y??0)*r,m=Math.max(2,(s.w??0)*t),x=Math.max(2,(s.h??0)*r);e.beginPath(),e.ellipse(c,S,m,x,0,0,Math.PI*2),e.fillStyle=ge(h,.22),e.fill(),e.lineWidth=a+2,e.strokeStyle="rgba(0,0,0,0.55)",e.stroke(),e.beginPath(),e.ellipse(c,S,m,x,0,0,Math.PI*2),e.lineWidth=a,e.strokeStyle=h,e.stroke();return}if(o.shape==="ARROW"){const c=(s.x??0)*t,S=(s.y??0)*r,m=c+(s.w??0)*t,x=S+(s.h??0)*r;e.lineWidth=a+2,e.strokeStyle="rgba(0,0,0,0.55)",e.beginPath(),e.moveTo(c,S),e.lineTo(m,x),e.stroke(),e.lineWidth=a,e.strokeStyle=h,e.beginPath(),e.moveTo(c,S),e.lineTo(m,x),e.stroke();const j=Math.atan2(x-S,m-c),I=Math.max(14,a*3);e.fillStyle=h,e.beginPath(),e.moveTo(m,x),e.lineTo(m-I*Math.cos(j-.4),x-I*Math.sin(j-.4)),e.lineTo(m-I*Math.cos(j+.4),x-I*Math.sin(j+.4)),e.closePath(),e.fill();return}if(o.shape==="TEXT"&&o.text){const c=Math.max(16,Math.round(Math.min(t,r)*.035));e.font=`bold ${c}px sans-serif`,e.lineWidth=3,e.strokeStyle="rgba(0,0,0,0.65)",e.strokeText(o.text,(s.x??0)*t,(s.y??0)*r),e.fillStyle=h,e.fillText(o.text,(s.x??0)*t,(s.y??0)*r);return}if(o.shape==="FREEHAND"&&(((y=s.points)==null?void 0:y.length)??0)>=2){const c=s.points,S=()=>{e.beginPath(),e.moveTo(c[0][0]*t,c[0][1]*r);for(let m=1;m<c.length;m++)e.lineTo(c[m][0]*t,c[m][1]*r)};e.lineWidth=a+2,e.strokeStyle="rgba(0,0,0,0.55)",S(),e.stroke(),e.lineWidth=a,e.strokeStyle=h,S(),e.stroke();return}const b=(s.x??0)*t,v=(s.y??0)*r,g=Math.max(2,(s.w??0)*t),f=Math.max(2,(s.h??0)*r);e.fillStyle=ge(h,.22),e.fillRect(b,v,g,f),e.lineWidth=a+2,e.strokeStyle="rgba(0,0,0,0.55)",e.strokeRect(b,v,g,f),e.lineWidth=a,e.strokeStyle=h,e.strokeRect(b,v,g,f)}function xe(e,t,r,o,s){if(o<=0||s<=0)return null;if(e==="CIRCLE"){const g=Math.hypot(r.curX-r.startX,r.curY-r.startY);return g<=4?null:{shape:e,color:t,geometry:{x:r.startX/o,y:r.startY/s,w:g/o,h:g/s}}}if(e==="ARROW"){const g=r.curX-r.startX,f=r.curY-r.startY;return Math.hypot(g,f)<=6?null:{shape:e,color:t,geometry:{x:r.startX/o,y:r.startY/s,w:g/o,h:f/s}}}if(e==="FREEHAND"){if(r.points.length<2)return null;const g=r.points.map(S=>S[0]),f=r.points.map(S=>S[1]),y=Math.min(...g),c=Math.min(...f);return{shape:e,color:t,geometry:{x:y/o,y:c/s,w:Math.max(.005,(Math.max(...g)-y)/o),h:Math.max(.005,(Math.max(...f)-c)/s),points:r.points.map(([S,m])=>[S/o,m/s])}}}const h=Math.min(r.startX,r.curX)/o,a=Math.min(r.startY,r.curY)/s,b=Math.abs(r.curX-r.startX)/o,v=Math.abs(r.curY-r.startY)/s;return b<=.005||v<=.005?null:{shape:e,color:t,geometry:{x:h,y:a,w:b,h:v}}}function Tt({enabled:e,shape:t,color:r,onCommit:o,committed:s,onCommittedChange:h,mediaAspect:a}){const b=u.useRef(null),[v,g]=u.useState(null),[f,y]=u.useState([]),[c,S]=u.useState(null),m=s??f,x=u.useRef(m),j=u.useRef(v),I=u.useRef(t),D=u.useRef(r),T=u.useRef(e);x.current=m,j.current=v,I.current=t,D.current=r,T.current=e;const k=u.useCallback(l=>{const w=l(x.current);x.current=w,h?h(w):y(w)},[h]),M=u.useCallback(()=>{const l=b.current;if(!l)return;const w=l.getContext("2d");if(!w)return;w.clearRect(0,0,l.width,l.height);for(const A of x.current)ce(w,l.width,l.height,A);const C=j.current;if(C){const A=xe(I.current,D.current,C,l.width,l.height);A&&ce(w,l.width,l.height,A)}},[]);u.useEffect(()=>{const l=b.current;if(!l)return;const w=()=>{const A=Math.max(1,Math.round(l.clientWidth)),_=Math.max(1,Math.round(l.clientHeight));(l.width!==A||l.height!==_)&&(l.width=A,l.height=_),M()};w();const C=new ResizeObserver(w);return C.observe(l),()=>C.disconnect()},[M]),u.useEffect(()=>{M()},[v,m,M]),u.useEffect(()=>{var A;const l=(A=b.current)==null?void 0:A.parentElement;if(!l)return;const w=()=>{const _=a?Te(l.clientWidth,l.clientHeight,a):null;S(L=>Rt(L,_)?L:_)};w();const C=new ResizeObserver(w);return C.observe(l),()=>C.disconnect()},[a]),u.useEffect(()=>{var w;if(e)return;g(null);const l=b.current;if(l&&l.hasPointerCapture)try{for(let C=0;C<8;C++)(w=l.hasPointerCapture)!=null&&w.call(l,C)&&l.releasePointerCapture(C)}catch{}},[e]);const U=l=>{const C=b.current.getBoundingClientRect();return{px:l.clientX-C.left,py:l.clientY-C.top,w:C.width,h:C.height}},E=l=>{const w=j.current;if(!w||!T.current){g(null);return}const C=b.current;if(!C||C.width<=0){g(null);return}const A=U(l),_=xe(I.current,D.current,{...w,curX:A.px,curY:A.py,points:me(w.points,A.px,A.py)},A.w,A.h);_&&(k(L=>[...L,_]),o(_,Et(_,A.w,A.h))),g(null)},i=l=>{if(!e||l.button!==0)return;l.preventDefault(),l.currentTarget.setPointerCapture(l.pointerId);const w=U(l);g({startX:w.px,startY:w.py,curX:w.px,curY:w.py,points:[[w.px,w.py]]})},p=l=>{if(!j.current)return;const w=U(l);g(C=>C&&{...C,curX:w.px,curY:w.py,points:me(C.points,w.px,w.py)})},R=l=>{try{l.currentTarget.releasePointerCapture(l.pointerId)}catch{}E(l)};return n.jsx("canvas",{ref:b,style:{position:"absolute",...c?{left:`${c.left}px`,top:`${c.top}px`,width:`${c.width}px`,height:`${c.height}px`}:{inset:0,width:"100%",height:"100%"},pointerEvents:e?"auto":"none",cursor:e?"crosshair":"default",zIndex:e?40:25},onPointerDown:i,onPointerMove:p,onPointerUp:R,onPointerCancel:R})}function jt(e,t,r,o,s,h,a=!1){const b=Te(r.width,r.height,h);let v=(e-r.left-b.left)/b.width,g=(t-r.top-b.top)/b.height;return!(v>=0&&v<=1&&g>=0&&g<=1)&&!a?null:(v=Math.min(1,Math.max(0,v)),g=Math.min(1,Math.max(0,g)),{x:Math.round(v*o),y:Math.round(g*s)})}const Ct=5e3;function At(e,t){if(e.httpStatus===404)return{ended:!0,startedAt:t};if(e.httpStatus!==200)return{ended:!1,startedAt:t};const r=e.body??{};return r.status!=="running"?{ended:!0,startedAt:t}:t&&r.startedAt&&r.startedAt!==t?{ended:!0,startedAt:t}:{ended:!1,startedAt:t??r.startedAt}}function It(e,t,r,o=Ct){const s=u.useRef(r);s.current=r,u.useEffect(()=>{if(!t)return;let h=!1,a=!1,b;const v=async()=>{if(!(a||h)){a=!0;try{const f=await fetch(`/xenon/api/control/${encodeURIComponent(e)}/stream/status`),y=f.ok?await f.json().catch(()=>{}):void 0;if(h)return;const c=At({httpStatus:f.status,body:y},b);b=c.startedAt,c.ended&&(h=!0,s.current())}catch{}finally{a=!1}}};v();const g=setInterval(v,o);return()=>{h=!0,clearInterval(g)}},[e,t,o])}const Dt=3,kt=45e3,be=[2e3,5e3,1e4];function _t(e){const t=Math.max(0,Math.min(e,be.length-1));return be[t]}function Mt(e){return e<Dt}function ve(e){const t=(e.lastError||"").toLowerCase();return/did not find test app|not installed|webdriveragentrunner|applicationverification/.test(t)?"WebDriverAgent is not installed on this device. Install and trust WDA, then retry.":/unsupported ios version|manualpairingtunnelstart/.test(t)?"This device’s iOS version is not supported for live streaming on this host.":/econnrefused|econnreset|connection reset|tunnel/.test(t)?"Lost the connection to the device tunnel. Reconnect the device, then retry.":e.lastError&&e.lastError.trim()?e.lastError.trim():"We couldn’t start the live stream for this device."}function $t(e){for(let t=0;t+4<e.length;t++){const r=e[t]===0&&e[t+1]===0&&e[t+2]===0&&e[t+3]===1,o=e[t]===0&&e[t+1]===0&&e[t+2]===1;if(!r&&!o)continue;const s=t+(r?4:3);if((e[s]&31)===7){const h=a=>a.toString(16).padStart(2,"0");return`avc1.${h(e[s+1])}${h(e[s+2])}${h(e[s+3])}`}}return"avc1.42e01e"}const Ot=({wsUrl:e,onFatal:t,onReady:r,onFrameSize:o,className:s})=>{const h=u.useRef(null),a=u.useRef(t);a.current=t;const b=u.useRef(r);b.current=r;const v=u.useRef(o);return v.current=o,u.useEffect(()=>{var D;const g=window,f=h.current;if(typeof g.VideoDecoder>"u"||!f){(D=a.current)==null||D.call(a);return}const y=f.getContext("2d");let c=!1,S=!1,m=!0,x=0;const j=new g.VideoDecoder({output:T=>{var k,M;if(c){T.close();return}(f.width!==T.displayWidth||f.height!==T.displayHeight)&&(f.width=T.displayWidth,f.height=T.displayHeight,(k=v.current)==null||k.call(v,T.displayWidth,T.displayHeight)),y==null||y.drawImage(T,0,0),T.close(),m&&(m=!1,(M=b.current)==null||M.call(b))},error:()=>{var T;return(T=a.current)==null?void 0:T.call(a)}}),I=new WebSocket(e);return I.binaryType="arraybuffer",I.onerror=()=>{var T;return(T=a.current)==null?void 0:T.call(a)},I.onclose=()=>{var T;c||(T=a.current)==null||T.call(a)},I.onmessage=T=>{var E;const k=T.data,M=new DataView(k).getUint8(0),U=new Uint8Array(k,1);if(M===0){if(S)return;try{j.configure({codec:$t(U),optimizeForLatency:!0}),S=!0}catch{(E=a.current)==null||E.call(a)}return}if(!(!S||j.state!=="configured"))try{j.decode(new g.EncodedVideoChunk({type:M===1?"key":"delta",timestamp:x,data:U})),x+=11111}catch{}},()=>{c=!0;try{I.close()}catch{}try{j.state!=="closed"&&j.close()}catch{}}},[e]),n.jsx("canvas",{ref:h,className:s,style:{width:"100%",height:"100%",objectFit:"contain",display:"block"}})};function Pt(e,t,r){return(e==="android"||e==="androidtv"||e==="android-tv")&&t==="h264"&&r?"h264":"mjpeg"}const Lt=10,Bt=500;function zt({udid:e,name:t,recordingId:r,annotateMode:o,shape:s,color:h,aspect:a="9 / 16",screenWidth:b,screenHeight:v,platform:g,onAnnotation:f,overlayAnnotations:y,onOverlayAnnotationsChange:c,onRemove:S}){const[m,x]=u.useState("connecting"),[j,I]=u.useState(),D=u.useCallback((d,N)=>{if(!(d>0)||!(N>0))return;const B=d/N;I(z=>z!==void 0&&Math.abs(z-B)<.001?z:B)},[]),[T,k]=u.useState(0),[M,U]=u.useState(null),E=u.useRef(0),i=u.useRef(null),[p,R]=u.useState(""),[l,w]=u.useState([]),[C,A]=u.useState(!1),_=u.useRef(null),L=u.useRef(null),Y=g==="android"||g==="androidtv"||g==="android-tv",$=g==="ios"||g==="tvos";u.useEffect(()=>{let d=!1;if(r){U(null),x("connecting"),k(Date.now()),O.startStream(e).catch(()=>{});return}const N=typeof window.VideoDecoder<"u";return(async()=>{try{const B=encodeURIComponent(e),z=await fetch(`/xenon/api/control/${B}/stream/status`);if(!z.ok)return;const P=await z.json();if(Pt(g||"",P==null?void 0:P.type,N)!=="h264"||!(P!=null&&P.h264Path))return;const G=await fetch(`/xenon/api/control/${B}/stream/ticket`,{method:"POST"});if(!G.ok)return;const{ticket:X}=await G.json();if(d||!X)return;const Q=`${window.location.protocol==="https:"?"wss":"ws"}://${window.location.host}${P.h264Path}?ticket=${encodeURIComponent(X)}`;U(Q)}catch{}})(),()=>{d=!0}},[e,g,r]);const F=!o&&!!b&&!!v,oe=(d,N,B,z=!1)=>jt(d,N,B,b,v,j,z),De=(d,N,B)=>{const z=Date.now()+Math.random(),P=d-B.left,G=N-B.top;w(X=>[...X,{id:z,x:P,y:G}]),window.setTimeout(()=>{w(X=>X.filter(J=>J.id!==z))},500)},ke=d=>{if(!F||m==="unavailable"||d.button!==0)return;const N=d.currentTarget;N.focus(),oe(d.clientX,d.clientY,N.getBoundingClientRect())&&(N.setPointerCapture(d.pointerId),L.current={startX:d.clientX,startY:d.clientY,startTime:Date.now(),rect:N.getBoundingClientRect()},De(d.clientX,d.clientY,L.current.rect))},_e=async d=>{var Q,ue;const N=L.current;if(L.current=null,!N||!F)return;try{d.currentTarget.releasePointerCapture(d.pointerId)}catch{}const B=d.clientX-N.startX,z=d.clientY-N.startY,P=Math.hypot(B,z),G=Date.now()-N.startTime,X=oe(N.startX,N.startY,N.rect,!0),J=P<Lt;try{if(J&&G<Bt)await O.tap(e,X.x,X.y);else if(J)await((ue=(Q=O).touchAndHold)==null?void 0:ue.call(Q,e,X.x,X.y,G));else{const ee=oe(d.clientX,d.clientY,N.rect,!0);await O.swipe(e,X.x,X.y,ee.x,ee.y)}}catch(ee){console.error(`[DeviceTile] gesture failed for ${e}`,ee)}},Me=()=>{L.current=null},$e=async d=>{if(!F||m==="unavailable"||d.metaKey||d.ctrlKey||d.altKey)return;const N=d.key;try{if(N.length===1){d.preventDefault(),await O.typeText(e,N);return}if(N==="Backspace"){d.preventDefault(),Y?await O.pressKey(e,67):await O.typeText(e,"\b");return}if(N==="Enter"){d.preventDefault(),Y?await O.pressKey(e,66):await O.typeText(e,`
2
- `);return}if(N==="Tab"){d.preventDefault(),await O.typeText(e," ");return}N==="Escape"&&Y&&(d.preventDefault(),await O.pressKey(e,te.BACK))}catch(B){console.error(`[DeviceTile] keystroke "${N}" failed for ${e}`,B)}},Oe=()=>O.pressKey(e,Y?te.HOME:qe.HOME).catch(d=>console.error(`[DeviceTile] home failed for ${e}`,d)),Pe=()=>O.pressKey(e,te.BACK).catch(d=>console.error(`[DeviceTile] back failed for ${e}`,d)),Le=()=>O.pressKey(e,te.APP_SWITCH).catch(d=>console.error(`[DeviceTile] app-switch failed for ${e}`,d)),Be=async()=>{try{const d=await O.getScreenshot(e),N=(d==null?void 0:d.screenshot)??(d==null?void 0:d.value)??d;if(!N)return;const B=await fetch(`data:image/png;base64,${N}`).then(G=>G.blob()),z=URL.createObjectURL(B),P=document.createElement("a");P.href=z,P.download=`${t||e}-${Date.now()}.png`,document.body.appendChild(P),P.click(),P.remove(),setTimeout(()=>URL.revokeObjectURL(z),1e3)}catch(d){console.error(`[DeviceTile] screenshot failed for ${e}`,d)}};u.useEffect(()=>{console.log(`[DeviceTile] Rendering ${e} in state: ${m}`)},[e,m]);const ze=`/xenon/api/control/${encodeURIComponent(e)}/stream?t=${T}`,de=u.useCallback(async()=>{try{const d=await fetch(`/xenon/api/control/${encodeURIComponent(e)}/stream/status`);if(!d.ok)throw new Error(String(d.status));const N=await d.json();R(ve({lastError:N==null?void 0:N.lastError,status:N==null?void 0:N.status}))}catch{R(ve({}))}},[e]),se=u.useCallback(()=>{const d=E.current;Mt(d)?(E.current=d+1,i.current&&clearTimeout(i.current),i.current=setTimeout(()=>{x("connecting"),k(Date.now())},_t(d))):(x("unavailable"),de())},[de]);u.useEffect(()=>{if(m!=="connecting")return;const d=setTimeout(se,kt);return()=>clearTimeout(d)},[m,T,se]),It(e,m==="live"&&!M,()=>{console.warn(`[DeviceTile] MJPEG stream ended for ${e}; reconnecting`),x("connecting"),k(Date.now())}),u.useEffect(()=>()=>{i.current&&clearTimeout(i.current)},[]);const Ue=()=>{i.current&&clearTimeout(i.current),E.current=0,R(""),x("connecting"),k(Date.now())},H=!!r,Z=t||e.slice(0,16)+"…";return n.jsxs("div",{className:"flex items-stretch justify-center w-full h-full min-h-0 min-w-0 gap-2",children:[n.jsxs("div",{className:"theme-dark relative bg-[var(--black)] rounded-lg overflow-hidden border border-[var(--border)] group max-h-full max-w-full self-center",style:{aspectRatio:a,height:"100%"},children:[m==="connecting"&&n.jsxs("div",{role:"status","aria-live":"polite",className:"flex flex-col items-center justify-center gap-1 px-4 text-center bg-[rgb(var(--rgb-well)/0.8)] text-[var(--text-dim)] absolute inset-0 z-20 pointer-events-none",children:[n.jsx("div",{"aria-hidden":!0,className:"w-10 h-10 mb-3 border-4 border-[var(--border)] border-t-[var(--text-dim)] rounded-full animate-spin"}),n.jsx("div",{className:"font-semibold text-[var(--text)]",children:"Starting stream…"}),n.jsx("div",{className:"text-xs text-[var(--text-dim)] truncate max-w-full",children:Z}),n.jsx("div",{className:"text-[11px] mt-3 text-[var(--text-dim)] leading-snug",children:$?"iPhone streams can take up to 20 seconds to start.":"Connecting to the device…"})]}),m==="unavailable"&&n.jsx("div",{role:"alert",className:"flex items-center justify-center bg-[var(--black)] text-[var(--text-dim)] absolute inset-0 z-20",children:n.jsxs("div",{className:"text-center p-6",children:[n.jsx(Ze,{"aria-hidden":!0,size:36,className:"mx-auto mb-3 text-[var(--text-dim)]"}),n.jsx("div",{className:"font-semibold text-[var(--text)]",children:"Connection failed"}),n.jsx("p",{className:"text-xs mt-2 text-[var(--text-dim)] leading-relaxed max-w-[240px] mx-auto",children:p||"We couldn’t start the live stream for this device."}),n.jsx("button",{type:"button",className:"mt-5 text-sm font-semibold px-4 py-2 rounded bg-[var(--color-accent)] hover:bg-[var(--color-accent-strong)] text-[var(--color-on-accent)] transition-colors",onClick:Ue,children:"Retry"})]})}),M?n.jsx(Ot,{wsUrl:M,className:"absolute inset-0 w-full h-full object-contain bg-black select-none pointer-events-none",onReady:()=>x("live"),onFrameSize:D,onFatal:()=>{console.warn(`[DeviceTile] H.264 fatal for ${e}; falling back to MJPEG`),U(null),x("connecting"),k(Date.now())}}):n.jsx("img",{src:ze,alt:Z,className:"absolute inset-0 w-full h-full object-contain bg-black select-none pointer-events-none",draggable:!1,style:{opacity:m==="live"?1:0,transition:"opacity 0.3s ease-in-out"},onLoad:d=>{console.log(`[DeviceTile] Image LOADED for ${e}`),D(d.currentTarget.naturalWidth,d.currentTarget.naturalHeight),E.current=0,i.current&&clearTimeout(i.current),x("live")},onError:d=>{console.error(`[DeviceTile] Image ERROR for ${e}`,d),se()}},T),F&&m!=="unavailable"&&n.jsx("div",{ref:_,className:`absolute inset-0 z-[35] touch-none outline-none ${C?"ring-2 ring-[rgb(var(--rgb-accent)/0.6)] ring-inset rounded-lg":""}`,tabIndex:0,onPointerDown:ke,onPointerUp:_e,onPointerCancel:Me,onKeyDown:$e,onFocus:()=>A(!0),onBlur:()=>A(!1)}),n.jsx("div",{className:"absolute inset-0 z-20 pointer-events-none overflow-hidden",children:l.map(d=>n.jsx("span",{className:"absolute block w-10 h-10 rounded-full border-2 border-[var(--color-accent-soft)] animate-ping",style:{left:d.x-20,top:d.y-20}},d.id))}),H&&n.jsx(Tt,{enabled:o,shape:s,color:h,committed:y,mediaAspect:j,onCommittedChange:c,onCommit:(d,N)=>f(r,d,N)}),H&&o&&m==="live"&&n.jsx("div",{className:"absolute top-3 left-14 right-3 z-30 flex justify-end pointer-events-none",children:n.jsx("span",{className:"px-2 py-0.5 rounded-sm bg-[var(--color-info)] text-white text-[10px] font-semibold shadow-lg whitespace-nowrap overflow-hidden text-ellipsis",children:"Annotating · Esc to stop"})}),H&&n.jsx("div",{className:"absolute top-3 left-3 z-30 pointer-events-none",children:n.jsx("span",{className:"px-2 py-0.5 rounded-sm bg-[var(--red-600)] text-white text-[9px] font-black shadow-lg",children:"REC"})}),n.jsxs("div",{className:"absolute top-3 left-3 z-30 flex flex-col gap-1.5 pointer-events-none opacity-0 group-hover:opacity-100 transition-opacity duration-150",children:[m==="live"&&n.jsx("span",{className:"px-2 py-0.5 rounded-sm bg-[var(--color-success)] text-[var(--color-on-success)] text-[11px] font-semibold shadow-lg w-fit",children:"Live"}),n.jsx("span",{className:"px-2 py-1 rounded bg-[rgb(var(--rgb-well)/0.8)] text-[var(--text)] text-[11px] font-medium backdrop-blur-md border border-[rgb(var(--rgb-fg)/0.1)] shadow-xl truncate max-w-[180px]",children:Z})]})]}),n.jsx(Ut,{streamState:m,recording:H,isIOS:$,isAndroid:Y,onClose:!H&&S?()=>S(e):void 0,sendHome:Oe,sendBack:Pe,sendAppSwitch:Le,captureScreenshot:Be,displayName:Z})]})}const re="w-7 h-7 flex items-center justify-center rounded-md hover:bg-[var(--surface-2)] hover:text-[var(--text)] transition-colors";function Ut({streamState:e,recording:t,isIOS:r,isAndroid:o,onClose:s,sendHome:h,sendBack:a,sendAppSwitch:b,captureScreenshot:v,displayName:g}){const f=e==="live";return!s&&!f?null:n.jsxs("div",{className:"self-stretch w-9 flex flex-col items-center justify-between gap-1 py-2 rounded-lg bg-[var(--surface)] border border-[var(--border)] text-[var(--text-dim)]",children:[n.jsx("div",{className:"flex flex-col items-center gap-1",children:s&&n.jsx("button",{type:"button","aria-label":`Remove ${g}`,title:"Remove from the grid",onClick:s,className:"w-7 h-7 flex items-center justify-center rounded-md hover:bg-[rgb(var(--rgb-red)/0.15)] hover:text-[var(--color-danger)] transition-colors",children:n.jsx(Ve,{"aria-hidden":!0,size:16})})}),f&&n.jsxs("div",{className:"flex flex-col items-center gap-1.5 my-auto",children:[(o||r)&&n.jsx("button",{type:"button","aria-label":"Home",title:"Home",onClick:h,className:re,children:n.jsx(He,{"aria-hidden":!0,size:15})}),o&&n.jsx("button",{type:"button","aria-label":"Back",title:"Back",onClick:a,className:re,children:n.jsx(Qe,{"aria-hidden":!0,size:16})}),o&&n.jsx("button",{type:"button","aria-label":"Recent apps",title:"Recent apps",onClick:b,className:re,children:n.jsx(Ne,{"aria-hidden":!0,size:13})})]}),f&&n.jsx("div",{className:"flex flex-col items-center gap-1",children:n.jsx("button",{type:"button","aria-label":"Screenshot",title:"Screenshot",onClick:v,className:re,children:n.jsx(Je,{"aria-hidden":!0,size:15})})})]})}const Yt={1:"1fr","2x1":"1fr 1fr","2x2":"1fr 1fr","3x2":"1fr 1fr 1fr"},Xt={1:"1fr","2x1":"1fr","2x2":"1fr 1fr","3x2":"1fr 1fr"},Vt={1:1,"2x1":2,"2x2":4,"3x2":6};function Ft({layout:e,tiles:t,annotateMode:r,shape:o,color:s,onAnnotation:h,overlayAnnotationsByRecording:a,onOverlayAnnotationsChange:b,onRemove:v,onDropDevice:g}){const f=ot(e,t.length),y=Vt[f];t.length;const c=t.length,S=e==="auto"?Math.max(c,1):y,m=Math.max(0,S-c);return n.jsxs("div",{style:{display:"grid",gap:8,gridTemplateColumns:Yt[f],gridTemplateRows:Xt[f]},className:"h-full",children:[t.map(x=>n.jsx(zt,{udid:x.udid,name:x.name,mjpegPort:x.mjpegPort,recordingId:x.recordingId,aspect:x.aspect,screenWidth:x.screenWidth,screenHeight:x.screenHeight,platform:x.platform,annotateMode:r,shape:o,color:s,overlayAnnotations:x.recordingId?a==null?void 0:a[x.recordingId]:void 0,onOverlayAnnotationsChange:x.recordingId&&b?j=>b(x.recordingId,j):void 0,onAnnotation:h,onRemove:v},x.udid)),Array.from({length:m},(x,j)=>n.jsx(Gt,{onDropDevice:g},`empty-${j}`))]})}function Gt({onDropDevice:e}){const[t,r]=u.useState(!1);return n.jsxs("div",{onDragOver:o=>{e&&(o.preventDefault(),o.dataTransfer.dropEffect="copy",t||r(!0))},onDragLeave:()=>r(!1),onDrop:o=>{if(r(!1),!e)return;o.preventDefault();const s=o.dataTransfer.getData("application/x-xenon-udid")||o.dataTransfer.getData("text/plain");s&&e(s)},className:`flex flex-col items-center justify-center gap-2 rounded-lg border border-dashed transition-colors ${t?"border-[rgb(var(--rgb-accent)/0.6)] bg-[rgb(var(--rgb-accent)/0.05)]":"border-[var(--border)] bg-[rgb(var(--rgb-fg)/0.02)]"} text-[var(--text-dim)] min-h-[120px]`,children:[n.jsx("div",{"aria-hidden":"true",className:`w-8 h-8 rounded-full flex items-center justify-center ${t?"bg-[rgb(var(--rgb-accent)/0.15)] text-[var(--color-accent-soft)]":"bg-[rgb(var(--rgb-fg)/0.05)] text-[rgb(var(--rgb-fg)/0.6)]"}`,children:n.jsx(et,{size:16})}),n.jsx("div",{className:"text-xs font-medium",children:"Drag a device here"}),n.jsx("div",{className:"text-[10px] opacity-70",children:"or click one in the list"})]})}const K="/xenon/api/recordings";class je extends Error{constructor(t){super(t.message??t.error),this.body=t}}async function ne(e,t){const r=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:t?JSON.stringify(t):void 0});if(r.status===409)throw new je(await r.json());if(!r.ok)throw new Error(`HTTP ${r.status}`);return r.json()}function Kt(e,t){return ne(K,{udids:e,...t})}function Wt(e){return ne(`${K}/${encodeURIComponent(e)}/stop`)}function ye(e,t){return ne(`${K}/${encodeURIComponent(e)}/annotation`,t)}function Ht(e,t){return ne(`${K}/${encodeURIComponent(e)}/annotations/clear`,{timecodeMs:t})}async function Jt(){const e=await fetch(`${K}/active`);if(!e.ok)throw new Error(`HTTP ${e.status}`);return e.json()}function qt(e){return`${K}/${encodeURIComponent(e)}/videos.zip`}function Zt(e,t){return`${K}/${encodeURIComponent(e)}/video.mp4`}function Qt(e){return`${K}/${encodeURIComponent(e)}/composite.mp4`}function er(e,t){return t==="starting"?"Starting…":e<=1?"Record":`Record ${e} devices`}const q={"aria-hidden":!0,size:14,className:"shrink-0"};function tr({selectedUdids:e,onClearMarks:t}){const{state:r,dispatch:o}=at(),[s,h]=u.useState(()=>Date.now());u.useEffect(()=>{if(r.recordingPhase!=="recording"&&r.recordingPhase!=="stopping")return;h(Date.now());const E=window.setInterval(()=>h(Date.now()),250);return()=>window.clearInterval(E)},[r.recordingPhase]);const a=r.startedAt&&(r.recordingPhase==="recording"||r.recordingPhase==="stopping")?s-r.startedAt:0,b=r.recordingPhase==="starting"||r.recordingPhase==="stopping",v=r.recordingPhase==="idle"&&e.length>0&&!b,g=r.recordingPhase==="recording"||r.recording&&r.tiles.some(E=>!!E.recordingId),f=g&&!b,y=f,c=y&&r.annotateMode,S=!!r.groupId&&r.recordingPhase==="idle",m=e.length>1||r.downloadableVideoCount>1,x=S&&r.compositeEnabled,j=S&&!r.compositeEnabled&&(r.downloadableVideoCount===1||r.downloadableVideoCount===0&&e.length<=1),I=async()=>{var E;if(v){o({type:"SET_RECORDING_PHASE",phase:"starting"}),o({type:"SET_BANNER",banner:null});try{const i=await Kt(e);if(!((E=i.recordings)!=null&&E.length)){o({type:"SET_RECORDING_PHASE",phase:"idle"}),o({type:"SET_BANNER",banner:{tone:"error",message:"Recording did not start. Check that live preview is working, then try again."}});return}const p={};for(const l of i.recordings)p[l.udid]=l.id;const R=e.length-i.recordings.length;o({type:"START_RECORDING",groupId:i.groupId,startedAt:Date.now(),tileIds:p,compositeEnabled:i.compositeEnabled===!0}),R>0?o({type:"SET_BANNER",banner:{tone:"error",message:`Recording started on ${i.recordings.length} of ${e.length} devices (${R} failed).`}}):o({type:"SET_BANNER",banner:null})}catch(i){if(o({type:"SET_RECORDING_PHASE",phase:"idle"}),i instanceof je)if(i.body.error==="device_busy"){const p=(i.body.busyDevices??[]).map(R=>`${R.udid} (${R.reason})`).join(", ");o({type:"SET_BANNER",banner:{tone:"error",message:`Cannot start — these devices are busy: ${p}`}})}else o({type:"SET_BANNER",banner:{tone:"error",message:`Server-wide recording cap reached (${i.body.active}/${i.body.limit}).`}});else o({type:"SET_BANNER",banner:{tone:"error",message:`Recording failed: ${i.message}`}})}}},D=async()=>{if(!(!r.groupId||r.recordingPhase!=="recording")){o({type:"SET_RECORDING_PHASE",phase:"stopping"});try{const E=await Wt(r.groupId),i=(E.recordings??[]).filter(R=>R.status==="STOPPED"&&(R.sizeBytes??0)>=1024),p=(E.recordings??[]).filter(R=>R.status!=="STOPPED");o({type:"STOP_RECORDING",downloadableVideoCount:i.length,compositeEnabled:r.compositeEnabled}),i.length===0?o({type:"SET_BANNER",banner:{tone:"error",message:p.length>0?`Recording failed on ${p.length} device(s). Nothing to download.`:"Recording stopped but no playable video was produced."}}):p.length>0?o({type:"SET_BANNER",banner:{tone:"info",message:`${i.length} ready, ${p.length} failed. Download with the button above.`}}):o({type:"SET_BANNER",banner:{tone:"info",message:i.length===1?"Video ready. Download it with the button above.":`${i.length} videos ready. Download them with the button above.`}})}catch(E){o({type:"STOP_RECORDING"}),o({type:"SET_BANNER",banner:{tone:"error",message:`Stop failed: ${E.message}`}})}}},T=E=>{const i=E==="annotate";i&&!y||i!==r.annotateMode&&o({type:"SET_ANNOTATE_MODE",enabled:i})};u.useEffect(()=>{if(!r.annotateMode)return;const E=i=>{var R;if(i.key!=="Escape"||i.repeat)return;const p=i.target;p&&((R=p.closest)!=null&&R.call(p,"input, textarea, select")||p.isContentEditable)||o({type:"SET_ANNOTATE_MODE",enabled:!1})};return window.addEventListener("keydown",E),()=>window.removeEventListener("keydown",E)},[r.annotateMode,o]);const k=()=>{y&&t()},M=Object.values(r.overlayAnnotations).some(E=>((E==null?void 0:E.length)??0)>0),U=[{id:"RECT",label:"Rect"},{id:"CIRCLE",label:"Circle"},{id:"ARROW",label:"Arrow"},{id:"FREEHAND",label:"Draw"}];return n.jsxs("div",{className:"flex items-center gap-2 flex-wrap justify-end",children:[r.recordingPhase==="recording"||r.recordingPhase==="stopping"?n.jsxs("span",{className:"inline-flex items-center gap-1.5 px-2 py-1 rounded text-xs font-mono tabular-nums bg-[rgb(var(--rgb-red-600)/0.2)] text-[var(--red-200)] border border-[rgb(var(--rgb-red)/0.4)]",title:"Recording elapsed time",children:[n.jsx("span",{className:"inline-block w-1.5 h-1.5 rounded-full bg-[var(--red)] animate-pulse"}),"REC ",lt(a),r.recordingPhase==="stopping"?" · Stopping…":""]}):n.jsxs("button",{type:"button",onClick:I,disabled:!v,title:e.length===0?"Add a device to the grid first":"Record every device on the grid",className:"inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded bg-[var(--red-600)] text-white disabled:opacity-40 disabled:cursor-not-allowed light:disabled:bg-transparent light:disabled:text-[var(--text)] light:disabled:ring-1 light:disabled:ring-inset light:disabled:ring-[color:var(--border)]",children:[n.jsx(Re,{...q,size:10,fill:"currentColor"}),er(e.length,r.recordingPhase)]}),n.jsxs("button",{type:"button",onClick:D,disabled:!f,className:"inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded border border-[var(--border)] disabled:opacity-40 disabled:cursor-not-allowed",children:[n.jsx(Ne,{...q,size:12}),r.recordingPhase==="stopping"?"Stopping…":"Stop"]}),n.jsx(tt,{size:"sm",value:r.annotateMode?"annotate":"interact",onChange:T,segments:[{value:"interact",label:"Interact",title:"Tap, swipe and type on the devices (Esc)",keyShortcuts:"Escape"},{value:"annotate",label:"Annotate",title:y?"Draw marks on the recording":"Start recording to annotate",disabled:!y}]}),g&&n.jsxs("div",{className:"flex items-center gap-1 ml-1 pl-2 border-l border-[var(--border)]",children:[U.map(E=>n.jsx("button",{type:"button",disabled:!c,"aria-pressed":r.shape===E.id,onClick:()=>o({type:"SET_SHAPE",shape:E.id}),className:`px-2 py-1 text-xs rounded border disabled:opacity-40 disabled:cursor-not-allowed ${r.shape===E.id?"bg-[var(--surface-2)] border-[var(--color-info)] text-[rgb(var(--rgb-fg))]":"border-[var(--border)] opacity-80 hover:opacity-100"}`,children:E.label},E.id)),n.jsx("input",{type:"color",value:r.color,disabled:!c,onChange:E=>o({type:"SET_COLOR",color:E.target.value}),title:"Annotation color","aria-label":"Annotation color",className:"w-7 h-7 rounded border border-[var(--border)] bg-transparent cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed"}),n.jsx("button",{type:"button",onClick:k,disabled:!y||!M,title:"Clear marks from the preview and the recording",className:"px-2 py-1 text-xs rounded border border-[var(--border)] hover:bg-[var(--surface-2)] disabled:opacity-40 disabled:cursor-not-allowed",children:"Clear marks"})]}),S&&j&&n.jsxs("a",{href:Zt(r.groupId),className:"ml-1 inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded border border-[var(--border)] hover:bg-[var(--surface-2)]",download:!0,children:[n.jsx(ie,{...q}),"Download video"]}),S&&!j&&n.jsxs("a",{href:qt(r.groupId),className:"ml-1 inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded border border-[var(--border)] hover:bg-[var(--surface-2)]",download:`videos-${r.groupId}.zip`,title:"ZIP of mp4 files only (no JSON extras)",children:[n.jsx(ie,{...q}),"Download ",m?"videos":"video"]}),x&&n.jsxs("a",{href:Qt(r.groupId),className:"inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded border border-[var(--border)] hover:bg-[var(--surface-2)]",download:`side-by-side-${r.groupId}.mp4`,title:"All devices in one side-by-side video",children:[n.jsx(ie,{...q}),"Side-by-side"]})]})}function rr({remainingSec:e,onContinue:t,onReleaseNow:r}){return n.jsx("div",{role:"dialog","aria-modal":"true","aria-labelledby":"idle-warning-title",className:"fixed inset-0 z-40 bg-black/60 flex items-center justify-center",children:n.jsxs("div",{className:"bg-[var(--bg)] border border-[var(--border)] rounded-lg w-full max-w-md p-6",children:[n.jsx("h3",{id:"idle-warning-title",className:"text-base font-semibold mb-2",children:"Are you still there?"}),n.jsxs("p",{className:"text-sm text-[var(--text-dim)] mb-4",children:["Your devices will be released in"," ",n.jsxs("span",{className:"text-[var(--text)] font-mono font-semibold",children:[e,"s"]})," due to inactivity. Click ",n.jsx("strong",{children:"Continue Session"})," to keep them locked."]}),n.jsxs("div",{className:"flex justify-end gap-2",children:[n.jsx("button",{type:"button",onClick:r,className:"h-9 px-3 rounded-md border border-[var(--border)] text-sm text-[var(--text-dim)] hover:text-[var(--text)]",children:"Release now"}),n.jsx("button",{type:"button",autoFocus:!0,onClick:t,className:"h-9 px-4 rounded-md bg-[var(--color-accent)] text-[var(--color-on-accent)] text-sm font-medium",children:"Continue session"})]})]})})}function nr({message:e,onRestore:t,onDismiss:r}){return n.jsxs("div",{role:"status",className:"text-sm rounded border border-[var(--border)] bg-[var(--surface-2)] text-[var(--text)] px-3 py-2 flex items-center gap-2",children:[n.jsx(rt,{"aria-hidden":!0,size:14,className:"shrink-0 text-[var(--text-dim)]"}),n.jsx("span",{className:"flex-1",children:e}),t&&n.jsx(fe,{variant:"tonal",size:"sm",onClick:t,children:"Restore devices"}),n.jsx(fe,{variant:"ghost",size:"sm",onClick:r,children:"Dismiss"})]})}function Ce(e){var t;return((t=e.marketingName)==null?void 0:t.trim())||e.name||e.udid}function Ae(e){if(!e)return"9 / 16";const t=Number(e.screenWidth),r=Number(e.screenHeight);if(Number.isFinite(t)&&Number.isFinite(r)&&t>0&&r>0)return`${t} / ${r}`;const o=(e.platform||"").toLowerCase();return o==="tvos"||o==="androidtv"||o==="android-tv"?"16 / 9":"9 / 16"}function ae(e){const t=Number(e.screenWidth),r=Number(e.screenHeight);return{udid:e.udid,name:Ce(e),mjpegPort:0,aspect:Ae(e),screenWidth:Number.isFinite(t)&&t>0?t:void 0,screenHeight:Number.isFinite(r)&&r>0?r:void 0,platform:e.platform}}function or(e,t){return t?"blocked":e?"remove":"add"}function le(e,t,r){return!r||!e?!1:e===`manual_${r}_${t}`}function sr(e,t){return e.busy?le(e.session_id,e.udid,t):!1}function ir(e,t){return e>0&&t==="idle"}function ar(e,t,r){const o=[],s=[];for(const h of e){const a=t.find(v=>v.udid===h.udid),b=(a==null?void 0:a.name)||h.name||h.udid;a?a.offline?s.push({name:b,reason:"offline"}):a.busy&&!le(a.session_id,a.udid,r)?s.push({name:b,reason:"in_use"}):o.push(a):s.push({name:b,reason:"gone"})}return{restore:o,skipped:s}}const Ie=(e,t)=>`${e} ${t}${e===1?"":"s"}`;function cr(e,t){return`Released ${Ie(e,"device")} after ${t} minutes without activity.`}const lr={in_use:"is now in use by someone else.",offline:"is offline.",gone:"is no longer connected."};function dr(e,t){return t.length===0?null:[e>0?`Restored ${Ie(e,"device")}.`:"No devices restored.",...t.map(o=>`${o.name} ${lr[o.reason]}`)].join(" ")}function ur(){let e=Promise.resolve();return{enqueue(t){const r=e.then(t,t);return e=r.then(()=>{},()=>{}),r}}}const we=["mousemove","mousedown","keydown","touchstart","wheel"];function fr({idleAfterMs:e,warningSec:t,onWarning:r,onTimeout:o,enabled:s}){const[h,a]=u.useState(!1),[b,v]=u.useState(null),g=u.useRef(null),f=u.useRef(null),y=u.useRef(!1),c=u.useRef(r),S=u.useRef(o);c.current=r,S.current=o;function m(){g.current&&(clearTimeout(g.current),g.current=null),f.current&&(clearInterval(f.current),f.current=null)}function x(){y.current=!0,a(!0),v(t),c.current(t);let D=t;f.current=setInterval(()=>{D-=1,D<=0?(m(),y.current=!1,a(!1),v(null),S.current()):v(D)},1e3)}function j(){m(),y.current=!1,a(!1),v(null);const D=e-t*1e3;g.current=setTimeout(x,Math.max(0,D))}function I(){s&&j()}return u.useEffect(()=>{if(!s){m(),y.current=!1,a(!1),v(null);return}function D(){y.current||j()}return we.forEach(T=>window.addEventListener(T,D,{passive:!0})),j(),()=>{we.forEach(T=>window.removeEventListener(T,D)),m()}},[s,e,t]),{warning:h,remainingSec:b,reset:I}}const Ee=5*60*1e3,hr=30;function pr(e,t){if(e.busy)return e.session_id?e.session_id.startsWith("manual_")?le(e.session_id,e.udid,t)?"manual_self":"manual_other":"automation":"unknown"}function mr(e,t){return{udid:e.udid,name:Ce(e),altName:e.name,platform:e.platform,busy:e.busy,busyReason:pr(e,t),mjpegServerPort:e.mjpegServerPort,offline:!!e.offline}}function Ar(){const[e,t]=ct(),[r,o]=u.useState([]),[s,h]=u.useState("loading"),[a,b]=u.useState(0),[v,g]=u.useState(null),f=u.useRef(!1),y=u.useRef(ur());u.useEffect(()=>{let i=!1;return fetch("/xenon/api/auth/me",{credentials:"include"}).then(p=>p.ok?p.json():null).then(p=>{!i&&(p!=null&&p.userId)&&g(p.userId)}).catch(()=>{}),()=>{i=!0}},[]),u.useEffect(()=>{let i=!1;const p=async()=>{try{const l=await O.getDevices();if(i)return;o(Array.isArray(l)?l:[]),h("ready")}catch{i||h("error")}};p();const R=window.setInterval(p,5e3);return()=>{i=!0,window.clearInterval(R)}},[a]),u.useEffect(()=>{let i=!1;if(!(!v||f.current))return f.current=!0,(async()=>{var l;let p=[],R=[];try{const w=await O.getDevices();p=Array.isArray(w)?w:[];const C=p.filter(_=>sr(_,v));if(R=(await Promise.all(C.map(async _=>{try{const L=await fetch(`/xenon/api/control/${encodeURIComponent(_.udid)}/stream/status`);if(!L.ok)return null;const Y=await L.json();return(Y==null?void 0:Y.status)==="running"?_:null}catch{return null}}))).filter(_=>_!==null).map(ae),i)return;R.length>0&&t({type:"SET_TILES",tiles:R})}catch{}try{const{serverNow:w,groups:C}=await Jt(),A=C[0];if(i||!A)return;const _=new Set(R.map($=>$.udid)),L=A.recordings.filter($=>!_.has($.udid)).map($=>p.find(F=>F.udid===$.udid)).filter($=>!!$).map(ae);L.length>0&&t({type:"SET_TILES",tiles:[...R,...L]});const Y={};for(const $ of A.annotations){let F;try{F=JSON.parse($.geometry)}catch{continue}(Y[l=$.recordingId]??(Y[l]=[])).push({shape:$.shape,color:$.color,geometry:F,text:$.text??void 0})}t({type:"REHYDRATE_RECORDING",groupId:A.groupId,startedAt:Date.now()-(w-Date.parse(A.startedAt)),tileIds:Object.fromEntries(A.recordings.map($=>[$.udid,$.id])),compositeEnabled:A.compositeEnabled,overlayAnnotations:Y})}catch{}})(),()=>{i=!0}},[v,t]),u.useEffect(()=>{for(const i of e.tiles){if(i.screenWidth&&i.screenHeight)continue;const p=r.find(w=>w.udid===i.udid);if(!p)continue;const R=Number(p.screenWidth),l=Number(p.screenHeight);Number.isFinite(R)&&R>0&&Number.isFinite(l)&&l>0&&t({type:"PATCH_TILE_DIMS",udid:i.udid,screenWidth:R,screenHeight:l,aspect:Ae(p)})}},[r,e.tiles,t]);const c=u.useMemo(()=>new Set(e.tiles.map(i=>i.udid)),[e.tiles]),S=u.useMemo(()=>r.map(i=>mr(i,v)),[r,v]),m=async i=>{t({type:"ADD_TILE",tile:ae(i)});const p=await O.startStream(i.udid).catch(()=>null);Ge(p)&&t({type:"REMOVE_TILE",udid:i.udid})},x=async i=>{const p=or(e.tiles.some(l=>l.udid===i),e.recording);if(p==="blocked"){t({type:"SET_ERROR_BANNER",message:"Stop recording before changing the devices on the grid."});return}if(p==="remove"){await j(i);return}const R=r.find(l=>l.udid===i);R&&await m(R)},j=async i=>{t({type:"REMOVE_TILE",udid:i});try{await fetch(`/xenon/api/control/${encodeURIComponent(i)}/stream/stop`,{method:"POST"})}catch{}b(p=>p+1)},I=(i,p,R)=>{if(!e.groupId)return;const l=e.groupId,w=e.startedAt?Date.now()-e.startedAt:0,C={recordingId:i,timecodeMs:w,shape:p.shape,geometry:JSON.stringify(p.geometry),color:p.color,text:p.text};y.current.enqueue(async()=>{try{return await ye(l,R?{...C,image:R}:C)}catch(A){if(!R)throw A;return ye(l,C)}}).catch(A=>t({type:"SET_ERROR_BANNER",message:`Annotation failed: ${A.message}`}))},D=()=>{if(!e.groupId)return;const i=e.groupId,p=e.startedAt?Date.now()-e.startedAt:0;t({type:"CLEAR_OVERLAY_ANNOTATIONS"}),y.current.enqueue(()=>Ht(i,p)).catch(()=>t({type:"SET_ERROR_BANNER",message:"Couldn't clear marks from the recording. They will still appear in the video."}))},T=()=>{for(const i of e.tiles){const p=`/xenon/api/control/${encodeURIComponent(i.udid)}/stream/stop`;try{navigator.sendBeacon?navigator.sendBeacon(p):fetch(p,{method:"POST",keepalive:!0}).catch(()=>{})}catch{}}e.tiles.forEach(i=>t({type:"REMOVE_TILE",udid:i.udid}))},[k,M]=u.useState(null),U=async()=>{const i=k==null?void 0:k.tiles;if(!i)return;const p=ar(i,r,v);for(const l of p.restore)await m(l);const R=dr(p.restore.length,p.skipped);M(R?{message:R,tiles:null}:null),b(l=>l+1)},E=fr({idleAfterMs:Ee,warningSec:hr,enabled:ir(e.tiles.length,e.recordingPhase),onWarning:()=>{},onTimeout:()=>{const i=e.tiles;T(),M({message:cr(i.length,Ee/6e4),tiles:i})}});return n.jsxs(Se.Provider,{value:{state:e,dispatch:t},children:[n.jsxs("div",{className:"flex flex-col h-full p-4 gap-3",children:[n.jsxs("header",{className:"flex items-center justify-between gap-3",children:[n.jsxs("div",{className:"flex items-center gap-3",children:[n.jsx(nt,{icon:Fe,children:"Live devices"}),n.jsx(pt,{value:e.layout,onChange:i=>t({type:"SET_LAYOUT",layout:i})})]}),n.jsx(tr,{selectedUdids:e.tiles.map(i=>i.udid),onClearMarks:D})]}),e.banner&&n.jsxs("div",{role:"alert",className:`text-sm rounded border px-3 py-2 flex items-center gap-2 ${e.banner.tone==="error"?"border-[rgb(var(--rgb-red)/0.4)] bg-[rgb(var(--rgb-red)/0.1)] text-[var(--red-100)]":"border-[rgb(var(--rgb-success)/0.4)] bg-[rgb(var(--rgb-success)/0.1)] text-[var(--text)]"}`,children:[n.jsx("span",{className:"flex-1",children:e.banner.message}),n.jsx("button",{type:"button",className:"text-xs opacity-80 hover:opacity-100",onClick:()=>t({type:"SET_BANNER",banner:null}),children:"Dismiss"})]}),k&&n.jsx(nr,{message:k.message,onRestore:k.tiles&&!e.recording?U:void 0,onDismiss:()=>M(null)}),n.jsxs("div",{className:"grid grid-cols-[260px_1fr] gap-3 flex-1 min-h-0",children:[n.jsxs("aside",{className:"flex flex-col gap-2 border border-[var(--border)] rounded p-3 overflow-y-auto min-h-0",children:[n.jsxs("div",{className:"flex items-center justify-between",children:[n.jsx("span",{className:"text-xs text-[var(--text-dim)]",children:"Devices"}),n.jsx("button",{className:"text-xs underline opacity-70 hover:opacity-100",onClick:()=>b(i=>i+1),children:"Refresh"})]}),n.jsx(ft,{devices:S,inMosaic:c,onToggle:x,status:s}),n.jsx("p",{className:"mt-2 text-[11px] text-[var(--text-dim)] leading-relaxed",children:"Click a device to add it to the grid. Record captures every device on the grid; after Stop, download the video."})]}),n.jsx("main",{className:"border border-[var(--border)] rounded p-2 overflow-y-auto h-full min-h-0",children:n.jsx(Ft,{layout:e.layout,tiles:e.tiles,annotateMode:e.annotateMode,shape:e.shape,color:e.color,overlayAnnotationsByRecording:e.overlayAnnotations,onOverlayAnnotationsChange:(i,p)=>t({type:"SET_OVERLAY_ANNOTATIONS",recordingId:i,annotations:p}),onAnnotation:I,onRemove:j,onDropDevice:x})})]})]}),E.warning&&E.remainingSec!==null&&n.jsx(rr,{remainingSec:E.remainingSec,onContinue:E.reset,onReleaseNow:T})]})}export{Ar as default};
1
+ import{r as u,j as n,B as Ye,z as Xe,X as O,y as Ve,T as Fe,_ as Ge}from"./index-CbC9kGzR.js";import{p as Ke}from"./labels-C21SA4JG.js";import{C as We}from"./circle-check-CY1FVKEM.js";import{C as Re,A as te,H as He,S as Ne,a as Je,I as qe}from"./keycodes-DwpzQkCL.js";import{V as Ze}from"./video-off-Dhb4hlQJ.js";import{C as Qe}from"./chevron-left-DfBtWaTB.js";import{P as et}from"./plus-CUw6PQEq.js";import{S as tt}from"./SegmentedControl-Dv49e2ww.js";import{D as ie}from"./download-eLe3MTlf.js";import{B as fe}from"./button-DltzrxJt.js";import{C as rt}from"./clock-C3HFHOjc.js";import{a as nt}from"./page-header-DNv41R4K.js";import"./utils-CDN07tui.js";function ot(e,t){return e!=="auto"?e:t<=1?"1":t===2?"2x1":t<=4?"2x2":"3x2"}const st={selected:new Set,layout:"auto",tiles:[],groupId:null,compositeEnabled:!1,downloadableVideoCount:0,recordingPhase:"idle",recording:!1,startedAt:null,annotateMode:!1,shape:"RECT",color:"#ff3333",overlayAnnotations:{},errorBanner:null,banner:null};function it(e,t){var r;switch(t.type){case"SET_LAYOUT":return{...e,layout:t.layout};case"TOGGLE_SELECTED":{const o=new Set(e.selected);return o.has(t.udid)?o.delete(t.udid):o.add(t.udid),{...e,selected:o}}case"CLEAR_SELECTED":return{...e,selected:new Set};case"SET_TILES":return{...e,tiles:t.tiles};case"ADD_TILE":return e.tiles.some(o=>o.udid===t.tile.udid)?e:{...e,tiles:[...e.tiles,t.tile]};case"PATCH_TILE_DIMS":{let o=!1;const s=e.tiles.map(h=>h.udid!==t.udid||h.screenWidth&&h.screenHeight?h:(o=!0,{...h,screenWidth:t.screenWidth,screenHeight:t.screenHeight,aspect:t.aspect??h.aspect}));return o?{...e,tiles:s}:e}case"REMOVE_TILE":return e.recordingPhase!=="idle"?e:{...e,tiles:e.tiles.filter(o=>o.udid!==t.udid)};case"BIND_RECORDING_IDS":{const o=e.tiles.map(s=>({...s,recordingId:t.map[s.udid]??s.recordingId}));return{...e,tiles:o}}case"SET_RECORDING_PHASE":{const o=t.phase;return{...e,recordingPhase:o,recording:o==="recording"||o==="stopping"}}case"START_RECORDING":{const o=e.tiles.map(s=>({...s,recordingId:t.tileIds[s.udid]??s.recordingId}));return{...e,groupId:t.groupId,compositeEnabled:t.compositeEnabled===!0,downloadableVideoCount:0,recordingPhase:"recording",recording:!0,annotateMode:!1,startedAt:t.startedAt,overlayAnnotations:{},tiles:o}}case"REHYDRATE_RECORDING":{const o=e.tiles.map(s=>({...s,recordingId:t.tileIds[s.udid]??s.recordingId}));return{...e,groupId:t.groupId,compositeEnabled:t.compositeEnabled,downloadableVideoCount:0,recordingPhase:"recording",recording:!0,annotateMode:!1,startedAt:t.startedAt,overlayAnnotations:t.overlayAnnotations,tiles:o}}case"STOP_RECORDING":{const o=e.tiles.map(s=>({...s,recordingId:void 0}));return{...e,recording:!1,recordingPhase:"idle",annotateMode:!1,overlayAnnotations:{},downloadableVideoCount:t.downloadableVideoCount??e.downloadableVideoCount,compositeEnabled:t.compositeEnabled!==void 0?t.compositeEnabled:e.compositeEnabled,tiles:o}}case"SET_ANNOTATE_MODE":return{...e,annotateMode:t.enabled};case"SET_SHAPE":return{...e,shape:t.shape};case"SET_COLOR":return{...e,color:t.color};case"SET_OVERLAY_ANNOTATIONS":return{...e,overlayAnnotations:{...e.overlayAnnotations,[t.recordingId]:t.annotations}};case"CLEAR_OVERLAY_ANNOTATIONS":return{...e,overlayAnnotations:{}};case"SET_ERROR_BANNER":return{...e,errorBanner:t.message,banner:t.message?{tone:"error",message:t.message}:null};case"SET_BANNER":return{...e,banner:t.banner,errorBanner:((r=t.banner)==null?void 0:r.tone)==="error"?t.banner.message:null};default:return e}}const Se=u.createContext(null);function at(){const e=u.useContext(Se);if(!e)throw new Error("useMosaic must be used inside <MosaicContext.Provider>");return e}function ct(){return u.useReducer(it,st)}function lt(e){const t=Math.max(0,Math.floor(e/1e3)),r=Math.floor(t/3600),o=Math.floor(t%3600/60),s=t%60;return r>0?`${r}:${String(o).padStart(2,"0")}:${String(s).padStart(2,"0")}`:`${o}:${String(s).padStart(2,"0")}`}function dt(e){switch(e){case"automation":return"In automation";case"manual_other":return"Manual control by another user";case"manual_self":return"On your grid";case"recording_other_group":return"Recording in another group";default:return e?"Busy":null}}const he=[{id:"ios",label:"iOS",match:e=>e==="ios"},{id:"android",label:"Android",match:e=>e==="android"},{id:"tvos",label:"tvOS",match:e=>e==="tvos"},{id:"androidtv",label:"Android TV",match:e=>e==="androidtv"||e==="android-tv"},{id:"other",label:"Other",match:()=>!0}],W={available:"bg-[var(--color-success)]",inUse:"bg-[var(--color-warning)]",offline:"bg-[rgb(var(--rgb-offline))]"},ut=[["available",W.available],["in use",W.inUse],["offline",W.offline]];function pe(e){return Ke(e)}function ft({devices:e,inMosaic:t,onToggle:r,status:o="ready"}){const[s,h]=u.useState(""),[a,b]=u.useState({}),v=u.useMemo(()=>{const f=s.trim().toLowerCase();return f?e.filter(y=>y.udid.toLowerCase().includes(f)||(y.name??"").toLowerCase().includes(f)||(y.altName??"").toLowerCase().includes(f)||(y.platform??"").toLowerCase().includes(f)):e},[e,s]),g=u.useMemo(()=>{const f=he.map(c=>({id:c.id,label:c.label,rows:[]})),y=c=>f.find((S,m)=>he[m].match(c))??f[f.length-1];for(const c of v)y((c.platform??"").toLowerCase()).rows.push(c);return f.filter(c=>c.rows.length>0)},[v]);if(e.length===0){const f=o==="loading"?"Loading devices…":o==="error"?"Couldn’t load devices. Retrying…":"No devices online.";return n.jsx("div",{role:"status",className:"text-xs text-[var(--text-dim)] p-3",children:f})}return n.jsxs("div",{className:"flex flex-col gap-2",children:[n.jsxs("div",{className:"relative",children:[n.jsx(Ye,{"aria-hidden":!0,size:12,className:"absolute left-2 top-1/2 -translate-y-1/2 text-[var(--text-dim)]"}),n.jsx("input",{type:"text",value:s,placeholder:"Filter devices...",onChange:f=>h(f.target.value),className:"w-full pl-7 pr-2 py-1.5 text-xs rounded border border-[var(--border)] bg-transparent placeholder:text-[var(--text-dim)] focus:outline-none focus:border-[var(--color-info)]"})]}),g.map(f=>{const y=a[f.id];return n.jsxs("section",{className:"flex flex-col gap-1",children:[n.jsxs("button",{type:"button","aria-expanded":!y,onClick:()=>b(c=>({...c,[f.id]:!c[f.id]})),className:"flex items-center justify-between w-full text-[11px] text-[var(--text-dim)] hover:text-[rgb(var(--rgb-fg))] px-1 py-0.5",children:[n.jsxs("span",{className:"flex items-center gap-1.5",children:[n.jsx(Xe,{"aria-hidden":!0,size:12,className:`transition-transform ${y?"-rotate-90":"rotate-0"}`}),f.label]}),n.jsx("span",{children:f.rows.length})]}),!y&&n.jsx("ul",{className:"flex flex-col gap-1 text-sm",children:f.rows.map(c=>{const S=c.busyReason==="manual_self",m=t.has(c.udid),x=!!c.busy&&!S&&!m||!!c.offline,j=c.offline?"Offline":dt(c.busyReason),I=!x,D=[c.name??c.udid,c.platform&&pe(c.platform)].concat(x&&j?[j]:[]).filter(Boolean).join(", ");return n.jsx("li",{children:n.jsxs("button",{type:"button",disabled:x,draggable:!x,onDragStart:T=>{T.dataTransfer.effectAllowed="copy",T.dataTransfer.setData("application/x-xenon-udid",c.udid),T.dataTransfer.setData("text/plain",c.udid)},onClick:()=>r(c.udid),"aria-label":D,"aria-pressed":m,className:`w-full flex items-center gap-2 px-2 py-1.5 rounded text-left border transition-colors ${x?"opacity-60 cursor-not-allowed border-transparent":m?"border-[rgb(var(--rgb-accent)/0.4)] bg-[rgb(var(--rgb-accent)/0.05)] hover:bg-[rgb(var(--rgb-accent)/0.1)]":"border-transparent hover:border-[var(--border)] hover:bg-[var(--surface-2)]"}`,title:x?`${j} — release first`:m?"Click to remove from the grid":"Click to add to the grid (or drag to a cell)",children:[m?n.jsx(We,{"aria-hidden":!0,size:14,className:"shrink-0 text-[var(--color-accent-soft)]"}):n.jsx(Re,{"aria-hidden":!0,size:14,className:"shrink-0 text-[var(--text-dim)]"}),n.jsx("span",{"aria-hidden":!0,className:`inline-block w-1.5 h-1.5 rounded-full ${c.offline?W.offline:I?W.available:W.inUse}`}),n.jsx("span",{className:"font-medium flex-1 truncate text-[13px]",children:c.name??c.udid}),c.platform&&n.jsx("span",{className:"text-[11px] px-1.5 py-0.5 rounded bg-[var(--surface-2)] text-[var(--text-dim)]",children:pe(c.platform)})]})},c.udid)})})]},f.id)}),s&&g.length===0&&n.jsxs("div",{className:"text-xs text-[var(--text-dim)] px-1 py-2",children:['No devices match "',s,'".']}),n.jsx("div",{className:"text-[10px] text-[var(--text-dim)] px-1 pt-2 flex items-center gap-3",children:ut.map(([f,y])=>n.jsxs("span",{className:"inline-flex items-center gap-1",children:[n.jsx("span",{className:`w-1.5 h-1.5 rounded-full inline-block ${y}`}),f]},f))})]})}const ht=[{id:"1",label:"1",icon:n.jsx(mt,{})},{id:"2x1",label:"2×1",icon:n.jsx(gt,{})},{id:"2x2",label:"2×2",icon:n.jsx(xt,{})},{id:"3x2",label:"3×2",icon:n.jsx(bt,{})},{id:"auto",label:"Auto",icon:n.jsx(vt,{})}];function pt({value:e,onChange:t}){return n.jsx("div",{role:"tablist",className:"inline-flex border border-[var(--border)] rounded-md overflow-hidden text-xs bg-[rgb(var(--rgb-white)/0.02)]",children:ht.map(r=>{const o=e===r.id;return n.jsxs("button",{role:"tab","aria-selected":o,onClick:()=>t(r.id),className:`flex items-center gap-1.5 px-2.5 py-1.5 border-r border-[var(--border)] last:border-r-0 transition-colors ${o?"bg-[var(--surface-2)] text-[rgb(var(--rgb-fg))]":"text-[var(--text-dim)] hover:bg-[var(--surface-2)] hover:text-[rgb(var(--rgb-fg))]"}`,title:`Layout: ${r.label}`,children:[n.jsx("span",{className:"w-3.5 h-3.5 inline-flex items-center justify-center",children:r.icon}),n.jsx("span",{children:r.label})]},r.id)})})}function V(e){return n.jsx("rect",{rx:1.2,ry:1.2,fill:"currentColor",...e})}function mt(){return n.jsx("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",children:V({x:2,y:2,width:10,height:10})})}function gt(){return n.jsxs("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",children:[V({x:1.5,y:3,width:5,height:8}),V({x:7.5,y:3,width:5,height:8})]})}function xt(){return n.jsxs("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",children:[V({x:1.5,y:1.5,width:5,height:5}),V({x:7.5,y:1.5,width:5,height:5}),V({x:1.5,y:7.5,width:5,height:5}),V({x:7.5,y:7.5,width:5,height:5})]})}function bt(){return n.jsxs("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",children:[V({x:1,y:1.5,width:3.3,height:5}),V({x:5.35,y:1.5,width:3.3,height:5}),V({x:9.7,y:1.5,width:3.3,height:5}),V({x:1,y:7.5,width:3.3,height:5}),V({x:5.35,y:7.5,width:3.3,height:5}),V({x:9.7,y:7.5,width:3.3,height:5})]})}function vt(){return n.jsxs("svg",{viewBox:"0 0 14 14",className:"w-3.5 h-3.5",fill:"none",stroke:"currentColor",strokeWidth:"1.4",children:[n.jsx("rect",{x:"2",y:"2",width:"10",height:"10",rx:"1.5"}),n.jsx("circle",{cx:"7",cy:"7",r:"1.5",fill:"currentColor",stroke:"none"})]})}const yt=1600;function wt(e,t){const r=yt/Math.max(e,t);return{w:Math.round(e*r),h:Math.round(t*r)}}function Et(e,t,r,o=document){if(t<=0||r<=0)return null;const{w:s,h}=wt(t,r),a=o.createElement("canvas");a.width=s,a.height=h;const b=a.getContext("2d");if(!b)return null;b.scale(s/t,h/r),ce(b,t,r,e);try{return a.toDataURL("image/png")}catch{return null}}function Te(e,t,r){const o={left:0,top:0,width:e,height:t};if(!r||!(r>0)||e<=0||t<=0)return o;const s=e/t;if(Math.abs(s-r)<1e-6)return o;if(r>s){const a=e/r;return{left:0,top:(t-a)/2,width:e,height:a}}const h=t*r;return{left:(e-h)/2,top:0,width:h,height:t}}const Rt=(e,t)=>e===t||!!e&&!!t&&e.left===t.left&&e.top===t.top&&e.width===t.width&&e.height===t.height,Nt=2,St=2e3;function me(e,t,r){if(e.length>=St)return e;const o=e[e.length-1];return o&&Math.hypot(t-o[0],r-o[1])<Nt?e:[...e,[t,r]]}function ge(e,t){const r=(e||"#ff3333").trim();if(/^#[0-9a-fA-F]{6}$/.test(r)){const o=parseInt(r.slice(1,3),16),s=parseInt(r.slice(3,5),16),h=parseInt(r.slice(5,7),16);return`rgba(${o},${s},${h},${t})`}return r}function ce(e,t,r,o){var y;const s=o.geometry,h=o.color||"#ff3333",a=Math.max(4,Math.round(Math.min(t,r)*.008));if(e.lineCap="round",e.lineJoin="round",o.shape==="CIRCLE"){const c=(s.x??0)*t,S=(s.y??0)*r,m=Math.max(2,(s.w??0)*t),x=Math.max(2,(s.h??0)*r);e.beginPath(),e.ellipse(c,S,m,x,0,0,Math.PI*2),e.fillStyle=ge(h,.22),e.fill(),e.lineWidth=a+2,e.strokeStyle="rgba(0,0,0,0.55)",e.stroke(),e.beginPath(),e.ellipse(c,S,m,x,0,0,Math.PI*2),e.lineWidth=a,e.strokeStyle=h,e.stroke();return}if(o.shape==="ARROW"){const c=(s.x??0)*t,S=(s.y??0)*r,m=c+(s.w??0)*t,x=S+(s.h??0)*r;e.lineWidth=a+2,e.strokeStyle="rgba(0,0,0,0.55)",e.beginPath(),e.moveTo(c,S),e.lineTo(m,x),e.stroke(),e.lineWidth=a,e.strokeStyle=h,e.beginPath(),e.moveTo(c,S),e.lineTo(m,x),e.stroke();const j=Math.atan2(x-S,m-c),I=Math.max(14,a*3);e.fillStyle=h,e.beginPath(),e.moveTo(m,x),e.lineTo(m-I*Math.cos(j-.4),x-I*Math.sin(j-.4)),e.lineTo(m-I*Math.cos(j+.4),x-I*Math.sin(j+.4)),e.closePath(),e.fill();return}if(o.shape==="TEXT"&&o.text){const c=Math.max(16,Math.round(Math.min(t,r)*.035));e.font=`bold ${c}px sans-serif`,e.lineWidth=3,e.strokeStyle="rgba(0,0,0,0.65)",e.strokeText(o.text,(s.x??0)*t,(s.y??0)*r),e.fillStyle=h,e.fillText(o.text,(s.x??0)*t,(s.y??0)*r);return}if(o.shape==="FREEHAND"&&(((y=s.points)==null?void 0:y.length)??0)>=2){const c=s.points,S=()=>{e.beginPath(),e.moveTo(c[0][0]*t,c[0][1]*r);for(let m=1;m<c.length;m++)e.lineTo(c[m][0]*t,c[m][1]*r)};e.lineWidth=a+2,e.strokeStyle="rgba(0,0,0,0.55)",S(),e.stroke(),e.lineWidth=a,e.strokeStyle=h,S(),e.stroke();return}const b=(s.x??0)*t,v=(s.y??0)*r,g=Math.max(2,(s.w??0)*t),f=Math.max(2,(s.h??0)*r);e.fillStyle=ge(h,.22),e.fillRect(b,v,g,f),e.lineWidth=a+2,e.strokeStyle="rgba(0,0,0,0.55)",e.strokeRect(b,v,g,f),e.lineWidth=a,e.strokeStyle=h,e.strokeRect(b,v,g,f)}function xe(e,t,r,o,s){if(o<=0||s<=0)return null;if(e==="CIRCLE"){const g=Math.hypot(r.curX-r.startX,r.curY-r.startY);return g<=4?null:{shape:e,color:t,geometry:{x:r.startX/o,y:r.startY/s,w:g/o,h:g/s}}}if(e==="ARROW"){const g=r.curX-r.startX,f=r.curY-r.startY;return Math.hypot(g,f)<=6?null:{shape:e,color:t,geometry:{x:r.startX/o,y:r.startY/s,w:g/o,h:f/s}}}if(e==="FREEHAND"){if(r.points.length<2)return null;const g=r.points.map(S=>S[0]),f=r.points.map(S=>S[1]),y=Math.min(...g),c=Math.min(...f);return{shape:e,color:t,geometry:{x:y/o,y:c/s,w:Math.max(.005,(Math.max(...g)-y)/o),h:Math.max(.005,(Math.max(...f)-c)/s),points:r.points.map(([S,m])=>[S/o,m/s])}}}const h=Math.min(r.startX,r.curX)/o,a=Math.min(r.startY,r.curY)/s,b=Math.abs(r.curX-r.startX)/o,v=Math.abs(r.curY-r.startY)/s;return b<=.005||v<=.005?null:{shape:e,color:t,geometry:{x:h,y:a,w:b,h:v}}}function Tt({enabled:e,shape:t,color:r,onCommit:o,committed:s,onCommittedChange:h,mediaAspect:a}){const b=u.useRef(null),[v,g]=u.useState(null),[f,y]=u.useState([]),[c,S]=u.useState(null),m=s??f,x=u.useRef(m),j=u.useRef(v),I=u.useRef(t),D=u.useRef(r),T=u.useRef(e);x.current=m,j.current=v,I.current=t,D.current=r,T.current=e;const k=u.useCallback(l=>{const w=l(x.current);x.current=w,h?h(w):y(w)},[h]),M=u.useCallback(()=>{const l=b.current;if(!l)return;const w=l.getContext("2d");if(!w)return;w.clearRect(0,0,l.width,l.height);for(const A of x.current)ce(w,l.width,l.height,A);const C=j.current;if(C){const A=xe(I.current,D.current,C,l.width,l.height);A&&ce(w,l.width,l.height,A)}},[]);u.useEffect(()=>{const l=b.current;if(!l)return;const w=()=>{const A=Math.max(1,Math.round(l.clientWidth)),_=Math.max(1,Math.round(l.clientHeight));(l.width!==A||l.height!==_)&&(l.width=A,l.height=_),M()};w();const C=new ResizeObserver(w);return C.observe(l),()=>C.disconnect()},[M]),u.useEffect(()=>{M()},[v,m,M]),u.useEffect(()=>{var A;const l=(A=b.current)==null?void 0:A.parentElement;if(!l)return;const w=()=>{const _=a?Te(l.clientWidth,l.clientHeight,a):null;S(L=>Rt(L,_)?L:_)};w();const C=new ResizeObserver(w);return C.observe(l),()=>C.disconnect()},[a]),u.useEffect(()=>{var w;if(e)return;g(null);const l=b.current;if(l&&l.hasPointerCapture)try{for(let C=0;C<8;C++)(w=l.hasPointerCapture)!=null&&w.call(l,C)&&l.releasePointerCapture(C)}catch{}},[e]);const U=l=>{const C=b.current.getBoundingClientRect();return{px:l.clientX-C.left,py:l.clientY-C.top,w:C.width,h:C.height}},E=l=>{const w=j.current;if(!w||!T.current){g(null);return}const C=b.current;if(!C||C.width<=0){g(null);return}const A=U(l),_=xe(I.current,D.current,{...w,curX:A.px,curY:A.py,points:me(w.points,A.px,A.py)},A.w,A.h);_&&(k(L=>[...L,_]),o(_,Et(_,A.w,A.h))),g(null)},i=l=>{if(!e||l.button!==0)return;l.preventDefault(),l.currentTarget.setPointerCapture(l.pointerId);const w=U(l);g({startX:w.px,startY:w.py,curX:w.px,curY:w.py,points:[[w.px,w.py]]})},p=l=>{if(!j.current)return;const w=U(l);g(C=>C&&{...C,curX:w.px,curY:w.py,points:me(C.points,w.px,w.py)})},R=l=>{try{l.currentTarget.releasePointerCapture(l.pointerId)}catch{}E(l)};return n.jsx("canvas",{ref:b,style:{position:"absolute",...c?{left:`${c.left}px`,top:`${c.top}px`,width:`${c.width}px`,height:`${c.height}px`}:{inset:0,width:"100%",height:"100%"},pointerEvents:e?"auto":"none",cursor:e?"crosshair":"default",zIndex:e?40:25},onPointerDown:i,onPointerMove:p,onPointerUp:R,onPointerCancel:R})}function jt(e,t,r,o,s,h,a=!1){const b=Te(r.width,r.height,h);let v=(e-r.left-b.left)/b.width,g=(t-r.top-b.top)/b.height;return!(v>=0&&v<=1&&g>=0&&g<=1)&&!a?null:(v=Math.min(1,Math.max(0,v)),g=Math.min(1,Math.max(0,g)),{x:Math.round(v*o),y:Math.round(g*s)})}const Ct=5e3;function At(e,t){if(e.httpStatus===404)return{ended:!0,startedAt:t};if(e.httpStatus!==200)return{ended:!1,startedAt:t};const r=e.body??{};return r.status!=="running"?{ended:!0,startedAt:t}:t&&r.startedAt&&r.startedAt!==t?{ended:!0,startedAt:t}:{ended:!1,startedAt:t??r.startedAt}}function It(e,t,r,o=Ct){const s=u.useRef(r);s.current=r,u.useEffect(()=>{if(!t)return;let h=!1,a=!1,b;const v=async()=>{if(!(a||h)){a=!0;try{const f=await fetch(`/xenon/api/control/${encodeURIComponent(e)}/stream/status`),y=f.ok?await f.json().catch(()=>{}):void 0;if(h)return;const c=At({httpStatus:f.status,body:y},b);b=c.startedAt,c.ended&&(h=!0,s.current())}catch{}finally{a=!1}}};v();const g=setInterval(v,o);return()=>{h=!0,clearInterval(g)}},[e,t,o])}const Dt=3,kt=45e3,be=[2e3,5e3,1e4];function _t(e){const t=Math.max(0,Math.min(e,be.length-1));return be[t]}function Mt(e){return e<Dt}function ve(e){const t=(e.lastError||"").toLowerCase();return/did not find test app|not installed|webdriveragentrunner|applicationverification/.test(t)?"WebDriverAgent is not installed on this device. Install and trust WDA, then retry.":/unsupported ios version|manualpairingtunnelstart/.test(t)?"This device’s iOS version is not supported for live streaming on this host.":/econnrefused|econnreset|connection reset|tunnel/.test(t)?"Lost the connection to the device tunnel. Reconnect the device, then retry.":e.lastError&&e.lastError.trim()?e.lastError.trim():"We couldn’t start the live stream for this device."}function $t(e){for(let t=0;t+4<e.length;t++){const r=e[t]===0&&e[t+1]===0&&e[t+2]===0&&e[t+3]===1,o=e[t]===0&&e[t+1]===0&&e[t+2]===1;if(!r&&!o)continue;const s=t+(r?4:3);if((e[s]&31)===7){const h=a=>a.toString(16).padStart(2,"0");return`avc1.${h(e[s+1])}${h(e[s+2])}${h(e[s+3])}`}}return"avc1.42e01e"}const Ot=({wsUrl:e,onFatal:t,onReady:r,onFrameSize:o,className:s})=>{const h=u.useRef(null),a=u.useRef(t);a.current=t;const b=u.useRef(r);b.current=r;const v=u.useRef(o);return v.current=o,u.useEffect(()=>{var D;const g=window,f=h.current;if(typeof g.VideoDecoder>"u"||!f){(D=a.current)==null||D.call(a);return}const y=f.getContext("2d");let c=!1,S=!1,m=!0,x=0;const j=new g.VideoDecoder({output:T=>{var k,M;if(c){T.close();return}(f.width!==T.displayWidth||f.height!==T.displayHeight)&&(f.width=T.displayWidth,f.height=T.displayHeight,(k=v.current)==null||k.call(v,T.displayWidth,T.displayHeight)),y==null||y.drawImage(T,0,0),T.close(),m&&(m=!1,(M=b.current)==null||M.call(b))},error:()=>{var T;return(T=a.current)==null?void 0:T.call(a)}}),I=new WebSocket(e);return I.binaryType="arraybuffer",I.onerror=()=>{var T;return(T=a.current)==null?void 0:T.call(a)},I.onclose=()=>{var T;c||(T=a.current)==null||T.call(a)},I.onmessage=T=>{var E;const k=T.data,M=new DataView(k).getUint8(0),U=new Uint8Array(k,1);if(M===0){if(S)return;try{j.configure({codec:$t(U),optimizeForLatency:!0}),S=!0}catch{(E=a.current)==null||E.call(a)}return}if(!(!S||j.state!=="configured"))try{j.decode(new g.EncodedVideoChunk({type:M===1?"key":"delta",timestamp:x,data:U})),x+=11111}catch{}},()=>{c=!0;try{I.close()}catch{}try{j.state!=="closed"&&j.close()}catch{}}},[e]),n.jsx("canvas",{ref:h,className:s,style:{width:"100%",height:"100%",objectFit:"contain",display:"block"}})};function Pt(e,t,r){return(e==="android"||e==="androidtv"||e==="android-tv")&&t==="h264"&&r?"h264":"mjpeg"}const Lt=10,Bt=500;function zt({udid:e,name:t,recordingId:r,annotateMode:o,shape:s,color:h,aspect:a="9 / 16",screenWidth:b,screenHeight:v,platform:g,onAnnotation:f,overlayAnnotations:y,onOverlayAnnotationsChange:c,onRemove:S}){const[m,x]=u.useState("connecting"),[j,I]=u.useState(),D=u.useCallback((d,N)=>{if(!(d>0)||!(N>0))return;const B=d/N;I(z=>z!==void 0&&Math.abs(z-B)<.001?z:B)},[]),[T,k]=u.useState(0),[M,U]=u.useState(null),E=u.useRef(0),i=u.useRef(null),[p,R]=u.useState(""),[l,w]=u.useState([]),[C,A]=u.useState(!1),_=u.useRef(null),L=u.useRef(null),Y=g==="android"||g==="androidtv"||g==="android-tv",$=g==="ios"||g==="tvos";u.useEffect(()=>{let d=!1;if(r){U(null),x("connecting"),k(Date.now()),O.startStream(e).catch(()=>{});return}const N=typeof window.VideoDecoder<"u";return(async()=>{try{const B=encodeURIComponent(e),z=await fetch(`/xenon/api/control/${B}/stream/status`);if(!z.ok)return;const P=await z.json();if(Pt(g||"",P==null?void 0:P.type,N)!=="h264"||!(P!=null&&P.h264Path))return;const G=await fetch(`/xenon/api/control/${B}/stream/ticket`,{method:"POST"});if(!G.ok)return;const{ticket:X}=await G.json();if(d||!X)return;const Q=`${window.location.protocol==="https:"?"wss":"ws"}://${window.location.host}${P.h264Path}?ticket=${encodeURIComponent(X)}`;U(Q)}catch{}})(),()=>{d=!0}},[e,g,r]);const F=!o&&!!b&&!!v,oe=(d,N,B,z=!1)=>jt(d,N,B,b,v,j,z),De=(d,N,B)=>{const z=Date.now()+Math.random(),P=d-B.left,G=N-B.top;w(X=>[...X,{id:z,x:P,y:G}]),window.setTimeout(()=>{w(X=>X.filter(J=>J.id!==z))},500)},ke=d=>{if(!F||m==="unavailable"||d.button!==0)return;const N=d.currentTarget;N.focus(),oe(d.clientX,d.clientY,N.getBoundingClientRect())&&(N.setPointerCapture(d.pointerId),L.current={startX:d.clientX,startY:d.clientY,startTime:Date.now(),rect:N.getBoundingClientRect()},De(d.clientX,d.clientY,L.current.rect))},_e=async d=>{var Q,ue;const N=L.current;if(L.current=null,!N||!F)return;try{d.currentTarget.releasePointerCapture(d.pointerId)}catch{}const B=d.clientX-N.startX,z=d.clientY-N.startY,P=Math.hypot(B,z),G=Date.now()-N.startTime,X=oe(N.startX,N.startY,N.rect,!0),J=P<Lt;try{if(J&&G<Bt)await O.tap(e,X.x,X.y);else if(J)await((ue=(Q=O).touchAndHold)==null?void 0:ue.call(Q,e,X.x,X.y,G));else{const ee=oe(d.clientX,d.clientY,N.rect,!0);await O.swipe(e,X.x,X.y,ee.x,ee.y)}}catch(ee){console.error(`[DeviceTile] gesture failed for ${e}`,ee)}},Me=()=>{L.current=null},$e=async d=>{if(!F||m==="unavailable"||d.metaKey||d.ctrlKey||d.altKey)return;const N=d.key;try{if(N.length===1){d.preventDefault(),await O.typeText(e,N);return}if(N==="Backspace"){d.preventDefault(),Y?await O.pressKey(e,67):await O.typeText(e,"\b");return}if(N==="Enter"){d.preventDefault(),Y?await O.pressKey(e,66):await O.typeText(e,`
2
+ `);return}if(N==="Tab"){d.preventDefault(),await O.typeText(e," ");return}N==="Escape"&&Y&&(d.preventDefault(),await O.pressKey(e,te.BACK))}catch(B){console.error(`[DeviceTile] keystroke "${N}" failed for ${e}`,B)}},Oe=()=>O.pressKey(e,Y?te.HOME:qe.HOME).catch(d=>console.error(`[DeviceTile] home failed for ${e}`,d)),Pe=()=>O.pressKey(e,te.BACK).catch(d=>console.error(`[DeviceTile] back failed for ${e}`,d)),Le=()=>O.pressKey(e,te.APP_SWITCH).catch(d=>console.error(`[DeviceTile] app-switch failed for ${e}`,d)),Be=async()=>{try{const d=await O.getScreenshot(e),N=(d==null?void 0:d.screenshot)??(d==null?void 0:d.value)??d;if(!N)return;const B=await fetch(`data:image/png;base64,${N}`).then(G=>G.blob()),z=URL.createObjectURL(B),P=document.createElement("a");P.href=z,P.download=`${t||e}-${Date.now()}.png`,document.body.appendChild(P),P.click(),P.remove(),setTimeout(()=>URL.revokeObjectURL(z),1e3)}catch(d){console.error(`[DeviceTile] screenshot failed for ${e}`,d)}};u.useEffect(()=>{console.log(`[DeviceTile] Rendering ${e} in state: ${m}`)},[e,m]);const ze=`/xenon/api/control/${encodeURIComponent(e)}/stream?t=${T}`,de=u.useCallback(async()=>{try{const d=await fetch(`/xenon/api/control/${encodeURIComponent(e)}/stream/status`);if(!d.ok)throw new Error(String(d.status));const N=await d.json();R(ve({lastError:N==null?void 0:N.lastError,status:N==null?void 0:N.status}))}catch{R(ve({}))}},[e]),se=u.useCallback(()=>{const d=E.current;Mt(d)?(E.current=d+1,i.current&&clearTimeout(i.current),i.current=setTimeout(()=>{x("connecting"),k(Date.now())},_t(d))):(x("unavailable"),de())},[de]);u.useEffect(()=>{if(m!=="connecting")return;const d=setTimeout(se,kt);return()=>clearTimeout(d)},[m,T,se]),It(e,m==="live"&&!M,()=>{console.warn(`[DeviceTile] MJPEG stream ended for ${e}; reconnecting`),x("connecting"),k(Date.now())}),u.useEffect(()=>()=>{i.current&&clearTimeout(i.current)},[]);const Ue=()=>{i.current&&clearTimeout(i.current),E.current=0,R(""),x("connecting"),k(Date.now())},H=!!r,Z=t||e.slice(0,16)+"…";return n.jsxs("div",{className:"flex items-stretch justify-center w-full h-full min-h-0 min-w-0 gap-2",children:[n.jsxs("div",{className:"theme-dark relative bg-[var(--black)] rounded-lg overflow-hidden border border-[var(--border)] group max-h-full max-w-full self-center",style:{aspectRatio:a,height:"100%"},children:[m==="connecting"&&n.jsxs("div",{role:"status","aria-live":"polite",className:"flex flex-col items-center justify-center gap-1 px-4 text-center bg-[rgb(var(--rgb-well)/0.8)] text-[var(--text-dim)] absolute inset-0 z-20 pointer-events-none",children:[n.jsx("div",{"aria-hidden":!0,className:"w-10 h-10 mb-3 border-4 border-[var(--border)] border-t-[var(--text-dim)] rounded-full animate-spin"}),n.jsx("div",{className:"font-semibold text-[var(--text)]",children:"Starting stream…"}),n.jsx("div",{className:"text-xs text-[var(--text-dim)] truncate max-w-full",children:Z}),n.jsx("div",{className:"text-[11px] mt-3 text-[var(--text-dim)] leading-snug",children:$?"iPhone streams can take up to 20 seconds to start.":"Connecting to the device…"})]}),m==="unavailable"&&n.jsx("div",{role:"alert",className:"flex items-center justify-center bg-[var(--black)] text-[var(--text-dim)] absolute inset-0 z-20",children:n.jsxs("div",{className:"text-center p-6",children:[n.jsx(Ze,{"aria-hidden":!0,size:36,className:"mx-auto mb-3 text-[var(--text-dim)]"}),n.jsx("div",{className:"font-semibold text-[var(--text)]",children:"Connection failed"}),n.jsx("p",{className:"text-xs mt-2 text-[var(--text-dim)] leading-relaxed max-w-[240px] mx-auto",children:p||"We couldn’t start the live stream for this device."}),n.jsx("button",{type:"button",className:"mt-5 text-sm font-semibold px-4 py-2 rounded bg-[var(--color-accent)] hover:bg-[var(--color-accent-strong)] text-[var(--color-on-accent)] transition-colors",onClick:Ue,children:"Retry"})]})}),M?n.jsx(Ot,{wsUrl:M,className:"absolute inset-0 w-full h-full object-contain bg-black select-none pointer-events-none",onReady:()=>x("live"),onFrameSize:D,onFatal:()=>{console.warn(`[DeviceTile] H.264 fatal for ${e}; falling back to MJPEG`),U(null),x("connecting"),k(Date.now())}}):n.jsx("img",{src:ze,alt:Z,className:"absolute inset-0 w-full h-full object-contain bg-black select-none pointer-events-none",draggable:!1,style:{opacity:m==="live"?1:0,transition:"opacity 0.3s ease-in-out"},onLoad:d=>{console.log(`[DeviceTile] Image LOADED for ${e}`),D(d.currentTarget.naturalWidth,d.currentTarget.naturalHeight),E.current=0,i.current&&clearTimeout(i.current),x("live")},onError:d=>{console.error(`[DeviceTile] Image ERROR for ${e}`,d),se()}},T),F&&m!=="unavailable"&&n.jsx("div",{ref:_,className:`absolute inset-0 z-[35] touch-none outline-none ${C?"ring-2 ring-[rgb(var(--rgb-accent)/0.6)] ring-inset rounded-lg":""}`,tabIndex:0,onPointerDown:ke,onPointerUp:_e,onPointerCancel:Me,onKeyDown:$e,onFocus:()=>A(!0),onBlur:()=>A(!1)}),n.jsx("div",{className:"absolute inset-0 z-20 pointer-events-none overflow-hidden",children:l.map(d=>n.jsx("span",{className:"absolute block w-10 h-10 rounded-full border-2 border-[var(--color-accent-soft)] animate-ping",style:{left:d.x-20,top:d.y-20}},d.id))}),H&&n.jsx(Tt,{enabled:o,shape:s,color:h,committed:y,mediaAspect:j,onCommittedChange:c,onCommit:(d,N)=>f(r,d,N)}),H&&o&&m==="live"&&n.jsx("div",{className:"absolute top-3 left-14 right-3 z-30 flex justify-end pointer-events-none",children:n.jsx("span",{className:"px-2 py-0.5 rounded-sm bg-[var(--color-info)] text-white text-[10px] font-semibold shadow-lg whitespace-nowrap overflow-hidden text-ellipsis",children:"Annotating · Esc to stop"})}),H&&n.jsx("div",{className:"absolute top-3 left-3 z-30 pointer-events-none",children:n.jsx("span",{className:"px-2 py-0.5 rounded-sm bg-[var(--red-600)] text-white text-[9px] font-black shadow-lg",children:"REC"})}),n.jsxs("div",{className:"absolute top-3 left-3 z-30 flex flex-col gap-1.5 pointer-events-none opacity-0 group-hover:opacity-100 transition-opacity duration-150",children:[m==="live"&&n.jsx("span",{className:"px-2 py-0.5 rounded-sm bg-[var(--color-success)] text-[var(--color-on-success)] text-[11px] font-semibold shadow-lg w-fit",children:"Live"}),n.jsx("span",{className:"px-2 py-1 rounded bg-[rgb(var(--rgb-well)/0.8)] text-[var(--text)] text-[11px] font-medium backdrop-blur-md border border-[rgb(var(--rgb-fg)/0.1)] shadow-xl truncate max-w-[180px]",children:Z})]})]}),n.jsx(Ut,{streamState:m,recording:H,isIOS:$,isAndroid:Y,onClose:!H&&S?()=>S(e):void 0,sendHome:Oe,sendBack:Pe,sendAppSwitch:Le,captureScreenshot:Be,displayName:Z})]})}const re="w-7 h-7 flex items-center justify-center rounded-md hover:bg-[var(--surface-2)] hover:text-[var(--text)] transition-colors";function Ut({streamState:e,recording:t,isIOS:r,isAndroid:o,onClose:s,sendHome:h,sendBack:a,sendAppSwitch:b,captureScreenshot:v,displayName:g}){const f=e==="live";return!s&&!f?null:n.jsxs("div",{className:"self-stretch w-9 flex flex-col items-center justify-between gap-1 py-2 rounded-lg bg-[var(--surface)] border border-[var(--border)] text-[var(--text-dim)]",children:[n.jsx("div",{className:"flex flex-col items-center gap-1",children:s&&n.jsx("button",{type:"button","aria-label":`Remove ${g}`,title:"Remove from the grid",onClick:s,className:"w-7 h-7 flex items-center justify-center rounded-md hover:bg-[rgb(var(--rgb-red)/0.15)] hover:text-[var(--color-danger)] transition-colors",children:n.jsx(Ve,{"aria-hidden":!0,size:16})})}),f&&n.jsxs("div",{className:"flex flex-col items-center gap-1.5 my-auto",children:[(o||r)&&n.jsx("button",{type:"button","aria-label":"Home",title:"Home",onClick:h,className:re,children:n.jsx(He,{"aria-hidden":!0,size:15})}),o&&n.jsx("button",{type:"button","aria-label":"Back",title:"Back",onClick:a,className:re,children:n.jsx(Qe,{"aria-hidden":!0,size:16})}),o&&n.jsx("button",{type:"button","aria-label":"Recent apps",title:"Recent apps",onClick:b,className:re,children:n.jsx(Ne,{"aria-hidden":!0,size:13})})]}),f&&n.jsx("div",{className:"flex flex-col items-center gap-1",children:n.jsx("button",{type:"button","aria-label":"Screenshot",title:"Screenshot",onClick:v,className:re,children:n.jsx(Je,{"aria-hidden":!0,size:15})})})]})}const Yt={1:"1fr","2x1":"1fr 1fr","2x2":"1fr 1fr","3x2":"1fr 1fr 1fr"},Xt={1:"1fr","2x1":"1fr","2x2":"1fr 1fr","3x2":"1fr 1fr"},Vt={1:1,"2x1":2,"2x2":4,"3x2":6};function Ft({layout:e,tiles:t,annotateMode:r,shape:o,color:s,onAnnotation:h,overlayAnnotationsByRecording:a,onOverlayAnnotationsChange:b,onRemove:v,onDropDevice:g}){const f=ot(e,t.length),y=Vt[f];t.length;const c=t.length,S=e==="auto"?Math.max(c,1):y,m=Math.max(0,S-c);return n.jsxs("div",{style:{display:"grid",gap:8,gridTemplateColumns:Yt[f],gridTemplateRows:Xt[f]},className:"h-full",children:[t.map(x=>n.jsx(zt,{udid:x.udid,name:x.name,mjpegPort:x.mjpegPort,recordingId:x.recordingId,aspect:x.aspect,screenWidth:x.screenWidth,screenHeight:x.screenHeight,platform:x.platform,annotateMode:r,shape:o,color:s,overlayAnnotations:x.recordingId?a==null?void 0:a[x.recordingId]:void 0,onOverlayAnnotationsChange:x.recordingId&&b?j=>b(x.recordingId,j):void 0,onAnnotation:h,onRemove:v},x.udid)),Array.from({length:m},(x,j)=>n.jsx(Gt,{onDropDevice:g},`empty-${j}`))]})}function Gt({onDropDevice:e}){const[t,r]=u.useState(!1);return n.jsxs("div",{onDragOver:o=>{e&&(o.preventDefault(),o.dataTransfer.dropEffect="copy",t||r(!0))},onDragLeave:()=>r(!1),onDrop:o=>{if(r(!1),!e)return;o.preventDefault();const s=o.dataTransfer.getData("application/x-xenon-udid")||o.dataTransfer.getData("text/plain");s&&e(s)},className:`flex flex-col items-center justify-center gap-2 rounded-lg border border-dashed transition-colors ${t?"border-[rgb(var(--rgb-accent)/0.6)] bg-[rgb(var(--rgb-accent)/0.05)]":"border-[var(--border)] bg-[rgb(var(--rgb-fg)/0.02)]"} text-[var(--text-dim)] min-h-[120px]`,children:[n.jsx("div",{"aria-hidden":"true",className:`w-8 h-8 rounded-full flex items-center justify-center ${t?"bg-[rgb(var(--rgb-accent)/0.15)] text-[var(--color-accent-soft)]":"bg-[rgb(var(--rgb-fg)/0.05)] text-[rgb(var(--rgb-fg)/0.6)]"}`,children:n.jsx(et,{size:16})}),n.jsx("div",{className:"text-xs font-medium",children:"Drag a device here"}),n.jsx("div",{className:"text-[10px] opacity-70",children:"or click one in the list"})]})}const K="/xenon/api/recordings";class je extends Error{constructor(t){super(t.message??t.error),this.body=t}}async function ne(e,t){const r=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:t?JSON.stringify(t):void 0});if(r.status===409)throw new je(await r.json());if(!r.ok)throw new Error(`HTTP ${r.status}`);return r.json()}function Kt(e,t){return ne(K,{udids:e,...t})}function Wt(e){return ne(`${K}/${encodeURIComponent(e)}/stop`)}function ye(e,t){return ne(`${K}/${encodeURIComponent(e)}/annotation`,t)}function Ht(e,t){return ne(`${K}/${encodeURIComponent(e)}/annotations/clear`,{timecodeMs:t})}async function Jt(){const e=await fetch(`${K}/active`);if(!e.ok)throw new Error(`HTTP ${e.status}`);return e.json()}function qt(e){return`${K}/${encodeURIComponent(e)}/videos.zip`}function Zt(e,t){return`${K}/${encodeURIComponent(e)}/video.mp4`}function Qt(e){return`${K}/${encodeURIComponent(e)}/composite.mp4`}function er(e,t){return t==="starting"?"Starting…":e<=1?"Record":`Record ${e} devices`}const q={"aria-hidden":!0,size:14,className:"shrink-0"};function tr({selectedUdids:e,onClearMarks:t}){const{state:r,dispatch:o}=at(),[s,h]=u.useState(()=>Date.now());u.useEffect(()=>{if(r.recordingPhase!=="recording"&&r.recordingPhase!=="stopping")return;h(Date.now());const E=window.setInterval(()=>h(Date.now()),250);return()=>window.clearInterval(E)},[r.recordingPhase]);const a=r.startedAt&&(r.recordingPhase==="recording"||r.recordingPhase==="stopping")?s-r.startedAt:0,b=r.recordingPhase==="starting"||r.recordingPhase==="stopping",v=r.recordingPhase==="idle"&&e.length>0&&!b,g=r.recordingPhase==="recording"||r.recording&&r.tiles.some(E=>!!E.recordingId),f=g&&!b,y=f,c=y&&r.annotateMode,S=!!r.groupId&&r.recordingPhase==="idle",m=e.length>1||r.downloadableVideoCount>1,x=S&&r.compositeEnabled,j=S&&!r.compositeEnabled&&(r.downloadableVideoCount===1||r.downloadableVideoCount===0&&e.length<=1),I=async()=>{var E;if(v){o({type:"SET_RECORDING_PHASE",phase:"starting"}),o({type:"SET_BANNER",banner:null});try{const i=await Kt(e);if(!((E=i.recordings)!=null&&E.length)){o({type:"SET_RECORDING_PHASE",phase:"idle"}),o({type:"SET_BANNER",banner:{tone:"error",message:"Recording did not start. Check that live preview is working, then try again."}});return}const p={};for(const l of i.recordings)p[l.udid]=l.id;const R=e.length-i.recordings.length;o({type:"START_RECORDING",groupId:i.groupId,startedAt:Date.now(),tileIds:p,compositeEnabled:i.compositeEnabled===!0}),R>0?o({type:"SET_BANNER",banner:{tone:"error",message:`Recording started on ${i.recordings.length} of ${e.length} devices (${R} failed).`}}):o({type:"SET_BANNER",banner:null})}catch(i){if(o({type:"SET_RECORDING_PHASE",phase:"idle"}),i instanceof je)if(i.body.error==="device_busy"){const p=(i.body.busyDevices??[]).map(R=>`${R.udid} (${R.reason})`).join(", ");o({type:"SET_BANNER",banner:{tone:"error",message:`Cannot start — these devices are busy: ${p}`}})}else o({type:"SET_BANNER",banner:{tone:"error",message:`Server-wide recording cap reached (${i.body.active}/${i.body.limit}).`}});else o({type:"SET_BANNER",banner:{tone:"error",message:`Recording failed: ${i.message}`}})}}},D=async()=>{if(!(!r.groupId||r.recordingPhase!=="recording")){o({type:"SET_RECORDING_PHASE",phase:"stopping"});try{const E=await Wt(r.groupId),i=(E.recordings??[]).filter(R=>R.status==="STOPPED"&&(R.sizeBytes??0)>=1024),p=(E.recordings??[]).filter(R=>R.status!=="STOPPED");o({type:"STOP_RECORDING",downloadableVideoCount:i.length,compositeEnabled:r.compositeEnabled}),i.length===0?o({type:"SET_BANNER",banner:{tone:"error",message:p.length>0?`Recording failed on ${p.length} device(s). Nothing to download.`:"Recording stopped but no playable video was produced."}}):p.length>0?o({type:"SET_BANNER",banner:{tone:"info",message:`${i.length} ready, ${p.length} failed. Download with the button above.`}}):o({type:"SET_BANNER",banner:{tone:"info",message:i.length===1?"Video ready. Download it with the button above.":`${i.length} videos ready. Download them with the button above.`}})}catch(E){o({type:"STOP_RECORDING"}),o({type:"SET_BANNER",banner:{tone:"error",message:`Stop failed: ${E.message}`}})}}},T=E=>{const i=E==="annotate";i&&!y||i!==r.annotateMode&&o({type:"SET_ANNOTATE_MODE",enabled:i})};u.useEffect(()=>{if(!r.annotateMode)return;const E=i=>{var R;if(i.key!=="Escape"||i.repeat)return;const p=i.target;p&&((R=p.closest)!=null&&R.call(p,"input, textarea, select")||p.isContentEditable)||o({type:"SET_ANNOTATE_MODE",enabled:!1})};return window.addEventListener("keydown",E),()=>window.removeEventListener("keydown",E)},[r.annotateMode,o]);const k=()=>{y&&t()},M=Object.values(r.overlayAnnotations).some(E=>((E==null?void 0:E.length)??0)>0),U=[{id:"RECT",label:"Rect"},{id:"CIRCLE",label:"Circle"},{id:"ARROW",label:"Arrow"},{id:"FREEHAND",label:"Draw"}];return n.jsxs("div",{className:"flex items-center gap-2 flex-wrap justify-end",children:[r.recordingPhase==="recording"||r.recordingPhase==="stopping"?n.jsxs("span",{className:"inline-flex items-center gap-1.5 px-2 py-1 rounded text-xs font-mono tabular-nums bg-[rgb(var(--rgb-red-600)/0.2)] text-[var(--red-200)] border border-[rgb(var(--rgb-red)/0.4)]",title:"Recording elapsed time",children:[n.jsx("span",{className:"inline-block w-1.5 h-1.5 rounded-full bg-[var(--red)] animate-pulse"}),"REC ",lt(a),r.recordingPhase==="stopping"?" · Stopping…":""]}):n.jsxs("button",{type:"button",onClick:I,disabled:!v,title:e.length===0?"Add a device to the grid first":"Record every device on the grid",className:"inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded bg-[var(--red-600)] text-white disabled:opacity-40 disabled:cursor-not-allowed light:disabled:bg-transparent light:disabled:text-[var(--text)] light:disabled:ring-1 light:disabled:ring-inset light:disabled:ring-[color:var(--border)]",children:[n.jsx(Re,{...q,size:10,fill:"currentColor"}),er(e.length,r.recordingPhase)]}),n.jsxs("button",{type:"button",onClick:D,disabled:!f,className:"inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded border border-[var(--border)] disabled:opacity-40 disabled:cursor-not-allowed",children:[n.jsx(Ne,{...q,size:12}),r.recordingPhase==="stopping"?"Stopping…":"Stop"]}),n.jsx(tt,{size:"sm",value:r.annotateMode?"annotate":"interact",onChange:T,segments:[{value:"interact",label:"Interact",title:"Tap, swipe and type on the devices (Esc)",keyShortcuts:"Escape"},{value:"annotate",label:"Annotate",title:y?"Draw marks on the recording":"Start recording to annotate",disabled:!y}]}),g&&n.jsxs("div",{className:"flex items-center gap-1 ml-1 pl-2 border-l border-[var(--border)]",children:[U.map(E=>n.jsx("button",{type:"button",disabled:!c,"aria-pressed":r.shape===E.id,onClick:()=>o({type:"SET_SHAPE",shape:E.id}),className:`px-2 py-1 text-xs rounded border disabled:opacity-40 disabled:cursor-not-allowed ${r.shape===E.id?"bg-[var(--surface-2)] border-[var(--color-info)] text-[rgb(var(--rgb-fg))]":"border-[var(--border)] opacity-80 hover:opacity-100"}`,children:E.label},E.id)),n.jsx("input",{type:"color",value:r.color,disabled:!c,onChange:E=>o({type:"SET_COLOR",color:E.target.value}),title:"Annotation color","aria-label":"Annotation color",className:"w-7 h-7 rounded border border-[var(--border)] bg-transparent cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed"}),n.jsx("button",{type:"button",onClick:k,disabled:!y||!M,title:"Clear marks from the preview and the recording",className:"px-2 py-1 text-xs rounded border border-[var(--border)] hover:bg-[var(--surface-2)] disabled:opacity-40 disabled:cursor-not-allowed",children:"Clear marks"})]}),S&&j&&n.jsxs("a",{href:Zt(r.groupId),className:"ml-1 inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded border border-[var(--border)] hover:bg-[var(--surface-2)]",download:!0,children:[n.jsx(ie,{...q}),"Download video"]}),S&&!j&&n.jsxs("a",{href:qt(r.groupId),className:"ml-1 inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded border border-[var(--border)] hover:bg-[var(--surface-2)]",download:`videos-${r.groupId}.zip`,title:"ZIP of mp4 files only (no JSON extras)",children:[n.jsx(ie,{...q}),"Download ",m?"videos":"video"]}),x&&n.jsxs("a",{href:Qt(r.groupId),className:"inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded border border-[var(--border)] hover:bg-[var(--surface-2)]",download:`side-by-side-${r.groupId}.mp4`,title:"All devices in one side-by-side video",children:[n.jsx(ie,{...q}),"Side-by-side"]})]})}function rr({remainingSec:e,onContinue:t,onReleaseNow:r}){return n.jsx("div",{role:"dialog","aria-modal":"true","aria-labelledby":"idle-warning-title",className:"fixed inset-0 z-40 bg-black/60 flex items-center justify-center",children:n.jsxs("div",{className:"bg-[var(--bg)] border border-[var(--border)] rounded-lg w-full max-w-md p-6",children:[n.jsx("h3",{id:"idle-warning-title",className:"text-base font-semibold mb-2",children:"Are you still there?"}),n.jsxs("p",{className:"text-sm text-[var(--text-dim)] mb-4",children:["Your devices will be released in"," ",n.jsxs("span",{className:"text-[var(--text)] font-mono font-semibold",children:[e,"s"]})," due to inactivity. Click ",n.jsx("strong",{children:"Continue Session"})," to keep them locked."]}),n.jsxs("div",{className:"flex justify-end gap-2",children:[n.jsx("button",{type:"button",onClick:r,className:"h-9 px-3 rounded-md border border-[var(--border)] text-sm text-[var(--text-dim)] hover:text-[var(--text)]",children:"Release now"}),n.jsx("button",{type:"button",autoFocus:!0,onClick:t,className:"h-9 px-4 rounded-md bg-[var(--color-accent)] text-[var(--color-on-accent)] text-sm font-medium",children:"Continue session"})]})]})})}function nr({message:e,onRestore:t,onDismiss:r}){return n.jsxs("div",{role:"status",className:"text-sm rounded border border-[var(--border)] bg-[var(--surface-2)] text-[var(--text)] px-3 py-2 flex items-center gap-2",children:[n.jsx(rt,{"aria-hidden":!0,size:14,className:"shrink-0 text-[var(--text-dim)]"}),n.jsx("span",{className:"flex-1",children:e}),t&&n.jsx(fe,{variant:"tonal",size:"sm",onClick:t,children:"Restore devices"}),n.jsx(fe,{variant:"ghost",size:"sm",onClick:r,children:"Dismiss"})]})}function Ce(e){var t;return((t=e.marketingName)==null?void 0:t.trim())||e.name||e.udid}function Ae(e){if(!e)return"9 / 16";const t=Number(e.screenWidth),r=Number(e.screenHeight);if(Number.isFinite(t)&&Number.isFinite(r)&&t>0&&r>0)return`${t} / ${r}`;const o=(e.platform||"").toLowerCase();return o==="tvos"||o==="androidtv"||o==="android-tv"?"16 / 9":"9 / 16"}function ae(e){const t=Number(e.screenWidth),r=Number(e.screenHeight);return{udid:e.udid,name:Ce(e),mjpegPort:0,aspect:Ae(e),screenWidth:Number.isFinite(t)&&t>0?t:void 0,screenHeight:Number.isFinite(r)&&r>0?r:void 0,platform:e.platform}}function or(e,t){return t?"blocked":e?"remove":"add"}function le(e,t,r){return!r||!e?!1:e===`manual_${r}_${t}`}function sr(e,t){return e.busy?le(e.session_id,e.udid,t):!1}function ir(e,t){return e>0&&t==="idle"}function ar(e,t,r){const o=[],s=[];for(const h of e){const a=t.find(v=>v.udid===h.udid),b=(a==null?void 0:a.name)||h.name||h.udid;a?a.offline?s.push({name:b,reason:"offline"}):a.busy&&!le(a.session_id,a.udid,r)?s.push({name:b,reason:"in_use"}):o.push(a):s.push({name:b,reason:"gone"})}return{restore:o,skipped:s}}const Ie=(e,t)=>`${e} ${t}${e===1?"":"s"}`;function cr(e,t){return`Released ${Ie(e,"device")} after ${t} minutes without activity.`}const lr={in_use:"is now in use by someone else.",offline:"is offline.",gone:"is no longer connected."};function dr(e,t){return t.length===0?null:[e>0?`Restored ${Ie(e,"device")}.`:"No devices restored.",...t.map(o=>`${o.name} ${lr[o.reason]}`)].join(" ")}function ur(){let e=Promise.resolve();return{enqueue(t){const r=e.then(t,t);return e=r.then(()=>{},()=>{}),r}}}const we=["mousemove","mousedown","keydown","touchstart","wheel"];function fr({idleAfterMs:e,warningSec:t,onWarning:r,onTimeout:o,enabled:s}){const[h,a]=u.useState(!1),[b,v]=u.useState(null),g=u.useRef(null),f=u.useRef(null),y=u.useRef(!1),c=u.useRef(r),S=u.useRef(o);c.current=r,S.current=o;function m(){g.current&&(clearTimeout(g.current),g.current=null),f.current&&(clearInterval(f.current),f.current=null)}function x(){y.current=!0,a(!0),v(t),c.current(t);let D=t;f.current=setInterval(()=>{D-=1,D<=0?(m(),y.current=!1,a(!1),v(null),S.current()):v(D)},1e3)}function j(){m(),y.current=!1,a(!1),v(null);const D=e-t*1e3;g.current=setTimeout(x,Math.max(0,D))}function I(){s&&j()}return u.useEffect(()=>{if(!s){m(),y.current=!1,a(!1),v(null);return}function D(){y.current||j()}return we.forEach(T=>window.addEventListener(T,D,{passive:!0})),j(),()=>{we.forEach(T=>window.removeEventListener(T,D)),m()}},[s,e,t]),{warning:h,remainingSec:b,reset:I}}const Ee=5*60*1e3,hr=30;function pr(e,t){if(e.busy)return e.session_id?e.session_id.startsWith("manual_")?le(e.session_id,e.udid,t)?"manual_self":"manual_other":"automation":"unknown"}function mr(e,t){return{udid:e.udid,name:Ce(e),altName:e.name,platform:e.platform,busy:e.busy,busyReason:pr(e,t),mjpegServerPort:e.mjpegServerPort,offline:!!e.offline}}function Ar(){const[e,t]=ct(),[r,o]=u.useState([]),[s,h]=u.useState("loading"),[a,b]=u.useState(0),[v,g]=u.useState(null),f=u.useRef(!1),y=u.useRef(ur());u.useEffect(()=>{let i=!1;return fetch("/xenon/api/auth/me",{credentials:"include"}).then(p=>p.ok?p.json():null).then(p=>{!i&&(p!=null&&p.userId)&&g(p.userId)}).catch(()=>{}),()=>{i=!0}},[]),u.useEffect(()=>{let i=!1;const p=async()=>{try{const l=await O.getDevices();if(i)return;o(Array.isArray(l)?l:[]),h("ready")}catch{i||h("error")}};p();const R=window.setInterval(p,5e3);return()=>{i=!0,window.clearInterval(R)}},[a]),u.useEffect(()=>{let i=!1;if(!(!v||f.current))return f.current=!0,(async()=>{var l;let p=[],R=[];try{const w=await O.getDevices();p=Array.isArray(w)?w:[];const C=p.filter(_=>sr(_,v));if(R=(await Promise.all(C.map(async _=>{try{const L=await fetch(`/xenon/api/control/${encodeURIComponent(_.udid)}/stream/status`);if(!L.ok)return null;const Y=await L.json();return(Y==null?void 0:Y.status)==="running"?_:null}catch{return null}}))).filter(_=>_!==null).map(ae),i)return;R.length>0&&t({type:"SET_TILES",tiles:R})}catch{}try{const{serverNow:w,groups:C}=await Jt(),A=C[0];if(i||!A)return;const _=new Set(R.map($=>$.udid)),L=A.recordings.filter($=>!_.has($.udid)).map($=>p.find(F=>F.udid===$.udid)).filter($=>!!$).map(ae);L.length>0&&t({type:"SET_TILES",tiles:[...R,...L]});const Y={};for(const $ of A.annotations){let F;try{F=JSON.parse($.geometry)}catch{continue}(Y[l=$.recordingId]??(Y[l]=[])).push({shape:$.shape,color:$.color,geometry:F,text:$.text??void 0})}t({type:"REHYDRATE_RECORDING",groupId:A.groupId,startedAt:Date.now()-(w-Date.parse(A.startedAt)),tileIds:Object.fromEntries(A.recordings.map($=>[$.udid,$.id])),compositeEnabled:A.compositeEnabled,overlayAnnotations:Y})}catch{}})(),()=>{i=!0}},[v,t]),u.useEffect(()=>{for(const i of e.tiles){if(i.screenWidth&&i.screenHeight)continue;const p=r.find(w=>w.udid===i.udid);if(!p)continue;const R=Number(p.screenWidth),l=Number(p.screenHeight);Number.isFinite(R)&&R>0&&Number.isFinite(l)&&l>0&&t({type:"PATCH_TILE_DIMS",udid:i.udid,screenWidth:R,screenHeight:l,aspect:Ae(p)})}},[r,e.tiles,t]);const c=u.useMemo(()=>new Set(e.tiles.map(i=>i.udid)),[e.tiles]),S=u.useMemo(()=>r.map(i=>mr(i,v)),[r,v]),m=async i=>{t({type:"ADD_TILE",tile:ae(i)});const p=await O.startStream(i.udid).catch(()=>null);Ge(p)&&t({type:"REMOVE_TILE",udid:i.udid})},x=async i=>{const p=or(e.tiles.some(l=>l.udid===i),e.recording);if(p==="blocked"){t({type:"SET_ERROR_BANNER",message:"Stop recording before changing the devices on the grid."});return}if(p==="remove"){await j(i);return}const R=r.find(l=>l.udid===i);R&&await m(R)},j=async i=>{t({type:"REMOVE_TILE",udid:i});try{await fetch(`/xenon/api/control/${encodeURIComponent(i)}/stream/leave`,{method:"POST"})}catch{}b(p=>p+1)},I=(i,p,R)=>{if(!e.groupId)return;const l=e.groupId,w=e.startedAt?Date.now()-e.startedAt:0,C={recordingId:i,timecodeMs:w,shape:p.shape,geometry:JSON.stringify(p.geometry),color:p.color,text:p.text};y.current.enqueue(async()=>{try{return await ye(l,R?{...C,image:R}:C)}catch(A){if(!R)throw A;return ye(l,C)}}).catch(A=>t({type:"SET_ERROR_BANNER",message:`Annotation failed: ${A.message}`}))},D=()=>{if(!e.groupId)return;const i=e.groupId,p=e.startedAt?Date.now()-e.startedAt:0;t({type:"CLEAR_OVERLAY_ANNOTATIONS"}),y.current.enqueue(()=>Ht(i,p)).catch(()=>t({type:"SET_ERROR_BANNER",message:"Couldn't clear marks from the recording. They will still appear in the video."}))},T=()=>{for(const i of e.tiles){const p=`/xenon/api/control/${encodeURIComponent(i.udid)}/stream/leave`;try{navigator.sendBeacon?navigator.sendBeacon(p):fetch(p,{method:"POST",keepalive:!0}).catch(()=>{})}catch{}}e.tiles.forEach(i=>t({type:"REMOVE_TILE",udid:i.udid}))},[k,M]=u.useState(null),U=async()=>{const i=k==null?void 0:k.tiles;if(!i)return;const p=ar(i,r,v);for(const l of p.restore)await m(l);const R=dr(p.restore.length,p.skipped);M(R?{message:R,tiles:null}:null),b(l=>l+1)},E=fr({idleAfterMs:Ee,warningSec:hr,enabled:ir(e.tiles.length,e.recordingPhase),onWarning:()=>{},onTimeout:()=>{const i=e.tiles;T(),M({message:cr(i.length,Ee/6e4),tiles:i})}});return n.jsxs(Se.Provider,{value:{state:e,dispatch:t},children:[n.jsxs("div",{className:"flex flex-col h-full p-4 gap-3",children:[n.jsxs("header",{className:"flex items-center justify-between gap-3",children:[n.jsxs("div",{className:"flex items-center gap-3",children:[n.jsx(nt,{icon:Fe,children:"Live devices"}),n.jsx(pt,{value:e.layout,onChange:i=>t({type:"SET_LAYOUT",layout:i})})]}),n.jsx(tr,{selectedUdids:e.tiles.map(i=>i.udid),onClearMarks:D})]}),e.banner&&n.jsxs("div",{role:"alert",className:`text-sm rounded border px-3 py-2 flex items-center gap-2 ${e.banner.tone==="error"?"border-[rgb(var(--rgb-red)/0.4)] bg-[rgb(var(--rgb-red)/0.1)] text-[var(--red-100)]":"border-[rgb(var(--rgb-success)/0.4)] bg-[rgb(var(--rgb-success)/0.1)] text-[var(--text)]"}`,children:[n.jsx("span",{className:"flex-1",children:e.banner.message}),n.jsx("button",{type:"button",className:"text-xs opacity-80 hover:opacity-100",onClick:()=>t({type:"SET_BANNER",banner:null}),children:"Dismiss"})]}),k&&n.jsx(nr,{message:k.message,onRestore:k.tiles&&!e.recording?U:void 0,onDismiss:()=>M(null)}),n.jsxs("div",{className:"grid grid-cols-[260px_1fr] gap-3 flex-1 min-h-0",children:[n.jsxs("aside",{className:"flex flex-col gap-2 border border-[var(--border)] rounded p-3 overflow-y-auto min-h-0",children:[n.jsxs("div",{className:"flex items-center justify-between",children:[n.jsx("span",{className:"text-xs text-[var(--text-dim)]",children:"Devices"}),n.jsx("button",{className:"text-xs underline opacity-70 hover:opacity-100",onClick:()=>b(i=>i+1),children:"Refresh"})]}),n.jsx(ft,{devices:S,inMosaic:c,onToggle:x,status:s}),n.jsx("p",{className:"mt-2 text-[11px] text-[var(--text-dim)] leading-relaxed",children:"Click a device to add it to the grid. Record captures every device on the grid; after Stop, download the video."})]}),n.jsx("main",{className:"border border-[var(--border)] rounded p-2 overflow-y-auto h-full min-h-0",children:n.jsx(Ft,{layout:e.layout,tiles:e.tiles,annotateMode:e.annotateMode,shape:e.shape,color:e.color,overlayAnnotationsByRecording:e.overlayAnnotations,onOverlayAnnotationsChange:(i,p)=>t({type:"SET_OVERLAY_ANNOTATIONS",recordingId:i,annotations:p}),onAnnotation:I,onRemove:j,onDropDevice:x})})]})]}),E.warning&&E.remainingSec!==null&&n.jsx(rr,{remainingSec:E.remainingSec,onContinue:E.reset,onReleaseNow:T})]})}export{Ar as default};
@@ -1 +1 @@
1
- import{j as s}from"./index-BpueX0rJ.js";const i=({icon:e,title:m,description:t,action:a})=>s.jsxs("div",{className:"empty-state",children:[e&&s.jsx("div",{className:"empty-state-icon",children:e}),s.jsx("div",{className:"empty-state-title",children:m}),t&&s.jsx("div",{className:"empty-state-desc",children:t}),a&&s.jsx("div",{className:"empty-state-action",children:a})]});export{i as E};
1
+ import{j as s}from"./index-CbC9kGzR.js";const i=({icon:e,title:m,description:t,action:a})=>s.jsxs("div",{className:"empty-state",children:[e&&s.jsx("div",{className:"empty-state-icon",children:e}),s.jsx("div",{className:"empty-state-title",children:m}),t&&s.jsx("div",{className:"empty-state-desc",children:t}),a&&s.jsx("div",{className:"empty-state-action",children:a})]});export{i as E};
@@ -1 +1 @@
1
- import{j as s}from"./index-BpueX0rJ.js";const r=({label:e,description:l,children:c,error:a,htmlFor:d})=>s.jsxs("div",{className:"fg",children:[s.jsx("label",{className:"fg-label",htmlFor:d,children:e}),l&&s.jsx("div",{className:"fg-desc",children:l}),s.jsx("div",{className:"fg-control",children:c}),a&&s.jsx("div",{className:"fg-error",children:a})]});export{r as F};
1
+ import{j as s}from"./index-CbC9kGzR.js";const r=({label:e,description:l,children:c,error:a,htmlFor:d})=>s.jsxs("div",{className:"fg",children:[s.jsx("label",{className:"fg-label",htmlFor:d,children:e}),l&&s.jsx("div",{className:"fg-desc",children:l}),s.jsx("div",{className:"fg-control",children:c}),a&&s.jsx("div",{className:"fg-error",children:a})]});export{r as F};
@@ -1,4 +1,4 @@
1
- import{r as i,j as h,t as at,R as xe,v as it,y as st}from"./index-BpueX0rJ.js";function me(e,t){if(typeof e=="function")return e(t);e!=null&&(e.current=t)}function De(...e){return t=>{let n=!1;const r=e.map(o=>{const a=me(o,t);return!n&&typeof a=="function"&&(n=!0),a});if(n)return()=>{for(let o=0;o<r.length;o++){const a=r[o];typeof a=="function"?a():me(e[o],null)}}}}function I(...e){return i.useCallback(De(...e),e)}function Oe(e){const t=ct(e),n=i.forwardRef((r,o)=>{const{children:a,...c}=r,s=i.Children.toArray(a),d=s.find(lt);if(d){const u=d.props.children,f=s.map(v=>v===d?i.Children.count(u)>1?i.Children.only(null):i.isValidElement(u)?u.props.children:null:v);return h.jsx(t,{...c,ref:o,children:i.isValidElement(u)?i.cloneElement(u,void 0,f):null})}return h.jsx(t,{...c,ref:o,children:a})});return n.displayName=`${e}.Slot`,n}function ct(e){const t=i.forwardRef((n,r)=>{const{children:o,...a}=n;if(i.isValidElement(o)){const c=ft(o),s=dt(a,o.props);return o.type!==i.Fragment&&(s.ref=r?De(r,c):c),i.cloneElement(o,s)}return i.Children.count(o)>1?i.Children.only(null):null});return t.displayName=`${e}.SlotClone`,t}var ut=Symbol("radix.slottable");function lt(e){return i.isValidElement(e)&&typeof e.type=="function"&&"__radixId"in e.type&&e.type.__radixId===ut}function dt(e,t){const n={...t};for(const r in t){const o=e[r],a=t[r];/^on[A-Z]/.test(r)?o&&a?n[r]=(...s)=>{const d=a(...s);return o(...s),d}:o&&(n[r]=o):r==="style"?n[r]={...o,...a}:r==="className"&&(n[r]=[o,a].filter(Boolean).join(" "))}return{...e,...n}}function ft(e){var r,o;let t=(r=Object.getOwnPropertyDescriptor(e.props,"ref"))==null?void 0:r.get,n=t&&"isReactWarning"in t&&t.isReactWarning;return n?e.ref:(t=(o=Object.getOwnPropertyDescriptor(e,"ref"))==null?void 0:o.get,n=t&&"isReactWarning"in t&&t.isReactWarning,n?e.props.ref:e.props.ref||e.ref)}var vt=["a","button","div","form","h2","h3","img","input","label","li","nav","ol","p","select","span","svg","ul"],D=vt.reduce((e,t)=>{const n=Oe(`Primitive.${t}`),r=i.forwardRef((o,a)=>{const{asChild:c,...s}=o,d=c?n:t;return typeof window<"u"&&(window[Symbol.for("radix-ui")]=!0),h.jsx(d,{...s,ref:a})});return r.displayName=`Primitive.${t}`,{...e,[t]:r}},{});function mt(e,t){e&&at.flushSync(()=>e.dispatchEvent(t))}function ht(e,t){const n=i.createContext(t),r=a=>{const{children:c,...s}=a,d=i.useMemo(()=>s,Object.values(s));return h.jsx(n.Provider,{value:d,children:c})};r.displayName=e+"Provider";function o(a){const c=i.useContext(n);if(c)return c;if(t!==void 0)return t;throw new Error(`\`${a}\` must be used within \`${e}\``)}return[r,o]}function pt(e,t=[]){let n=[];function r(a,c){const s=i.createContext(c),d=n.length;n=[...n,c];const u=v=>{var y;const{scope:m,children:g,...w}=v,l=((y=m==null?void 0:m[e])==null?void 0:y[d])||s,p=i.useMemo(()=>w,Object.values(w));return h.jsx(l.Provider,{value:p,children:g})};u.displayName=a+"Provider";function f(v,m){var l;const g=((l=m==null?void 0:m[e])==null?void 0:l[d])||s,w=i.useContext(g);if(w)return w;if(c!==void 0)return c;throw new Error(`\`${v}\` must be used within \`${a}\``)}return[u,f]}const o=()=>{const a=n.map(c=>i.createContext(c));return function(s){const d=(s==null?void 0:s[e])||a;return i.useMemo(()=>({[`__scope${e}`]:{...s,[e]:d}}),[s,d])}};return o.scopeName=e,[r,gt(o,...t)]}function gt(...e){const t=e[0];if(e.length===1)return t;const n=()=>{const r=e.map(o=>({useScope:o(),scopeName:o.scopeName}));return function(a){const c=r.reduce((s,{useScope:d,scopeName:u})=>{const v=d(a)[`__scope${u}`];return{...s,...v}},{});return i.useMemo(()=>({[`__scope${t.scopeName}`]:c}),[c])}};return n.scopeName=t.scopeName,n}function B(e){const t=i.useRef(e);return i.useEffect(()=>{t.current=e}),i.useMemo(()=>(...n)=>{var r;return(r=t.current)==null?void 0:r.call(t,...n)},[])}var U=globalThis!=null&&globalThis.document?i.useLayoutEffect:()=>{};function A(e,t,{checkForDefaultPrevented:n=!0}={}){return function(o){if(e==null||e(o),n===!1||!o.defaultPrevented)return t==null?void 0:t(o)}}function yt(e,t=globalThis==null?void 0:globalThis.document){const n=B(e);i.useEffect(()=>{const r=o=>{o.key==="Escape"&&n(o)};return t.addEventListener("keydown",r,{capture:!0}),()=>t.removeEventListener("keydown",r,{capture:!0})},[n,t])}var Et="DismissableLayer",ce="dismissableLayer.update",bt="dismissableLayer.pointerDownOutside",Ct="dismissableLayer.focusOutside",he,Ae=i.createContext({layers:new Set,layersWithOutsidePointerEventsDisabled:new Set,branches:new Set}),Te=i.forwardRef((e,t)=>{const{disableOutsidePointerEvents:n=!1,onEscapeKeyDown:r,onPointerDownOutside:o,onFocusOutside:a,onInteractOutside:c,onDismiss:s,...d}=e,u=i.useContext(Ae),[f,v]=i.useState(null),m=(f==null?void 0:f.ownerDocument)??(globalThis==null?void 0:globalThis.document),[,g]=i.useState({}),w=I(t,E=>v(E)),l=Array.from(u.layers),[p]=[...u.layersWithOutsidePointerEventsDisabled].slice(-1),y=l.indexOf(p),b=f?l.indexOf(f):-1,C=u.layersWithOutsidePointerEventsDisabled.size>0,S=b>=y,R=Rt(E=>{const T=E.target,L=[...u.branches].some(W=>W.contains(T));!S||L||(o==null||o(E),c==null||c(E),E.defaultPrevented||s==null||s())},m),N=Nt(E=>{const T=E.target;[...u.branches].some(W=>W.contains(T))||(a==null||a(E),c==null||c(E),E.defaultPrevented||s==null||s())},m);return yt(E=>{b===u.layers.size-1&&(r==null||r(E),!E.defaultPrevented&&s&&(E.preventDefault(),s()))},m),i.useEffect(()=>{if(f)return n&&(u.layersWithOutsidePointerEventsDisabled.size===0&&(he=m.body.style.pointerEvents,m.body.style.pointerEvents="none"),u.layersWithOutsidePointerEventsDisabled.add(f)),u.layers.add(f),pe(),()=>{n&&u.layersWithOutsidePointerEventsDisabled.size===1&&(m.body.style.pointerEvents=he)}},[f,m,n,u]),i.useEffect(()=>()=>{f&&(u.layers.delete(f),u.layersWithOutsidePointerEventsDisabled.delete(f),pe())},[f,u]),i.useEffect(()=>{const E=()=>g({});return document.addEventListener(ce,E),()=>document.removeEventListener(ce,E)},[]),h.jsx(D.div,{...d,ref:w,style:{pointerEvents:C?S?"auto":"none":void 0,...e.style},onFocusCapture:A(e.onFocusCapture,N.onFocusCapture),onBlurCapture:A(e.onBlurCapture,N.onBlurCapture),onPointerDownCapture:A(e.onPointerDownCapture,R.onPointerDownCapture)})});Te.displayName=Et;var St="DismissableLayerBranch",wt=i.forwardRef((e,t)=>{const n=i.useContext(Ae),r=i.useRef(null),o=I(t,r);return i.useEffect(()=>{const a=r.current;if(a)return n.branches.add(a),()=>{n.branches.delete(a)}},[n.branches]),h.jsx(D.div,{...e,ref:o})});wt.displayName=St;function Rt(e,t=globalThis==null?void 0:globalThis.document){const n=B(e),r=i.useRef(!1),o=i.useRef(()=>{});return i.useEffect(()=>{const a=s=>{if(s.target&&!r.current){let d=function(){Me(bt,n,u,{discrete:!0})};const u={originalEvent:s};s.pointerType==="touch"?(t.removeEventListener("click",o.current),o.current=d,t.addEventListener("click",o.current,{once:!0})):d()}else t.removeEventListener("click",o.current);r.current=!1},c=window.setTimeout(()=>{t.addEventListener("pointerdown",a)},0);return()=>{window.clearTimeout(c),t.removeEventListener("pointerdown",a),t.removeEventListener("click",o.current)}},[t,n]),{onPointerDownCapture:()=>r.current=!0}}function Nt(e,t=globalThis==null?void 0:globalThis.document){const n=B(e),r=i.useRef(!1);return i.useEffect(()=>{const o=a=>{a.target&&!r.current&&Me(Ct,n,{originalEvent:a},{discrete:!1})};return t.addEventListener("focusin",o),()=>t.removeEventListener("focusin",o)},[t,n]),{onFocusCapture:()=>r.current=!0,onBlurCapture:()=>r.current=!1}}function pe(){const e=new CustomEvent(ce);document.dispatchEvent(e)}function Me(e,t,n,{discrete:r}){const o=n.originalEvent.target,a=new CustomEvent(e,{bubbles:!1,cancelable:!0,detail:n});t&&o.addEventListener(e,t,{once:!0}),r?mt(o,a):o.dispatchEvent(a)}var Pt=xe[" useId ".trim().toString()]||(()=>{}),xt=0;function ee(e){const[t,n]=i.useState(Pt());return U(()=>{n(r=>r??String(xt++))},[e]),e||(t?`radix-${t}`:"")}var Dt=xe[" useInsertionEffect ".trim().toString()]||U;function Ot({prop:e,defaultProp:t,onChange:n=()=>{},caller:r}){const[o,a,c]=At({defaultProp:t,onChange:n}),s=e!==void 0,d=s?e:o;{const f=i.useRef(e!==void 0);i.useEffect(()=>{const v=f.current;v!==s&&console.warn(`${r} is changing from ${v?"controlled":"uncontrolled"} to ${s?"controlled":"uncontrolled"}. Components should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled value for the lifetime of the component.`),f.current=s},[s,r])}const u=i.useCallback(f=>{var v;if(s){const m=Tt(f)?f(e):f;m!==e&&((v=c.current)==null||v.call(c,m))}else a(f)},[s,e,a,c]);return[d,u]}function At({defaultProp:e,onChange:t}){const[n,r]=i.useState(e),o=i.useRef(n),a=i.useRef(t);return Dt(()=>{a.current=t},[t]),i.useEffect(()=>{var c;o.current!==n&&((c=a.current)==null||c.call(a,n),o.current=n)},[n,o]),[n,r,a]}function Tt(e){return typeof e=="function"}var te="focusScope.autoFocusOnMount",ne="focusScope.autoFocusOnUnmount",ge={bubbles:!1,cancelable:!0},Mt="FocusScope",Ie=i.forwardRef((e,t)=>{const{loop:n=!1,trapped:r=!1,onMountAutoFocus:o,onUnmountAutoFocus:a,...c}=e,[s,d]=i.useState(null),u=B(o),f=B(a),v=i.useRef(null),m=I(t,l=>d(l)),g=i.useRef({paused:!1,pause(){this.paused=!0},resume(){this.paused=!1}}).current;i.useEffect(()=>{if(r){let l=function(C){if(g.paused||!s)return;const S=C.target;s.contains(S)?v.current=S:O(v.current,{select:!0})},p=function(C){if(g.paused||!s)return;const S=C.relatedTarget;S!==null&&(s.contains(S)||O(v.current,{select:!0}))},y=function(C){if(document.activeElement===document.body)for(const R of C)R.removedNodes.length>0&&O(s)};document.addEventListener("focusin",l),document.addEventListener("focusout",p);const b=new MutationObserver(y);return s&&b.observe(s,{childList:!0,subtree:!0}),()=>{document.removeEventListener("focusin",l),document.removeEventListener("focusout",p),b.disconnect()}}},[r,s,g.paused]),i.useEffect(()=>{if(s){Ee.add(g);const l=document.activeElement;if(!s.contains(l)){const y=new CustomEvent(te,ge);s.addEventListener(te,u),s.dispatchEvent(y),y.defaultPrevented||(It(jt(Le(s)),{select:!0}),document.activeElement===l&&O(s))}return()=>{s.removeEventListener(te,u),setTimeout(()=>{const y=new CustomEvent(ne,ge);s.addEventListener(ne,f),s.dispatchEvent(y),y.defaultPrevented||O(l??document.body,{select:!0}),s.removeEventListener(ne,f),Ee.remove(g)},0)}}},[s,u,f,g]);const w=i.useCallback(l=>{if(!n&&!r||g.paused)return;const p=l.key==="Tab"&&!l.altKey&&!l.ctrlKey&&!l.metaKey,y=document.activeElement;if(p&&y){const b=l.currentTarget,[C,S]=Lt(b);C&&S?!l.shiftKey&&y===S?(l.preventDefault(),n&&O(C,{select:!0})):l.shiftKey&&y===C&&(l.preventDefault(),n&&O(S,{select:!0})):y===b&&l.preventDefault()}},[n,r,g.paused]);return h.jsx(D.div,{tabIndex:-1,...c,ref:m,onKeyDown:w})});Ie.displayName=Mt;function It(e,{select:t=!1}={}){const n=document.activeElement;for(const r of e)if(O(r,{select:t}),document.activeElement!==n)return}function Lt(e){const t=Le(e),n=ye(t,e),r=ye(t.reverse(),e);return[n,r]}function Le(e){const t=[],n=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT,{acceptNode:r=>{const o=r.tagName==="INPUT"&&r.type==="hidden";return r.disabled||r.hidden||o?NodeFilter.FILTER_SKIP:r.tabIndex>=0?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}});for(;n.nextNode();)t.push(n.currentNode);return t}function ye(e,t){for(const n of e)if(!_t(n,{upTo:t}))return n}function _t(e,{upTo:t}){if(getComputedStyle(e).visibility==="hidden")return!0;for(;e;){if(t!==void 0&&e===t)return!1;if(getComputedStyle(e).display==="none")return!0;e=e.parentElement}return!1}function Ft(e){return e instanceof HTMLInputElement&&"select"in e}function O(e,{select:t=!1}={}){if(e&&e.focus){const n=document.activeElement;e.focus({preventScroll:!0}),e!==n&&Ft(e)&&t&&e.select()}}var Ee=kt();function kt(){let e=[];return{add(t){const n=e[0];t!==n&&(n==null||n.pause()),e=be(e,t),e.unshift(t)},remove(t){var n;e=be(e,t),(n=e[0])==null||n.resume()}}}function be(e,t){const n=[...e],r=n.indexOf(t);return r!==-1&&n.splice(r,1),n}function jt(e){return e.filter(t=>t.tagName!=="A")}var Wt="Portal",_e=i.forwardRef((e,t)=>{var s;const{container:n,...r}=e,[o,a]=i.useState(!1);U(()=>a(!0),[]);const c=n||o&&((s=globalThis==null?void 0:globalThis.document)==null?void 0:s.body);return c?it.createPortal(h.jsx(D.div,{...r,ref:t}),c):null});_e.displayName=Wt;function Bt(e,t){return i.useReducer((n,r)=>t[n][r]??n,e)}var q=e=>{const{present:t,children:n}=e,r=Ut(t),o=typeof n=="function"?n({present:r.isPresent}):i.Children.only(n),a=I(r.ref,$t(o));return typeof n=="function"||r.isPresent?i.cloneElement(o,{ref:a}):null};q.displayName="Presence";function Ut(e){const[t,n]=i.useState(),r=i.useRef(null),o=i.useRef(e),a=i.useRef("none"),c=e?"mounted":"unmounted",[s,d]=Bt(c,{mounted:{UNMOUNT:"unmounted",ANIMATION_OUT:"unmountSuspended"},unmountSuspended:{MOUNT:"mounted",ANIMATION_END:"unmounted"},unmounted:{MOUNT:"mounted"}});return i.useEffect(()=>{const u=V(r.current);a.current=s==="mounted"?u:"none"},[s]),U(()=>{const u=r.current,f=o.current;if(f!==e){const m=a.current,g=V(u);e?d("MOUNT"):g==="none"||(u==null?void 0:u.display)==="none"?d("UNMOUNT"):d(f&&m!==g?"ANIMATION_OUT":"UNMOUNT"),o.current=e}},[e,d]),U(()=>{if(t){let u;const f=t.ownerDocument.defaultView??window,v=g=>{const l=V(r.current).includes(CSS.escape(g.animationName));if(g.target===t&&l&&(d("ANIMATION_END"),!o.current)){const p=t.style.animationFillMode;t.style.animationFillMode="forwards",u=f.setTimeout(()=>{t.style.animationFillMode==="forwards"&&(t.style.animationFillMode=p)})}},m=g=>{g.target===t&&(a.current=V(r.current))};return t.addEventListener("animationstart",m),t.addEventListener("animationcancel",v),t.addEventListener("animationend",v),()=>{f.clearTimeout(u),t.removeEventListener("animationstart",m),t.removeEventListener("animationcancel",v),t.removeEventListener("animationend",v)}}else d("ANIMATION_END")},[t,d]),{isPresent:["mounted","unmountSuspended"].includes(s),ref:i.useCallback(u=>{r.current=u?getComputedStyle(u):null,n(u)},[])}}function V(e){return(e==null?void 0:e.animationName)||"none"}function $t(e){var r,o;let t=(r=Object.getOwnPropertyDescriptor(e.props,"ref"))==null?void 0:r.get,n=t&&"isReactWarning"in t&&t.isReactWarning;return n?e.ref:(t=(o=Object.getOwnPropertyDescriptor(e,"ref"))==null?void 0:o.get,n=t&&"isReactWarning"in t&&t.isReactWarning,n?e.props.ref:e.props.ref||e.ref)}var re=0;function Vt(){i.useEffect(()=>{const e=document.querySelectorAll("[data-radix-focus-guard]");return document.body.insertAdjacentElement("afterbegin",e[0]??Ce()),document.body.insertAdjacentElement("beforeend",e[1]??Ce()),re++,()=>{re===1&&document.querySelectorAll("[data-radix-focus-guard]").forEach(t=>t.remove()),re--}},[])}function Ce(){const e=document.createElement("span");return e.setAttribute("data-radix-focus-guard",""),e.tabIndex=0,e.style.outline="none",e.style.opacity="0",e.style.position="fixed",e.style.pointerEvents="none",e}var x=function(){return x=Object.assign||function(t){for(var n,r=1,o=arguments.length;r<o;r++){n=arguments[r];for(var a in n)Object.prototype.hasOwnProperty.call(n,a)&&(t[a]=n[a])}return t},x.apply(this,arguments)};function Fe(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols=="function")for(var o=0,r=Object.getOwnPropertySymbols(e);o<r.length;o++)t.indexOf(r[o])<0&&Object.prototype.propertyIsEnumerable.call(e,r[o])&&(n[r[o]]=e[r[o]]);return n}function Kt(e,t,n){if(n||arguments.length===2)for(var r=0,o=t.length,a;r<o;r++)(a||!(r in t))&&(a||(a=Array.prototype.slice.call(t,0,r)),a[r]=t[r]);return e.concat(a||Array.prototype.slice.call(t))}var H="right-scroll-bar-position",z="width-before-scroll-bar",Gt="with-scroll-bars-hidden",Xt="--removed-body-scroll-bar-size";function oe(e,t){return typeof e=="function"?e(t):e&&(e.current=t),e}function Yt(e,t){var n=i.useState(function(){return{value:e,callback:t,facade:{get current(){return n.value},set current(r){var o=n.value;o!==r&&(n.value=r,n.callback(r,o))}}}})[0];return n.callback=t,n.facade}var Ht=typeof window<"u"?i.useLayoutEffect:i.useEffect,Se=new WeakMap;function zt(e,t){var n=Yt(null,function(r){return e.forEach(function(o){return oe(o,r)})});return Ht(function(){var r=Se.get(n);if(r){var o=new Set(r),a=new Set(e),c=n.current;o.forEach(function(s){a.has(s)||oe(s,null)}),a.forEach(function(s){o.has(s)||oe(s,c)})}Se.set(n,e)},[e]),n}function Zt(e){return e}function qt(e,t){t===void 0&&(t=Zt);var n=[],r=!1,o={read:function(){if(r)throw new Error("Sidecar: could not `read` from an `assigned` medium. `read` could be used only with `useMedium`.");return n.length?n[n.length-1]:e},useMedium:function(a){var c=t(a,r);return n.push(c),function(){n=n.filter(function(s){return s!==c})}},assignSyncMedium:function(a){for(r=!0;n.length;){var c=n;n=[],c.forEach(a)}n={push:function(s){return a(s)},filter:function(){return n}}},assignMedium:function(a){r=!0;var c=[];if(n.length){var s=n;n=[],s.forEach(a),c=n}var d=function(){var f=c;c=[],f.forEach(a)},u=function(){return Promise.resolve().then(d)};u(),n={push:function(f){c.push(f),u()},filter:function(f){return c=c.filter(f),n}}}};return o}function Qt(e){e===void 0&&(e={});var t=qt(null);return t.options=x({async:!0,ssr:!1},e),t}var ke=function(e){var t=e.sideCar,n=Fe(e,["sideCar"]);if(!t)throw new Error("Sidecar: please provide `sideCar` property to import the right car");var r=t.read();if(!r)throw new Error("Sidecar medium not found");return i.createElement(r,x({},n))};ke.isSideCarExport=!0;function Jt(e,t){return e.useMedium(t),ke}var je=Qt(),ae=function(){},Q=i.forwardRef(function(e,t){var n=i.useRef(null),r=i.useState({onScrollCapture:ae,onWheelCapture:ae,onTouchMoveCapture:ae}),o=r[0],a=r[1],c=e.forwardProps,s=e.children,d=e.className,u=e.removeScrollBar,f=e.enabled,v=e.shards,m=e.sideCar,g=e.noRelative,w=e.noIsolation,l=e.inert,p=e.allowPinchZoom,y=e.as,b=y===void 0?"div":y,C=e.gapMode,S=Fe(e,["forwardProps","children","className","removeScrollBar","enabled","shards","sideCar","noRelative","noIsolation","inert","allowPinchZoom","as","gapMode"]),R=m,N=zt([n,t]),E=x(x({},S),o);return i.createElement(i.Fragment,null,f&&i.createElement(R,{sideCar:je,removeScrollBar:u,shards:v,noRelative:g,noIsolation:w,inert:l,setCallbacks:a,allowPinchZoom:!!p,lockRef:n,gapMode:C}),c?i.cloneElement(i.Children.only(s),x(x({},E),{ref:N})):i.createElement(b,x({},E,{className:d,ref:N}),s))});Q.defaultProps={enabled:!0,removeScrollBar:!0,inert:!1};Q.classNames={fullWidth:z,zeroRight:H};var en=function(){if(typeof __webpack_nonce__<"u")return __webpack_nonce__};function tn(){if(!document)return null;var e=document.createElement("style");e.type="text/css";var t=en();return t&&e.setAttribute("nonce",t),e}function nn(e,t){e.styleSheet?e.styleSheet.cssText=t:e.appendChild(document.createTextNode(t))}function rn(e){var t=document.head||document.getElementsByTagName("head")[0];t.appendChild(e)}var on=function(){var e=0,t=null;return{add:function(n){e==0&&(t=tn())&&(nn(t,n),rn(t)),e++},remove:function(){e--,!e&&t&&(t.parentNode&&t.parentNode.removeChild(t),t=null)}}},an=function(){var e=on();return function(t,n){i.useEffect(function(){return e.add(t),function(){e.remove()}},[t&&n])}},We=function(){var e=an(),t=function(n){var r=n.styles,o=n.dynamic;return e(r,o),null};return t},sn={left:0,top:0,right:0,gap:0},ie=function(e){return parseInt(e||"",10)||0},cn=function(e){var t=window.getComputedStyle(document.body),n=t[e==="padding"?"paddingLeft":"marginLeft"],r=t[e==="padding"?"paddingTop":"marginTop"],o=t[e==="padding"?"paddingRight":"marginRight"];return[ie(n),ie(r),ie(o)]},un=function(e){if(e===void 0&&(e="margin"),typeof window>"u")return sn;var t=cn(e),n=document.documentElement.clientWidth,r=window.innerWidth;return{left:t[0],top:t[1],right:t[2],gap:Math.max(0,r-n+t[2]-t[0])}},ln=We(),j="data-scroll-locked",dn=function(e,t,n,r){var o=e.left,a=e.top,c=e.right,s=e.gap;return n===void 0&&(n="margin"),`
1
+ import{r as i,j as h,t as at,R as xe,v as it,y as st}from"./index-CbC9kGzR.js";function me(e,t){if(typeof e=="function")return e(t);e!=null&&(e.current=t)}function De(...e){return t=>{let n=!1;const r=e.map(o=>{const a=me(o,t);return!n&&typeof a=="function"&&(n=!0),a});if(n)return()=>{for(let o=0;o<r.length;o++){const a=r[o];typeof a=="function"?a():me(e[o],null)}}}}function I(...e){return i.useCallback(De(...e),e)}function Oe(e){const t=ct(e),n=i.forwardRef((r,o)=>{const{children:a,...c}=r,s=i.Children.toArray(a),d=s.find(lt);if(d){const u=d.props.children,f=s.map(v=>v===d?i.Children.count(u)>1?i.Children.only(null):i.isValidElement(u)?u.props.children:null:v);return h.jsx(t,{...c,ref:o,children:i.isValidElement(u)?i.cloneElement(u,void 0,f):null})}return h.jsx(t,{...c,ref:o,children:a})});return n.displayName=`${e}.Slot`,n}function ct(e){const t=i.forwardRef((n,r)=>{const{children:o,...a}=n;if(i.isValidElement(o)){const c=ft(o),s=dt(a,o.props);return o.type!==i.Fragment&&(s.ref=r?De(r,c):c),i.cloneElement(o,s)}return i.Children.count(o)>1?i.Children.only(null):null});return t.displayName=`${e}.SlotClone`,t}var ut=Symbol("radix.slottable");function lt(e){return i.isValidElement(e)&&typeof e.type=="function"&&"__radixId"in e.type&&e.type.__radixId===ut}function dt(e,t){const n={...t};for(const r in t){const o=e[r],a=t[r];/^on[A-Z]/.test(r)?o&&a?n[r]=(...s)=>{const d=a(...s);return o(...s),d}:o&&(n[r]=o):r==="style"?n[r]={...o,...a}:r==="className"&&(n[r]=[o,a].filter(Boolean).join(" "))}return{...e,...n}}function ft(e){var r,o;let t=(r=Object.getOwnPropertyDescriptor(e.props,"ref"))==null?void 0:r.get,n=t&&"isReactWarning"in t&&t.isReactWarning;return n?e.ref:(t=(o=Object.getOwnPropertyDescriptor(e,"ref"))==null?void 0:o.get,n=t&&"isReactWarning"in t&&t.isReactWarning,n?e.props.ref:e.props.ref||e.ref)}var vt=["a","button","div","form","h2","h3","img","input","label","li","nav","ol","p","select","span","svg","ul"],D=vt.reduce((e,t)=>{const n=Oe(`Primitive.${t}`),r=i.forwardRef((o,a)=>{const{asChild:c,...s}=o,d=c?n:t;return typeof window<"u"&&(window[Symbol.for("radix-ui")]=!0),h.jsx(d,{...s,ref:a})});return r.displayName=`Primitive.${t}`,{...e,[t]:r}},{});function mt(e,t){e&&at.flushSync(()=>e.dispatchEvent(t))}function ht(e,t){const n=i.createContext(t),r=a=>{const{children:c,...s}=a,d=i.useMemo(()=>s,Object.values(s));return h.jsx(n.Provider,{value:d,children:c})};r.displayName=e+"Provider";function o(a){const c=i.useContext(n);if(c)return c;if(t!==void 0)return t;throw new Error(`\`${a}\` must be used within \`${e}\``)}return[r,o]}function pt(e,t=[]){let n=[];function r(a,c){const s=i.createContext(c),d=n.length;n=[...n,c];const u=v=>{var y;const{scope:m,children:g,...w}=v,l=((y=m==null?void 0:m[e])==null?void 0:y[d])||s,p=i.useMemo(()=>w,Object.values(w));return h.jsx(l.Provider,{value:p,children:g})};u.displayName=a+"Provider";function f(v,m){var l;const g=((l=m==null?void 0:m[e])==null?void 0:l[d])||s,w=i.useContext(g);if(w)return w;if(c!==void 0)return c;throw new Error(`\`${v}\` must be used within \`${a}\``)}return[u,f]}const o=()=>{const a=n.map(c=>i.createContext(c));return function(s){const d=(s==null?void 0:s[e])||a;return i.useMemo(()=>({[`__scope${e}`]:{...s,[e]:d}}),[s,d])}};return o.scopeName=e,[r,gt(o,...t)]}function gt(...e){const t=e[0];if(e.length===1)return t;const n=()=>{const r=e.map(o=>({useScope:o(),scopeName:o.scopeName}));return function(a){const c=r.reduce((s,{useScope:d,scopeName:u})=>{const v=d(a)[`__scope${u}`];return{...s,...v}},{});return i.useMemo(()=>({[`__scope${t.scopeName}`]:c}),[c])}};return n.scopeName=t.scopeName,n}function B(e){const t=i.useRef(e);return i.useEffect(()=>{t.current=e}),i.useMemo(()=>(...n)=>{var r;return(r=t.current)==null?void 0:r.call(t,...n)},[])}var U=globalThis!=null&&globalThis.document?i.useLayoutEffect:()=>{};function A(e,t,{checkForDefaultPrevented:n=!0}={}){return function(o){if(e==null||e(o),n===!1||!o.defaultPrevented)return t==null?void 0:t(o)}}function yt(e,t=globalThis==null?void 0:globalThis.document){const n=B(e);i.useEffect(()=>{const r=o=>{o.key==="Escape"&&n(o)};return t.addEventListener("keydown",r,{capture:!0}),()=>t.removeEventListener("keydown",r,{capture:!0})},[n,t])}var Et="DismissableLayer",ce="dismissableLayer.update",bt="dismissableLayer.pointerDownOutside",Ct="dismissableLayer.focusOutside",he,Ae=i.createContext({layers:new Set,layersWithOutsidePointerEventsDisabled:new Set,branches:new Set}),Te=i.forwardRef((e,t)=>{const{disableOutsidePointerEvents:n=!1,onEscapeKeyDown:r,onPointerDownOutside:o,onFocusOutside:a,onInteractOutside:c,onDismiss:s,...d}=e,u=i.useContext(Ae),[f,v]=i.useState(null),m=(f==null?void 0:f.ownerDocument)??(globalThis==null?void 0:globalThis.document),[,g]=i.useState({}),w=I(t,E=>v(E)),l=Array.from(u.layers),[p]=[...u.layersWithOutsidePointerEventsDisabled].slice(-1),y=l.indexOf(p),b=f?l.indexOf(f):-1,C=u.layersWithOutsidePointerEventsDisabled.size>0,S=b>=y,R=Rt(E=>{const T=E.target,L=[...u.branches].some(W=>W.contains(T));!S||L||(o==null||o(E),c==null||c(E),E.defaultPrevented||s==null||s())},m),N=Nt(E=>{const T=E.target;[...u.branches].some(W=>W.contains(T))||(a==null||a(E),c==null||c(E),E.defaultPrevented||s==null||s())},m);return yt(E=>{b===u.layers.size-1&&(r==null||r(E),!E.defaultPrevented&&s&&(E.preventDefault(),s()))},m),i.useEffect(()=>{if(f)return n&&(u.layersWithOutsidePointerEventsDisabled.size===0&&(he=m.body.style.pointerEvents,m.body.style.pointerEvents="none"),u.layersWithOutsidePointerEventsDisabled.add(f)),u.layers.add(f),pe(),()=>{n&&u.layersWithOutsidePointerEventsDisabled.size===1&&(m.body.style.pointerEvents=he)}},[f,m,n,u]),i.useEffect(()=>()=>{f&&(u.layers.delete(f),u.layersWithOutsidePointerEventsDisabled.delete(f),pe())},[f,u]),i.useEffect(()=>{const E=()=>g({});return document.addEventListener(ce,E),()=>document.removeEventListener(ce,E)},[]),h.jsx(D.div,{...d,ref:w,style:{pointerEvents:C?S?"auto":"none":void 0,...e.style},onFocusCapture:A(e.onFocusCapture,N.onFocusCapture),onBlurCapture:A(e.onBlurCapture,N.onBlurCapture),onPointerDownCapture:A(e.onPointerDownCapture,R.onPointerDownCapture)})});Te.displayName=Et;var St="DismissableLayerBranch",wt=i.forwardRef((e,t)=>{const n=i.useContext(Ae),r=i.useRef(null),o=I(t,r);return i.useEffect(()=>{const a=r.current;if(a)return n.branches.add(a),()=>{n.branches.delete(a)}},[n.branches]),h.jsx(D.div,{...e,ref:o})});wt.displayName=St;function Rt(e,t=globalThis==null?void 0:globalThis.document){const n=B(e),r=i.useRef(!1),o=i.useRef(()=>{});return i.useEffect(()=>{const a=s=>{if(s.target&&!r.current){let d=function(){Me(bt,n,u,{discrete:!0})};const u={originalEvent:s};s.pointerType==="touch"?(t.removeEventListener("click",o.current),o.current=d,t.addEventListener("click",o.current,{once:!0})):d()}else t.removeEventListener("click",o.current);r.current=!1},c=window.setTimeout(()=>{t.addEventListener("pointerdown",a)},0);return()=>{window.clearTimeout(c),t.removeEventListener("pointerdown",a),t.removeEventListener("click",o.current)}},[t,n]),{onPointerDownCapture:()=>r.current=!0}}function Nt(e,t=globalThis==null?void 0:globalThis.document){const n=B(e),r=i.useRef(!1);return i.useEffect(()=>{const o=a=>{a.target&&!r.current&&Me(Ct,n,{originalEvent:a},{discrete:!1})};return t.addEventListener("focusin",o),()=>t.removeEventListener("focusin",o)},[t,n]),{onFocusCapture:()=>r.current=!0,onBlurCapture:()=>r.current=!1}}function pe(){const e=new CustomEvent(ce);document.dispatchEvent(e)}function Me(e,t,n,{discrete:r}){const o=n.originalEvent.target,a=new CustomEvent(e,{bubbles:!1,cancelable:!0,detail:n});t&&o.addEventListener(e,t,{once:!0}),r?mt(o,a):o.dispatchEvent(a)}var Pt=xe[" useId ".trim().toString()]||(()=>{}),xt=0;function ee(e){const[t,n]=i.useState(Pt());return U(()=>{n(r=>r??String(xt++))},[e]),e||(t?`radix-${t}`:"")}var Dt=xe[" useInsertionEffect ".trim().toString()]||U;function Ot({prop:e,defaultProp:t,onChange:n=()=>{},caller:r}){const[o,a,c]=At({defaultProp:t,onChange:n}),s=e!==void 0,d=s?e:o;{const f=i.useRef(e!==void 0);i.useEffect(()=>{const v=f.current;v!==s&&console.warn(`${r} is changing from ${v?"controlled":"uncontrolled"} to ${s?"controlled":"uncontrolled"}. Components should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled value for the lifetime of the component.`),f.current=s},[s,r])}const u=i.useCallback(f=>{var v;if(s){const m=Tt(f)?f(e):f;m!==e&&((v=c.current)==null||v.call(c,m))}else a(f)},[s,e,a,c]);return[d,u]}function At({defaultProp:e,onChange:t}){const[n,r]=i.useState(e),o=i.useRef(n),a=i.useRef(t);return Dt(()=>{a.current=t},[t]),i.useEffect(()=>{var c;o.current!==n&&((c=a.current)==null||c.call(a,n),o.current=n)},[n,o]),[n,r,a]}function Tt(e){return typeof e=="function"}var te="focusScope.autoFocusOnMount",ne="focusScope.autoFocusOnUnmount",ge={bubbles:!1,cancelable:!0},Mt="FocusScope",Ie=i.forwardRef((e,t)=>{const{loop:n=!1,trapped:r=!1,onMountAutoFocus:o,onUnmountAutoFocus:a,...c}=e,[s,d]=i.useState(null),u=B(o),f=B(a),v=i.useRef(null),m=I(t,l=>d(l)),g=i.useRef({paused:!1,pause(){this.paused=!0},resume(){this.paused=!1}}).current;i.useEffect(()=>{if(r){let l=function(C){if(g.paused||!s)return;const S=C.target;s.contains(S)?v.current=S:O(v.current,{select:!0})},p=function(C){if(g.paused||!s)return;const S=C.relatedTarget;S!==null&&(s.contains(S)||O(v.current,{select:!0}))},y=function(C){if(document.activeElement===document.body)for(const R of C)R.removedNodes.length>0&&O(s)};document.addEventListener("focusin",l),document.addEventListener("focusout",p);const b=new MutationObserver(y);return s&&b.observe(s,{childList:!0,subtree:!0}),()=>{document.removeEventListener("focusin",l),document.removeEventListener("focusout",p),b.disconnect()}}},[r,s,g.paused]),i.useEffect(()=>{if(s){Ee.add(g);const l=document.activeElement;if(!s.contains(l)){const y=new CustomEvent(te,ge);s.addEventListener(te,u),s.dispatchEvent(y),y.defaultPrevented||(It(jt(Le(s)),{select:!0}),document.activeElement===l&&O(s))}return()=>{s.removeEventListener(te,u),setTimeout(()=>{const y=new CustomEvent(ne,ge);s.addEventListener(ne,f),s.dispatchEvent(y),y.defaultPrevented||O(l??document.body,{select:!0}),s.removeEventListener(ne,f),Ee.remove(g)},0)}}},[s,u,f,g]);const w=i.useCallback(l=>{if(!n&&!r||g.paused)return;const p=l.key==="Tab"&&!l.altKey&&!l.ctrlKey&&!l.metaKey,y=document.activeElement;if(p&&y){const b=l.currentTarget,[C,S]=Lt(b);C&&S?!l.shiftKey&&y===S?(l.preventDefault(),n&&O(C,{select:!0})):l.shiftKey&&y===C&&(l.preventDefault(),n&&O(S,{select:!0})):y===b&&l.preventDefault()}},[n,r,g.paused]);return h.jsx(D.div,{tabIndex:-1,...c,ref:m,onKeyDown:w})});Ie.displayName=Mt;function It(e,{select:t=!1}={}){const n=document.activeElement;for(const r of e)if(O(r,{select:t}),document.activeElement!==n)return}function Lt(e){const t=Le(e),n=ye(t,e),r=ye(t.reverse(),e);return[n,r]}function Le(e){const t=[],n=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT,{acceptNode:r=>{const o=r.tagName==="INPUT"&&r.type==="hidden";return r.disabled||r.hidden||o?NodeFilter.FILTER_SKIP:r.tabIndex>=0?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}});for(;n.nextNode();)t.push(n.currentNode);return t}function ye(e,t){for(const n of e)if(!_t(n,{upTo:t}))return n}function _t(e,{upTo:t}){if(getComputedStyle(e).visibility==="hidden")return!0;for(;e;){if(t!==void 0&&e===t)return!1;if(getComputedStyle(e).display==="none")return!0;e=e.parentElement}return!1}function Ft(e){return e instanceof HTMLInputElement&&"select"in e}function O(e,{select:t=!1}={}){if(e&&e.focus){const n=document.activeElement;e.focus({preventScroll:!0}),e!==n&&Ft(e)&&t&&e.select()}}var Ee=kt();function kt(){let e=[];return{add(t){const n=e[0];t!==n&&(n==null||n.pause()),e=be(e,t),e.unshift(t)},remove(t){var n;e=be(e,t),(n=e[0])==null||n.resume()}}}function be(e,t){const n=[...e],r=n.indexOf(t);return r!==-1&&n.splice(r,1),n}function jt(e){return e.filter(t=>t.tagName!=="A")}var Wt="Portal",_e=i.forwardRef((e,t)=>{var s;const{container:n,...r}=e,[o,a]=i.useState(!1);U(()=>a(!0),[]);const c=n||o&&((s=globalThis==null?void 0:globalThis.document)==null?void 0:s.body);return c?it.createPortal(h.jsx(D.div,{...r,ref:t}),c):null});_e.displayName=Wt;function Bt(e,t){return i.useReducer((n,r)=>t[n][r]??n,e)}var q=e=>{const{present:t,children:n}=e,r=Ut(t),o=typeof n=="function"?n({present:r.isPresent}):i.Children.only(n),a=I(r.ref,$t(o));return typeof n=="function"||r.isPresent?i.cloneElement(o,{ref:a}):null};q.displayName="Presence";function Ut(e){const[t,n]=i.useState(),r=i.useRef(null),o=i.useRef(e),a=i.useRef("none"),c=e?"mounted":"unmounted",[s,d]=Bt(c,{mounted:{UNMOUNT:"unmounted",ANIMATION_OUT:"unmountSuspended"},unmountSuspended:{MOUNT:"mounted",ANIMATION_END:"unmounted"},unmounted:{MOUNT:"mounted"}});return i.useEffect(()=>{const u=V(r.current);a.current=s==="mounted"?u:"none"},[s]),U(()=>{const u=r.current,f=o.current;if(f!==e){const m=a.current,g=V(u);e?d("MOUNT"):g==="none"||(u==null?void 0:u.display)==="none"?d("UNMOUNT"):d(f&&m!==g?"ANIMATION_OUT":"UNMOUNT"),o.current=e}},[e,d]),U(()=>{if(t){let u;const f=t.ownerDocument.defaultView??window,v=g=>{const l=V(r.current).includes(CSS.escape(g.animationName));if(g.target===t&&l&&(d("ANIMATION_END"),!o.current)){const p=t.style.animationFillMode;t.style.animationFillMode="forwards",u=f.setTimeout(()=>{t.style.animationFillMode==="forwards"&&(t.style.animationFillMode=p)})}},m=g=>{g.target===t&&(a.current=V(r.current))};return t.addEventListener("animationstart",m),t.addEventListener("animationcancel",v),t.addEventListener("animationend",v),()=>{f.clearTimeout(u),t.removeEventListener("animationstart",m),t.removeEventListener("animationcancel",v),t.removeEventListener("animationend",v)}}else d("ANIMATION_END")},[t,d]),{isPresent:["mounted","unmountSuspended"].includes(s),ref:i.useCallback(u=>{r.current=u?getComputedStyle(u):null,n(u)},[])}}function V(e){return(e==null?void 0:e.animationName)||"none"}function $t(e){var r,o;let t=(r=Object.getOwnPropertyDescriptor(e.props,"ref"))==null?void 0:r.get,n=t&&"isReactWarning"in t&&t.isReactWarning;return n?e.ref:(t=(o=Object.getOwnPropertyDescriptor(e,"ref"))==null?void 0:o.get,n=t&&"isReactWarning"in t&&t.isReactWarning,n?e.props.ref:e.props.ref||e.ref)}var re=0;function Vt(){i.useEffect(()=>{const e=document.querySelectorAll("[data-radix-focus-guard]");return document.body.insertAdjacentElement("afterbegin",e[0]??Ce()),document.body.insertAdjacentElement("beforeend",e[1]??Ce()),re++,()=>{re===1&&document.querySelectorAll("[data-radix-focus-guard]").forEach(t=>t.remove()),re--}},[])}function Ce(){const e=document.createElement("span");return e.setAttribute("data-radix-focus-guard",""),e.tabIndex=0,e.style.outline="none",e.style.opacity="0",e.style.position="fixed",e.style.pointerEvents="none",e}var x=function(){return x=Object.assign||function(t){for(var n,r=1,o=arguments.length;r<o;r++){n=arguments[r];for(var a in n)Object.prototype.hasOwnProperty.call(n,a)&&(t[a]=n[a])}return t},x.apply(this,arguments)};function Fe(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&typeof Object.getOwnPropertySymbols=="function")for(var o=0,r=Object.getOwnPropertySymbols(e);o<r.length;o++)t.indexOf(r[o])<0&&Object.prototype.propertyIsEnumerable.call(e,r[o])&&(n[r[o]]=e[r[o]]);return n}function Kt(e,t,n){if(n||arguments.length===2)for(var r=0,o=t.length,a;r<o;r++)(a||!(r in t))&&(a||(a=Array.prototype.slice.call(t,0,r)),a[r]=t[r]);return e.concat(a||Array.prototype.slice.call(t))}var H="right-scroll-bar-position",z="width-before-scroll-bar",Gt="with-scroll-bars-hidden",Xt="--removed-body-scroll-bar-size";function oe(e,t){return typeof e=="function"?e(t):e&&(e.current=t),e}function Yt(e,t){var n=i.useState(function(){return{value:e,callback:t,facade:{get current(){return n.value},set current(r){var o=n.value;o!==r&&(n.value=r,n.callback(r,o))}}}})[0];return n.callback=t,n.facade}var Ht=typeof window<"u"?i.useLayoutEffect:i.useEffect,Se=new WeakMap;function zt(e,t){var n=Yt(null,function(r){return e.forEach(function(o){return oe(o,r)})});return Ht(function(){var r=Se.get(n);if(r){var o=new Set(r),a=new Set(e),c=n.current;o.forEach(function(s){a.has(s)||oe(s,null)}),a.forEach(function(s){o.has(s)||oe(s,c)})}Se.set(n,e)},[e]),n}function Zt(e){return e}function qt(e,t){t===void 0&&(t=Zt);var n=[],r=!1,o={read:function(){if(r)throw new Error("Sidecar: could not `read` from an `assigned` medium. `read` could be used only with `useMedium`.");return n.length?n[n.length-1]:e},useMedium:function(a){var c=t(a,r);return n.push(c),function(){n=n.filter(function(s){return s!==c})}},assignSyncMedium:function(a){for(r=!0;n.length;){var c=n;n=[],c.forEach(a)}n={push:function(s){return a(s)},filter:function(){return n}}},assignMedium:function(a){r=!0;var c=[];if(n.length){var s=n;n=[],s.forEach(a),c=n}var d=function(){var f=c;c=[],f.forEach(a)},u=function(){return Promise.resolve().then(d)};u(),n={push:function(f){c.push(f),u()},filter:function(f){return c=c.filter(f),n}}}};return o}function Qt(e){e===void 0&&(e={});var t=qt(null);return t.options=x({async:!0,ssr:!1},e),t}var ke=function(e){var t=e.sideCar,n=Fe(e,["sideCar"]);if(!t)throw new Error("Sidecar: please provide `sideCar` property to import the right car");var r=t.read();if(!r)throw new Error("Sidecar medium not found");return i.createElement(r,x({},n))};ke.isSideCarExport=!0;function Jt(e,t){return e.useMedium(t),ke}var je=Qt(),ae=function(){},Q=i.forwardRef(function(e,t){var n=i.useRef(null),r=i.useState({onScrollCapture:ae,onWheelCapture:ae,onTouchMoveCapture:ae}),o=r[0],a=r[1],c=e.forwardProps,s=e.children,d=e.className,u=e.removeScrollBar,f=e.enabled,v=e.shards,m=e.sideCar,g=e.noRelative,w=e.noIsolation,l=e.inert,p=e.allowPinchZoom,y=e.as,b=y===void 0?"div":y,C=e.gapMode,S=Fe(e,["forwardProps","children","className","removeScrollBar","enabled","shards","sideCar","noRelative","noIsolation","inert","allowPinchZoom","as","gapMode"]),R=m,N=zt([n,t]),E=x(x({},S),o);return i.createElement(i.Fragment,null,f&&i.createElement(R,{sideCar:je,removeScrollBar:u,shards:v,noRelative:g,noIsolation:w,inert:l,setCallbacks:a,allowPinchZoom:!!p,lockRef:n,gapMode:C}),c?i.cloneElement(i.Children.only(s),x(x({},E),{ref:N})):i.createElement(b,x({},E,{className:d,ref:N}),s))});Q.defaultProps={enabled:!0,removeScrollBar:!0,inert:!1};Q.classNames={fullWidth:z,zeroRight:H};var en=function(){if(typeof __webpack_nonce__<"u")return __webpack_nonce__};function tn(){if(!document)return null;var e=document.createElement("style");e.type="text/css";var t=en();return t&&e.setAttribute("nonce",t),e}function nn(e,t){e.styleSheet?e.styleSheet.cssText=t:e.appendChild(document.createTextNode(t))}function rn(e){var t=document.head||document.getElementsByTagName("head")[0];t.appendChild(e)}var on=function(){var e=0,t=null;return{add:function(n){e==0&&(t=tn())&&(nn(t,n),rn(t)),e++},remove:function(){e--,!e&&t&&(t.parentNode&&t.parentNode.removeChild(t),t=null)}}},an=function(){var e=on();return function(t,n){i.useEffect(function(){return e.add(t),function(){e.remove()}},[t&&n])}},We=function(){var e=an(),t=function(n){var r=n.styles,o=n.dynamic;return e(r,o),null};return t},sn={left:0,top:0,right:0,gap:0},ie=function(e){return parseInt(e||"",10)||0},cn=function(e){var t=window.getComputedStyle(document.body),n=t[e==="padding"?"paddingLeft":"marginLeft"],r=t[e==="padding"?"paddingTop":"marginTop"],o=t[e==="padding"?"paddingRight":"marginRight"];return[ie(n),ie(r),ie(o)]},un=function(e){if(e===void 0&&(e="margin"),typeof window>"u")return sn;var t=cn(e),n=document.documentElement.clientWidth,r=window.innerWidth;return{left:t[0],top:t[1],right:t[2],gap:Math.max(0,r-n+t[2]-t[0])}},ln=We(),j="data-scroll-locked",dn=function(e,t,n,r){var o=e.left,a=e.top,c=e.right,s=e.gap;return n===void 0&&(n="margin"),`
2
2
  .`.concat(Gt,` {
3
3
  overflow: hidden `).concat(r,`;
4
4
  padding-right: `).concat(s,"px ").concat(r,`;
@@ -1 +1 @@
1
- import{j as e}from"./index-BpueX0rJ.js";const s=({kind:n,size:a=6,className:l})=>e.jsx("span",{className:`status-dot status-dot-${n}${l?" "+l:""}`,style:{width:a,height:a},"aria-hidden":!0});function d({segments:n,value:a,onChange:l,size:o="md",label:i}){return e.jsx("div",{className:`seg seg-${o}`,role:"tablist","aria-label":i,children:n.map(t=>e.jsxs("button",{role:"tab","aria-selected":t.value===a,"aria-label":t.title&&typeof t.label=="string"?t.label:void 0,"aria-keyshortcuts":t.keyShortcuts,title:t.title,disabled:t.disabled,className:`seg-btn${t.value===a?" seg-btn-active":""}`,onClick:()=>{t.disabled||l(t.value)},type:"button",children:[t.tone&&e.jsx(s,{kind:t.tone}),e.jsx("span",{children:t.label}),typeof t.count=="number"&&e.jsx("span",{className:`seg-count${t.count===0?" seg-count-zero":""}`,children:t.count})]},t.value))})}export{d as S};
1
+ import{j as e}from"./index-CbC9kGzR.js";const s=({kind:n,size:a=6,className:l})=>e.jsx("span",{className:`status-dot status-dot-${n}${l?" "+l:""}`,style:{width:a,height:a},"aria-hidden":!0});function d({segments:n,value:a,onChange:l,size:o="md",label:i}){return e.jsx("div",{className:`seg seg-${o}`,role:"tablist","aria-label":i,children:n.map(t=>e.jsxs("button",{role:"tab","aria-selected":t.value===a,"aria-label":t.title&&typeof t.label=="string"?t.label:void 0,"aria-keyshortcuts":t.keyShortcuts,title:t.title,disabled:t.disabled,className:`seg-btn${t.value===a?" seg-btn-active":""}`,onClick:()=>{t.disabled||l(t.value)},type:"button",children:[t.tone&&e.jsx(s,{kind:t.tone}),e.jsx("span",{children:t.label}),typeof t.count=="number"&&e.jsx("span",{className:`seg-count${t.count===0?" seg-count-zero":""}`,children:t.count})]},t.value))})}export{d as S};
@@ -1,4 +1,4 @@
1
- import{c as n,j as s,D as h}from"./index-BpueX0rJ.js";import{B as r}from"./button-B4yBI9rz.js";/**
1
+ import{c as n,j as s,D as h}from"./index-CbC9kGzR.js";import{B as r}from"./button-DltzrxJt.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{j as t}from"./index-BpueX0rJ.js";const x=({className:s,...a})=>t.jsx("table",{className:`tbl${s?" "+s:""}`,...a}),j=s=>t.jsx("thead",{...s}),c=s=>t.jsx("tbody",{...s}),e=s=>t.jsx("tr",{...s}),n=s=>t.jsx("th",{...s}),T=s=>t.jsx("td",{...s});export{x as T,j as a,e as b,n as c,c as d,T as e};
1
+ import{j as t}from"./index-CbC9kGzR.js";const x=({className:s,...a})=>t.jsx("table",{className:`tbl${s?" "+s:""}`,...a}),j=s=>t.jsx("thead",{...s}),c=s=>t.jsx("tbody",{...s}),e=s=>t.jsx("tr",{...s}),n=s=>t.jsx("th",{...s}),T=s=>t.jsx("td",{...s});export{x as T,j as a,e as b,n as c,c as d,T as e};
@@ -1,4 +1,4 @@
1
- import{c as t}from"./index-BpueX0rJ.js";/**
1
+ import{c as t}from"./index-CbC9kGzR.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 p,x as z,r as c,X as m,j as e,S as k,D as N,P as I,Q as $}from"./index-BpueX0rJ.js";/* empty css */import{S,A as F}from"./SettingCard-B5QGLufn.js";import{P as B}from"./page-header-Dlf-n7I6.js";import{L as T}from"./lock-D7AfKT4W.js";import{C as b}from"./circle-check-DFS84uuw.js";import{A as D}from"./activity-BKpt4jQ5.js";import"./button-B4yBI9rz.js";import"./utils-CDN07tui.js";/**
1
+ import{c as p,x as z,r as c,X as m,j as e,S as k,D as N,V as I,W as $}from"./index-CbC9kGzR.js";/* empty css */import{S,A as F}from"./SettingCard-WgZ0tJaW.js";import{P as B}from"./page-header-DNv41R4K.js";import{L as T}from"./lock-CP7rT2zw.js";import{C as b}from"./circle-check-CY1FVKEM.js";import{A as D}from"./activity-BPmKT1-Z.js";import"./button-DltzrxJt.js";import"./utils-CDN07tui.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -18,4 +18,4 @@ import{c as p,x as z,r as c,X as m,j as e,S as k,D as N,P as I,Q as $}from"./ind
18
18
  *
19
19
  * This source code is licensed under the ISC license.
20
20
  * See the LICENSE file in the root directory of this source tree.
21
- */const O=[["path",{d:"M10 8h4",key:"1sr2af"}],["path",{d:"M12 21v-9",key:"17s77i"}],["path",{d:"M12 8V3",key:"13r4qs"}],["path",{d:"M17 16h4",key:"h1uq16"}],["path",{d:"M19 12V3",key:"o1uvq1"}],["path",{d:"M19 21v-5",key:"qua636"}],["path",{d:"M3 14h4",key:"bcjad9"}],["path",{d:"M5 10V3",key:"cb8scm"}],["path",{d:"M5 21v-7",key:"1w1uti"}]],V=p("sliders-vertical",O),_={aiProvider:"gemini",aiModel:"",aiBaseUrl:"",geminiModel:"",openaiModel:"",anthropicModel:"",ollamaModel:"",geminiSet:!1,openaiSet:!1,anthropicSet:!1,aiTemperature:1,aiMaxTokens:4096,aiTopP:1},X=(s,i)=>s.aiProvider===i.aiProvider&&s.aiTemperature===i.aiTemperature&&s.aiMaxTokens===i.aiMaxTokens&&s.aiTopP===i.aiTopP,o=s=>{switch(s){case"gemini":return"gemini-3-flash-preview";case"openai":return"gpt-4o";case"anthropic":return"claude-sonnet-4-6";case"ollama":return"llama3";default:return"—"}},Y=s=>{switch(s){case"ollama":return"http://localhost:11434";default:return"Provider default"}},se=()=>{const{toast:s}=z(),[i,r]=c.useState(_),[h,u]=c.useState(_),[w,g]=c.useState(!0),[x,v]=c.useState(!1),[f,j]=c.useState(!1);c.useEffect(()=>{P()},[]);const P=async()=>{g(!0);try{const a=await m.getGlobalConfig(),n={aiProvider:a.aiProvider||"gemini",aiModel:a.aiModel||"",aiBaseUrl:a.aiBaseUrl||"",geminiModel:a.geminiModel||"",openaiModel:a.openaiModel||"",anthropicModel:a.anthropicModel||"",ollamaModel:a.ollamaModel||"",geminiSet:!!a.geminiSet,openaiSet:!!a.openaiSet,anthropicSet:!!a.anthropicSet,aiTemperature:typeof a.aiTemperature=="number"?a.aiTemperature:1,aiMaxTokens:typeof a.aiMaxTokens=="number"?a.aiMaxTokens:4096,aiTopP:typeof a.aiTopP=="number"?a.aiTopP:1};r(n),u(n)}catch(a){console.error("Failed to load AISettings",a),s("Failed to access AI configuration.","error")}finally{g(!1)}},C=async()=>{v(!0);try{await m.updateGlobalConfig({aiProvider:i.aiProvider,aiTemperature:i.aiTemperature,aiMaxTokens:i.aiMaxTokens,aiTopP:i.aiTopP}),u(i),s("AI engine configuration saved.","success")}catch(a){console.error("Failed to save AISettings",a),s($(a),"error")}finally{v(!1)}},A=async()=>{j(!0);const a=Date.now();try{const n=await m.testAIConfig({aiProvider:i.aiProvider}),l=Date.now()-a;n.success?s(`${n.message} (${l}ms)`,"success"):s(n.message,"error")}catch(n){s(`Connection failed: ${(n==null?void 0:n.message)||"unknown error"}`,"error")}finally{j(!1)}},d=[{id:"gemini",name:"Google Gemini",description:`${o("gemini")} — Multimodal reasoning`,icon:e.jsx("span",{className:"ai-provider-glyph",children:"G"}),isConfigured:!!i.geminiSet},{id:"openai",name:"OpenAI",description:`${o("openai")} — OpenAI v1 compatible`,icon:e.jsx(q,{size:18}),isConfigured:!!i.openaiSet},{id:"anthropic",name:"Anthropic",description:`${o("anthropic")} — Advanced analysis`,icon:e.jsx(k,{size:18}),isConfigured:!!i.anthropicSet},{id:"ollama",name:"Ollama",description:"Local / self-hosted — no API key required",icon:e.jsx(R,{size:18}),isConfigured:!!i.ollamaModel||!!i.aiModel||!!i.aiBaseUrl}],t=d.find(a=>a.id===i.aiProvider),y=d.filter(a=>a.isConfigured).length,M=!X(i,h);return w?e.jsxs("div",{className:"settings-loading",children:[e.jsx(N,{className:"animate-spin",size:32}),e.jsx("span",{children:"Synchronizing Global State..."})]}):e.jsxs("div",{className:"settings-container",children:[e.jsx(B,{icon:I,title:"AI engine",subtitle:e.jsxs(e.Fragment,{children:["All credentials and endpoints are managed via environment variables.",e.jsxs("span",{className:"page-header-subnote",children:[e.jsx(T,{size:12}),"Select the active provider from configured options below."]})]})}),e.jsx("div",{className:"settings-content",children:e.jsxs("div",{className:"settings-grid settings-grid--two-equal",children:[e.jsx(S,{icon:e.jsx(k,{size:16}),title:"Provider registry",titleExtra:e.jsxs("span",{className:`provider-count-pill ${y>0?"is-ok":"is-empty"}`,children:[y," / ",d.length," configured"]}),description:"Providers are activated via environment variables. Select a configured engine to activate.",children:e.jsx("div",{className:"provider-list",children:d.map(a=>{const n=i.aiProvider===a.id,l=a.isConfigured;return e.jsxs("button",{type:"button",className:`provider-row ${n?"is-active":""} ${l?"":"is-disabled"}`,onClick:()=>l&&r({...i,aiProvider:a.id}),disabled:!l,title:l?`Activate ${a.name}`:`Set XENON_${a.id.toUpperCase()}_API_KEY to enable`,children:[e.jsx("div",{className:"provider-row__icon",children:a.icon}),e.jsxs("div",{className:"provider-row__body",children:[e.jsx("div",{className:"provider-row__name",children:a.name}),e.jsx("div",{className:"provider-row__desc",children:a.description}),e.jsx("div",{className:"provider-row__status",children:n?e.jsxs("span",{className:"provider-status provider-status--active",children:[e.jsx(b,{size:11}),a.isConfigured?"Active":"Active — no key"]}):a.isConfigured?e.jsxs("span",{className:"provider-status provider-status--ready",children:[e.jsx(b,{size:11}),"READY"]}):e.jsxs("span",{className:"provider-status provider-status--off",children:[e.jsx(T,{size:10}),"Not set"]})})]})]},a.id)})})}),e.jsxs(S,{icon:e.jsx(L,{size:16}),title:"Runtime configuration",description:"Environmental overrides for AI model endpoints and identifiers.",children:[e.jsxs("div",{className:"ai-config-display",children:[e.jsxs("div",{className:"ai-config-row",children:[e.jsx("span",{className:"ai-config-label",children:"Active provider"}),e.jsxs("span",{className:"ai-config-value",children:[t==null?void 0:t.icon,(t==null?void 0:t.name)||"—"]})]}),e.jsxs("div",{className:"ai-config-row",children:[e.jsx("span",{className:"ai-config-label",children:"Model"}),e.jsxs("span",{className:"ai-config-value mono",children:[e.jsxs("span",{children:[i.aiProvider==="gemini"&&(i.geminiModel||i.aiModel||o("gemini")),i.aiProvider==="openai"&&(i.openaiModel||i.aiModel||o("openai")),i.aiProvider==="anthropic"&&(i.anthropicModel||i.aiModel||o("anthropic")),i.aiProvider==="ollama"&&(i.ollamaModel||i.aiModel||o("ollama"))]}),e.jsx("span",{className:"ai-config-default",children:"Default"})]})]}),e.jsxs("div",{className:"ai-config-row",children:[e.jsx("span",{className:"ai-config-label",children:"Base URL"}),e.jsxs("span",{className:"ai-config-value mono",children:[e.jsx("span",{children:i.aiBaseUrl||Y(i.aiProvider)}),!i.aiBaseUrl&&e.jsx("span",{className:"ai-config-default",children:"Default"})]})]})]}),e.jsxs("div",{className:"model-params",children:[e.jsxs("div",{className:"model-params__header",children:[e.jsx(V,{size:14}),e.jsx("span",{children:"Model Parameters"})]}),e.jsxs("div",{className:"model-param",children:[e.jsxs("div",{className:"model-param__label-row",children:[e.jsx("label",{htmlFor:"ai-temp",children:"Temperature"}),e.jsx("span",{className:"model-param__value",children:i.aiTemperature.toFixed(1)})]}),e.jsx("input",{id:"ai-temp",type:"range",min:0,max:2,step:.1,value:i.aiTemperature,onChange:a=>r({...i,aiTemperature:parseFloat(a.target.value)}),className:"model-param__slider"})]}),e.jsxs("div",{className:"model-param",children:[e.jsx("div",{className:"model-param__label-row",children:e.jsx("label",{htmlFor:"ai-max-tokens",children:"Max tokens"})}),e.jsx("div",{className:"setting-input-wrapper",children:e.jsx("input",{id:"ai-max-tokens",type:"number",min:256,step:128,value:i.aiMaxTokens,onChange:a=>r({...i,aiMaxTokens:parseInt(a.target.value,10)||0})})})]}),e.jsxs("div",{className:"model-param",children:[e.jsxs("div",{className:"model-param__label-row",children:[e.jsx("label",{htmlFor:"ai-top-p",children:"Top P"}),e.jsx("span",{className:"model-param__value",children:i.aiTopP.toFixed(2)})]}),e.jsx("input",{id:"ai-top-p",type:"range",min:0,max:1,step:.01,value:i.aiTopP,onChange:a=>r({...i,aiTopP:parseFloat(a.target.value)}),className:"model-param__slider"})]})]}),e.jsxs("button",{type:"button",className:"test-connection-btn",onClick:A,disabled:f||!(t!=null&&t.isConfigured),children:[f?e.jsx(N,{size:14,className:"animate-spin"}):e.jsx(D,{size:14}),e.jsx("span",{children:"Test Connection"})]})]})]})}),(M||x)&&e.jsx(F,{onSave:C,onDiscard:()=>r(h),isSaving:x,isDirty:M,saveLabel:"Save configuration"})]})};export{se as AISettings};
21
+ */const V=[["path",{d:"M10 8h4",key:"1sr2af"}],["path",{d:"M12 21v-9",key:"17s77i"}],["path",{d:"M12 8V3",key:"13r4qs"}],["path",{d:"M17 16h4",key:"h1uq16"}],["path",{d:"M19 12V3",key:"o1uvq1"}],["path",{d:"M19 21v-5",key:"qua636"}],["path",{d:"M3 14h4",key:"bcjad9"}],["path",{d:"M5 10V3",key:"cb8scm"}],["path",{d:"M5 21v-7",key:"1w1uti"}]],O=p("sliders-vertical",V),_={aiProvider:"gemini",aiModel:"",aiBaseUrl:"",geminiModel:"",openaiModel:"",anthropicModel:"",ollamaModel:"",geminiSet:!1,openaiSet:!1,anthropicSet:!1,aiTemperature:1,aiMaxTokens:4096,aiTopP:1},X=(s,i)=>s.aiProvider===i.aiProvider&&s.aiTemperature===i.aiTemperature&&s.aiMaxTokens===i.aiMaxTokens&&s.aiTopP===i.aiTopP,o=s=>{switch(s){case"gemini":return"gemini-3-flash-preview";case"openai":return"gpt-4o";case"anthropic":return"claude-sonnet-4-6";case"ollama":return"llama3";default:return"—"}},Y=s=>{switch(s){case"ollama":return"http://localhost:11434";default:return"Provider default"}},se=()=>{const{toast:s}=z(),[i,r]=c.useState(_),[h,u]=c.useState(_),[w,g]=c.useState(!0),[x,v]=c.useState(!1),[f,j]=c.useState(!1);c.useEffect(()=>{P()},[]);const P=async()=>{g(!0);try{const a=await m.getGlobalConfig(),n={aiProvider:a.aiProvider||"gemini",aiModel:a.aiModel||"",aiBaseUrl:a.aiBaseUrl||"",geminiModel:a.geminiModel||"",openaiModel:a.openaiModel||"",anthropicModel:a.anthropicModel||"",ollamaModel:a.ollamaModel||"",geminiSet:!!a.geminiSet,openaiSet:!!a.openaiSet,anthropicSet:!!a.anthropicSet,aiTemperature:typeof a.aiTemperature=="number"?a.aiTemperature:1,aiMaxTokens:typeof a.aiMaxTokens=="number"?a.aiMaxTokens:4096,aiTopP:typeof a.aiTopP=="number"?a.aiTopP:1};r(n),u(n)}catch(a){console.error("Failed to load AISettings",a),s("Failed to access AI configuration.","error")}finally{g(!1)}},C=async()=>{v(!0);try{await m.updateGlobalConfig({aiProvider:i.aiProvider,aiTemperature:i.aiTemperature,aiMaxTokens:i.aiMaxTokens,aiTopP:i.aiTopP}),u(i),s("AI engine configuration saved.","success")}catch(a){console.error("Failed to save AISettings",a),s($(a),"error")}finally{v(!1)}},A=async()=>{j(!0);const a=Date.now();try{const n=await m.testAIConfig({aiProvider:i.aiProvider}),l=Date.now()-a;n.success?s(`${n.message} (${l}ms)`,"success"):s(n.message,"error")}catch(n){s(`Connection failed: ${(n==null?void 0:n.message)||"unknown error"}`,"error")}finally{j(!1)}},d=[{id:"gemini",name:"Google Gemini",description:`${o("gemini")} — Multimodal reasoning`,icon:e.jsx("span",{className:"ai-provider-glyph",children:"G"}),isConfigured:!!i.geminiSet},{id:"openai",name:"OpenAI",description:`${o("openai")} — OpenAI v1 compatible`,icon:e.jsx(q,{size:18}),isConfigured:!!i.openaiSet},{id:"anthropic",name:"Anthropic",description:`${o("anthropic")} — Advanced analysis`,icon:e.jsx(k,{size:18}),isConfigured:!!i.anthropicSet},{id:"ollama",name:"Ollama",description:"Local / self-hosted — no API key required",icon:e.jsx(R,{size:18}),isConfigured:!!i.ollamaModel||!!i.aiModel||!!i.aiBaseUrl}],t=d.find(a=>a.id===i.aiProvider),y=d.filter(a=>a.isConfigured).length,M=!X(i,h);return w?e.jsxs("div",{className:"settings-loading",children:[e.jsx(N,{className:"animate-spin",size:32}),e.jsx("span",{children:"Synchronizing Global State..."})]}):e.jsxs("div",{className:"settings-container",children:[e.jsx(B,{icon:I,title:"AI engine",subtitle:e.jsxs(e.Fragment,{children:["All credentials and endpoints are managed via environment variables.",e.jsxs("span",{className:"page-header-subnote",children:[e.jsx(T,{size:12}),"Select the active provider from configured options below."]})]})}),e.jsx("div",{className:"settings-content",children:e.jsxs("div",{className:"settings-grid settings-grid--two-equal",children:[e.jsx(S,{icon:e.jsx(k,{size:16}),title:"Provider registry",titleExtra:e.jsxs("span",{className:`provider-count-pill ${y>0?"is-ok":"is-empty"}`,children:[y," / ",d.length," configured"]}),description:"Providers are activated via environment variables. Select a configured engine to activate.",children:e.jsx("div",{className:"provider-list",children:d.map(a=>{const n=i.aiProvider===a.id,l=a.isConfigured;return e.jsxs("button",{type:"button",className:`provider-row ${n?"is-active":""} ${l?"":"is-disabled"}`,onClick:()=>l&&r({...i,aiProvider:a.id}),disabled:!l,title:l?`Activate ${a.name}`:`Set XENON_${a.id.toUpperCase()}_API_KEY to enable`,children:[e.jsx("div",{className:"provider-row__icon",children:a.icon}),e.jsxs("div",{className:"provider-row__body",children:[e.jsx("div",{className:"provider-row__name",children:a.name}),e.jsx("div",{className:"provider-row__desc",children:a.description}),e.jsx("div",{className:"provider-row__status",children:n?e.jsxs("span",{className:"provider-status provider-status--active",children:[e.jsx(b,{size:11}),a.isConfigured?"Active":"Active — no key"]}):a.isConfigured?e.jsxs("span",{className:"provider-status provider-status--ready",children:[e.jsx(b,{size:11}),"READY"]}):e.jsxs("span",{className:"provider-status provider-status--off",children:[e.jsx(T,{size:10}),"Not set"]})})]})]},a.id)})})}),e.jsxs(S,{icon:e.jsx(L,{size:16}),title:"Runtime configuration",description:"Environmental overrides for AI model endpoints and identifiers.",children:[e.jsxs("div",{className:"ai-config-display",children:[e.jsxs("div",{className:"ai-config-row",children:[e.jsx("span",{className:"ai-config-label",children:"Active provider"}),e.jsxs("span",{className:"ai-config-value",children:[t==null?void 0:t.icon,(t==null?void 0:t.name)||"—"]})]}),e.jsxs("div",{className:"ai-config-row",children:[e.jsx("span",{className:"ai-config-label",children:"Model"}),e.jsxs("span",{className:"ai-config-value mono",children:[e.jsxs("span",{children:[i.aiProvider==="gemini"&&(i.geminiModel||i.aiModel||o("gemini")),i.aiProvider==="openai"&&(i.openaiModel||i.aiModel||o("openai")),i.aiProvider==="anthropic"&&(i.anthropicModel||i.aiModel||o("anthropic")),i.aiProvider==="ollama"&&(i.ollamaModel||i.aiModel||o("ollama"))]}),e.jsx("span",{className:"ai-config-default",children:"Default"})]})]}),e.jsxs("div",{className:"ai-config-row",children:[e.jsx("span",{className:"ai-config-label",children:"Base URL"}),e.jsxs("span",{className:"ai-config-value mono",children:[e.jsx("span",{children:i.aiBaseUrl||Y(i.aiProvider)}),!i.aiBaseUrl&&e.jsx("span",{className:"ai-config-default",children:"Default"})]})]})]}),e.jsxs("div",{className:"model-params",children:[e.jsxs("div",{className:"model-params__header",children:[e.jsx(O,{size:14}),e.jsx("span",{children:"Model Parameters"})]}),e.jsxs("div",{className:"model-param",children:[e.jsxs("div",{className:"model-param__label-row",children:[e.jsx("label",{htmlFor:"ai-temp",children:"Temperature"}),e.jsx("span",{className:"model-param__value",children:i.aiTemperature.toFixed(1)})]}),e.jsx("input",{id:"ai-temp",type:"range",min:0,max:2,step:.1,value:i.aiTemperature,onChange:a=>r({...i,aiTemperature:parseFloat(a.target.value)}),className:"model-param__slider"})]}),e.jsxs("div",{className:"model-param",children:[e.jsx("div",{className:"model-param__label-row",children:e.jsx("label",{htmlFor:"ai-max-tokens",children:"Max tokens"})}),e.jsx("div",{className:"setting-input-wrapper",children:e.jsx("input",{id:"ai-max-tokens",type:"number",min:256,step:128,value:i.aiMaxTokens,onChange:a=>r({...i,aiMaxTokens:parseInt(a.target.value,10)||0})})})]}),e.jsxs("div",{className:"model-param",children:[e.jsxs("div",{className:"model-param__label-row",children:[e.jsx("label",{htmlFor:"ai-top-p",children:"Top P"}),e.jsx("span",{className:"model-param__value",children:i.aiTopP.toFixed(2)})]}),e.jsx("input",{id:"ai-top-p",type:"range",min:0,max:1,step:.01,value:i.aiTopP,onChange:a=>r({...i,aiTopP:parseFloat(a.target.value)}),className:"model-param__slider"})]})]}),e.jsxs("button",{type:"button",className:"test-connection-btn",onClick:A,disabled:f||!(t!=null&&t.isConfigured),children:[f?e.jsx(N,{size:14,className:"animate-spin"}):e.jsx(D,{size:14}),e.jsx("span",{children:"Test Connection"})]})]})]})}),(M||x)&&e.jsx(F,{onSave:C,onDiscard:()=>r(h),isSaving:x,isDirty:M,saveLabel:"Save configuration"})]})};export{se as AISettings};