diff --git a/server/data/barcode-registry.json b/server/data/barcode-registry.json index bcd94b7c..0390463a 100644 --- a/server/data/barcode-registry.json +++ b/server/data/barcode-registry.json @@ -2,9 +2,23 @@ "codes": { "r001": { "type": "rover", - "entityId": "Freaky", + "entityId": "freaky", "label": "Freaky" }, + "r002": { + "type": "rover", + "entityId": "walle", + "label": "WALL-E" + }, + "r003": { + "type": "rover", + "entityId": "bweeble", + "label": "Bweeble" + }, + + + + "o001": { "type": "object", "entityId": "woodblock", diff --git a/server/public/assets/index-BhQJmAe_.js b/server/public/assets/index-DNxiEuzr.js similarity index 99% rename from server/public/assets/index-BhQJmAe_.js rename to server/public/assets/index-DNxiEuzr.js index 99f20d88..0c9a7cb6 100644 --- a/server/public/assets/index-BhQJmAe_.js +++ b/server/public/assets/index-DNxiEuzr.js @@ -123,4 +123,4 @@ wok yeast yogurt shrimp -fling`;function nK(t){return t?t.charAt(0).toUpperCase()+t.slice(1):""}function lK(){const t=String(aK).split(/\r?\n/).map(r=>r.trim()).filter(Boolean);return t.length?(t[Math.floor(Math.random()*t.length)]||"").trim():""}function E8(){const{setNickname:t}=k2(),{value:a,status:r,save:o}=E1("profile",{nickname:""}),h=m.useRef(!1);m.useEffect(()=>{if(r!=="ready"||h.current||(a.nickname||"").trim())return;h.current=!0;const v=nK(lK()).slice(0,32);if(!v)return;(async()=>{try{await t(v)}catch{}finally{o({nickname:v})}})()},[o,t,r,a.nickname])}function T8(){const t=Z2(),a=o1(A=>A.connected),{identifySession:r}=k2(),{value:o,status:h,save:f}=E1("identity",{cookieUserId:""}),{value:v,status:x}=E1("profile",{nickname:""}),{value:z,status:g}=E1("overseerPreference",{enabled:!1}),p=m.useRef(!1),M=m.useRef(null),y=m.useRef(null),C=h==="ready"&&x==="ready"&&g==="ready",L=(o?.cookieUserId||"").trim(),S=(v?.nickname||"").trim(),w=!!z?.enabled,H=m.useCallback(()=>{y.current&&(clearTimeout(y.current),y.current=null)},[]),j=m.useCallback(async()=>{if(!(!C||!a||!t?.id||p.current)){p.current=!0;try{const B=((await r({cookieUserId:L,nickname:S,overseerEnabled:w}))?.cookieUserId||"").trim();B&&B!==L&&f(T=>({...T||{},cookieUserId:B})),M.current=t.id,H()}catch{H(),y.current=setTimeout(()=>{j()},2e3)}finally{p.current=!1}}},[H,a,L,r,S,w,C,f,t?.id]);m.useEffect(()=>{!C||!a||!t?.id||M.current!==t.id&&j()},[a,C,j,t?.id]),m.useEffect(()=>{!C||!a||!t?.id||j()},[C,a,t?.id,L,S,w,j]),m.useEffect(()=>{const A=()=>{t?.connected&&j()},B=()=>{typeof document>"u"||document.visibilityState!=="visible"||t?.connected&&j()};return window.addEventListener("online",A),document.addEventListener("visibilitychange",B),()=>{window.removeEventListener("online",A),document.removeEventListener("visibilitychange",B)}},[j,t?.connected]),m.useEffect(()=>{if(!C||!t?.connected)return;const A=setInterval(()=>{t?.connected&&j()},6e4);return()=>clearInterval(A)},[C,j,t?.connected]),m.useEffect(()=>()=>H(),[H])}const Ue=1e4,Ze=28,rK=14;function iK(t){const a=String(t||"").trim(),r=a.startsWith("#")?a.slice(1):a;if(!/^[0-9a-fA-F]{3}$|^[0-9a-fA-F]{6}$/.test(r))return null;const o=r.length===3?r.split("").map(h=>h+h).join(""):r;return{r:Number.parseInt(o.slice(0,2),16),g:Number.parseInt(o.slice(2,4),16),b:Number.parseInt(o.slice(4,6),16)}}function us(t,a){return`rgba(${t.r}, ${t.g}, ${t.b}, ${a})`}function q7({layout:t="desktop",className:a="",dismissable:r=!0}){const o=o1(B=>{const T=B.session?.globalObjective?.text;return T?String(T).trim():""}),h=o1(B=>{const T=String(B.session?.assignment?.roverId||"").trim();return T&&(Array.isArray(B.session?.roster)?B.session.roster:[]).find(N=>String(N?.id)===T)?.color||null}),f=t==="mobile-portrait"||t==="mobile-landscape"||t==="mobile",[v,x]=m.useState(!1),[z,g]=m.useState(Ze),[p,M]=m.useState(0),y=m.useRef(null),C=m.useRef(null),L=m.useRef(null);m.useEffect(()=>{if(!o){x(!1);return}if(x(!0),!f||!r)return;const B=Date.now();M(Ue);const T=setTimeout(()=>x(!1),Ue),E=setInterval(()=>{const R=Date.now()-B;M(Math.max(0,Ue-R))},250);return()=>{clearTimeout(T),clearInterval(E)}},[o,f]),m.useEffect(()=>{if(!o)return;g(Ze);let B=0;const T=()=>{const R=L.current,N=C.current;if(!R||!N)return;const O=R.clientWidth;if(!O)return;const $=N.scrollWidth;if(!$)return;const I=Math.min(1,O/$),P=Math.max(rK,Math.floor(Ze*I));g(P)};B=window.requestAnimationFrame(T);const E=new ResizeObserver(()=>{window.cancelAnimationFrame(B),B=window.requestAnimationFrame(T)});return y.current&&E.observe(y.current),()=>{window.cancelAnimationFrame(B),E.disconnect()}},[o]);const S=m.useMemo(()=>["panel-section flex w-full items-center justify-center border border-neutral-500/60 shadow-[0_1px_0_rgba(255,255,255,0.05)_inset,0_10px_24px_rgba(0,0,0,0.28)]",f?"rounded-none":"rounded","px-1 py-1 text-center font-semibold tracking-tight",a].filter(Boolean).join(" "),[a,f]),w=iK(h),H=w?{borderColor:us(w,.35),backgroundImage:`linear-gradient(90deg, rgba(23,23,23,0.96) 0%, rgba(38,38,38,0.94) 58%, ${us(w,.18)} 100%)`}:void 0;if(!o||!v)return null;const j=f?Math.ceil(p/1e3):null,A=r?{onClick:()=>x(!1),role:"button",tabIndex:0}:{};return l.jsx("div",{ref:y,className:S,style:{...H||{},fontSize:`${z}px`,lineHeight:1.1},...A,children:l.jsxs("span",{className:"flex w-full items-stretch gap-0.5 whitespace-nowrap rounded-md",children:[l.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:[l.jsx("span",{children:"Global"}),l.jsx("span",{children:"Objective"})]}),l.jsx("span",{ref:L,className:"flex-1 overflow-hidden text-slate-100",children:l.jsx("span",{ref:C,className:"block",children:o})}),f?l.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:[j,"s"]}):null]})})}const sK=3200;function oK(t={}){const a=typeof t.rewardName=="string"&&t.rewardName.trim()?t.rewardName.trim():"Unknown Event",r=Number.isFinite(Number(t.goal))?Math.max(1,Math.floor(Number(t.goal))):0,o=Number.isFinite(Number(t.count))?Math.max(0,Math.floor(Number(t.count))):r;return{rewardName:a,goal:r,count:o,ts:Date.now()}}function $c(){const t=Z2(),{value:a}=E1("audio",d2),r=Number.isFinite(a?.masterVolume)?a.masterVolume:d2.masterVolume,o=Number.isFinite(a?.alertVolume)?a.alertVolume:d2.alertVolume,h=Math.max(0,Math.min(1,r*o)),[f,v]=m.useState(null),x=m.useRef(null);return m.useEffect(()=>{x.current=new Audio("/tada.mp3"),x.current.volume=h,x.current.load()},[h]),m.useEffect(()=>{let z=null;function g(){const y=x.current;y&&(y.volume=h,y.currentTime=0,y.play().catch(()=>{}))}function p(y={}){const C=oK(y);v(C),g(),z&&clearTimeout(z),z=setTimeout(()=>{v(null)},sK)}function M(y){p(y?.detail||{})}return t.on("buttonBox:rewardRun",p),window.addEventListener("buttonBox:rewardRunLocalTest",M),()=>{z&&clearTimeout(z),t.off("buttonBox:rewardRun",p),window.removeEventListener("buttonBox:rewardRunLocalTest",M)}},[h,t]),f?l.jsx("div",{className:"pointer-events-none fixed inset-0 z-[120] flex items-center justify-center bg-black/75 px-1 py-1",children:l.jsx("div",{className:"pointer-events-auto w-full max-w-2xl",children:l.jsx("div",{className:"surface rounded-none border-2 border-cyan-300 bg-amber-100/95 px-1 py-1 text-center text-black shadow-2xl",children:l.jsxs("div",{className:"flex items-center justify-center gap-1 border-2 border-blue-600 bg-yellow-100 px-0.5 py-1",children:[l.jsx("img",{src:"/party1.gif",alt:"",className:"hidden shrink-0 sm:block"}),l.jsxs("div",{children:[l.jsxs("p",{className:"font-mono text-2xl font-bold text-red-700 sm:text-3xl",children:["Running event: ",f.rewardName,"!"]}),l.jsxs("p",{className:"font-mono text-xl font-bold text-blue-800 sm:text-2xl",children:[f.count,"/",f.goal]})]}),l.jsx("img",{src:"/party2.gif",alt:"",className:"hidden shrink-0 sm:block"})]})})})}):null}const uK=4e3;function hs(...t){return t.filter(Boolean).join(" ")}function eu(){const t=Z2(),[a,r]=m.useState(!!t?.connected),[o,h]=m.useState(""),[f,v]=m.useState(!0),[x,z]=m.useState(!1),g=m.useRef(null);m.useEffect(()=>{const L=()=>{g.current&&(clearTimeout(g.current),g.current=null)},S=()=>{L(),v(!0),z(!1)},w=()=>{L(),g.current=setTimeout(()=>{z(!0)},uK)},H=()=>{r(!0),h(""),S(),w()},j=T=>{r(!1),h(typeof T=="string"?T:"disconnected"),S()},A=T=>{r(!1),h(T?.message||"connect error"),S()},B=()=>{r(!1),S()};return t.on("connect",H),t.on("disconnect",j),t.on("connect_error",A),t.io.on("reconnect_attempt",B),t.connected&&w(),()=>{L(),t.off("connect",H),t.off("disconnect",j),t.off("connect_error",A),t.io.off("reconnect_attempt",B)}},[t]);const p=typeof navigator<"u"?navigator.onLine===!1:!1,M=a?"Connected to socket.io":p?"Offline":"Reconnecting...",y=a?"":o,C=a?"bg-emerald-700 text-emerald-100":p?"bg-red-800 text-red-100":"bg-amber-800 text-amber-100";return l.jsx("div",{className:hs("fixed bottom-2 left-2 z-[120] transition-opacity duration-500",!f&&"hidden",x?"opacity-0 pointer-events-none":"opacity-100"),"aria-live":"polite",children:l.jsxs("div",{className:hs("rounded-sm px-2 py-1 text-xs",C),children:[l.jsx("span",{className:"font-semibold",children:M}),y?l.jsxs("span",{className:"ml-1 opacity-85",children:["(",y,")"]}):null]})})}function hK(){const[t,a]=m.useState(()=>typeof window>"u"||window.innerWidth>=1024?"desktop":window.innerWidth>window.innerHeight?"mobile-landscape":"mobile-portrait");return m.useEffect(()=>{function r(){if(typeof window>"u")return;const{innerWidth:o,innerHeight:h}=window;o>=1024?a("desktop"):o>h?a("mobile-landscape"):a("mobile-portrait")}return r(),window.addEventListener("resize",r),()=>window.removeEventListener("resize",r)},[]),t}function dK({layout:t,onOpenHelpOverlay:a}){return l.jsxs("div",{className:`flex h-full ${H2} overflow-hidden`,children:[l.jsxs("div",{className:`flex min-w-0 flex-[1.22] flex-col ${H2} overflow-y-auto pr-0`,children:[l.jsx(Ec,{}),l.jsx(Tv,{}),l.jsx(dv,{})]}),l.jsxs("div",{className:`flex min-w-0 flex-1 flex-col ${H2} overflow-y-auto`,children:[l.jsx(q7,{layout:t}),l.jsx(DQ,{layout:t,onOpenHelpOverlay:a})]})]})}function cu({layout:t,onOpenHelpOverlay:a,roomPanelId:r}){const[o,h]=m.useState("chat"),f=o1(w=>!!w.session?.isVerified),v=o1(w=>String(w.session?.assignment?.roverId||"").trim()),x=o1(w=>{const H=String(w.session?.assignment?.roverId||"").trim();return H&&w.session?.audioForward?.[H]||null}),{state:z}=V2(),{value:g}=E1("vipAudio",{openMicEnabled:!1,pttMode:"live"}),p=f?"bg-emerald-400":"bg-amber-400",M=!!z?.mic?.pttActive,y=!!g?.openMicEnabled,C=g?.pttMode==="clip"?"clip":"live",L=!!(v&&f&&(C==="clip"?M:y||M)),S=!!(v&&f&&C==="clip"&&x?.source==="upload"&&x?.state==="playing");return l.jsx("section",{className:"text-base",children:l.jsxs(Oc,{defaultTab:"chat",currentTab:o,onTabChange:h,children:[l.jsxs(_c,{children:[l.jsx(i4,{id:"chat",children:"Chat"}),l.jsx(i4,{id:"vip",highlight:S?"green":L?"pink":"none",children:l.jsxs("span",{className:"inline-flex items-center gap-0.5",children:[l.jsx("span",{children:"VIP"}),l.jsx("span",{className:`inline-block h-1.5 w-1.5 rounded-full ${p}`,"aria-hidden":"true",title:f?"Verified":"Not verified"})]})}),l.jsx(i4,{id:"roomcontrols",children:"Room Controls"}),l.jsx(i4,{id:"help",children:"Help"}),l.jsx(i4,{id:"settings",children:"Settings"})]}),l.jsxs(Uc,{children:[l.jsx(s4,{id:"chat",children:l.jsxs("div",{className:u6,children:[l.jsx(k8,{nicknameLayout:"stacked"}),l.jsxs("div",{className:u6,children:[l.jsx("div",{className:`grid ${H2} md:grid-cols-[minmax(0,1.4fr)_minmax(0,1fr)]`,children:l.jsx(Zc,{})}),l.jsxs("div",{className:`grid ${H2} grid-cols-[minmax(0,1fr)_minmax(0,1fr)]`,children:[l.jsx(tu,{}),l.jsx(E7,{hideNicknameForm:!0})]})]})]})}),l.jsx(s4,{id:"vip",keepMounted:!0,children:l.jsx(Wo,{isActive:o==="vip"})}),l.jsx(s4,{id:"roomcontrols",children:l.jsxs("div",{className:u6,children:[l.jsx(Uo,{}),l.jsx(T7,{}),l.jsx(kc,{panelId:r}),l.jsx(Bo,{})]})}),l.jsx(s4,{id:"help",children:l.jsx(Xo,{layout:t,onOpenOverlay:a})}),l.jsx(s4,{id:"settings",children:l.jsxs("div",{className:u6,children:[l.jsx(Yo,{}),l.jsx(jo,{})]})})]})]})})}function fK({onOpenHelpOverlay:t,swapMobileControlColumns:a=!1}){return l.jsxs("div",{className:`flex flex-col ${H2}`,children:[l.jsx(Ec,{layoutFormat:"mobile-portrait"}),l.jsx(cP,{swapColumns:a}),l.jsxs("div",{className:`grid ${H2} grid-cols-[minmax(0,1fr)_minmax(0,1.4fr)]`,children:[l.jsx(Sc,{panelId:"replay-sources-mobile-portrait"}),l.jsx(Q7,{})]}),l.jsx(cu,{layout:"mobile-portrait",onOpenHelpOverlay:t,roomPanelId:"mobile-portrait-room"})]})}function mK({onOpenHelpOverlay:t,swapMobileControlColumns:a=!1}){const r="self-start h-[min(100svh,32rem)]",o=a?l.jsx(k7,{layout:"landscape",className:r}):l.jsx(F7,{layout:"landscape",className:r}),h=a?l.jsx(F7,{layout:"landscape",className:r}):l.jsx(k7,{layout:"landscape",className:r});return l.jsxs("div",{className:`flex flex-col ${H2}`,children:[l.jsxs("section",{className:`grid min-h-screen grid-cols-[minmax(0,0.7fr)_minmax(0,2.1fr)_minmax(0,0.7fr)] ${H2}`,children:[o,l.jsxs("div",{children:[l.jsx(Ec,{layoutFormat:"mobile-landscape"}),l.jsxs("div",{className:`grid ${H2} grid-cols-[minmax(0,1fr)_minmax(0,1.4fr)]`,children:[l.jsx(Sc,{panelId:"replay-sources-mobile-landscape"}),l.jsx(Q7,{})]})]}),h]}),l.jsx("div",{className:`flex flex-col ${H2} pb-0`,children:l.jsx(cu,{layout:"mobile-landscape",onOpenHelpOverlay:t,roomPanelId:"mobile-landscape-room"})})]})}function vK(){const t=hK(),a=t==="desktop",r=JQ(t);return l.jsx("div",{className:`${qY} text-slate-100 ${a?"h-screen overflow-hidden":"min-h-screen"}`,children:l.jsx(pK,{layout:t,isDesktop:a,fullscreen:r})})}function pK({layout:t,isDesktop:a,fullscreen:r}){E8(),T8();const{visible:o,mode:h,isIOS:f,nativeSupported:v,enterFullscreen:x,dismiss:z,showPrompt:g}=r,{value:p,save:M}=E1("help",{showOnLoad:!0}),{value:y,status:C,save:L}=E1("quickstart",{showOnLoad:!0}),{value:S}=E1("page",{swapMobileControlColumns:!1}),w=!!S?.swapMobileControlColumns,H=w?"left":"right",j=!a&&(f||v),A=o1(k=>k.latestRequestedReplay),{clearReplayModal:B}=k2(),[T,E]=m.useState(!1),[R,N]=m.useState(!1);m.useEffect(()=>{C==="ready"&&N(y?.showOnLoad!==!1)},[C,y?.showOnLoad]);const O=m.useCallback(()=>E(!0),[]),$=m.useCallback(()=>E(!1),[]),I=m.useCallback(()=>N(!1),[]),P=m.useCallback(async()=>{if(f){g();return}await x()||g()},[x,f,g]),u1=m.useCallback(k=>{const D=!!k;L(U=>({...U??{},showOnLoad:D})),D||N(!1)},[L]),h1=m.useCallback(()=>{N(!1),E(!0)},[]),a1=m.useMemo(()=>a?l.jsx(dK,{layout:t,onOpenHelpOverlay:O}):t==="mobile-landscape"?l.jsx(mK,{onOpenHelpOverlay:O,swapMobileControlColumns:w}):l.jsx(fK,{onOpenHelpOverlay:O,swapMobileControlColumns:w}),[a,t,O,w]);return l.jsxs(bI,{children:[l.jsx(kI,{}),l.jsx(II,{}),l.jsxs("main",{className:`flex w-full flex-col ${H2} text-base ${a?"h-full overflow-hidden":""}`,children:[a?null:l.jsx(q7,{layout:t}),a1]}),l.jsx(Lc,{}),l.jsx($c,{}),l.jsx(PQ,{}),l.jsx($Q,{}),l.jsx(eu,{}),l.jsx(WQ,{visible:T,layout:t,onClose:$,showOnLoad:p?.showOnLoad!==!1,onToggleShowOnLoad:k=>M(D=>({...D??{},showOnLoad:!!k}))}),l.jsx(YQ,{visible:o,mode:h,onEnterFullscreen:x,onDismiss:z}),l.jsx(cK,{visible:R,layout:t,showOnLoad:y?.showOnLoad!==!1,onToggleShowOnLoad:u1,onOpenHelp:h1,onClose:I}),l.jsx(Z7,{replay:A,onClose:B}),j?l.jsx(QQ,{side:H,onClick:P}):null]})}function K7(){const{session:t,setRole:a,subscribeAll:r,connected:o}=v0(),[h,f]=m.useState(!1);return m.useEffect(()=>{let v=!1;async function x(){if(t?.mode==="lockdown"){f(!1);return}try{t?.role!=="spectator"&&await a("spectator"),await r(),v||f(!0)}catch(z){console.error("Failed to enter spectator mode",z),v||f(!1)}}return x(),()=>{v=!0}},[o,t?.mode,t?.role,a,r]),h}function gK(){const[t,a]=m.useState(()=>typeof window>"u"?!1:window.matchMedia("(max-aspect-ratio: 4/3)").matches);return m.useEffect(()=>{if(typeof window>"u")return;const r=window.matchMedia("(max-aspect-ratio: 4/3)"),o=h=>a(h.matches);return r.addEventListener?r.addEventListener("change",o):r.addListener(o),()=>{r.removeEventListener?r.removeEventListener("change",o):r.removeListener(o)}},[]),t}function xK({show:t=!1,roverId:a=null,sensors:r,batteryConfig:o,mobileHud:h=!1}){const f=G2(a),v=o1(p=>a?(p.session?.roster||[]).find(C=>String(C.id)===String(a))?.battery??null:null),x=r??f?.sensors??null,z=o??v,g=F8({charge:x?.batteryChargeMah??null,config:z});return!t||!g?.available?null:l.jsx("div",{className:"pointer-events-none absolute right-1 top-1/2 flex h-[70%] -translate-y-1/2 flex-col items-center justify-center rounded bg-black/60 px-0.5 pb-1 pt-1",children:l.jsx(I7,{visual:g,orientation:"vertical",variant:"inline",compact:h,className:"h-full w-4"})})}const zK=U2.memo(xK);function MK({roverId:t=null,label:a,fitParent:r=!1,layoutFormat:o="desktop"}){return l.jsx("div",{className:`flex flex-col gap-0.5 ${r?"h-full":""}`,children:l.jsxs("div",{className:`relative w-full overflow-hidden bg-black ${r?"h-full flex-1":"aspect-[4/3]"}`,children:[l.jsx(H8,{roverId:t,label:a}),l.jsx(qo,{roverId:t,variant:"spectator",mobileHud:!1}),l.jsx(To,{roverId:t,layoutFormat:o,variant:"spectator",mobileHud:!1,labelScale:1}),l.jsx(Do,{roverId:t,compact:!1}),l.jsx(Oo,{roverId:t,compact:!1}),l.jsx(zK,{show:!0,roverId:t,mobileHud:!1})]})})}function bK({rover:t}){return l.jsx("article",{className:"min-h-[16rem] rounded bg-zinc-900 p-0 sm:min-h-[18rem]",children:l.jsx("div",{className:"min-h-0 overflow-hidden rounded bg-black/20",children:l.jsx(MK,{roverId:t.id,label:t.name})})})}function yK({roster:t}){return t.length===0?l.jsx("p",{className:"col-span-full text-slate-400",children:"No rovers registered."}):l.jsx("section",{className:"grid grid-cols-1 gap-0.5 md:grid-cols-2",children:t.map(a=>l.jsx(bK,{rover:a},a.id))})}function CK(){return l.jsx("section",{className:"min-h-0",children:l.jsx("div",{className:"surface min-h-[14rem] overflow-hidden",children:l.jsx(kc,{defaultOrientation:"horizontal",hideLayoutToggle:!0,hideHeader:!0,panelId:"spectator-secondary"})})})}function wK({className:t=""}){return l.jsx("div",{className:`panel ${t}`,children:l.jsx(jo,{})})}function HK(){const{session:t}=v0(),a=o1(M=>M.latestReplay),{clearLatestReplay:r}=k2(),o=t?.mode==="lockdown";E8(),T8(),K7();const h=gK(),f=t?.roster??[];if(o)return l.jsx("div",{className:"flex min-h-screen items-center justify-center bg-black text-slate-200",children:l.jsxs("div",{className:"surface max-w-md space-y-0.5 p-1 text-center text-sm",children:[l.jsx("p",{className:"text-lg font-semibold text-white",children:"Spectate disabled during lockdown."}),l.jsx("p",{className:"text-slate-300",children:"Please wait until the server leaves lockdown to view streams."})]})});const v=h?"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]",x=h?"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",z=h?"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",g="",p=h?"h-64":"";return l.jsxs("div",{className:"min-h-screen bg-black text-slate-100 md:h-screen md:overflow-hidden",children:[l.jsxs("main",{className:v,children:[l.jsxs("section",{className:z,children:[h?l.jsxs("div",{className:`${g} ${p} flex flex-col gap-0.5`,children:[l.jsx(q7,{layout:"desktop",dismissable:!1,className:"text-sm"}),l.jsx(T7,{}),l.jsx("div",{className:"min-h-0 flex-1",children:l.jsx(E7,{hideNicknameForm:!0,hideHeader:!0,compact:!0,fillHeight:!0,className:"h-full"})})]}):l.jsxs("div",{className:g,children:[l.jsx(q7,{layout:"desktop",dismissable:!1,className:"text-sm"}),l.jsx(T7,{})]}),l.jsx("div",{className:`${g} ${h?`${p} overflow-y-auto`:""}`,children:l.jsx("div",{className:"panel h-full",children:l.jsx(Q7,{title:"Rovers"})})}),h?null:l.jsx("div",{className:`${g} flex-1 min-h-0`,children:l.jsx(E7,{hideNicknameForm:!0,hideHeader:!0,compact:!0,fillHeight:!0,className:"h-full"})}),l.jsx("div",{className:`${g} ${h?p:"flex-[1.1] min-h-0"}`,children:l.jsx(k8,{allowSpectatorInput:!0,hideSpectatorNotice:!0,fillHeight:!0})}),l.jsx("div",{className:`${g} ${h?p:""}`,children:l.jsx(wK,{className:`${h?"h-full":"h-40"} overflow-hidden`})})]}),l.jsxs("section",{className:x,children:[l.jsx(yK,{roster:f}),l.jsx(CK,{})]})]}),l.jsx(Lc,{}),l.jsx($c,{}),l.jsx(Z7,{replay:a,onClose:r})]})}function SK(){return l.jsx(HK,{})}function VK({children:t}){return l.jsx("div",{className:"flex h-full w-full items-center justify-start overflow-hidden bg-black",children:l.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:l.jsx("div",{className:"flex h-full w-full items-center justify-center overflow-hidden",children:t})})})}function AK({roverId:t,session:a}){const r=a?.activeDrivers?.[t]||null,h=(a?.users||[]).find(x=>x.socketId===r)?.nickname||(r?r.slice(0,6):"No driver"),f=a?.mode,v=a?.turnQueues?.[t];return f==="turns"&&v?.current?`${h}`:h}function LK({rover:t,frame:a}){const r=a?.sensors?.batteryChargeMah??null,o=t?.battery??null;return F8({batteryState:t?.batteryState??null,charge:r,config:o})}function s3({children:t,className:a="",maxSize:r=1e3,minSize:o=14,style:h=void 0}){const f=m.useRef(null),v=m.useRef(null),[x,z]=m.useState(r);return m.useLayoutEffect(()=>{const g=f.current,p=v.current;if(!g||!p)return;let M=null;const y=()=>{const S=g.clientWidth;if(!S){C();return}let w=o,H=r,j=o;for(;w<=H;){const A=Math.floor((w+H)/2);p.style.fontSize=`${A}px`,p.scrollWidth<=S?(j=A,w=A+1):H=A-1}z(j)},C=()=>{M&&cancelAnimationFrame(M),M=requestAnimationFrame(y)};C();const L=new ResizeObserver(C);return L.observe(g),()=>{M&&cancelAnimationFrame(M),L.disconnect()}},[t,r,o]),l.jsx("div",{ref:f,className:"w-full min-w-0",children:l.jsx("div",{ref:v,className:`whitespace-nowrap ${a}`,style:{fontSize:`${x}px`,lineHeight:1.1,...h||{}},children:t})})}function ds({rover:t,frame:a,driverLabel:r,sessionInfo:o,videoMode:h="snapshot",snapshotFeed:f,withDivider:v=!1,showPreview:x=!0,variant:z="stacked"}){const g=LK({rover:t,frame:a}),p=g?.available?g.percentDisplay:null,M=z==="active";return l.jsxs("div",{className:`relative flex min-w-0 flex-1 flex-col gap-4 overflow-hidden bg-black px-0 py-0 ${v?"border-r border-slate-700/60":""}`,children:[l.jsx(I7,{visual:g,orientation:M?"vertical":"horizontal",variant:"background"}),M?l.jsxs("div",{className:"relative z-10 flex min-w-0 flex-1 flex-col justify-between text-center",children:[l.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:l.jsx(C4,{rover:t,fallback:t.id,as:s3,className:"leading-none",maxSize:1e3,minSize:18})}),r?l.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:l.jsx(s3,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:16,children:r})}):l.jsx("div",{}),l.jsx("div",{className:"relative min-w-0 overflow-hidden bg-transparent px-0 py-0 leading-none",children:l.jsx("div",{className:"relative",children:l.jsx(s3,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:16,children:p==null?"--%":`${p}%`})})})]}):l.jsxs(l.Fragment,{children:[l.jsxs("div",{className:"relative z-10 flex min-w-0 flex-col gap-1 text-center",children:[l.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:l.jsx(C4,{rover:t,fallback:t.id,as:s3,className:"leading-none",maxSize:1e3,minSize:18})}),r?l.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:l.jsx(s3,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:16,children:r})}):null,l.jsx("div",{className:"relative min-w-0 overflow-hidden bg-transparent px-0 py-0 leading-none",children:l.jsx("div",{className:"relative",children:l.jsx(s3,{className:"font-semibold leading-none text-white",maxSize:80,minSize:16,children:p==null?"--%":`${p}%`})})})]}),l.jsx("div",{className:"relative z-10 flex min-w-0 flex-1 flex-col gap-4",children:l.jsx("div",{className:"flex w-full min-w-0 flex-1 flex-col items-center gap-4",children:x?l.jsx("div",{className:"mt-auto w-full",children:l.jsx("div",{className:"w-full aspect-[4/3]",children:l.jsx(H8,{sessionInfo:o,videoMode:h,snapshotFeed:f,audioSessionInfo:null,label:t.name||t.id,sensors:a?.sensors||null})})}):null})})]})]})}const BK=2e4,jK=3600*1e3;function NK(){const{session:t}=v0(),a=K7();E8(),T8();const r=t?.mode==="lockdown",o=!!t?.isLocalNetwork,h=iv(),f=t?.roster??[],[v,x]=m.useState(0),z=t?.activeDrivers||{},g=m.useMemo(()=>f.filter($=>z[$.id]),[f,z]),p=g.length?g:f,M=No(p.map($=>$.id),{enabled:!r&&!o,version:t?.mode}),y=m.useMemo(()=>o?p.map($=>({type:"rover",id:$.id,key:$.id})):[],[o,p]),C=oc(y,{enabled:!r&&o,version:t?.mode}),L=m.useMemo(()=>g.flatMap($=>{if(!$?.id||!$.media?.audioPublishUrl)return[];const I=String($.id);return[{type:"rover",id:`${I}-audio`,key:`${I}-audio`}]}),[g]),S=oc(L,{enabled:!r,version:t?.mode}),w=m.useMemo(()=>{if(!g.length)return[];if(!o){const I=g.filter(P=>M[P.id]?.objectUrl);return I.length?I:g}const $=g.filter(I=>{const P=C[I.id];return P?.url&&!P?.error});return $.length?$:g},[g,M,C,o]),H=m.useMemo(()=>w.map($=>({type:"rover",rover:$})),[w]),j=m.useMemo(()=>H.map($=>`r:${$.rover.id}`).join("|"),[H]);m.useEffect(()=>{x(0)},[j]),m.useEffect(()=>{if(!H.length)return;const $=setInterval(()=>{x(I=>(I+1)%H.length)},BK);return()=>clearInterval($)},[H.length,j]);const A=H.length?H[v%H.length]:null,B=A?.type==="rover"?A.rover:null,T=!o&&B&&M[B.id]||null,E=o&&B&&C[B.id]||null,R=B&&S[`${B.id}-audio`]||null,N=B&&h[B.id]||null,O=B?AK({roverId:B.id,session:t}):null;return r?l.jsx("div",{className:"relative flex h-screen w-screen items-center justify-center bg-black text-slate-200",children:l.jsxs("div",{className:"surface max-w-sm space-y-0.5 p-1 text-center text-sm",children:[l.jsx("p",{className:"text-lg font-semibold text-white",children:"Mini spectator is disabled in lockdown."}),l.jsx("p",{className:"text-slate-300",children:"It will automatically resume once lockdown ends."})]})}):g.length?l.jsxs("div",{className:"relative flex h-screen w-screen overflow-hidden bg-black text-slate-100",children:[l.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:a?B?l.jsx(VK,{children:o?l.jsx("div",{className:"relative h-full w-full",children:H.map($=>{const I=$.rover,P=B?.id===I.id;return l.jsx("div",{className:`absolute inset-0 ${P?"opacity-100":"opacity-0 pointer-events-none"}`,children:l.jsx(H8,{sessionInfo:C[I.id]||null,videoMode:"whep",snapshotFeed:null,audioSessionInfo:P?R:null,forceMute:!P,label:I.name||I.id,sensors:h[I.id]?.sensors||null})},I.id)})}):l.jsx(H8,{sessionInfo:null,videoMode:"snapshot",snapshotFeed:T,audioSessionInfo:R,label:B.name||B.id,sensors:N?.sensors||null})}):l.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:g.length?"No sources available.":"No active drivers."}):l.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:"Switching to spectator…"})}),l.jsx("aside",{className:"flex h-full min-w-0 flex-1 flex-col border-l border-slate-800/60 bg-black",children:B?l.jsx(ds,{rover:B,frame:N,driverLabel:O,sessionInfo:o?E:null,videoMode:o?"whep":"snapshot",snapshotFeed:o?null:M[B.id]||null,showPreview:!1,variant:"active"}):l.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:"No active rover."})})]}):l.jsx("div",{className:"relative flex h-screen w-screen overflow-hidden bg-black text-slate-100",children:l.jsx("section",{className:"flex h-full w-full gap-x-3 bg-slate-900 px-0",children:f.length?f.map($=>l.jsx(ds,{rover:$,frame:h[$.id]||null,driverLabel:null,sessionInfo:o&&C[$.id]||null,videoMode:o?"whep":"snapshot",snapshotFeed:o?null:M[$.id]||null,showPreview:!0,withDivider:!1},$.id)):l.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:"No rovers available."})})})}function FK(){return m.useEffect(()=>{if(typeof window>"u")return;const t=setTimeout(()=>{const a=new URL(window.location.href);a.searchParams.set("refresh",Date.now().toString()),window.location.replace(a.toString())},jK);return()=>clearTimeout(t)},[]),l.jsxs(l.Fragment,{children:[l.jsx(NK,{}),l.jsx(Lc,{scale:3})]})}function au(t){return String(t?.nickname||t?.socketId?.slice(0,6)||"unknown").trim()}function kK({roverId:t,session:a}){const r=a?.activeDrivers?.[t]||null;if(!r)return null;const o=(a?.users||[]).find(h=>h.socketId===r);return{socketId:r,label:au(o||{socketId:r})}}function RK({rover:t,frame:a}){return F8({batteryState:t?.batteryState??null,charge:a?.sensors?.batteryChargeMah??null,config:t?.battery??null})}function EK(t){return t?.available?t.urgentActive?`${t.percentDisplay}% Low`:t.warnActive?`${t.percentDisplay}% Low`:`${t.percentDisplay}%`:"--"}function TK(t,a){const r=[];return t?.private?.enabled&&t?.private?.open&&r.push("Private"),(a?.urgentActive||a?.warnActive)&&r.push("Low"),r.join(" · ")}function qK(t){return t<=1?"grid-cols-1":t===2||t===4?"grid-cols-2":"grid-cols-3"}function DK(...t){return t.filter(Boolean).join(" ")}function OK({users:t=[]}){const a=m.useRef(null),r=m.useRef(null),o=m.useRef(null),[h,f]=m.useState(!1),v=m.useMemo(()=>t.filter(g=>g?.role!=="spectator").map(au).filter(Boolean).sort((g,p)=>g.localeCompare(p)),[t]);m.useEffect(()=>{const g=a.current,p=o.current;if(!g||!p)return;const M=()=>{f(p.scrollWidth>g.clientWidth+4)};M();const y=new ResizeObserver(M);return y.observe(g),y.observe(p),()=>y.disconnect()},[v]),m.useEffect(()=>{const g=r.current;if(!g||!h)return;const p=g.animate([{transform:"translateX(0)"},{transform:"translateX(-50%)"}],{duration:42e3,iterations:1/0,easing:"linear"});return()=>p.cancel()},[h,v]);const z=(v.length?v:["No one online"]).map((g,p)=>l.jsx("span",{className:"shrink-0 px-[1.6vw] font-black tracking-normal text-slate-100",children:g},`${g}-${p}`));return l.jsx("div",{ref:a,className:"relative h-full min-w-0 overflow-hidden border-b border-slate-800/80 bg-black",children:l.jsxs("div",{ref:r,className:DK("flex h-full w-max items-center whitespace-nowrap text-[clamp(2.5rem,5.3vh,5.8rem)] leading-none"),children:[l.jsx("div",{ref:o,className:"flex h-full items-center",children:z}),h?l.jsx("div",{className:"flex h-full items-center","aria-hidden":"true",children:z}):null]})})}function $e(...t){return t.filter(Boolean).join(" ")}function _K({rover:t,session:a}){const r=G2(t?.id),o=RK({rover:t,frame:r}),h=kK({roverId:t?.id,session:a}),f=TK(t,o),v=EK(o),x=!!h,z=!!o?.urgentActive,g=!!o?.warnActive,p=!!t?.locked;return l.jsxs("article",{className:$e("relative min-h-0 overflow-hidden border border-slate-800 bg-black",p?"border-red-400 ring-4 ring-red-500/80":"",!p&&x?"ring-2 ring-sky-400/80":"",!p&&z?"ring-4 ring-red-500/90":!p&&g?"ring-2 ring-amber-300/80":""),children:[l.jsx(I7,{visual:o,variant:"background",orientation:"vertical"}),l.jsxs("div",{className:"relative z-10 grid h-full min-h-0 grid-rows-[auto_minmax(0,1fr)_auto] gap-[0.55vh] p-[0.85vw] text-center",children:[l.jsxs("div",{className:"grid min-w-0 grid-cols-[minmax(0,1fr)_auto] items-start gap-[0.8vw]",children:[l.jsx("div",{className:"min-w-0",children:l.jsx(C4,{rover:t,fallback:t?.id,as:s3,className:"leading-none",maxSize:108,minSize:26})}),p?l.jsxs("div",{className:"max-w-[40vw] border-4 border-red-100 bg-red-700 px-[1vw] py-[0.55vh] text-center text-[clamp(2rem,5vh,5.2rem)] font-black leading-none text-white",children:[l.jsx("div",{children:"LOCKED"}),t?.lockReason?l.jsx("div",{className:"mt-[0.35vh] text-[clamp(1.2rem,2.9vh,3rem)] leading-none text-red-50",children:t.lockReason}):null]}):null]}),l.jsxs("div",{className:"grid min-h-0 min-w-0 grid-cols-[minmax(0,1.45fr)_minmax(0,0.85fr)] items-center gap-[1vw]",children:[l.jsx("div",{className:"min-w-0",children:l.jsx(s3,{className:$e("font-black leading-none",x?"text-white":"text-slate-400"),maxSize:172,minSize:38,children:h?.label||"Idle"})}),l.jsx("div",{className:"min-w-0",children:l.jsx(s3,{className:$e("font-black leading-none",z?"text-red-100":g?"text-amber-100":"text-slate-100"),maxSize:136,minSize:32,children:v})})]}),f?l.jsx("div",{className:"min-w-0 text-[clamp(1.25rem,2.5vh,2.6rem)] font-black leading-none text-amber-100",children:f}):l.jsx("div",{"aria-hidden":"true"})]})]})}function UK({roster:t=[],session:a}){return t.length?l.jsx("section",{className:`grid h-full min-h-0 ${qK(t.length)} auto-rows-fr gap-0.5 bg-slate-950 p-0.5`,children:t.map(r=>l.jsx(_K,{rover:r,session:a},r.id))}):l.jsx("section",{className:"flex h-full min-h-0 items-center justify-center border-b border-slate-800 bg-black text-[clamp(2.5rem,7vh,7rem)] font-black text-slate-500",children:"No rovers"})}function ZK(){return l.jsx("section",{className:"h-full min-h-0 overflow-hidden border-t border-slate-800 bg-black",children:l.jsx("div",{className:"origin-top-left",style:{width:`calc(100% / ${4.6})`,height:`calc(100% / ${4.6})`,transform:`scale(${4.6})`},children:l.jsx(k8,{minimal:!0,fillHeight:!0,hideSpectatorNotice:!0})})})}function $K(){const{session:t}=v0(),a=o1(h=>h.latestReplay),{clearLatestReplay:r}=k2(),o=t?.mode==="lockdown";return E8(),T8(),K7(),o?l.jsx("div",{className:"flex h-screen w-screen items-center justify-center bg-black text-[clamp(2.5rem,8vh,8rem)] font-black text-slate-200",children:"Lockdown"}):l.jsxs("div",{className:"display-page flex h-screen w-screen flex-col overflow-hidden bg-black text-slate-100",children:[l.jsx("div",{className:"h-[8vh] min-h-[4rem] shrink-0",children:l.jsx(OK,{users:t?.users||[]})}),l.jsx("div",{className:"min-h-0 flex-[0.72]",children:l.jsx(UK,{roster:t?.roster||[],session:t})}),l.jsx("div",{className:"min-h-0 flex-[1.28]",children:l.jsx(ZK,{})}),l.jsx($c,{}),l.jsx(Z7,{replay:a,onClose:r})]})}function GK(){return l.jsx($K,{})}const IK=1500,PK=700,fs=/female|samantha|victoria|zira|karen|moira|serena|ava|susan|hazel|google uk english female/i;function YK(t){const a=typeof t?.getVoices=="function"?t.getVoices():[];if(!a.length)return null;const r=a.filter(o=>String(o?.lang||"").toLowerCase().startsWith("en"));return r.find(o=>fs.test(String(o?.name||"")))||a.find(o=>fs.test(String(o?.name||"")))||r[0]||a[0]||null}function QK(t){const a=m.useRef(null),r=m.useRef(null),o=m.useRef(null);m.useEffect(()=>()=>{window.clearTimeout(a.current),window.clearTimeout(r.current)},[]),m.useEffect(()=>{const h=String(t?.speechText||"").trim(),f=t?.scannedAt?`${t.scannedAt}:${h}`:"";if(!h||!f||o.current===f)return;let v=!1;o.current=f;function x(){window.clearTimeout(a.current),window.clearTimeout(r.current),a.current=null,r.current=null}function z(){v||(x(),a.current=window.setTimeout(()=>g(),PK))}function g(){if(v)return;const p=window.speechSynthesis;if(!p||typeof window.SpeechSynthesisUtterance!="function"){z();return}x(),p.cancel();const M=new window.SpeechSynthesisUtterance(h),y=YK(p);y&&(M.voice=y,M.lang=y.lang),M.rate=.92,M.pitch=1,M.volume=1,M.onstart=()=>{window.clearTimeout(r.current),r.current=null},M.onend=()=>{x()},M.onerror=()=>{z()},p.speak(M),r.current=window.setTimeout(()=>{p.cancel(),z()},IK)}return g(),()=>{v=!0,x()}},[t])}const ms={beepAllowed:!1,lastScan:null,registryError:null};function KK(){const t=window.AudioContext||window.webkitAudioContext;if(!t)return;const a=new t,r=a.createOscillator(),o=a.createGain(),h=a.currentTime;r.type="square",r.frequency.setValueAtTime(980,h),o.gain.setValueAtTime(1e-4,h),o.gain.exponentialRampToValueAtTime(.95,h+.015),o.gain.exponentialRampToValueAtTime(1e-4,h+.2),r.connect(o),o.connect(a.destination),r.start(h),r.stop(h+.22),r.onended=()=>{a.close().catch(()=>{})}}function XK(){const t=Z2(),a=m.useRef(null),r=m.useRef(null),[o,h]=m.useState(ms),[f,v]=m.useState(!1);E8(),T8(),K7(),QK(o.lastScan);const x=m.useCallback(()=>{a.current?.focus()},[]);m.useEffect(()=>{x()},[x]),m.useEffect(()=>()=>{window.clearTimeout(r.current)},[]),m.useEffect(()=>{function M(y={}){h({...ms,...y&&typeof y=="object"?y:{}})}return t.on("barcode:state",M),()=>{t.off("barcode:state",M)}},[t]);const z=m.useCallback(()=>{const M=String(a.current?.value||"").trim();if(!M){x();return}o.beepAllowed&&(window.clearTimeout(r.current),v(!0),r.current=window.setTimeout(()=>{v(!1)},120),KK()),t.emit("barcode:scan",{code:M},()=>{}),a.current.value="",x()},[x,o.beepAllowed,t]),p=o.lastScan?.label||"waiting";return l.jsxs("main",{className:`flex min-h-screen cursor-default flex-col items-center justify-center overflow-hidden px-6 text-center ${f?"bg-white text-black":"bg-black text-white"}`,onClick:x,children:[l.jsx("input",{ref:a,"aria-label":"barcode scanner input",className:"absolute left-0 top-0 h-px w-px opacity-0",autoCapitalize:"off",autoComplete:"off",autoCorrect:"off",spellCheck:!1,onKeyDown:M=>{M.key==="Enter"&&(M.preventDefault(),z())}}),l.jsx("section",{className:"flex min-h-screen w-full items-center justify-center",children:l.jsx("h1",{className:"max-w-full break-words text-[18vw] font-black leading-none tracking-normal",children:p})}),l.jsx(eu,{})]})}function JK(){return l.jsx(XK,{})}function u7(t){if(!t||!t.length)return null;const a=Math.floor(Math.random()*t.length);return t[a]||null}function WK(){if(typeof document>"u"||!document.body)return;const t=document.body.getElementsByTagName("*");if(!t||t.length<2)return;const a=u7(t),r=u7(t),o=a?.classList?.[0]||null;if(o&&r?.classList)try{r.classList.add(o)}catch{}const h=u7(t),f=u7(t),v=h?.classList?.[1]||null;if(v&&f?.classList)try{f.classList.add(v)}catch{}}function tX(){const t=o1(a=>!!a.session?.moderation?.isDeterred);return m.useEffect(()=>{if(!t)return;const a=window.setInterval(()=>{WK()},1);return()=>{window.clearInterval(a)}},[t]),null}Vd.createRoot(document.getElementById("root")).render(l.jsx(m.StrictMode,{children:l.jsx(tv,{children:l.jsx(nv,{children:l.jsx(rv,{children:l.jsx(Dv,{children:l.jsxs(CI,{children:[l.jsx(tX,{}),l.jsx(Zf,{children:l.jsxs(Mf,{children:[l.jsx(a0,{path:"/",element:l.jsx(vK,{})}),l.jsx(a0,{path:"/spectate",element:l.jsx(SK,{})}),l.jsx(a0,{path:"/mini",element:l.jsx(FK,{})}),l.jsx(a0,{path:"/display",element:l.jsx(GK,{})}),l.jsx(a0,{path:"/scanner",element:l.jsx(JK,{})})]})})]})})})})})})); +fling`;function nK(t){return t?t.charAt(0).toUpperCase()+t.slice(1):""}function lK(){const t=String(aK).split(/\r?\n/).map(r=>r.trim()).filter(Boolean);return t.length?(t[Math.floor(Math.random()*t.length)]||"").trim():""}function E8(){const{setNickname:t}=k2(),{value:a,status:r,save:o}=E1("profile",{nickname:""}),h=m.useRef(!1);m.useEffect(()=>{if(r!=="ready"||h.current||(a.nickname||"").trim())return;h.current=!0;const v=nK(lK()).slice(0,32);if(!v)return;(async()=>{try{await t(v)}catch{}finally{o({nickname:v})}})()},[o,t,r,a.nickname])}function T8(){const t=Z2(),a=o1(A=>A.connected),{identifySession:r}=k2(),{value:o,status:h,save:f}=E1("identity",{cookieUserId:""}),{value:v,status:x}=E1("profile",{nickname:""}),{value:z,status:g}=E1("overseerPreference",{enabled:!1}),p=m.useRef(!1),M=m.useRef(null),y=m.useRef(null),C=h==="ready"&&x==="ready"&&g==="ready",L=(o?.cookieUserId||"").trim(),S=(v?.nickname||"").trim(),w=!!z?.enabled,H=m.useCallback(()=>{y.current&&(clearTimeout(y.current),y.current=null)},[]),j=m.useCallback(async()=>{if(!(!C||!a||!t?.id||p.current)){p.current=!0;try{const B=((await r({cookieUserId:L,nickname:S,overseerEnabled:w}))?.cookieUserId||"").trim();B&&B!==L&&f(T=>({...T||{},cookieUserId:B})),M.current=t.id,H()}catch{H(),y.current=setTimeout(()=>{j()},2e3)}finally{p.current=!1}}},[H,a,L,r,S,w,C,f,t?.id]);m.useEffect(()=>{!C||!a||!t?.id||M.current!==t.id&&j()},[a,C,j,t?.id]),m.useEffect(()=>{!C||!a||!t?.id||j()},[C,a,t?.id,L,S,w,j]),m.useEffect(()=>{const A=()=>{t?.connected&&j()},B=()=>{typeof document>"u"||document.visibilityState!=="visible"||t?.connected&&j()};return window.addEventListener("online",A),document.addEventListener("visibilitychange",B),()=>{window.removeEventListener("online",A),document.removeEventListener("visibilitychange",B)}},[j,t?.connected]),m.useEffect(()=>{if(!C||!t?.connected)return;const A=setInterval(()=>{t?.connected&&j()},6e4);return()=>clearInterval(A)},[C,j,t?.connected]),m.useEffect(()=>()=>H(),[H])}const Ue=1e4,Ze=28,rK=14;function iK(t){const a=String(t||"").trim(),r=a.startsWith("#")?a.slice(1):a;if(!/^[0-9a-fA-F]{3}$|^[0-9a-fA-F]{6}$/.test(r))return null;const o=r.length===3?r.split("").map(h=>h+h).join(""):r;return{r:Number.parseInt(o.slice(0,2),16),g:Number.parseInt(o.slice(2,4),16),b:Number.parseInt(o.slice(4,6),16)}}function us(t,a){return`rgba(${t.r}, ${t.g}, ${t.b}, ${a})`}function q7({layout:t="desktop",className:a="",dismissable:r=!0}){const o=o1(B=>{const T=B.session?.globalObjective?.text;return T?String(T).trim():""}),h=o1(B=>{const T=String(B.session?.assignment?.roverId||"").trim();return T&&(Array.isArray(B.session?.roster)?B.session.roster:[]).find(N=>String(N?.id)===T)?.color||null}),f=t==="mobile-portrait"||t==="mobile-landscape"||t==="mobile",[v,x]=m.useState(!1),[z,g]=m.useState(Ze),[p,M]=m.useState(0),y=m.useRef(null),C=m.useRef(null),L=m.useRef(null);m.useEffect(()=>{if(!o){x(!1);return}if(x(!0),!f||!r)return;const B=Date.now();M(Ue);const T=setTimeout(()=>x(!1),Ue),E=setInterval(()=>{const R=Date.now()-B;M(Math.max(0,Ue-R))},250);return()=>{clearTimeout(T),clearInterval(E)}},[o,f]),m.useEffect(()=>{if(!o)return;g(Ze);let B=0;const T=()=>{const R=L.current,N=C.current;if(!R||!N)return;const O=R.clientWidth;if(!O)return;const $=N.scrollWidth;if(!$)return;const I=Math.min(1,O/$),P=Math.max(rK,Math.floor(Ze*I));g(P)};B=window.requestAnimationFrame(T);const E=new ResizeObserver(()=>{window.cancelAnimationFrame(B),B=window.requestAnimationFrame(T)});return y.current&&E.observe(y.current),()=>{window.cancelAnimationFrame(B),E.disconnect()}},[o]);const S=m.useMemo(()=>["panel-section flex w-full items-center justify-center border border-neutral-500/60 shadow-[0_1px_0_rgba(255,255,255,0.05)_inset,0_10px_24px_rgba(0,0,0,0.28)]",f?"rounded-none":"rounded","px-1 py-1 text-center font-semibold tracking-tight",a].filter(Boolean).join(" "),[a,f]),w=iK(h),H=w?{borderColor:us(w,.35),backgroundImage:`linear-gradient(90deg, rgba(23,23,23,0.96) 0%, rgba(38,38,38,0.94) 58%, ${us(w,.18)} 100%)`}:void 0;if(!o||!v)return null;const j=f?Math.ceil(p/1e3):null,A=r?{onClick:()=>x(!1),role:"button",tabIndex:0}:{};return l.jsx("div",{ref:y,className:S,style:{...H||{},fontSize:`${z}px`,lineHeight:1.1},...A,children:l.jsxs("span",{className:"flex w-full items-stretch gap-0.5 whitespace-nowrap rounded-md",children:[l.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:[l.jsx("span",{children:"Global"}),l.jsx("span",{children:"Objective"})]}),l.jsx("span",{ref:L,className:"flex-1 overflow-hidden text-slate-100",children:l.jsx("span",{ref:C,className:"block",children:o})}),f?l.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:[j,"s"]}):null]})})}const sK=3200;function oK(t={}){const a=typeof t.rewardName=="string"&&t.rewardName.trim()?t.rewardName.trim():"Unknown Event",r=Number.isFinite(Number(t.goal))?Math.max(1,Math.floor(Number(t.goal))):0,o=Number.isFinite(Number(t.count))?Math.max(0,Math.floor(Number(t.count))):r;return{rewardName:a,goal:r,count:o,ts:Date.now()}}function $c(){const t=Z2(),{value:a}=E1("audio",d2),r=Number.isFinite(a?.masterVolume)?a.masterVolume:d2.masterVolume,o=Number.isFinite(a?.alertVolume)?a.alertVolume:d2.alertVolume,h=Math.max(0,Math.min(1,r*o)),[f,v]=m.useState(null),x=m.useRef(null);return m.useEffect(()=>{x.current=new Audio("/tada.mp3"),x.current.volume=h,x.current.load()},[h]),m.useEffect(()=>{let z=null;function g(){const y=x.current;y&&(y.volume=h,y.currentTime=0,y.play().catch(()=>{}))}function p(y={}){const C=oK(y);v(C),g(),z&&clearTimeout(z),z=setTimeout(()=>{v(null)},sK)}function M(y){p(y?.detail||{})}return t.on("buttonBox:rewardRun",p),window.addEventListener("buttonBox:rewardRunLocalTest",M),()=>{z&&clearTimeout(z),t.off("buttonBox:rewardRun",p),window.removeEventListener("buttonBox:rewardRunLocalTest",M)}},[h,t]),f?l.jsx("div",{className:"pointer-events-none fixed inset-0 z-[120] flex items-center justify-center bg-black/75 px-1 py-1",children:l.jsx("div",{className:"pointer-events-auto w-full max-w-2xl",children:l.jsx("div",{className:"surface rounded-none border-2 border-cyan-300 bg-amber-100/95 px-1 py-1 text-center text-black shadow-2xl",children:l.jsxs("div",{className:"flex items-center justify-center gap-1 border-2 border-blue-600 bg-yellow-100 px-0.5 py-1",children:[l.jsx("img",{src:"/party1.gif",alt:"",className:"hidden shrink-0 sm:block"}),l.jsxs("div",{children:[l.jsxs("p",{className:"font-mono text-2xl font-bold text-red-700 sm:text-3xl",children:["Running event: ",f.rewardName,"!"]}),l.jsxs("p",{className:"font-mono text-xl font-bold text-blue-800 sm:text-2xl",children:[f.count,"/",f.goal]})]}),l.jsx("img",{src:"/party2.gif",alt:"",className:"hidden shrink-0 sm:block"})]})})})}):null}const uK=4e3;function hs(...t){return t.filter(Boolean).join(" ")}function eu(){const t=Z2(),[a,r]=m.useState(!!t?.connected),[o,h]=m.useState(""),[f,v]=m.useState(!0),[x,z]=m.useState(!1),g=m.useRef(null);m.useEffect(()=>{const L=()=>{g.current&&(clearTimeout(g.current),g.current=null)},S=()=>{L(),v(!0),z(!1)},w=()=>{L(),g.current=setTimeout(()=>{z(!0)},uK)},H=()=>{r(!0),h(""),S(),w()},j=T=>{r(!1),h(typeof T=="string"?T:"disconnected"),S()},A=T=>{r(!1),h(T?.message||"connect error"),S()},B=()=>{r(!1),S()};return t.on("connect",H),t.on("disconnect",j),t.on("connect_error",A),t.io.on("reconnect_attempt",B),t.connected&&w(),()=>{L(),t.off("connect",H),t.off("disconnect",j),t.off("connect_error",A),t.io.off("reconnect_attempt",B)}},[t]);const p=typeof navigator<"u"?navigator.onLine===!1:!1,M=a?"Connected to socket.io":p?"Offline":"Reconnecting...",y=a?"":o,C=a?"bg-emerald-700 text-emerald-100":p?"bg-red-800 text-red-100":"bg-amber-800 text-amber-100";return l.jsx("div",{className:hs("fixed bottom-2 left-2 z-[120] transition-opacity duration-500",!f&&"hidden",x?"opacity-0 pointer-events-none":"opacity-100"),"aria-live":"polite",children:l.jsxs("div",{className:hs("rounded-sm px-2 py-1 text-xs",C),children:[l.jsx("span",{className:"font-semibold",children:M}),y?l.jsxs("span",{className:"ml-1 opacity-85",children:["(",y,")"]}):null]})})}function hK(){const[t,a]=m.useState(()=>typeof window>"u"||window.innerWidth>=1024?"desktop":window.innerWidth>window.innerHeight?"mobile-landscape":"mobile-portrait");return m.useEffect(()=>{function r(){if(typeof window>"u")return;const{innerWidth:o,innerHeight:h}=window;o>=1024?a("desktop"):o>h?a("mobile-landscape"):a("mobile-portrait")}return r(),window.addEventListener("resize",r),()=>window.removeEventListener("resize",r)},[]),t}function dK({layout:t,onOpenHelpOverlay:a}){return l.jsxs("div",{className:`flex h-full ${H2} overflow-hidden`,children:[l.jsxs("div",{className:`flex min-w-0 flex-[1.22] flex-col ${H2} overflow-y-auto pr-0`,children:[l.jsx(Ec,{}),l.jsx(Tv,{}),l.jsx(dv,{})]}),l.jsxs("div",{className:`flex min-w-0 flex-1 flex-col ${H2} overflow-y-auto`,children:[l.jsx(q7,{layout:t}),l.jsx(DQ,{layout:t,onOpenHelpOverlay:a})]})]})}function cu({layout:t,onOpenHelpOverlay:a,roomPanelId:r}){const[o,h]=m.useState("chat"),f=o1(w=>!!w.session?.isVerified),v=o1(w=>String(w.session?.assignment?.roverId||"").trim()),x=o1(w=>{const H=String(w.session?.assignment?.roverId||"").trim();return H&&w.session?.audioForward?.[H]||null}),{state:z}=V2(),{value:g}=E1("vipAudio",{openMicEnabled:!1,pttMode:"live"}),p=f?"bg-emerald-400":"bg-amber-400",M=!!z?.mic?.pttActive,y=!!g?.openMicEnabled,C=g?.pttMode==="clip"?"clip":"live",L=!!(v&&f&&(C==="clip"?M:y||M)),S=!!(v&&f&&C==="clip"&&x?.source==="upload"&&x?.state==="playing");return l.jsx("section",{className:"text-base",children:l.jsxs(Oc,{defaultTab:"chat",currentTab:o,onTabChange:h,children:[l.jsxs(_c,{children:[l.jsx(i4,{id:"chat",children:"Chat"}),l.jsx(i4,{id:"vip",highlight:S?"green":L?"pink":"none",children:l.jsxs("span",{className:"inline-flex items-center gap-0.5",children:[l.jsx("span",{children:"VIP"}),l.jsx("span",{className:`inline-block h-1.5 w-1.5 rounded-full ${p}`,"aria-hidden":"true",title:f?"Verified":"Not verified"})]})}),l.jsx(i4,{id:"roomcontrols",children:"Room Controls"}),l.jsx(i4,{id:"help",children:"Help"}),l.jsx(i4,{id:"settings",children:"Settings"})]}),l.jsxs(Uc,{children:[l.jsx(s4,{id:"chat",children:l.jsxs("div",{className:u6,children:[l.jsx(k8,{nicknameLayout:"stacked"}),l.jsxs("div",{className:u6,children:[l.jsx("div",{className:`grid ${H2} md:grid-cols-[minmax(0,1.4fr)_minmax(0,1fr)]`,children:l.jsx(Zc,{})}),l.jsxs("div",{className:`grid ${H2} grid-cols-[minmax(0,1fr)_minmax(0,1fr)]`,children:[l.jsx(tu,{}),l.jsx(E7,{hideNicknameForm:!0})]})]})]})}),l.jsx(s4,{id:"vip",keepMounted:!0,children:l.jsx(Wo,{isActive:o==="vip"})}),l.jsx(s4,{id:"roomcontrols",children:l.jsxs("div",{className:u6,children:[l.jsx(Uo,{}),l.jsx(T7,{}),l.jsx(kc,{panelId:r}),l.jsx(Bo,{})]})}),l.jsx(s4,{id:"help",children:l.jsx(Xo,{layout:t,onOpenOverlay:a})}),l.jsx(s4,{id:"settings",children:l.jsxs("div",{className:u6,children:[l.jsx(Yo,{}),l.jsx(jo,{})]})})]})]})})}function fK({onOpenHelpOverlay:t,swapMobileControlColumns:a=!1}){return l.jsxs("div",{className:`flex flex-col ${H2}`,children:[l.jsx(Ec,{layoutFormat:"mobile-portrait"}),l.jsx(cP,{swapColumns:a}),l.jsxs("div",{className:`grid ${H2} grid-cols-[minmax(0,1fr)_minmax(0,1.4fr)]`,children:[l.jsx(Sc,{panelId:"replay-sources-mobile-portrait"}),l.jsx(Q7,{})]}),l.jsx(cu,{layout:"mobile-portrait",onOpenHelpOverlay:t,roomPanelId:"mobile-portrait-room"})]})}function mK({onOpenHelpOverlay:t,swapMobileControlColumns:a=!1}){const r="self-start h-[min(100svh,32rem)]",o=a?l.jsx(k7,{layout:"landscape",className:r}):l.jsx(F7,{layout:"landscape",className:r}),h=a?l.jsx(F7,{layout:"landscape",className:r}):l.jsx(k7,{layout:"landscape",className:r});return l.jsxs("div",{className:`flex flex-col ${H2}`,children:[l.jsxs("section",{className:`grid min-h-screen grid-cols-[minmax(0,0.7fr)_minmax(0,2.1fr)_minmax(0,0.7fr)] ${H2}`,children:[o,l.jsxs("div",{children:[l.jsx(Ec,{layoutFormat:"mobile-landscape"}),l.jsxs("div",{className:`grid ${H2} grid-cols-[minmax(0,1fr)_minmax(0,1.4fr)]`,children:[l.jsx(Sc,{panelId:"replay-sources-mobile-landscape"}),l.jsx(Q7,{})]})]}),h]}),l.jsx("div",{className:`flex flex-col ${H2} pb-0`,children:l.jsx(cu,{layout:"mobile-landscape",onOpenHelpOverlay:t,roomPanelId:"mobile-landscape-room"})})]})}function vK(){const t=hK(),a=t==="desktop",r=JQ(t);return l.jsx("div",{className:`${qY} text-slate-100 ${a?"h-screen overflow-hidden":"min-h-screen"}`,children:l.jsx(pK,{layout:t,isDesktop:a,fullscreen:r})})}function pK({layout:t,isDesktop:a,fullscreen:r}){E8(),T8();const{visible:o,mode:h,isIOS:f,nativeSupported:v,enterFullscreen:x,dismiss:z,showPrompt:g}=r,{value:p,save:M}=E1("help",{showOnLoad:!0}),{value:y,status:C,save:L}=E1("quickstart",{showOnLoad:!0}),{value:S}=E1("page",{swapMobileControlColumns:!1}),w=!!S?.swapMobileControlColumns,H=w?"left":"right",j=!a&&(f||v),A=o1(k=>k.latestRequestedReplay),{clearReplayModal:B}=k2(),[T,E]=m.useState(!1),[R,N]=m.useState(!1);m.useEffect(()=>{C==="ready"&&N(y?.showOnLoad!==!1)},[C,y?.showOnLoad]);const O=m.useCallback(()=>E(!0),[]),$=m.useCallback(()=>E(!1),[]),I=m.useCallback(()=>N(!1),[]),P=m.useCallback(async()=>{if(f){g();return}await x()||g()},[x,f,g]),u1=m.useCallback(k=>{const D=!!k;L(U=>({...U??{},showOnLoad:D})),D||N(!1)},[L]),h1=m.useCallback(()=>{N(!1),E(!0)},[]),a1=m.useMemo(()=>a?l.jsx(dK,{layout:t,onOpenHelpOverlay:O}):t==="mobile-landscape"?l.jsx(mK,{onOpenHelpOverlay:O,swapMobileControlColumns:w}):l.jsx(fK,{onOpenHelpOverlay:O,swapMobileControlColumns:w}),[a,t,O,w]);return l.jsxs(bI,{children:[l.jsx(kI,{}),l.jsx(II,{}),l.jsxs("main",{className:`flex w-full flex-col ${H2} text-base ${a?"h-full overflow-hidden":""}`,children:[a?null:l.jsx(q7,{layout:t}),a1]}),l.jsx(Lc,{}),l.jsx($c,{}),l.jsx(PQ,{}),l.jsx($Q,{}),l.jsx(eu,{}),l.jsx(WQ,{visible:T,layout:t,onClose:$,showOnLoad:p?.showOnLoad!==!1,onToggleShowOnLoad:k=>M(D=>({...D??{},showOnLoad:!!k}))}),l.jsx(YQ,{visible:o,mode:h,onEnterFullscreen:x,onDismiss:z}),l.jsx(cK,{visible:R,layout:t,showOnLoad:y?.showOnLoad!==!1,onToggleShowOnLoad:u1,onOpenHelp:h1,onClose:I}),l.jsx(Z7,{replay:A,onClose:B}),j?l.jsx(QQ,{side:H,onClick:P}):null]})}function K7(){const{session:t,setRole:a,subscribeAll:r,connected:o}=v0(),[h,f]=m.useState(!1);return m.useEffect(()=>{let v=!1;async function x(){if(t?.mode==="lockdown"){f(!1);return}try{t?.role!=="spectator"&&await a("spectator"),await r(),v||f(!0)}catch(z){console.error("Failed to enter spectator mode",z),v||f(!1)}}return x(),()=>{v=!0}},[o,t?.mode,t?.role,a,r]),h}function gK(){const[t,a]=m.useState(()=>typeof window>"u"?!1:window.matchMedia("(max-aspect-ratio: 4/3)").matches);return m.useEffect(()=>{if(typeof window>"u")return;const r=window.matchMedia("(max-aspect-ratio: 4/3)"),o=h=>a(h.matches);return r.addEventListener?r.addEventListener("change",o):r.addListener(o),()=>{r.removeEventListener?r.removeEventListener("change",o):r.removeListener(o)}},[]),t}function xK({show:t=!1,roverId:a=null,sensors:r,batteryConfig:o,mobileHud:h=!1}){const f=G2(a),v=o1(p=>a?(p.session?.roster||[]).find(C=>String(C.id)===String(a))?.battery??null:null),x=r??f?.sensors??null,z=o??v,g=F8({charge:x?.batteryChargeMah??null,config:z});return!t||!g?.available?null:l.jsx("div",{className:"pointer-events-none absolute right-1 top-1/2 flex h-[70%] -translate-y-1/2 flex-col items-center justify-center rounded bg-black/60 px-0.5 pb-1 pt-1",children:l.jsx(I7,{visual:g,orientation:"vertical",variant:"inline",compact:h,className:"h-full w-4"})})}const zK=U2.memo(xK);function MK({roverId:t=null,label:a,fitParent:r=!1,layoutFormat:o="desktop"}){return l.jsx("div",{className:`flex flex-col gap-0.5 ${r?"h-full":""}`,children:l.jsxs("div",{className:`relative w-full overflow-hidden bg-black ${r?"h-full flex-1":"aspect-[4/3]"}`,children:[l.jsx(H8,{roverId:t,label:a}),l.jsx(qo,{roverId:t,variant:"spectator",mobileHud:!1}),l.jsx(To,{roverId:t,layoutFormat:o,variant:"spectator",mobileHud:!1,labelScale:1}),l.jsx(Do,{roverId:t,compact:!1}),l.jsx(Oo,{roverId:t,compact:!1}),l.jsx(zK,{show:!0,roverId:t,mobileHud:!1})]})})}function bK({rover:t}){return l.jsx("article",{className:"min-h-[16rem] rounded bg-zinc-900 p-0 sm:min-h-[18rem]",children:l.jsx("div",{className:"min-h-0 overflow-hidden rounded bg-black/20",children:l.jsx(MK,{roverId:t.id,label:t.name})})})}function yK({roster:t}){return t.length===0?l.jsx("p",{className:"col-span-full text-slate-400",children:"No rovers registered."}):l.jsx("section",{className:"grid grid-cols-1 gap-0.5 md:grid-cols-2",children:t.map(a=>l.jsx(bK,{rover:a},a.id))})}function CK(){return l.jsx("section",{className:"min-h-0",children:l.jsx("div",{className:"surface min-h-[14rem] overflow-hidden",children:l.jsx(kc,{defaultOrientation:"horizontal",hideLayoutToggle:!0,hideHeader:!0,panelId:"spectator-secondary"})})})}function wK({className:t=""}){return l.jsx("div",{className:`panel ${t}`,children:l.jsx(jo,{})})}function HK(){const{session:t}=v0(),a=o1(M=>M.latestReplay),{clearLatestReplay:r}=k2(),o=t?.mode==="lockdown";E8(),T8(),K7();const h=gK(),f=t?.roster??[];if(o)return l.jsx("div",{className:"flex min-h-screen items-center justify-center bg-black text-slate-200",children:l.jsxs("div",{className:"surface max-w-md space-y-0.5 p-1 text-center text-sm",children:[l.jsx("p",{className:"text-lg font-semibold text-white",children:"Spectate disabled during lockdown."}),l.jsx("p",{className:"text-slate-300",children:"Please wait until the server leaves lockdown to view streams."})]})});const v=h?"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]",x=h?"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",z=h?"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",g="",p=h?"h-64":"";return l.jsxs("div",{className:"min-h-screen bg-black text-slate-100 md:h-screen md:overflow-hidden",children:[l.jsxs("main",{className:v,children:[l.jsxs("section",{className:z,children:[h?l.jsxs("div",{className:`${g} ${p} flex flex-col gap-0.5`,children:[l.jsx(q7,{layout:"desktop",dismissable:!1,className:"text-sm"}),l.jsx(T7,{}),l.jsx("div",{className:"min-h-0 flex-1",children:l.jsx(E7,{hideNicknameForm:!0,hideHeader:!0,compact:!0,fillHeight:!0,className:"h-full"})})]}):l.jsxs("div",{className:g,children:[l.jsx(q7,{layout:"desktop",dismissable:!1,className:"text-sm"}),l.jsx(T7,{})]}),l.jsx("div",{className:`${g} ${h?`${p} overflow-y-auto`:""}`,children:l.jsx("div",{className:"panel h-full",children:l.jsx(Q7,{title:"Rovers"})})}),h?null:l.jsx("div",{className:`${g} flex-1 min-h-0`,children:l.jsx(E7,{hideNicknameForm:!0,hideHeader:!0,compact:!0,fillHeight:!0,className:"h-full"})}),l.jsx("div",{className:`${g} ${h?p:"flex-[1.1] min-h-0"}`,children:l.jsx(k8,{allowSpectatorInput:!0,hideSpectatorNotice:!0,fillHeight:!0})}),l.jsx("div",{className:`${g} ${h?p:""}`,children:l.jsx(wK,{className:`${h?"h-full":"h-40"} overflow-hidden`})})]}),l.jsxs("section",{className:x,children:[l.jsx(yK,{roster:f}),l.jsx(CK,{})]})]}),l.jsx(Lc,{}),l.jsx($c,{}),l.jsx(Z7,{replay:a,onClose:r})]})}function SK(){return l.jsx(HK,{})}function VK({children:t}){return l.jsx("div",{className:"flex h-full w-full items-center justify-start overflow-hidden bg-black",children:l.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:l.jsx("div",{className:"flex h-full w-full items-center justify-center overflow-hidden",children:t})})})}function AK({roverId:t,session:a}){const r=a?.activeDrivers?.[t]||null,h=(a?.users||[]).find(x=>x.socketId===r)?.nickname||(r?r.slice(0,6):"No driver"),f=a?.mode,v=a?.turnQueues?.[t];return f==="turns"&&v?.current?`${h}`:h}function LK({rover:t,frame:a}){const r=a?.sensors?.batteryChargeMah??null,o=t?.battery??null;return F8({batteryState:t?.batteryState??null,charge:r,config:o})}function s3({children:t,className:a="",maxSize:r=1e3,minSize:o=14,style:h=void 0}){const f=m.useRef(null),v=m.useRef(null),[x,z]=m.useState(r);return m.useLayoutEffect(()=>{const g=f.current,p=v.current;if(!g||!p)return;let M=null;const y=()=>{const S=g.clientWidth;if(!S){C();return}let w=o,H=r,j=o;for(;w<=H;){const A=Math.floor((w+H)/2);p.style.fontSize=`${A}px`,p.scrollWidth<=S?(j=A,w=A+1):H=A-1}z(j)},C=()=>{M&&cancelAnimationFrame(M),M=requestAnimationFrame(y)};C();const L=new ResizeObserver(C);return L.observe(g),()=>{M&&cancelAnimationFrame(M),L.disconnect()}},[t,r,o]),l.jsx("div",{ref:f,className:"w-full min-w-0",children:l.jsx("div",{ref:v,className:`whitespace-nowrap ${a}`,style:{fontSize:`${x}px`,lineHeight:1.1,...h||{}},children:t})})}function ds({rover:t,frame:a,driverLabel:r,sessionInfo:o,videoMode:h="snapshot",snapshotFeed:f,withDivider:v=!1,showPreview:x=!0,variant:z="stacked"}){const g=LK({rover:t,frame:a}),p=g?.available?g.percentDisplay:null,M=z==="active";return l.jsxs("div",{className:`relative flex min-w-0 flex-1 flex-col gap-4 overflow-hidden bg-black px-0 py-0 ${v?"border-r border-slate-700/60":""}`,children:[l.jsx(I7,{visual:g,orientation:M?"vertical":"horizontal",variant:"background"}),M?l.jsxs("div",{className:"relative z-10 flex min-w-0 flex-1 flex-col justify-between text-center",children:[l.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:l.jsx(C4,{rover:t,fallback:t.id,as:s3,className:"leading-none",maxSize:1e3,minSize:18})}),r?l.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:l.jsx(s3,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:16,children:r})}):l.jsx("div",{}),l.jsx("div",{className:"relative min-w-0 overflow-hidden bg-transparent px-0 py-0 leading-none",children:l.jsx("div",{className:"relative",children:l.jsx(s3,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:16,children:p==null?"--%":`${p}%`})})})]}):l.jsxs(l.Fragment,{children:[l.jsxs("div",{className:"relative z-10 flex min-w-0 flex-col gap-1 text-center",children:[l.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:l.jsx(C4,{rover:t,fallback:t.id,as:s3,className:"leading-none",maxSize:1e3,minSize:18})}),r?l.jsx("div",{className:"min-w-0 bg-transparent px-0 py-0 leading-none",children:l.jsx(s3,{className:"font-semibold leading-none text-white",maxSize:1e3,minSize:16,children:r})}):null,l.jsx("div",{className:"relative min-w-0 overflow-hidden bg-transparent px-0 py-0 leading-none",children:l.jsx("div",{className:"relative",children:l.jsx(s3,{className:"font-semibold leading-none text-white",maxSize:80,minSize:16,children:p==null?"--%":`${p}%`})})})]}),l.jsx("div",{className:"relative z-10 flex min-w-0 flex-1 flex-col gap-4",children:l.jsx("div",{className:"flex w-full min-w-0 flex-1 flex-col items-center gap-4",children:x?l.jsx("div",{className:"mt-auto w-full",children:l.jsx("div",{className:"w-full aspect-[4/3]",children:l.jsx(H8,{sessionInfo:o,videoMode:h,snapshotFeed:f,audioSessionInfo:null,label:t.name||t.id,sensors:a?.sensors||null})})}):null})})]})]})}const BK=2e4,jK=3600*1e3;function NK(){const{session:t}=v0(),a=K7();E8(),T8();const r=t?.mode==="lockdown",o=!!t?.isLocalNetwork,h=iv(),f=t?.roster??[],[v,x]=m.useState(0),z=t?.activeDrivers||{},g=m.useMemo(()=>f.filter($=>z[$.id]),[f,z]),p=g.length?g:f,M=No(p.map($=>$.id),{enabled:!r&&!o,version:t?.mode}),y=m.useMemo(()=>o?p.map($=>({type:"rover",id:$.id,key:$.id})):[],[o,p]),C=oc(y,{enabled:!r&&o,version:t?.mode}),L=m.useMemo(()=>g.flatMap($=>{if(!$?.id||!$.media?.audioPublishUrl)return[];const I=String($.id);return[{type:"rover",id:`${I}-audio`,key:`${I}-audio`}]}),[g]),S=oc(L,{enabled:!r,version:t?.mode}),w=m.useMemo(()=>{if(!g.length)return[];if(!o){const I=g.filter(P=>M[P.id]?.objectUrl);return I.length?I:g}const $=g.filter(I=>{const P=C[I.id];return P?.url&&!P?.error});return $.length?$:g},[g,M,C,o]),H=m.useMemo(()=>w.map($=>({type:"rover",rover:$})),[w]),j=m.useMemo(()=>H.map($=>`r:${$.rover.id}`).join("|"),[H]);m.useEffect(()=>{x(0)},[j]),m.useEffect(()=>{if(!H.length)return;const $=setInterval(()=>{x(I=>(I+1)%H.length)},BK);return()=>clearInterval($)},[H.length,j]);const A=H.length?H[v%H.length]:null,B=A?.type==="rover"?A.rover:null,T=!o&&B&&M[B.id]||null,E=o&&B&&C[B.id]||null,R=B&&S[`${B.id}-audio`]||null,N=B&&h[B.id]||null,O=B?AK({roverId:B.id,session:t}):null;return r?l.jsx("div",{className:"relative flex h-screen w-screen items-center justify-center bg-black text-slate-200",children:l.jsxs("div",{className:"surface max-w-sm space-y-0.5 p-1 text-center text-sm",children:[l.jsx("p",{className:"text-lg font-semibold text-white",children:"Mini spectator is disabled in lockdown."}),l.jsx("p",{className:"text-slate-300",children:"It will automatically resume once lockdown ends."})]})}):g.length?l.jsxs("div",{className:"relative flex h-screen w-screen overflow-hidden bg-black text-slate-100",children:[l.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:a?B?l.jsx(VK,{children:o?l.jsx("div",{className:"relative h-full w-full",children:H.map($=>{const I=$.rover,P=B?.id===I.id;return l.jsx("div",{className:`absolute inset-0 ${P?"opacity-100":"opacity-0 pointer-events-none"}`,children:l.jsx(H8,{sessionInfo:C[I.id]||null,videoMode:"whep",snapshotFeed:null,audioSessionInfo:P?R:null,forceMute:!P,label:I.name||I.id,sensors:h[I.id]?.sensors||null})},I.id)})}):l.jsx(H8,{sessionInfo:null,videoMode:"snapshot",snapshotFeed:T,audioSessionInfo:R,label:B.name||B.id,sensors:N?.sensors||null})}):l.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:g.length?"No sources available.":"No active drivers."}):l.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:"Switching to spectator…"})}),l.jsx("aside",{className:"flex h-full min-w-0 flex-1 flex-col border-l border-slate-800/60 bg-black",children:B?l.jsx(ds,{rover:B,frame:N,driverLabel:O,sessionInfo:o?E:null,videoMode:o?"whep":"snapshot",snapshotFeed:o?null:M[B.id]||null,showPreview:!1,variant:"active"}):l.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:"No active rover."})})]}):l.jsx("div",{className:"relative flex h-screen w-screen overflow-hidden bg-black text-slate-100",children:l.jsx("section",{className:"flex h-full w-full gap-x-3 bg-slate-900 px-0",children:f.length?f.map($=>l.jsx(ds,{rover:$,frame:h[$.id]||null,driverLabel:null,sessionInfo:o&&C[$.id]||null,videoMode:o?"whep":"snapshot",snapshotFeed:o?null:M[$.id]||null,showPreview:!0,withDivider:!1},$.id)):l.jsx("div",{className:"flex h-full w-full items-center justify-center text-sm text-slate-500",children:"No rovers available."})})})}function FK(){return m.useEffect(()=>{if(typeof window>"u")return;const t=setTimeout(()=>{const a=new URL(window.location.href);a.searchParams.set("refresh",Date.now().toString()),window.location.replace(a.toString())},jK);return()=>clearTimeout(t)},[]),l.jsxs(l.Fragment,{children:[l.jsx(NK,{}),l.jsx(Lc,{scale:3})]})}function au(t){return String(t?.nickname||t?.socketId?.slice(0,6)||"unknown").trim()}function kK({roverId:t,session:a}){const r=a?.activeDrivers?.[t]||null;if(!r)return null;const o=(a?.users||[]).find(h=>h.socketId===r);return{socketId:r,label:au(o||{socketId:r})}}function RK({rover:t,frame:a}){return F8({batteryState:t?.batteryState??null,charge:a?.sensors?.batteryChargeMah??null,config:t?.battery??null})}function EK(t){return t?.available?t.urgentActive?`${t.percentDisplay}% Low`:t.warnActive?`${t.percentDisplay}% Low`:`${t.percentDisplay}%`:"--"}function TK(t,a){const r=[];return t?.private?.enabled&&t?.private?.open&&r.push("Private"),(a?.urgentActive||a?.warnActive)&&r.push("Low"),r.join(" · ")}function qK(t){return t<=1?"grid-cols-1":t===2||t===4?"grid-cols-2":"grid-cols-3"}function DK(...t){return t.filter(Boolean).join(" ")}function OK({users:t=[]}){const a=m.useRef(null),r=m.useRef(null),o=m.useRef(null),[h,f]=m.useState(!1),v=m.useMemo(()=>t.filter(g=>g?.role!=="spectator").map(au).filter(Boolean).sort((g,p)=>g.localeCompare(p)),[t]);m.useEffect(()=>{const g=a.current,p=o.current;if(!g||!p)return;const M=()=>{f(p.scrollWidth>g.clientWidth+4)};M();const y=new ResizeObserver(M);return y.observe(g),y.observe(p),()=>y.disconnect()},[v]),m.useEffect(()=>{const g=r.current;if(!g||!h)return;const p=g.animate([{transform:"translateX(0)"},{transform:"translateX(-50%)"}],{duration:42e3,iterations:1/0,easing:"linear"});return()=>p.cancel()},[h,v]);const z=(v.length?v:["No one online"]).map((g,p)=>l.jsx("span",{className:"shrink-0 px-[1.6vw] font-black tracking-normal text-slate-100",children:g},`${g}-${p}`));return l.jsx("div",{ref:a,className:"relative h-full min-w-0 overflow-hidden border-b border-slate-800/80 bg-black",children:l.jsxs("div",{ref:r,className:DK("flex h-full w-max items-center whitespace-nowrap text-[clamp(2.5rem,5.3vh,5.8rem)] leading-none"),children:[l.jsx("div",{ref:o,className:"flex h-full items-center",children:z}),h?l.jsx("div",{className:"flex h-full items-center","aria-hidden":"true",children:z}):null]})})}function $e(...t){return t.filter(Boolean).join(" ")}function _K({rover:t,session:a}){const r=G2(t?.id),o=RK({rover:t,frame:r}),h=kK({roverId:t?.id,session:a}),f=TK(t,o),v=EK(o),x=!!h,z=!!o?.urgentActive,g=!!o?.warnActive,p=!!t?.locked;return l.jsxs("article",{className:$e("relative min-h-0 overflow-hidden border border-slate-800 bg-black",p?"border-red-400 ring-4 ring-red-500/80":"",!p&&x?"ring-2 ring-sky-400/80":"",!p&&z?"ring-4 ring-red-500/90":!p&&g?"ring-2 ring-amber-300/80":""),children:[l.jsx(I7,{visual:o,variant:"background",orientation:"vertical"}),l.jsxs("div",{className:"relative z-10 grid h-full min-h-0 grid-rows-[auto_minmax(0,1fr)_auto] gap-[0.55vh] p-[0.85vw] text-center",children:[l.jsxs("div",{className:"grid min-w-0 grid-cols-[minmax(0,1fr)_auto] items-start gap-[0.8vw]",children:[l.jsx("div",{className:"min-w-0",children:l.jsx(C4,{rover:t,fallback:t?.id,as:s3,className:"leading-none",maxSize:108,minSize:26})}),p?l.jsxs("div",{className:"max-w-[40vw] border-4 border-red-100 bg-red-700 px-[1vw] py-[0.55vh] text-center text-[clamp(2rem,5vh,5.2rem)] font-black leading-none text-white",children:[l.jsx("div",{children:"LOCKED"}),t?.lockReason?l.jsx("div",{className:"mt-[0.35vh] text-[clamp(1.2rem,2.9vh,3rem)] leading-none text-red-50",children:t.lockReason}):null]}):null]}),l.jsxs("div",{className:"grid min-h-0 min-w-0 grid-cols-[minmax(0,1.45fr)_minmax(0,0.85fr)] items-center gap-[1vw]",children:[l.jsx("div",{className:"min-w-0",children:l.jsx(s3,{className:$e("font-black leading-none",x?"text-white":"text-slate-400"),maxSize:172,minSize:38,children:h?.label||"Idle"})}),l.jsx("div",{className:"min-w-0",children:l.jsx(s3,{className:$e("font-black leading-none",z?"text-red-100":g?"text-amber-100":"text-slate-100"),maxSize:136,minSize:32,children:v})})]}),f?l.jsx("div",{className:"min-w-0 text-[clamp(1.25rem,2.5vh,2.6rem)] font-black leading-none text-amber-100",children:f}):l.jsx("div",{"aria-hidden":"true"})]})]})}function UK({roster:t=[],session:a}){return t.length?l.jsx("section",{className:`grid h-full min-h-0 ${qK(t.length)} auto-rows-fr gap-0.5 bg-slate-950 p-0.5`,children:t.map(r=>l.jsx(_K,{rover:r,session:a},r.id))}):l.jsx("section",{className:"flex h-full min-h-0 items-center justify-center border-b border-slate-800 bg-black text-[clamp(2.5rem,7vh,7rem)] font-black text-slate-500",children:"No rovers"})}function ZK(){return l.jsx("section",{className:"h-full min-h-0 overflow-hidden border-t border-slate-800 bg-black",children:l.jsx("div",{className:"origin-top-left",style:{width:`calc(100% / ${4.6})`,height:`calc(100% / ${4.6})`,transform:`scale(${4.6})`},children:l.jsx(k8,{minimal:!0,fillHeight:!0,hideSpectatorNotice:!0})})})}function $K(){const{session:t}=v0(),a=o1(h=>h.latestReplay),{clearLatestReplay:r}=k2(),o=t?.mode==="lockdown";return E8(),T8(),K7(),o?l.jsx("div",{className:"flex h-screen w-screen items-center justify-center bg-black text-[clamp(2.5rem,8vh,8rem)] font-black text-slate-200",children:"Lockdown"}):l.jsxs("div",{className:"display-page flex h-screen w-screen flex-col overflow-hidden bg-black text-slate-100",children:[l.jsx("div",{className:"h-[8vh] min-h-[4rem] shrink-0",children:l.jsx(OK,{users:t?.users||[]})}),l.jsx("div",{className:"min-h-0 flex-[0.72]",children:l.jsx(UK,{roster:t?.roster||[],session:t})}),l.jsx("div",{className:"min-h-0 flex-[1.28]",children:l.jsx(ZK,{})}),l.jsx($c,{}),l.jsx(Z7,{replay:a,onClose:r})]})}function GK(){return l.jsx($K,{})}const IK=1500,PK=700,fs=/female|samantha|victoria|allison|zira|karen|moira|serena|ava|susan|hazel|google (us|uk) english/i,YK=/whisper|bubbles|bells|boing|bad news|bahh|cellos|deranged|good news|hysterical|pipe organ|trinoids|zarvox/i;function QK(t){return YK.test(String(t?.name||""))}function KK(t){const a=typeof t?.getVoices=="function"?t.getVoices():[];if(!a.length)return null;const r=a.filter(f=>!QK(f)),o=r.find(f=>f?.default)||null,h=r.filter(f=>String(f?.lang||"").toLowerCase().startsWith("en"));return h.find(f=>fs.test(String(f?.name||"")))||r.find(f=>fs.test(String(f?.name||"")))||o||h[0]||r[0]||null}function XK(t){const a=m.useRef(null),r=m.useRef(null),o=m.useRef(null);m.useEffect(()=>()=>{window.clearTimeout(a.current),window.clearTimeout(r.current)},[]),m.useEffect(()=>{const h=String(t?.speechText||"").trim(),f=t?.scannedAt?`${t.scannedAt}:${h}`:"";if(!h||!f||o.current===f)return;let v=!1;o.current=f;function x(){window.clearTimeout(a.current),window.clearTimeout(r.current),a.current=null,r.current=null}function z(){v||(x(),a.current=window.setTimeout(()=>g(),PK))}function g(){if(v)return;const p=window.speechSynthesis;if(!p||typeof window.SpeechSynthesisUtterance!="function"){z();return}x(),p.cancel();const M=new window.SpeechSynthesisUtterance(h),y=KK(p);y&&(M.voice=y,M.lang=y.lang),M.rate=1,M.pitch=1,M.volume=1,M.onstart=()=>{window.clearTimeout(r.current),r.current=null},M.onend=()=>{x()},M.onerror=()=>{z()},p.speak(M),r.current=window.setTimeout(()=>{p.cancel(),z()},IK)}return g(),()=>{v=!0,x()}},[t])}const ms={beepAllowed:!1,lastScan:null,registryError:null};function JK(){const t=window.AudioContext||window.webkitAudioContext;if(!t)return;const a=new t,r=a.createOscillator(),o=a.createGain(),h=a.currentTime;r.type="square",r.frequency.setValueAtTime(980,h),o.gain.setValueAtTime(1e-4,h),o.gain.exponentialRampToValueAtTime(.95,h+.015),o.gain.exponentialRampToValueAtTime(1e-4,h+.2),r.connect(o),o.connect(a.destination),r.start(h),r.stop(h+.22),r.onended=()=>{a.close().catch(()=>{})}}function WK(){const t=Z2(),a=m.useRef(null),r=m.useRef(null),[o,h]=m.useState(ms),[f,v]=m.useState(!1);E8(),T8(),K7(),XK(o.lastScan);const x=m.useCallback(()=>{a.current?.focus()},[]);m.useEffect(()=>{x()},[x]),m.useEffect(()=>()=>{window.clearTimeout(r.current)},[]),m.useEffect(()=>{function M(y={}){h({...ms,...y&&typeof y=="object"?y:{}})}return t.on("barcode:state",M),()=>{t.off("barcode:state",M)}},[t]);const z=m.useCallback(()=>{const M=String(a.current?.value||"").trim();if(!M){x();return}o.beepAllowed&&(window.clearTimeout(r.current),v(!0),r.current=window.setTimeout(()=>{v(!1)},120),JK()),t.emit("barcode:scan",{code:M},()=>{}),a.current.value="",x()},[x,o.beepAllowed,t]),p=o.lastScan?.label||"waiting";return l.jsxs("main",{className:`flex min-h-screen cursor-default flex-col items-center justify-center overflow-hidden px-6 text-center ${f?"bg-white text-black":"bg-black text-white"}`,onClick:x,children:[l.jsx("input",{ref:a,"aria-label":"barcode scanner input",className:"absolute left-0 top-0 h-px w-px opacity-0",autoCapitalize:"off",autoComplete:"off",autoCorrect:"off",spellCheck:!1,onKeyDown:M=>{M.key==="Enter"&&(M.preventDefault(),z())}}),l.jsx("section",{className:"flex min-h-screen w-full items-center justify-center",children:l.jsx("h1",{className:"max-w-full break-words text-[18vw] font-black leading-none tracking-normal",children:p})}),l.jsx(eu,{})]})}function tX(){return l.jsx(WK,{})}function u7(t){if(!t||!t.length)return null;const a=Math.floor(Math.random()*t.length);return t[a]||null}function eX(){if(typeof document>"u"||!document.body)return;const t=document.body.getElementsByTagName("*");if(!t||t.length<2)return;const a=u7(t),r=u7(t),o=a?.classList?.[0]||null;if(o&&r?.classList)try{r.classList.add(o)}catch{}const h=u7(t),f=u7(t),v=h?.classList?.[1]||null;if(v&&f?.classList)try{f.classList.add(v)}catch{}}function cX(){const t=o1(a=>!!a.session?.moderation?.isDeterred);return m.useEffect(()=>{if(!t)return;const a=window.setInterval(()=>{eX()},1);return()=>{window.clearInterval(a)}},[t]),null}Vd.createRoot(document.getElementById("root")).render(l.jsx(m.StrictMode,{children:l.jsx(tv,{children:l.jsx(nv,{children:l.jsx(rv,{children:l.jsx(Dv,{children:l.jsxs(CI,{children:[l.jsx(cX,{}),l.jsx(Zf,{children:l.jsxs(Mf,{children:[l.jsx(a0,{path:"/",element:l.jsx(vK,{})}),l.jsx(a0,{path:"/spectate",element:l.jsx(SK,{})}),l.jsx(a0,{path:"/mini",element:l.jsx(FK,{})}),l.jsx(a0,{path:"/display",element:l.jsx(GK,{})}),l.jsx(a0,{path:"/scanner",element:l.jsx(tX,{})})]})})]})})})})})})); diff --git a/server/public/index.html b/server/public/index.html index 240cdbbf..95512a6d 100644 --- a/server/public/index.html +++ b/server/public/index.html @@ -11,7 +11,7 @@ Roomba Rover - + diff --git a/webui/src/scanner/ScannerApp/useScannerSpeech.js b/webui/src/scanner/ScannerApp/useScannerSpeech.js index 6de523d0..9db0b5d9 100644 --- a/webui/src/scanner/ScannerApp/useScannerSpeech.js +++ b/webui/src/scanner/ScannerApp/useScannerSpeech.js @@ -5,23 +5,31 @@ import { useEffect, useRef } from 'react'; const SPEECH_START_TIMEOUT_MS = 1500; const SPEECH_RETRY_DELAY_MS = 700; -const PREFERRED_VOICE_PATTERN = /female|samantha|victoria|zira|karen|moira|serena|ava|susan|hazel|google uk english female/i; +const PREFERRED_VOICE_PATTERN = /female|samantha|victoria|allison|zira|karen|moira|serena|ava|susan|hazel|google (us|uk) english/i; +const NOVELTY_VOICE_PATTERN = /whisper|bubbles|bells|boing|bad news|bahh|cellos|deranged|good news|hysterical|pipe organ|trinoids|zarvox/i; + +function isNoveltyVoice(voice) { + return NOVELTY_VOICE_PATTERN.test(String(voice?.name || '')); +} function pickScannerVoice(synth) { const voices = typeof synth?.getVoices === 'function' ? synth.getVoices() : []; if (!voices.length) return null; - const englishVoices = voices.filter((voice) => String(voice?.lang || '').toLowerCase().startsWith('en')); + const usableVoices = voices.filter((voice) => !isNoveltyVoice(voice)); + const defaultVoice = usableVoices.find((voice) => voice?.default) || null; + const englishVoices = usableVoices.filter((voice) => String(voice?.lang || '').toLowerCase().startsWith('en')); // Browser voice lists vary by operating system and installed speech packs, so // this is intentionally a preference rather than a requirement. A recognized // female-sounding English voice is best for the scanner speaker, but any - // English voice is better than failing to speak, and the browser default is - // the final fallback. + // normal/default voice is better than accidentally choosing a novelty voice + // like Whisper just because it appears early in the browser's voice list. return ( englishVoices.find((voice) => PREFERRED_VOICE_PATTERN.test(String(voice?.name || ''))) || - voices.find((voice) => PREFERRED_VOICE_PATTERN.test(String(voice?.name || ''))) || + usableVoices.find((voice) => PREFERRED_VOICE_PATTERN.test(String(voice?.name || ''))) || + defaultVoice || englishVoices[0] || - voices[0] || + usableVoices[0] || null ); } @@ -77,7 +85,7 @@ export default function useScannerSpeech(scan) { utterance.voice = preferredVoice; utterance.lang = preferredVoice.lang; } - utterance.rate = 0.92; + utterance.rate = 1; utterance.pitch = 1; utterance.volume = 1; utterance.onstart = () => {