diff --git a/server/public/assets/index-DJv47phz.js b/server/public/assets/index-CLITRLLE.js similarity index 98% rename from server/public/assets/index-DJv47phz.js rename to server/public/assets/index-CLITRLLE.js index db893ec4..53fe73d1 100644 --- a/server/public/assets/index-DJv47phz.js +++ b/server/public/assets/index-CLITRLLE.js @@ -116,4 +116,4 @@ wine wok yeast yogurt -`;function gN(a){return a?a.charAt(0).toUpperCase()+a.slice(1):""}function xN(){const a=String(pN).split(/\r?\n/).map(i=>i.trim()).filter(Boolean);return a.length?(a[Math.floor(Math.random()*a.length)]||"").trim():""}function zf(){const{setNickname:a}=_e(),{value:l,status:i,save:r}=dt("profile",{nickname:""}),f=m.useRef(!1);m.useEffect(()=>{if(i!=="ready"||f.current||(l.nickname||"").trim())return;f.current=!0;const h=gN(xN()).slice(0,32);if(!h)return;(async()=>{try{await a(h)}catch{}finally{r({nickname:h})}})()},[r,a,i,l.nickname])}const Uu=1e4,Hu=28,vN=14;function Hr({layout:a="desktop",className:l="",dismissable:i=!0}){const{session:r}=_e(),f=r?.communityGoal?.text?String(r.communityGoal.text).trim():"",d=a==="mobile-portrait"||a==="mobile-landscape"||a==="mobile",[h,x]=m.useState(!1),[p,v]=m.useState(Hu),[b,S]=m.useState(0),E=m.useRef(null),M=m.useRef(null),j=m.useRef(null);m.useEffect(()=>{if(!f){x(!1);return}if(x(!0),!d||!i)return;const C=Date.now();S(Uu);const R=setTimeout(()=>x(!1),Uu),_=setInterval(()=>{const Q=Date.now()-C;S(Math.max(0,Uu-Q))},250);return()=>{clearTimeout(R),clearInterval(_)}},[f,d]),m.useEffect(()=>{if(!f)return;v(Hu);let C=0;const R=()=>{const Q=j.current,ee=M.current;if(!Q||!ee)return;const U=Q.clientWidth;if(!U)return;const te=ee.scrollWidth;if(!te)return;const X=Math.min(1,U/te),K=Math.max(vN,Math.floor(Hu*X));v(K)};C=window.requestAnimationFrame(R);const _=new ResizeObserver(()=>{window.cancelAnimationFrame(C),C=window.requestAnimationFrame(R)});return E.current&&_.observe(E.current),()=>{window.cancelAnimationFrame(C),_.disconnect()}},[f]);const N=m.useMemo(()=>["panel-section flex w-full items-center justify-center",d?"rounded-none":"rounded","px-1 py-1 text-center font-semibold tracking-tight",l].filter(Boolean).join(" "),[l,d]);if(!f||!h)return null;const A=d?Math.ceil(b/1e3):null,w=i?{onClick:()=>x(!1),role:"button",tabIndex:0}:{};return o.jsx("div",{ref:E,className:N,style:{fontSize:`${p}px`,lineHeight:1.1},...w,children:o.jsxs("span",{className:"flex w-full items-stretch gap-0.5 whitespace-nowrap rounded-md",children:[o.jsxs("span",{className:"flex flex-col justify-center border-r border-slate-700/60 px-0.5 text-[0.55em] font-semibold leading-tight text-slate-400",children:[o.jsx("span",{children:"Community"}),o.jsx("span",{children:"Goal"})]}),o.jsx("span",{ref:j,className:"flex-1 overflow-hidden text-slate-100",children:o.jsx("span",{ref:M,className:"block",children:f})}),d?o.jsxs("span",{className:"flex items-center border-l border-slate-700/60 px-0.5 text-[0.55em] font-semibold uppercase tracking-wide text-slate-400",children:[A,"s"]}):null]})})}function yN(){const[a,l]=m.useState(()=>typeof window>"u"||window.innerWidth>=1024?"desktop":window.innerWidth>window.innerHeight?"mobile-landscape":"mobile-portrait");return m.useEffect(()=>{function i(){if(typeof window>"u")return;const{innerWidth:r,innerHeight:f}=window;r>=1024?l("desktop"):r>f?l("mobile-landscape"):l("mobile-portrait")}return i(),window.addEventListener("resize",i),()=>window.removeEventListener("resize",i)},[]),a}function bN({layout:a,onOpenHelpOverlay:l}){return o.jsxs("div",{className:"flex h-full gap-0.5 overflow-hidden",children:[o.jsxs("div",{className:"flex min-w-0 flex-[1.22] flex-col gap-0.5 overflow-y-auto pr-0",children:[o.jsx(Mf,{}),o.jsx(lS,{}),o.jsx(Ef,{})]}),o.jsxs("div",{className:"flex min-w-0 flex-1 flex-col gap-0.5 overflow-y-auto",children:[o.jsx(Hr,{layout:a}),o.jsx(Pj,{layout:a,onOpenHelpOverlay:l})]})]})}function ax({layout:a,onOpenHelpOverlay:l,roomPanelId:i,showTelemetry:r=!0}){return o.jsx("section",{className:"panel text-base",children:o.jsxs(_f,{defaultTab:"chat",children:[o.jsxs(Df,{children:[o.jsx(Zt,{id:"chat",children:"Chat"}),o.jsx(Zt,{id:"roomcontrols",children:"Room Controls"}),o.jsx(Zt,{id:"help",children:"Help"}),o.jsx(Zt,{id:"settings",children:"Settings"})]}),o.jsxs(Of,{children:[o.jsx(Ft,{id:"chat",children:o.jsxs("div",{className:"space-y-0.5",children:[o.jsx(Fr,{}),o.jsx(Ur,{})]})}),o.jsx(Ft,{id:"roomcontrols",children:o.jsxs("div",{className:"space-y-0.5",children:[o.jsx(Xg,{}),o.jsx(wf,{panelId:i})]})}),o.jsx(Ft,{id:"help",children:o.jsx(Pg,{layout:a,onOpenOverlay:l})}),o.jsx(Ft,{id:"settings",children:o.jsxs("div",{className:"space-y-0.5",children:[o.jsx(Jg,{}),o.jsx(Ef,{})]})})]})]})})}function SN({onOpenHelpOverlay:a}){return o.jsxs("div",{className:"flex flex-col gap-0.5",children:[o.jsx(Mf,{layoutFormat:"mobile-portrait"}),o.jsx(NA,{}),o.jsxs("div",{className:"grid gap-0.5 grid-cols-[minmax(0,1fr)_minmax(0,1.4fr)]",children:[o.jsx(yf,{panelId:"replay-sources-mobile-portrait"}),o.jsx(Jr,{})]}),o.jsx(ax,{layout:"mobile-portrait",onOpenHelpOverlay:a,roomPanelId:"mobile-portrait-room"})]})}function AN({onOpenHelpOverlay:a}){return o.jsxs("div",{className:"flex flex-col gap-0.5",children:[o.jsxs("section",{className:"grid min-h-screen grid-cols-[minmax(0,0.7fr)_minmax(0,2.1fr)_minmax(0,0.7fr)] gap-0.5",children:[o.jsx(AA,{}),o.jsxs("div",{children:[o.jsx(Mf,{layoutFormat:"mobile-landscape"}),o.jsxs("div",{className:"grid gap-0.5 grid-cols-[minmax(0,1fr)_minmax(0,1.4fr)]",children:[o.jsx(yf,{panelId:"replay-sources-mobile-landscape"}),o.jsx(Jr,{})]})]}),o.jsx(jA,{})]}),o.jsx("div",{className:"flex flex-col gap-0.5 pb-0",children:o.jsx(ax,{layout:"mobile-landscape",onOpenHelpOverlay:a,roomPanelId:"mobile-landscape-room",showTelemetry:!1})})]})}function jN(){const a=yN(),l=a==="desktop",i=mN(a);return o.jsx("div",{className:`bg-black text-slate-100 ${l?"h-screen overflow-hidden":"min-h-screen"}`,children:o.jsx(vf,{children:o.jsx(NN,{layout:a,isDesktop:l,fullscreen:i})})})}function NN({layout:a,isDesktop:l,fullscreen:i}){zf();const{visible:r,mode:f,enterFullscreen:d,dismiss:h}=i,{value:x,status:p,save:v}=dt("help",{showOnLoad:!0}),[b,S]=m.useState(!1);m.useEffect(()=>{p==="ready"&&S(x?.showOnLoad!==!1)},[p,x?.showOnLoad]);const E=m.useCallback(()=>S(!0),[]),M=m.useCallback(()=>S(!1),[]),j=m.useCallback(A=>{const w=!!A;v(C=>({...C??{},showOnLoad:w})),w||S(!1)},[v]),N=m.useMemo(()=>l?o.jsx(bN,{layout:a,onOpenHelpOverlay:E}):a==="mobile-landscape"?o.jsx(AN,{onOpenHelpOverlay:E}):o.jsx(SN,{onOpenHelpOverlay:E}),[l,a,E]);return o.jsxs($S,{children:[o.jsx(eA,{}),o.jsx(gA,{}),o.jsxs("main",{className:`flex w-full flex-col gap-0.5 text-base ${l?"h-full overflow-hidden":""}`,children:[l?null:o.jsx(Hr,{layout:a}),N]}),o.jsx(bf,{}),o.jsx(rN,{}),o.jsx(lN,{}),o.jsx(hN,{visible:b,layout:a,onClose:M,showOnLoad:x?.showOnLoad!==!1,onToggleShowOnLoad:j}),o.jsx(oN,{visible:r,mode:f,onEnterFullscreen:d,onDismiss:h})]})}function lx(){const{session:a,setRole:l,subscribeAll:i,connected:r}=_e(),[f,d]=m.useState(!1);return m.useEffect(()=>{let h=!1;async function x(){if(a?.mode==="lockdown"){d(!1);return}try{a?.role!=="spectator"&&await l("spectator"),await i(),h||d(!0)}catch(p){console.error("Failed to enter spectator mode",p),h||d(!1)}}return x(),()=>{h=!0}},[r,a?.mode,a?.role,l,i]),f}function wN(){const[a,l]=m.useState(()=>typeof window>"u"?!1:window.matchMedia("(max-aspect-ratio: 4/3)").matches);return m.useEffect(()=>{if(typeof window>"u")return;const i=window.matchMedia("(max-aspect-ratio: 4/3)"),r=f=>l(f.matches);return i.addEventListener?i.addEventListener("change",r):i.addListener(r),()=>{i.removeEventListener?i.removeEventListener("change",r):i.removeListener(r)}},[]),a}function EN({roverId:a,session:l}){const i=l?.activeDrivers?.[a]||null,f=(l?.users||[]).find(p=>p.socketId===i)?.nickname||(i?i.slice(0,6):"No driver"),d=l?.mode,h=l?.turnQueues?.[a];return d==="turns"&&h?.current?`${f} (turns)`:f}function CN({rover:a,frame:l,sessionInfo:i,videoMode:r,snapshotFeed:f,audioInfo:d,session:h}){const x=EN({roverId:a.id,session:h});return o.jsx("article",{className:"min-h-[16rem] rounded bg-zinc-900 p-0 sm:min-h-[18rem]",children:o.jsx("div",{className:"min-h-0 overflow-hidden rounded bg-black/20",children:o.jsx(Ks,{sessionInfo:i,videoMode:r,snapshotFeed:f,audioSessionInfo:d,label:a.name,telemetryFrame:l,batteryConfig:a.battery,hudVariant:"spectator",driverLabel:x,hudForceMap:!0,hudMapPosition:"top-center"})})})}function qN({roster:a,frames:l,videoSources:i,snapshotFeeds:r,audioSources:f,session:d,canSpectateVideo:h}){return a.length===0?o.jsx("p",{className:"col-span-full text-slate-400",children:"No rovers registered."}):o.jsx("section",{className:"grid grid-cols-1 gap-0.5 md:grid-cols-2",children:a.map(x=>o.jsx(CN,{rover:x,frame:l[x.id],sessionInfo:h&&i[x.id]||null,videoMode:h?"whep":"snapshot",snapshotFeed:h?null:r[x.id],audioInfo:f[`${x.id}-audio`],session:d,showHudMap:!0,hudMapPosition:"bottom-left"},x.id))})}function MN(){return o.jsx("section",{className:"min-h-0",children:o.jsx("div",{className:"surface min-h-[14rem] overflow-hidden",children:o.jsx(wf,{defaultOrientation:"horizontal",hideLayoutToggle:!0,hideHeader:!0,panelId:"spectator-secondary"})})})}function TN({className:a=""}){return o.jsx("div",{className:`panel ${a}`,children:o.jsx(Ef,{})})}function RN(){const{session:a}=_e(),l=a?.mode==="lockdown",i=!!a?.isLocalNetwork;zf(),lx();const r=wN(),f=xf(),d=a?.roster??[],h=Cf(d.map(A=>A.id),{enabled:!l&&!i,version:a?.mode}),x=i?d.map(A=>({type:"rover",id:A.id,key:A.id})):[],p=Qs(x,{enabled:!l&&i,version:a?.mode}),v=d.flatMap(A=>A.media?.audioPublishUrl?[{type:"rover",id:`${A.id}-audio`,key:`${A.id}-audio`}]:[]),b=Qs(v,{enabled:!l,version:a?.mode});if(l)return o.jsx("div",{className:"flex min-h-screen items-center justify-center bg-black text-slate-200",children:o.jsxs("div",{className:"surface max-w-md space-y-0.5 p-1 text-center text-sm",children:[o.jsx("p",{className:"text-lg font-semibold text-white",children:"Spectate disabled during lockdown."}),o.jsx("p",{className:"text-slate-300",children:"Please wait until the server leaves lockdown to view streams."})]})});const S=r?"flex min-h-screen flex-col bg-black text-slate-100 md:h-screen md:overflow-hidden":"grid min-h-screen grid-cols-1 gap-0.5 bg-black text-slate-100 md:h-full md:min-h-0 md:grid-cols-[minmax(0,1fr)_18rem] lg:grid-cols-[minmax(0,1fr)_20rem]",E=r?"order-2 flex min-h-0 min-w-0 flex-1 flex-col gap-0.5 overflow-y-auto":"order-1 flex min-h-0 min-w-0 flex-col gap-0.5 md:overflow-y-auto",M=r?"order-1 grid w-full min-h-0 items-stretch gap-0.5 border-b border-slate-800/60 bg-slate-950/90 p-0.5 grid-cols-[minmax(0,1fr)_minmax(0,0.7fr)_minmax(0,1.9fr)_minmax(0,0.7fr)]":"order-2 flex min-h-0 min-w-0 flex-col gap-0.5 border-l border-slate-800/60 bg-slate-950/90 md:h-full md:overflow-y-auto",j="",N=r?"h-64":"";return o.jsxs("div",{className:"min-h-screen bg-black text-slate-100 md:h-screen md:overflow-hidden",children:[o.jsxs("main",{className:S,children:[o.jsxs("section",{className:M,children:[r?o.jsxs("div",{className:`${j} ${N} flex flex-col gap-0.5`,children:[o.jsx(Hr,{layout:"desktop",dismissable:!1,className:"text-sm"}),o.jsx("div",{className:"min-h-0 flex-1",children:o.jsx(Ur,{hideNicknameForm:!0,hideHeader:!0,compact:!0,fillHeight:!0,className:"h-full"})})]}):o.jsx("div",{className:j,children:o.jsx(Hr,{layout:"desktop",dismissable:!1,className:"text-sm"})}),o.jsx("div",{className:`${j} ${r?`${N} overflow-y-auto`:""}`,children:o.jsx("div",{className:"panel h-full",children:o.jsx(Jr,{title:"Rovers"})})}),r?null:o.jsx("div",{className:`${j} flex-1 min-h-0`,children:o.jsx(Ur,{hideNicknameForm:!0,hideHeader:!0,compact:!0,fillHeight:!0,className:"h-full"})}),o.jsx("div",{className:`${j} ${r?N:"flex-[1.1] min-h-0"}`,children:o.jsx(Fr,{allowSpectatorInput:!0,hideSpectatorNotice:!0,fillHeight:!0})}),o.jsx("div",{className:`${j} ${r?N:""}`,children:o.jsx(TN,{className:`${r?"h-full":"h-40"} overflow-hidden`})})]}),o.jsxs("section",{className:E,children:[o.jsx(qN,{roster:d,frames:f,videoSources:p,snapshotFeeds:h,audioSources:b,session:a,canSpectateVideo:i}),o.jsx(MN,{})]})]}),o.jsx(bf,{})]})}function kN(){return o.jsx(vf,{children:o.jsx(RN,{})})}const _N=2e4,DN=10800*1e3;function ON({roverId:a,session:l}){const i=l?.activeDrivers?.[a]||null,f=(l?.users||[]).find(x=>x.socketId===i)?.nickname||(i?i.slice(0,6):"No driver"),d=l?.mode,h=l?.turnQueues?.[a];return d==="turns"&&h?.current?`${f}`:f}function BN({rover:a,frame:l}){const i=a?.batteryState?.percentDisplay;if(i!=null&&Number.isFinite(i))return Math.round(i);const r=a?.battery??null,f=l?.sensors?.batteryChargeMah??null,d=r?.Full??null,h=r?.Warn??null;if(f==null||d==null||h==null)return null;const x=d-h;if(x<=0)return null;const p=(f-h)/x;return Math.round(Math.max(0,Math.min(1,p))*100)}function zN({rover:a}){const l=a?.batteryState?.urgentActive??!1,i=a?.batteryState?.warnActive??!1;return l?"bg-red-500/40":i?"bg-amber-400/40":"bg-emerald-400/40"}function D0({rover:a,frame:l,driverLabel:i,sessionInfo:r,videoMode:f="snapshot",snapshotFeed:d,withDivider:h=!1,showPreview:x=!0,variant:p="stacked"}){const v=BN({rover:a,frame:l}),b=zN({rover:a}),S=p==="active",E=S?{height:`${v??0}%`,bottom:0,top:"auto"}:{width:`${v??0}%`},M=S?`pointer-events-none absolute bottom-0 left-0 right-0 ${b}`:`pointer-events-none absolute left-0 top-0 bottom-0 ${b}`;return o.jsxs("div",{className:`relative flex min-w-0 flex-1 flex-col gap-4 overflow-hidden bg-black px-0 py-0 ${h?"border-r border-slate-700/60":""}`,children:[o.jsx("div",{className:M,style:E}),S?o.jsxs("div",{className:"relative z-10 flex min-w-0 flex-1 flex-col justify-between text-center",children:[o.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:o.jsx(El,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:18,children:a.name||a.id})}),i?o.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:o.jsx(El,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:16,children:i})}):o.jsx("div",{}),o.jsx("div",{className:"relative min-w-0 overflow-hidden bg-transparent px-0 py-0 leading-none",children:o.jsx("div",{className:"relative",children:o.jsx(El,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:16,children:v==null?"--%":`${v}%`})})})]}):o.jsxs(o.Fragment,{children:[o.jsxs("div",{className:"relative z-10 flex min-w-0 flex-col gap-1 text-center",children:[o.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:o.jsx(El,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:18,children:a.name||a.id})}),i?o.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:o.jsx(El,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:16,children:i})}):null,o.jsx("div",{className:"relative min-w-0 overflow-hidden bg-transparent px-0 py-0 leading-none",children:o.jsx("div",{className:"relative",children:o.jsx(El,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:16,children:v==null?"--%":`${v}%`})})})]}),o.jsx("div",{className:"relative z-10 flex min-w-0 flex-1 flex-col gap-4",children:o.jsx("div",{className:"flex w-full min-w-0 flex-1 flex-col items-center gap-4",children:x?o.jsx("div",{className:"mt-auto w-full",children:o.jsx("div",{className:"w-full aspect-[4/3]",children:o.jsx(Ks,{sessionInfo:r,videoMode:f,snapshotFeed:d,audioSessionInfo:null,label:a.name||a.id,telemetryFrame:l,batteryConfig:a.battery,layoutFormat:"mobile",hudVariant:"none",fitParent:!0})})}):null})})]})]})}function El({children:a,className:l="",maxSize:i=1e3,minSize:r=14}){const f=m.useRef(null),d=m.useRef(null),[h,x]=m.useState(i);return m.useLayoutEffect(()=>{const p=f.current,v=d.current;if(!p||!v)return;let b=null;const S=()=>{const j=p.clientWidth;if(!j){E();return}let N=r,A=i,w=r;for(;N<=A;){const C=Math.floor((N+A)/2);v.style.fontSize=`${C}px`,v.scrollWidth<=j?(w=C,N=C+1):A=C-1}x(w)},E=()=>{b&&cancelAnimationFrame(b),b=requestAnimationFrame(S)};E();const M=new ResizeObserver(E);return M.observe(p),()=>{b&&cancelAnimationFrame(b),M.disconnect()}},[a,i,r]),o.jsx("div",{ref:f,className:"w-full min-w-0",children:o.jsx("div",{ref:d,className:`whitespace-nowrap ${l}`,style:{fontSize:`${h}px`,lineHeight:1.1},children:a})})}function LN(){const{session:a}=_e(),l=lx();zf();const i=a?.mode==="lockdown",r=!!a?.isLocalNetwork,f=xf(),d=a?.roster??[],[h,x]=m.useState(0),p=a?.activeDrivers||{},v=m.useMemo(()=>d.filter(K=>p[K.id]),[d,p]),b=v.length?v:d,S=Cf(b.map(K=>K.id),{enabled:!i&&!r,version:a?.mode}),E=m.useMemo(()=>r?b.map(K=>({type:"rover",id:K.id,key:K.id})):[],[r,b]),M=Qs(E,{enabled:!i&&r,version:a?.mode}),j=m.useMemo(()=>v.flatMap(K=>{if(!K?.id||!K.media?.audioPublishUrl)return[];const L=String(K.id);return[{type:"rover",id:`${L}-audio`,key:`${L}-audio`}]}),[v]),N=Qs(j,{enabled:!i,version:a?.mode}),A=m.useMemo(()=>{if(!v.length)return[];if(!r){const L=v.filter(Z=>S[Z.id]?.objectUrl);return L.length?L:v}const K=v.filter(L=>{const Z=M[L.id];return Z?.url&&!Z?.error});return K.length?K:v},[v,S,M,r]),w=m.useMemo(()=>A.map(K=>({type:"rover",rover:K})),[A]),C=m.useMemo(()=>w.map(K=>`r:${K.rover.id}`).join("|"),[w]);m.useEffect(()=>{x(0)},[C]),m.useEffect(()=>{if(!w.length)return;const K=setInterval(()=>{x(L=>(L+1)%w.length)},_N);return()=>clearInterval(K)},[w.length,C]);const R=w.length?w[h%w.length]:null,_=R?.type==="rover"?R.rover:null,Q=!r&&_&&S[_.id]||null,ee=r&&_&&M[_.id]||null,U=_&&N[`${_.id}-audio`]||null,te=_&&f[_.id]||null,X=_?ON({roverId:_.id,session:a}):null;return i?o.jsx("div",{className:"relative flex h-screen w-screen items-center justify-center bg-black text-slate-200",children:o.jsxs("div",{className:"surface max-w-sm space-y-0.5 p-1 text-center text-sm",children:[o.jsx("p",{className:"text-lg font-semibold text-white",children:"Mini spectator is disabled in lockdown."}),o.jsx("p",{className:"text-slate-300",children:"It will automatically resume once lockdown ends."})]})}):v.length?o.jsxs("div",{className:"relative flex h-screen w-screen overflow-hidden bg-black text-slate-100",children:[o.jsx("section",{className:"relative flex h-full shrink-0 items-center justify-start overflow-hidden bg-black",style:{width:"min(100vw, calc(100vh * 4 / 3))"},children:l?_?o.jsx(HN,{children:r?o.jsx("div",{className:"relative h-full w-full",children:w.map(K=>{const L=K.rover,Z=_?.id===L.id;return o.jsx("div",{className:`absolute inset-0 ${Z?"opacity-100":"opacity-0 pointer-events-none"}`,children:o.jsx(Ks,{sessionInfo:M[L.id]||null,videoMode:"whep",snapshotFeed:null,audioSessionInfo:Z?U:null,forceMute:!Z,label:L.name||L.id,telemetryFrame:f[L.id]||null,batteryConfig:L.battery,layoutFormat:"mobile",hudVariant:"none",fitParent:!0})},L.id)})}):o.jsx(Ks,{sessionInfo:null,videoMode:"snapshot",snapshotFeed:Q,audioSessionInfo:U,label:_.name||_.id,telemetryFrame:te,batteryConfig:_.battery,layoutFormat:"mobile",hudVariant:"none",fitParent:!0})}):o.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:v.length?"No sources available.":"No active drivers."}):o.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:"Switching to spectator…"})}),o.jsx("aside",{className:"flex h-full min-w-0 flex-1 flex-col border-l border-slate-800/60 bg-black",children:_?o.jsx(D0,{rover:_,frame:te,driverLabel:X,sessionInfo:r?ee:null,videoMode:r?"whep":"snapshot",snapshotFeed:r?null:S[_.id]||null,showPreview:!1,variant:"active"}):o.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:"No active rover."})})]}):o.jsx("div",{className:"relative flex h-screen w-screen overflow-hidden bg-black text-slate-100",children:o.jsx("section",{className:"flex h-full w-full gap-x-1",children:d.length?d.map((K,L)=>o.jsx(D0,{rover:K,frame:f[K.id]||null,driverLabel:null,sessionInfo:r&&M[K.id]||null,videoMode:r?"whep":"snapshot",snapshotFeed:r?null:S[K.id]||null,showPreview:!0,withDivider:!1},K.id)):o.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:"No rovers available."})})})}function UN(){return m.useEffect(()=>{if(typeof window>"u")return;const a=setTimeout(()=>{const l=new URL(window.location.href);l.searchParams.set("refresh",Date.now().toString()),window.location.replace(l.toString())},DN);return()=>clearTimeout(a)},[]),o.jsx(vf,{children:o.jsxs(o.Fragment,{children:[o.jsx(LN,{}),o.jsx(bf,{scale:3})]})})}function HN({children:a}){return o.jsx("div",{className:"flex h-full w-full items-center justify-start overflow-hidden bg-black",children:o.jsx("div",{className:"relative flex items-center justify-center overflow-hidden bg-black",style:{width:"min(100%, calc(100vh * 4 / 3))",height:"min(100%, calc(100vw * 3 / 4))",maxWidth:"100%",maxHeight:"100%",aspectRatio:"4 / 3"},children:o.jsx("div",{className:"flex h-full w-full items-center justify-center overflow-hidden",children:a})})})}qy.createRoot(document.getElementById("root")).render(o.jsx(m.StrictMode,{children:o.jsx(I1,{children:o.jsx(P1,{children:o.jsx(eS,{children:o.jsx(XS,{children:o.jsx($b,{children:o.jsxs(bb,{children:[o.jsx(Nr,{path:"/",element:o.jsx(jN,{})}),o.jsx(Nr,{path:"/spectate",element:o.jsx(kN,{})}),o.jsx(Nr,{path:"/mini",element:o.jsx(UN,{})})]})})})})})})})); +`;function gN(a){return a?a.charAt(0).toUpperCase()+a.slice(1):""}function xN(){const a=String(pN).split(/\r?\n/).map(i=>i.trim()).filter(Boolean);return a.length?(a[Math.floor(Math.random()*a.length)]||"").trim():""}function zf(){const{setNickname:a}=_e(),{value:l,status:i,save:r}=dt("profile",{nickname:""}),f=m.useRef(!1);m.useEffect(()=>{if(i!=="ready"||f.current||(l.nickname||"").trim())return;f.current=!0;const h=gN(xN()).slice(0,32);if(!h)return;(async()=>{try{await a(h)}catch{}finally{r({nickname:h})}})()},[r,a,i,l.nickname])}const Uu=1e4,Hu=28,vN=14;function Hr({layout:a="desktop",className:l="",dismissable:i=!0}){const{session:r}=_e(),f=r?.communityGoal?.text?String(r.communityGoal.text).trim():"",d=a==="mobile-portrait"||a==="mobile-landscape"||a==="mobile",[h,x]=m.useState(!1),[p,v]=m.useState(Hu),[b,S]=m.useState(0),E=m.useRef(null),M=m.useRef(null),j=m.useRef(null);m.useEffect(()=>{if(!f){x(!1);return}if(x(!0),!d||!i)return;const C=Date.now();S(Uu);const R=setTimeout(()=>x(!1),Uu),_=setInterval(()=>{const Q=Date.now()-C;S(Math.max(0,Uu-Q))},250);return()=>{clearTimeout(R),clearInterval(_)}},[f,d]),m.useEffect(()=>{if(!f)return;v(Hu);let C=0;const R=()=>{const Q=j.current,ee=M.current;if(!Q||!ee)return;const U=Q.clientWidth;if(!U)return;const te=ee.scrollWidth;if(!te)return;const X=Math.min(1,U/te),K=Math.max(vN,Math.floor(Hu*X));v(K)};C=window.requestAnimationFrame(R);const _=new ResizeObserver(()=>{window.cancelAnimationFrame(C),C=window.requestAnimationFrame(R)});return E.current&&_.observe(E.current),()=>{window.cancelAnimationFrame(C),_.disconnect()}},[f]);const N=m.useMemo(()=>["panel-section flex w-full items-center justify-center",d?"rounded-none":"rounded","px-1 py-1 text-center font-semibold tracking-tight",l].filter(Boolean).join(" "),[l,d]);if(!f||!h)return null;const A=d?Math.ceil(b/1e3):null,w=i?{onClick:()=>x(!1),role:"button",tabIndex:0}:{};return o.jsx("div",{ref:E,className:N,style:{fontSize:`${p}px`,lineHeight:1.1},...w,children:o.jsxs("span",{className:"flex w-full items-stretch gap-0.5 whitespace-nowrap rounded-md",children:[o.jsxs("span",{className:"flex flex-col justify-center border-r border-slate-700/60 px-0.5 text-[0.55em] font-semibold leading-tight text-slate-400",children:[o.jsx("span",{children:"Community"}),o.jsx("span",{children:"Goal"})]}),o.jsx("span",{ref:j,className:"flex-1 overflow-hidden text-slate-100",children:o.jsx("span",{ref:M,className:"block",children:f})}),d?o.jsxs("span",{className:"flex items-center border-l border-slate-700/60 px-0.5 text-[0.55em] font-semibold uppercase tracking-wide text-slate-400",children:[A,"s"]}):null]})})}function yN(){const[a,l]=m.useState(()=>typeof window>"u"||window.innerWidth>=1024?"desktop":window.innerWidth>window.innerHeight?"mobile-landscape":"mobile-portrait");return m.useEffect(()=>{function i(){if(typeof window>"u")return;const{innerWidth:r,innerHeight:f}=window;r>=1024?l("desktop"):r>f?l("mobile-landscape"):l("mobile-portrait")}return i(),window.addEventListener("resize",i),()=>window.removeEventListener("resize",i)},[]),a}function bN({layout:a,onOpenHelpOverlay:l}){return o.jsxs("div",{className:"flex h-full gap-0.5 overflow-hidden",children:[o.jsxs("div",{className:"flex min-w-0 flex-[1.22] flex-col gap-0.5 overflow-y-auto pr-0",children:[o.jsx(Mf,{}),o.jsx(lS,{}),o.jsx(Ef,{})]}),o.jsxs("div",{className:"flex min-w-0 flex-1 flex-col gap-0.5 overflow-y-auto",children:[o.jsx(Hr,{layout:a}),o.jsx(Pj,{layout:a,onOpenHelpOverlay:l})]})]})}function ax({layout:a,onOpenHelpOverlay:l,roomPanelId:i,showTelemetry:r=!0}){return o.jsx("section",{className:"panel text-base",children:o.jsxs(_f,{defaultTab:"chat",children:[o.jsxs(Df,{children:[o.jsx(Zt,{id:"chat",children:"Chat"}),o.jsx(Zt,{id:"roomcontrols",children:"Room Controls"}),o.jsx(Zt,{id:"help",children:"Help"}),o.jsx(Zt,{id:"settings",children:"Settings"})]}),o.jsxs(Of,{children:[o.jsx(Ft,{id:"chat",children:o.jsxs("div",{className:"space-y-0.5",children:[o.jsx(Fr,{}),o.jsx(Ur,{})]})}),o.jsx(Ft,{id:"roomcontrols",children:o.jsxs("div",{className:"space-y-0.5",children:[o.jsx(Xg,{}),o.jsx(wf,{panelId:i})]})}),o.jsx(Ft,{id:"help",children:o.jsx(Pg,{layout:a,onOpenOverlay:l})}),o.jsx(Ft,{id:"settings",children:o.jsxs("div",{className:"space-y-0.5",children:[o.jsx(Jg,{}),o.jsx(Ef,{})]})})]})]})})}function SN({onOpenHelpOverlay:a}){return o.jsxs("div",{className:"flex flex-col gap-0.5",children:[o.jsx(Mf,{layoutFormat:"mobile-portrait"}),o.jsx(NA,{}),o.jsxs("div",{className:"grid gap-0.5 grid-cols-[minmax(0,1fr)_minmax(0,1.4fr)]",children:[o.jsx(yf,{panelId:"replay-sources-mobile-portrait"}),o.jsx(Jr,{})]}),o.jsx(ax,{layout:"mobile-portrait",onOpenHelpOverlay:a,roomPanelId:"mobile-portrait-room"})]})}function AN({onOpenHelpOverlay:a}){return o.jsxs("div",{className:"flex flex-col gap-0.5",children:[o.jsxs("section",{className:"grid min-h-screen grid-cols-[minmax(0,0.7fr)_minmax(0,2.1fr)_minmax(0,0.7fr)] gap-0.5",children:[o.jsx(AA,{}),o.jsxs("div",{children:[o.jsx(Mf,{layoutFormat:"mobile-landscape"}),o.jsxs("div",{className:"grid gap-0.5 grid-cols-[minmax(0,1fr)_minmax(0,1.4fr)]",children:[o.jsx(yf,{panelId:"replay-sources-mobile-landscape"}),o.jsx(Jr,{})]})]}),o.jsx(jA,{})]}),o.jsx("div",{className:"flex flex-col gap-0.5 pb-0",children:o.jsx(ax,{layout:"mobile-landscape",onOpenHelpOverlay:a,roomPanelId:"mobile-landscape-room",showTelemetry:!1})})]})}function jN(){const a=yN(),l=a==="desktop",i=mN(a);return o.jsx("div",{className:`bg-black text-slate-100 ${l?"h-screen overflow-hidden":"min-h-screen"}`,children:o.jsx(vf,{children:o.jsx(NN,{layout:a,isDesktop:l,fullscreen:i})})})}function NN({layout:a,isDesktop:l,fullscreen:i}){zf();const{visible:r,mode:f,enterFullscreen:d,dismiss:h}=i,{value:x,status:p,save:v}=dt("help",{showOnLoad:!0}),[b,S]=m.useState(!1);m.useEffect(()=>{p==="ready"&&S(x?.showOnLoad!==!1)},[p,x?.showOnLoad]);const E=m.useCallback(()=>S(!0),[]),M=m.useCallback(()=>S(!1),[]),j=m.useCallback(A=>{const w=!!A;v(C=>({...C??{},showOnLoad:w})),w||S(!1)},[v]),N=m.useMemo(()=>l?o.jsx(bN,{layout:a,onOpenHelpOverlay:E}):a==="mobile-landscape"?o.jsx(AN,{onOpenHelpOverlay:E}):o.jsx(SN,{onOpenHelpOverlay:E}),[l,a,E]);return o.jsxs($S,{children:[o.jsx(eA,{}),o.jsx(gA,{}),o.jsxs("main",{className:`flex w-full flex-col gap-0.5 text-base ${l?"h-full overflow-hidden":""}`,children:[l?null:o.jsx(Hr,{layout:a}),N]}),o.jsx(bf,{}),o.jsx(rN,{}),o.jsx(lN,{}),o.jsx(hN,{visible:b,layout:a,onClose:M,showOnLoad:x?.showOnLoad!==!1,onToggleShowOnLoad:j}),o.jsx(oN,{visible:r,mode:f,onEnterFullscreen:d,onDismiss:h})]})}function lx(){const{session:a,setRole:l,subscribeAll:i,connected:r}=_e(),[f,d]=m.useState(!1);return m.useEffect(()=>{let h=!1;async function x(){if(a?.mode==="lockdown"){d(!1);return}try{a?.role!=="spectator"&&await l("spectator"),await i(),h||d(!0)}catch(p){console.error("Failed to enter spectator mode",p),h||d(!1)}}return x(),()=>{h=!0}},[r,a?.mode,a?.role,l,i]),f}function wN(){const[a,l]=m.useState(()=>typeof window>"u"?!1:window.matchMedia("(max-aspect-ratio: 4/3)").matches);return m.useEffect(()=>{if(typeof window>"u")return;const i=window.matchMedia("(max-aspect-ratio: 4/3)"),r=f=>l(f.matches);return i.addEventListener?i.addEventListener("change",r):i.addListener(r),()=>{i.removeEventListener?i.removeEventListener("change",r):i.removeListener(r)}},[]),a}function EN({roverId:a,session:l}){const i=l?.activeDrivers?.[a]||null,f=(l?.users||[]).find(p=>p.socketId===i)?.nickname||(i?i.slice(0,6):"No driver"),d=l?.mode,h=l?.turnQueues?.[a];return d==="turns"&&h?.current?`${f} (turns)`:f}function CN({rover:a,frame:l,sessionInfo:i,videoMode:r,snapshotFeed:f,audioInfo:d,session:h}){const x=EN({roverId:a.id,session:h});return o.jsx("article",{className:"min-h-[16rem] rounded bg-zinc-900 p-0 sm:min-h-[18rem]",children:o.jsx("div",{className:"min-h-0 overflow-hidden rounded bg-black/20",children:o.jsx(Ks,{sessionInfo:i,videoMode:r,snapshotFeed:f,audioSessionInfo:d,label:a.name,telemetryFrame:l,batteryConfig:a.battery,hudVariant:"spectator",driverLabel:x,hudForceMap:!0,hudMapPosition:"top-center"})})})}function qN({roster:a,frames:l,videoSources:i,snapshotFeeds:r,audioSources:f,session:d,canSpectateVideo:h}){return a.length===0?o.jsx("p",{className:"col-span-full text-slate-400",children:"No rovers registered."}):o.jsx("section",{className:"grid grid-cols-1 gap-0.5 md:grid-cols-2",children:a.map(x=>o.jsx(CN,{rover:x,frame:l[x.id],sessionInfo:h&&i[x.id]||null,videoMode:h?"whep":"snapshot",snapshotFeed:h?null:r[x.id],audioInfo:f[`${x.id}-audio`],session:d,showHudMap:!0,hudMapPosition:"bottom-left"},x.id))})}function MN(){return o.jsx("section",{className:"min-h-0",children:o.jsx("div",{className:"surface min-h-[14rem] overflow-hidden",children:o.jsx(wf,{defaultOrientation:"horizontal",hideLayoutToggle:!0,hideHeader:!0,panelId:"spectator-secondary"})})})}function TN({className:a=""}){return o.jsx("div",{className:`panel ${a}`,children:o.jsx(Ef,{})})}function RN(){const{session:a}=_e(),l=a?.mode==="lockdown",i=!!a?.isLocalNetwork;zf(),lx();const r=wN(),f=xf(),d=a?.roster??[],h=Cf(d.map(A=>A.id),{enabled:!l&&!i,version:a?.mode}),x=i?d.map(A=>({type:"rover",id:A.id,key:A.id})):[],p=Qs(x,{enabled:!l&&i,version:a?.mode}),v=d.flatMap(A=>A.media?.audioPublishUrl?[{type:"rover",id:`${A.id}-audio`,key:`${A.id}-audio`}]:[]),b=Qs(v,{enabled:!l,version:a?.mode});if(l)return o.jsx("div",{className:"flex min-h-screen items-center justify-center bg-black text-slate-200",children:o.jsxs("div",{className:"surface max-w-md space-y-0.5 p-1 text-center text-sm",children:[o.jsx("p",{className:"text-lg font-semibold text-white",children:"Spectate disabled during lockdown."}),o.jsx("p",{className:"text-slate-300",children:"Please wait until the server leaves lockdown to view streams."})]})});const S=r?"flex min-h-screen flex-col bg-black text-slate-100 md:h-screen md:overflow-hidden":"grid min-h-screen grid-cols-1 gap-0.5 bg-black text-slate-100 md:h-full md:min-h-0 md:grid-cols-[minmax(0,1fr)_18rem] lg:grid-cols-[minmax(0,1fr)_20rem]",E=r?"order-2 flex min-h-0 min-w-0 flex-1 flex-col gap-0.5 overflow-y-auto":"order-1 flex min-h-0 min-w-0 flex-col gap-0.5 md:overflow-y-auto",M=r?"order-1 grid w-full min-h-0 items-stretch gap-0.5 border-b border-slate-800/60 bg-slate-950/90 p-0.5 grid-cols-[minmax(0,1fr)_minmax(0,0.7fr)_minmax(0,1.9fr)_minmax(0,0.7fr)]":"order-2 flex min-h-0 min-w-0 flex-col gap-0.5 border-l border-slate-800/60 bg-slate-950/90 md:h-full md:overflow-y-auto",j="",N=r?"h-64":"";return o.jsxs("div",{className:"min-h-screen bg-black text-slate-100 md:h-screen md:overflow-hidden",children:[o.jsxs("main",{className:S,children:[o.jsxs("section",{className:M,children:[r?o.jsxs("div",{className:`${j} ${N} flex flex-col gap-0.5`,children:[o.jsx(Hr,{layout:"desktop",dismissable:!1,className:"text-sm"}),o.jsx("div",{className:"min-h-0 flex-1",children:o.jsx(Ur,{hideNicknameForm:!0,hideHeader:!0,compact:!0,fillHeight:!0,className:"h-full"})})]}):o.jsx("div",{className:j,children:o.jsx(Hr,{layout:"desktop",dismissable:!1,className:"text-sm"})}),o.jsx("div",{className:`${j} ${r?`${N} overflow-y-auto`:""}`,children:o.jsx("div",{className:"panel h-full",children:o.jsx(Jr,{title:"Rovers"})})}),r?null:o.jsx("div",{className:`${j} flex-1 min-h-0`,children:o.jsx(Ur,{hideNicknameForm:!0,hideHeader:!0,compact:!0,fillHeight:!0,className:"h-full"})}),o.jsx("div",{className:`${j} ${r?N:"flex-[1.1] min-h-0"}`,children:o.jsx(Fr,{allowSpectatorInput:!0,hideSpectatorNotice:!0,fillHeight:!0})}),o.jsx("div",{className:`${j} ${r?N:""}`,children:o.jsx(TN,{className:`${r?"h-full":"h-40"} overflow-hidden`})})]}),o.jsxs("section",{className:E,children:[o.jsx(qN,{roster:d,frames:f,videoSources:p,snapshotFeeds:h,audioSources:b,session:a,canSpectateVideo:i}),o.jsx(MN,{})]})]}),o.jsx(bf,{})]})}function kN(){return o.jsx(vf,{children:o.jsx(RN,{})})}const _N=2e4,DN=3600*1e3;function ON({roverId:a,session:l}){const i=l?.activeDrivers?.[a]||null,f=(l?.users||[]).find(x=>x.socketId===i)?.nickname||(i?i.slice(0,6):"No driver"),d=l?.mode,h=l?.turnQueues?.[a];return d==="turns"&&h?.current?`${f}`:f}function BN({rover:a,frame:l}){const i=a?.batteryState?.percentDisplay;if(i!=null&&Number.isFinite(i))return Math.round(i);const r=a?.battery??null,f=l?.sensors?.batteryChargeMah??null,d=r?.Full??null,h=r?.Warn??null;if(f==null||d==null||h==null)return null;const x=d-h;if(x<=0)return null;const p=(f-h)/x;return Math.round(Math.max(0,Math.min(1,p))*100)}function zN({rover:a}){const l=a?.batteryState?.urgentActive??!1,i=a?.batteryState?.warnActive??!1;return l?"bg-red-500/40":i?"bg-amber-400/40":"bg-emerald-400/40"}function D0({rover:a,frame:l,driverLabel:i,sessionInfo:r,videoMode:f="snapshot",snapshotFeed:d,withDivider:h=!1,showPreview:x=!0,variant:p="stacked"}){const v=BN({rover:a,frame:l}),b=zN({rover:a}),S=p==="active",E=S?{height:`${v??0}%`,bottom:0,top:"auto"}:{width:`${v??0}%`},M=S?`pointer-events-none absolute bottom-0 left-0 right-0 ${b}`:`pointer-events-none absolute left-0 top-0 bottom-0 ${b}`;return o.jsxs("div",{className:`relative flex min-w-0 flex-1 flex-col gap-4 overflow-hidden bg-black px-0 py-0 ${h?"border-r border-slate-700/60":""}`,children:[o.jsx("div",{className:M,style:E}),S?o.jsxs("div",{className:"relative z-10 flex min-w-0 flex-1 flex-col justify-between text-center",children:[o.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:o.jsx(El,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:18,children:a.name||a.id})}),i?o.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:o.jsx(El,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:16,children:i})}):o.jsx("div",{}),o.jsx("div",{className:"relative min-w-0 overflow-hidden bg-transparent px-0 py-0 leading-none",children:o.jsx("div",{className:"relative",children:o.jsx(El,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:16,children:v==null?"--%":`${v}%`})})})]}):o.jsxs(o.Fragment,{children:[o.jsxs("div",{className:"relative z-10 flex min-w-0 flex-col gap-1 text-center",children:[o.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:o.jsx(El,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:18,children:a.name||a.id})}),i?o.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:o.jsx(El,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:16,children:i})}):null,o.jsx("div",{className:"relative min-w-0 overflow-hidden bg-transparent px-0 py-0 leading-none",children:o.jsx("div",{className:"relative",children:o.jsx(El,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:16,children:v==null?"--%":`${v}%`})})})]}),o.jsx("div",{className:"relative z-10 flex min-w-0 flex-1 flex-col gap-4",children:o.jsx("div",{className:"flex w-full min-w-0 flex-1 flex-col items-center gap-4",children:x?o.jsx("div",{className:"mt-auto w-full",children:o.jsx("div",{className:"w-full aspect-[4/3]",children:o.jsx(Ks,{sessionInfo:r,videoMode:f,snapshotFeed:d,audioSessionInfo:null,label:a.name||a.id,telemetryFrame:l,batteryConfig:a.battery,layoutFormat:"mobile",hudVariant:"none",fitParent:!0})})}):null})})]})]})}function El({children:a,className:l="",maxSize:i=1e3,minSize:r=14}){const f=m.useRef(null),d=m.useRef(null),[h,x]=m.useState(i);return m.useLayoutEffect(()=>{const p=f.current,v=d.current;if(!p||!v)return;let b=null;const S=()=>{const j=p.clientWidth;if(!j){E();return}let N=r,A=i,w=r;for(;N<=A;){const C=Math.floor((N+A)/2);v.style.fontSize=`${C}px`,v.scrollWidth<=j?(w=C,N=C+1):A=C-1}x(w)},E=()=>{b&&cancelAnimationFrame(b),b=requestAnimationFrame(S)};E();const M=new ResizeObserver(E);return M.observe(p),()=>{b&&cancelAnimationFrame(b),M.disconnect()}},[a,i,r]),o.jsx("div",{ref:f,className:"w-full min-w-0",children:o.jsx("div",{ref:d,className:`whitespace-nowrap ${l}`,style:{fontSize:`${h}px`,lineHeight:1.1},children:a})})}function LN(){const{session:a}=_e(),l=lx();zf();const i=a?.mode==="lockdown",r=!!a?.isLocalNetwork,f=xf(),d=a?.roster??[],[h,x]=m.useState(0),p=a?.activeDrivers||{},v=m.useMemo(()=>d.filter(K=>p[K.id]),[d,p]),b=v.length?v:d,S=Cf(b.map(K=>K.id),{enabled:!i&&!r,version:a?.mode}),E=m.useMemo(()=>r?b.map(K=>({type:"rover",id:K.id,key:K.id})):[],[r,b]),M=Qs(E,{enabled:!i&&r,version:a?.mode}),j=m.useMemo(()=>v.flatMap(K=>{if(!K?.id||!K.media?.audioPublishUrl)return[];const L=String(K.id);return[{type:"rover",id:`${L}-audio`,key:`${L}-audio`}]}),[v]),N=Qs(j,{enabled:!i,version:a?.mode}),A=m.useMemo(()=>{if(!v.length)return[];if(!r){const L=v.filter(Z=>S[Z.id]?.objectUrl);return L.length?L:v}const K=v.filter(L=>{const Z=M[L.id];return Z?.url&&!Z?.error});return K.length?K:v},[v,S,M,r]),w=m.useMemo(()=>A.map(K=>({type:"rover",rover:K})),[A]),C=m.useMemo(()=>w.map(K=>`r:${K.rover.id}`).join("|"),[w]);m.useEffect(()=>{x(0)},[C]),m.useEffect(()=>{if(!w.length)return;const K=setInterval(()=>{x(L=>(L+1)%w.length)},_N);return()=>clearInterval(K)},[w.length,C]);const R=w.length?w[h%w.length]:null,_=R?.type==="rover"?R.rover:null,Q=!r&&_&&S[_.id]||null,ee=r&&_&&M[_.id]||null,U=_&&N[`${_.id}-audio`]||null,te=_&&f[_.id]||null,X=_?ON({roverId:_.id,session:a}):null;return i?o.jsx("div",{className:"relative flex h-screen w-screen items-center justify-center bg-black text-slate-200",children:o.jsxs("div",{className:"surface max-w-sm space-y-0.5 p-1 text-center text-sm",children:[o.jsx("p",{className:"text-lg font-semibold text-white",children:"Mini spectator is disabled in lockdown."}),o.jsx("p",{className:"text-slate-300",children:"It will automatically resume once lockdown ends."})]})}):v.length?o.jsxs("div",{className:"relative flex h-screen w-screen overflow-hidden bg-black text-slate-100",children:[o.jsx("section",{className:"relative flex h-full shrink-0 items-center justify-start overflow-hidden bg-black",style:{width:"min(100vw, calc(100vh * 4 / 3))"},children:l?_?o.jsx(HN,{children:r?o.jsx("div",{className:"relative h-full w-full",children:w.map(K=>{const L=K.rover,Z=_?.id===L.id;return o.jsx("div",{className:`absolute inset-0 ${Z?"opacity-100":"opacity-0 pointer-events-none"}`,children:o.jsx(Ks,{sessionInfo:M[L.id]||null,videoMode:"whep",snapshotFeed:null,audioSessionInfo:Z?U:null,forceMute:!Z,label:L.name||L.id,telemetryFrame:f[L.id]||null,batteryConfig:L.battery,layoutFormat:"mobile",hudVariant:"none",fitParent:!0})},L.id)})}):o.jsx(Ks,{sessionInfo:null,videoMode:"snapshot",snapshotFeed:Q,audioSessionInfo:U,label:_.name||_.id,telemetryFrame:te,batteryConfig:_.battery,layoutFormat:"mobile",hudVariant:"none",fitParent:!0})}):o.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:v.length?"No sources available.":"No active drivers."}):o.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:"Switching to spectator…"})}),o.jsx("aside",{className:"flex h-full min-w-0 flex-1 flex-col border-l border-slate-800/60 bg-black",children:_?o.jsx(D0,{rover:_,frame:te,driverLabel:X,sessionInfo:r?ee:null,videoMode:r?"whep":"snapshot",snapshotFeed:r?null:S[_.id]||null,showPreview:!1,variant:"active"}):o.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:"No active rover."})})]}):o.jsx("div",{className:"relative flex h-screen w-screen overflow-hidden bg-black text-slate-100",children:o.jsx("section",{className:"flex h-full w-full gap-x-1",children:d.length?d.map((K,L)=>o.jsx(D0,{rover:K,frame:f[K.id]||null,driverLabel:null,sessionInfo:r&&M[K.id]||null,videoMode:r?"whep":"snapshot",snapshotFeed:r?null:S[K.id]||null,showPreview:!0,withDivider:!1},K.id)):o.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:"No rovers available."})})})}function UN(){return m.useEffect(()=>{if(typeof window>"u")return;const a=setTimeout(()=>{const l=new URL(window.location.href);l.searchParams.set("refresh",Date.now().toString()),window.location.replace(l.toString())},DN);return()=>clearTimeout(a)},[]),o.jsx(vf,{children:o.jsxs(o.Fragment,{children:[o.jsx(LN,{}),o.jsx(bf,{scale:3})]})})}function HN({children:a}){return o.jsx("div",{className:"flex h-full w-full items-center justify-start overflow-hidden bg-black",children:o.jsx("div",{className:"relative flex items-center justify-center overflow-hidden bg-black",style:{width:"min(100%, calc(100vh * 4 / 3))",height:"min(100%, calc(100vw * 3 / 4))",maxWidth:"100%",maxHeight:"100%",aspectRatio:"4 / 3"},children:o.jsx("div",{className:"flex h-full w-full items-center justify-center overflow-hidden",children:a})})})}qy.createRoot(document.getElementById("root")).render(o.jsx(m.StrictMode,{children:o.jsx(I1,{children:o.jsx(P1,{children:o.jsx(eS,{children:o.jsx(XS,{children:o.jsx($b,{children:o.jsxs(bb,{children:[o.jsx(Nr,{path:"/",element:o.jsx(jN,{})}),o.jsx(Nr,{path:"/spectate",element:o.jsx(kN,{})}),o.jsx(Nr,{path:"/mini",element:o.jsx(UN,{})})]})})})})})})})); diff --git a/server/public/index.html b/server/public/index.html index 6a40123d..83454326 100644 --- a/server/public/index.html +++ b/server/public/index.html @@ -11,7 +11,7 @@ Multi Roomba Rover - + diff --git a/webui/src/mini/MiniSummaryApp.jsx b/webui/src/mini/MiniSummaryApp.jsx index dc21fb5b..9c0ef5b2 100644 --- a/webui/src/mini/MiniSummaryApp.jsx +++ b/webui/src/mini/MiniSummaryApp.jsx @@ -11,7 +11,7 @@ import AlertFeed from '../components/AlertFeed.jsx'; import useDefaultNickname from '../hooks/useDefaultNickname.js'; const ROTATE_MS = 20000; -const HARD_REFRESH_MS = 3 * 60 * 60 * 1000; +const HARD_REFRESH_MS = 1 * 60 * 60 * 1000; function formatDriverLabel({ roverId, session }) { const activeDriverId = session?.activeDrivers?.[roverId] || null;