const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/NeighborsMiniMap-DJtDAXli.js","assets/index-D_aPHvl1.js","assets/index-Cx5ENk0V.css","assets/leaflet-Kmmg5omM.js","assets/leaflet-Dgihpmma.css","assets/Popup-Sx9rYjUO.js"])))=>i.map(i=>d[i]); import{r as a,k as $,t as Z,j as e,I as oe,B,l as P,D as X,E as ue,F as me,_ as fe,G as xe,H as he,J as pe,R as ge,K as be,M as ve,N as ee,O as je,P as Ne}from"./index-D_aPHvl1.js";import{S as V}from"./separator-DL1oR9lA.js";const te=3,ye=2e3,we=20,H={loading:!1,attempt:0,error:null,fetched_at:null};function se(){return{status:{...H},nodeInfo:{...H},neighbors:{...H},acl:{...H},radioSettings:{...H},advertIntervals:{...H},ownerInfo:{...H},lppTelemetry:{...H}}}function re(){return{status:null,nodeInfo:null,neighbors:null,acl:null,radioSettings:null,advertIntervals:null,ownerInfo:null,lppTelemetry:null}}const z=new Map;function _e(t){switch(t){case"timeout":return"Login confirmation not heard";case"error":return"Login not confirmed";default:return"Repeater login not confirmed"}}function le(t){return{...t}}function ae(t){return{status:{...t.status,loading:!1},nodeInfo:{...t.nodeInfo,loading:!1},neighbors:{...t.neighbors,loading:!1},acl:{...t.acl,loading:!1},radioSettings:{...t.radioSettings,loading:!1},advertIntervals:{...t.advertIntervals,loading:!1},ownerInfo:{...t.ownerInfo,loading:!1},lppTelemetry:{...t.lppTelemetry,loading:!1}}}function ie(t){return t.map(s=>({...s}))}function Le(t){if(!t)return null;const s=z.get(t);return s?(z.delete(t),z.set(t,s),{loggedIn:s.loggedIn,loginError:s.loginError,paneData:le(s.paneData),paneStates:ae(s.paneStates),consoleHistory:ie(s.consoleHistory)}):null}function Re(t,s){if(z.delete(t),z.set(t,{loggedIn:s.loggedIn,loginError:s.loginError,paneData:le(s.paneData),paneStates:ae(s.paneStates),consoleHistory:ie(s.consoleHistory)}),z.size>we){const n=z.keys().next().value;n&&z.delete(n)}}function Se(t,s){switch(s){case"status":return $.repeaterStatus(t);case"nodeInfo":return $.repeaterNodeInfo(t);case"neighbors":return $.repeaterNeighbors(t);case"acl":return $.repeaterAcl(t);case"radioSettings":return $.repeaterRadioSettings(t);case"advertIntervals":return $.repeaterAdvertIntervals(t);case"ownerInfo":return $.repeaterOwnerInfo(t);case"lppTelemetry":return $.repeaterLppTelemetry(t)}}function ke(t,s={}){const n=t&&t.type==="contact"?t.id:null,r=Le(n),[o,l]=a.useState((r==null?void 0:r.loggedIn)??!1),[i,u]=a.useState(!1),[m,y]=a.useState((r==null?void 0:r.loginError)??null),[w,D]=a.useState((r==null?void 0:r.paneData)??re),[L,j]=a.useState((r==null?void 0:r.paneStates)??se),A=a.useRef((r==null?void 0:r.paneData)??re()),v=a.useRef((r==null?void 0:r.paneStates)??se()),[N,T]=a.useState((r==null?void 0:r.consoleHistory)??[]),[W,G]=a.useState(!1),c=a.useRef((t==null?void 0:t.id)??null),h=a.useRef(!0);a.useEffect(()=>{c.current=n},[n]),a.useEffect(()=>(h.current=!0,()=>{h.current=!1}),[]),a.useEffect(()=>{n&&Re(n,{loggedIn:o,loginError:m,paneData:w,paneStates:L,consoleHistory:N})},[N,n,o,m,w,L]),a.useEffect(()=>{A.current=w},[w]),a.useEffect(()=>{v.current=L},[L]);const p=a.useCallback(()=>!t||t.type!=="contact"?null:t.id,[t]),k=a.useCallback(async x=>{const S=p();if(!S)return;const _=S;u(!0),y(null);try{const d=await $.repeaterLogin(S,x);if(c.current!==_)return;if(l(!0),!d.authenticated){const g=d.message??"Repeater login was not confirmed";y(g),Z.error(_e(d.status),{description:g})}}catch(d){if(c.current!==_)return;const g=d instanceof Error?d.message:"Login failed";l(!0),y(g),Z.error("Login request failed",{description:`${g}. The dashboard is still available, but repeater operations may fail until a login succeeds.`})}finally{c.current===_&&u(!1)}},[p]),R=a.useCallback(async()=>{await k("")},[k]),I=a.useCallback(async x=>{const S=p();if(!S)return;const _=S;if(x==="neighbors"&&!s.hasAdvertLocation){const d=v.current.nodeInfo,g=A.current.nodeInfo;if((d.error!==null||d.fetched_at==null&&g==null)&&(await I("nodeInfo"),!h.current||c.current!==_))return}for(let d=1;d<=te;d++){if(!h.current||c.current!==_)return;const g={loading:!0,attempt:d,error:null,fetched_at:v.current[x].fetched_at??null};v.current={...v.current,[x]:g},j(C=>({...C,[x]:g}));try{const C=await Se(S,x);if(!h.current||c.current!==_)return;A.current={...A.current,[x]:C};const q={loading:!1,attempt:d,error:null,fetched_at:Date.now()};v.current={...v.current,[x]:q},D(E=>({...E,[x]:C})),j(E=>({...E,[x]:q}));return}catch(C){if(!h.current||c.current!==_)return;const q=C instanceof Error?C.message:"Request failed";if(d===te){const E={loading:!1,attempt:d,error:q,fetched_at:v.current[x].fetched_at??null};v.current={...v.current,[x]:E},j(de=>({...de,[x]:E})),Z.error(`Failed to fetch ${x}`,{description:q})}else await new Promise(E=>setTimeout(E,ye))}}},[p,s.hasAdvertLocation]),F=a.useCallback(async()=>{const x=["status","nodeInfo","neighbors","radioSettings","acl","advertIntervals","ownerInfo","lppTelemetry"];for(const S of x)await I(S)},[I]),b=a.useCallback(async x=>{const S=p();if(!S)return;const _=S,d=Math.floor(Date.now()/1e3);T(g=>[...g,{command:x,response:"",timestamp:d,outgoing:!0}]),G(!0);try{const g=await $.sendRepeaterCommand(S,x);if(c.current!==_)return;T(C=>[...C,{command:x,response:g.response,timestamp:g.sender_timestamp??d,outgoing:!1}])}catch(g){if(c.current!==_)return;const C=g instanceof Error?g.message:"Command failed";T(q=>[...q,{command:x,response:`Error: ${C}`,timestamp:d,outgoing:!1}])}finally{c.current===_&&G(!1)}},[p]),M=a.useCallback(async()=>{await b("advert.zerohop")},[b]),Y=a.useCallback(async()=>{await b("advert")},[b]),K=a.useCallback(async()=>{await b("reboot")},[b]),Q=a.useCallback(async()=>{const x=Math.floor(Date.now()/1e3);await b(`time ${x}`)},[b]);return{loggedIn:o,loginLoading:i,loginError:m,paneData:w,paneStates:L,consoleHistory:N,consoleLoading:W,login:k,loginAsGuest:R,refreshPane:I,loadAll:F,sendConsoleCommand:b,sendZeroHopAdvert:M,sendFloodAdvert:Y,rebootRepeater:K,syncClock:Q}}function Ce({repeaterName:t,loading:s,error:n,onLogin:r,onLoginAsGuest:o}){const[l,i]=a.useState(""),u=a.useCallback(async m=>{m.preventDefault(),!s&&await r(l.trim())},[l,s,r]);return e.jsx("div",{className:"flex-1 flex items-center justify-center p-4",children:e.jsxs("div",{className:"w-full max-w-sm space-y-6",children:[e.jsxs("div",{className:"text-center space-y-1",children:[e.jsx("h2",{className:"text-lg font-semibold",children:t}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Log in to access repeater dashboard"})]}),e.jsxs("form",{onSubmit:u,className:"space-y-4",autoComplete:"off",children:[e.jsx(oe,{type:"password",autoComplete:"off",name:"repeater-password","data-lpignore":"true","data-1p-ignore":"true","data-bwignore":"true",value:l,onChange:m=>i(m.target.value),placeholder:"Repeater password...","aria-label":"Repeater password",disabled:s,autoFocus:!0}),n&&e.jsx("p",{className:"text-sm text-destructive text-center",role:"alert",children:n}),e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx(B,{type:"submit",disabled:s,className:"w-full",children:s?"Logging in...":"Login with Password"}),e.jsx(B,{type:"button",variant:"outline",disabled:s,className:"w-full",onClick:o,children:"Login as Guest / ACLs"})]})]})]})})}function ce({className:t}){return e.jsx("svg",{className:t,fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"})})}function J(t){if(t<60)return`${t}s`;const s=Math.floor(t/86400),n=Math.floor(t%86400/3600),r=Math.floor(t%3600/60);return s>0?n>0&&r>0?`${s}d${n}h${r}m`:n>0?`${s}d${n}h`:r>0?`${s}d${r}m`:`${s}d`:n>0?r>0?`${n}h${r}m`:`${n}h`:`${r}m`}function De(t,s=Date.now()){let n;const r=t.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?\s*-\s*(\d{1,2})\/(\d{1,2})\/(\d{4})/);if(r){const[,w,D,L,j,A,v]=r;n=new Date(Date.UTC(+v,+A-1,+j,+w,+D,+(L??0)))}else n=new Date(t.replace(" ","T")+(t.includes("Z")||t.includes("UTC")?"":"Z"));if(isNaN(n.getTime()))return{text:"(invalid)",isLarge:!1};const o=Math.abs(s-n.getTime()),l=Math.floor(o/1e3);if(l>=86400)return{text:">24 hours!",isLarge:!0};const i=Math.floor(l/3600),u=Math.floor(l%3600/60),m=l%60,y=[];return i>0&&y.push(`${i}h`),u>0&&y.push(`${u}m`),y.push(`${m}s`),{text:y.join(""),isLarge:!1}}function ne(t){if(t==null)return"—";const s=t.trim();return s==="0"?"":`${s}h`}function Ie(t){const s=Math.max(0,Math.floor((Date.now()-t)/1e3));if(s<60)return"Just now";const n=Math.floor(s/60);if(n<60)return`${n} minute${n===1?"":"s"} ago`;const r=Math.floor(n/60);return`${r} hour${r===1?"":"s"} ago`}function Ae(t){return new Date(t).toLocaleTimeString([],{hour:"numeric",minute:"2-digit",second:"2-digit"})}function U({title:t,headerNote:s,state:n,onRefresh:r,disabled:o,children:l,className:i,contentClassName:u}){const m=n.fetched_at??null;return e.jsxs("div",{className:P("border border-border rounded-lg overflow-hidden",i),children:[e.jsxs("div",{className:"flex items-center justify-between px-3 py-2 bg-muted/50 border-b border-border",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("h3",{className:"text-sm font-medium",children:t}),s&&e.jsx("p",{className:"text-[11px] text-muted-foreground",children:s}),m&&e.jsxs("p",{className:"text-[11px] text-muted-foreground",title:new Date(m).toLocaleString(),children:["Fetched ",Ae(m)," (",Ie(m),")"]})]}),r&&e.jsx("button",{type:"button",onClick:r,disabled:o||n.loading,className:P("p-1 rounded transition-colors disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",o||n.loading?"text-muted-foreground":"text-success hover:bg-accent hover:text-success"),title:"Refresh","aria-label":`Refresh ${t}`,children:e.jsx(ce,{className:P("w-3.5 h-3.5",n.loading&&"animate-spin [animation-direction:reverse]")})})]}),n.error&&e.jsx("div",{className:"px-3 py-1.5 text-xs text-destructive bg-destructive/5 border-b border-border",children:n.error}),e.jsx("div",{className:P("p-3",u),children:n.loading?e.jsxs("p",{className:"text-sm text-muted-foreground italic",children:["Fetching",n.attempt>1?` (attempt ${n.attempt}/3)`:"","..."]}):l})]})}function O(){return e.jsx("p",{className:"text-sm text-muted-foreground italic",children:""})}function f({label:t,value:s}){return e.jsxs("div",{className:"flex justify-between items-center text-sm py-0.5",children:[e.jsx("span",{className:"text-muted-foreground",children:t}),e.jsx("span",{className:"font-medium text-right",children:s})]})}const $e={temperature:"°C",humidity:"%",barometer:"hPa",voltage:"V",current:"mA",luminosity:"lux",altitude:"m",power:"W",distance:"mm",energy:"kWh",direction:"°",concentration:"ppm",colour:""};function Te(t){return t.charAt(0).toUpperCase()+t.slice(1).replace(/_/g," ")}function Pe({sensor:t}){const s=Te(t.type_name);if(typeof t.value=="object"&&t.value!==null)return e.jsxs("div",{className:"py-0.5",children:[e.jsx("span",{className:"text-sm text-muted-foreground",children:s}),e.jsx("div",{className:"pl-3",children:Object.entries(t.value).map(([o,l])=>e.jsx(f,{label:o.charAt(0).toUpperCase()+o.slice(1),value:typeof l=="number"?l.toFixed(2):String(l)},o))})]});const n=$e[t.type_name]??"",r=typeof t.value=="number"?`${t.value%1===0?t.value:t.value.toFixed(2)}${n?` ${n}`:""}`:String(t.value);return e.jsx(f,{label:s,value:r})}function Fe({data:t,state:s,onRefresh:n,disabled:r}){return e.jsx(U,{title:"Telemetry",state:s,onRefresh:n,disabled:r,children:t?e.jsxs("div",{className:"space-y-2",children:[e.jsx(f,{label:"Battery",value:`${t.battery_volts.toFixed(3)}V`}),e.jsx(f,{label:"Uptime",value:J(t.uptime_seconds)}),e.jsx(f,{label:"TX Airtime",value:J(t.airtime_seconds)}),e.jsx(f,{label:"RX Airtime",value:J(t.rx_airtime_seconds)}),e.jsx(V,{className:"my-1"}),e.jsx(f,{label:"Noise Floor",value:`${t.noise_floor_dbm} dBm`}),e.jsx(f,{label:"Last RSSI",value:`${t.last_rssi_dbm} dBm`}),e.jsx(f,{label:"Last SNR",value:`${t.last_snr_db.toFixed(1)} dB`}),e.jsx(V,{className:"my-1"}),e.jsx(f,{label:"Packets",value:`${t.packets_received.toLocaleString()} rx / ${t.packets_sent.toLocaleString()} tx`}),e.jsx(f,{label:"Flood",value:`${t.recv_flood.toLocaleString()} rx / ${t.sent_flood.toLocaleString()} tx`}),e.jsx(f,{label:"Direct",value:`${t.recv_direct.toLocaleString()} rx / ${t.sent_direct.toLocaleString()} tx`}),e.jsx(f,{label:"Duplicates",value:`${t.flood_dups.toLocaleString()} flood / ${t.direct_dups.toLocaleString()} direct`}),e.jsx(V,{className:"my-1"}),e.jsx(f,{label:"TX Queue",value:t.tx_queue_len}),e.jsx(f,{label:"Debug Flags",value:t.full_events})]}):e.jsx(O,{})})}const Me=a.lazy(()=>fe(()=>import("./NeighborsMiniMap-DJtDAXli.js"),__vite__mapDeps([0,1,2,3,4,5])).then(t=>({default:t.NeighborsMiniMap})));function Ee({data:t,state:s,onRefresh:n,disabled:r,repeaterContact:o,contacts:l,nodeInfo:i,nodeInfoState:u,repeaterName:m}){const y=(o==null?void 0:o.lat)??null,w=(o==null?void 0:o.lon)??null,D=a.useMemo(()=>{const c=(i==null?void 0:i.lat)!=null?parseFloat(i.lat):null;return Number.isFinite(c)?c:null},[i==null?void 0:i.lat]),L=a.useMemo(()=>{const c=(i==null?void 0:i.lon)!=null?parseFloat(i.lon):null;return Number.isFinite(c)?c:null},[i==null?void 0:i.lon]),j=a.useMemo(()=>X(D,L)?{lat:D,lon:L,source:"reported"}:X(y,w)?{lat:y,lon:w,source:"advert"}:{lat:null,lon:null,source:null},[y,w,D,L]),A=(i==null?void 0:i.name)||(o==null?void 0:o.name)||m,v=j.source!==null,N=j.source==="reported"?"Using repeater-reported position":j.source==="advert"?"Using advert position":u.loading?"Waiting for repeater position":"No repeater position available",{neighborsWithCoords:T,sorted:W,hasDistances:G}=a.useMemo(()=>{if(!t)return{neighborsWithCoords:[],sorted:[],hasDistances:!1};const c=[],h=[];let p=!1;for(const k of t.neighbors){const R=l.find(M=>M.public_key.startsWith(k.pubkey_prefix)),I=(R==null?void 0:R.lat)??null,F=(R==null?void 0:R.lon)??null;let b=null;if(v&&X(I,F)){const M=ue(j.lat,j.lon,I,F);M!=null&&(b=me(M),p=!0)}h.push({...k,distance:b}),X(I,F)&&c.push({...k,lat:I,lon:F})}return h.sort((k,R)=>R.snr-k.snr),{neighborsWithCoords:c,sorted:h,hasDistances:p}},[l,t,v,j.lat,j.lon]);return e.jsx(U,{title:"Neighbors",headerNote:N,state:s,onRefresh:n,disabled:r,className:"flex min-h-0 flex-1 flex-col",contentClassName:"flex min-h-0 flex-1 flex-col",children:t?W.length===0?e.jsx("p",{className:"text-sm text-muted-foreground",children:"No neighbors reported"}):e.jsxs("div",{className:"flex min-h-0 flex-1 flex-col gap-2",children:[e.jsx("div",{className:"shrink-0 overflow-x-auto",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"text-left text-muted-foreground text-xs",children:[e.jsx("th",{className:"pb-1 font-medium",children:"Name"}),e.jsx("th",{className:"pb-1 font-medium text-right",children:"SNR"}),G&&e.jsx("th",{className:"pb-1 font-medium text-right",children:"Dist"}),e.jsx("th",{className:"pb-1 font-medium text-right",children:"Last Heard"})]})}),e.jsx("tbody",{children:W.map((c,h)=>{const p=c.distance,k=c.snr>=0?`+${c.snr.toFixed(1)}`:c.snr.toFixed(1),R=c.snr>=6?"text-success":c.snr>=0?"text-warning":"text-destructive";return e.jsxs("tr",{className:"border-t border-border/50",children:[e.jsx("td",{className:"py-1",children:c.name||c.pubkey_prefix}),e.jsxs("td",{className:P("py-1 text-right font-mono",R),children:[k," dB"]}),G&&e.jsx("td",{className:"py-1 text-right text-muted-foreground font-mono",children:p??"—"}),e.jsxs("td",{className:"py-1 text-right text-muted-foreground",children:[J(c.last_heard_seconds)," ago"]})]},h)})})]})}),v&&(T.length>0||v)?e.jsx(a.Suspense,{fallback:e.jsx("div",{className:"flex min-h-48 flex-1 items-center justify-center text-xs text-muted-foreground",children:"Loading map..."}),children:e.jsx(Me,{neighbors:T,radioLat:j.lat,radioLon:j.lon,radioName:A},T.map(c=>c.pubkey_prefix).join(","))}):e.jsx("div",{className:"rounded border border-border/70 bg-muted/20 px-3 py-2 text-xs text-muted-foreground",children:"Map and distance data are unavailable until this repeater has a valid position from either its advert or a Node Info fetch."})]}):e.jsx(O,{})})}function He({data:t,state:s,onRefresh:n,disabled:r}){const o={0:"bg-muted text-muted-foreground",1:"bg-info/10 text-info",2:"bg-success/10 text-success",3:"bg-warning/10 text-warning"};return e.jsx(U,{title:"ACL",state:s,onRefresh:n,disabled:r,children:t?t.acl.length===0?e.jsx("p",{className:"text-sm text-muted-foreground",children:"No ACL entries"}):e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"text-left text-muted-foreground text-xs",children:[e.jsx("th",{className:"pb-1 font-medium",children:"Name"}),e.jsx("th",{className:"pb-1 font-medium text-right",children:"Permission"})]})}),e.jsx("tbody",{children:t.acl.map((l,i)=>e.jsxs("tr",{className:"border-t border-border/50",children:[e.jsx("td",{className:"py-1",children:l.name||l.pubkey_prefix}),e.jsx("td",{className:"py-1 text-right",children:e.jsx("span",{className:P("text-xs px-1.5 py-0.5 rounded",o[l.permission]??"bg-muted text-muted-foreground"),children:l.permission_name})})]},i))})]}):e.jsx(O,{})})}function ze({data:t,state:s,onRefresh:n,disabled:r}){const o=a.useMemo(()=>t!=null&&t.clock_utc?De(t.clock_utc,s.fetched_at??void 0):null,[t==null?void 0:t.clock_utc,s.fetched_at]);return e.jsx(U,{title:"Node Info",state:s,onRefresh:n,disabled:r,children:t?e.jsxs("div",{children:[e.jsx(f,{label:"Name",value:t.name??"—"}),e.jsx(f,{label:"Lat / Lon",value:t.lat!=null||t.lon!=null?`${t.lat??"—"}, ${t.lon??"—"}`:"—"}),e.jsxs("div",{className:"flex justify-between text-sm py-0.5",children:[e.jsx("span",{className:"text-muted-foreground",children:"Clock (UTC)"}),e.jsxs("span",{children:[t.clock_utc??"—",o&&e.jsxs("span",{className:P("ml-2 text-xs",o.isLarge?"text-destructive":"text-muted-foreground"),children:["(drift: ",o.text,")"]})]})]})]}):e.jsx(O,{})})}function Be(t){if(t==null)return{display:"—",raw:null};const s=t.trim(),n=s.split(",").map(j=>j.trim());if(n.length!==4)return{display:s||"—",raw:s||null};const[r,o,l,i]=n,u=Number.parseFloat(r),m=Number.parseFloat(o),y=Number.parseInt(l,10),w=Number.parseInt(i,10);if(![u,m,y,w].every(Number.isFinite))return{display:s||"—",raw:s||null};const D=Number(u.toFixed(3)).toString(),L=Number(m.toFixed(3)).toString();return{display:`${D} MHz, BW ${L} kHz, SF${y}, CR${w}`,raw:s}}function Oe({data:t,state:s,onRefresh:n,disabled:r,advertData:o,advertState:l,onRefreshAdvert:i}){const u=Be((t==null?void 0:t.radio)??null);return e.jsxs(U,{title:"Radio Settings",state:s,onRefresh:n,disabled:r,children:[t?e.jsxs("div",{children:[e.jsx(f,{label:"Firmware",value:t.firmware_version??"—"}),e.jsx(f,{label:"Radio",value:e.jsx("span",{title:u.raw??void 0,children:u.display})}),e.jsx(f,{label:"TX Power",value:t.tx_power!=null?`${t.tx_power} dBm`:"—"}),e.jsx(f,{label:"Airtime Factor",value:t.airtime_factor??"—"}),e.jsx(f,{label:"Repeat Mode",value:t.repeat_enabled??"—"}),e.jsx(f,{label:"Max Flood Hops",value:t.flood_max??"—"})]}):e.jsx(O,{}),e.jsx(V,{className:"my-2"}),e.jsxs("div",{className:"flex items-center justify-between mb-1",children:[e.jsx("span",{className:"text-xs font-medium text-muted-foreground",children:"Advert Intervals"}),e.jsx("button",{type:"button",onClick:i,disabled:r||l.loading,className:P("p-1 rounded transition-colors disabled:opacity-50",r||l.loading?"text-muted-foreground":"text-success hover:bg-accent hover:text-success"),title:"Refresh Advert Intervals","aria-label":"Refresh Advert Intervals",children:e.jsx(ce,{className:P("w-3 h-3",l.loading&&"animate-spin [animation-direction:reverse]")})})]}),l.error&&e.jsx("p",{className:"text-xs text-destructive mb-1",children:l.error}),l.loading?e.jsxs("p",{className:"text-sm text-muted-foreground italic",children:["Fetching",l.attempt>1?` (attempt ${l.attempt}/3)`:"","..."]}):o?e.jsxs("div",{children:[e.jsx(f,{label:"Local Advert",value:ne(o.advert_interval)}),e.jsx(f,{label:"Flood Advert",value:ne(o.flood_advert_interval)})]}):e.jsx(O,{})]})}function We({data:t,state:s,onRefresh:n,disabled:r}){return e.jsx(U,{title:"LPP Sensors",state:s,onRefresh:n,disabled:r,children:t?t.sensors.length===0?e.jsx("p",{className:"text-sm text-muted-foreground",children:"No sensor data available"}):e.jsx("div",{className:"space-y-0.5",children:t.sensors.map((o,l)=>e.jsx(Pe,{sensor:o},l))}):e.jsx(O,{})})}function Ge({data:t,state:s,onRefresh:n,disabled:r}){return e.jsx(U,{title:"Owner Info",state:s,onRefresh:n,disabled:r,children:t?e.jsxs("div",{className:"break-all",children:[e.jsx(f,{label:"Owner Info",value:t.owner_info??"—"}),e.jsx(f,{label:"Guest Password",value:t.guest_password??"—"})]}):e.jsx(O,{})})}function qe({onSendZeroHopAdvert:t,onSendFloodAdvert:s,onSyncClock:n,onReboot:r,consoleLoading:o}){const[l,i]=a.useState(!1),u=a.useCallback(()=>{if(!l){i(!0);return}i(!1),r()},[l,r]);return a.useEffect(()=>{if(!l)return;const m=setTimeout(()=>i(!1),3e3);return()=>clearTimeout(m)},[l]),e.jsxs("div",{className:"border border-border rounded-lg overflow-hidden",children:[e.jsx("div",{className:"px-3 py-2 bg-muted/50 border-b border-border",children:e.jsx("h3",{className:"text-sm font-medium",children:"Actions"})}),e.jsxs("div",{className:"p-3 flex flex-wrap gap-2",children:[e.jsx(B,{variant:"outline",size:"sm",onClick:t,disabled:o,children:"Zero Hop Advert"}),e.jsx(B,{variant:"destructive",size:"sm",onClick:s,disabled:o,children:"Flood Advert"}),e.jsx(B,{variant:"outline",size:"sm",onClick:n,disabled:o,children:"Sync Clock"}),e.jsx(B,{variant:l?"destructive":"outline",size:"sm",onClick:u,disabled:o,children:l?"Confirm Reboot":"Reboot"})]})]})}function Ue({history:t,loading:s,onSend:n}){const[r,o]=a.useState(""),l=a.useRef(null);a.useEffect(()=>{l.current&&(l.current.scrollTop=l.current.scrollHeight)},[t]);const i=a.useCallback(async u=>{u.preventDefault();const m=r.trim();!m||s||(o(""),await n(m))},[r,s,n]);return e.jsxs("div",{className:"border border-border rounded-lg overflow-hidden col-span-full",children:[e.jsx("div",{className:"px-3 py-2 bg-muted/50 border-b border-border",children:e.jsx("h3",{className:"text-sm font-medium",children:"Console"})}),e.jsxs("div",{ref:l,className:"h-48 overflow-y-auto p-3 font-mono text-xs bg-console-bg/50 text-console space-y-1",children:[t.length===0&&e.jsx("p",{className:"text-muted-foreground italic",children:"Type a CLI command below..."}),t.map((u,m)=>u.outgoing?e.jsxs("div",{className:"text-console-command",children:["> ",u.command]},m):e.jsx("div",{className:"text-console/80 whitespace-pre-wrap",children:u.response},m)),s&&e.jsx("div",{className:"text-muted-foreground animate-pulse",children:"..."})]}),e.jsxs("form",{onSubmit:i,className:"flex gap-2 p-2 border-t border-border",children:[e.jsx(oe,{type:"text",autoComplete:"off",name:"console-input",value:r,onChange:u=>o(u.target.value),placeholder:"CLI command...","aria-label":"Console command",disabled:s,className:"flex-1 font-mono text-sm"}),e.jsx(B,{type:"submit",size:"sm",disabled:s||!r.trim(),children:"Send"})]})]})}function Ve({conversation:t,contacts:s,favorites:n,notificationsSupported:r,notificationsEnabled:o,notificationsPermission:l,radioLat:i,radioLon:u,radioName:m,onTrace:y,onPathDiscovery:w,onToggleNotifications:D,onToggleFavorite:L,onDeleteContact:j}){const[A,v]=a.useState(!1),N=s.find(g=>g.public_key===t.id)??null,T=X((N==null?void 0:N.lat)??null,(N==null?void 0:N.lon)??null),{loggedIn:W,loginLoading:G,loginError:c,paneData:h,paneStates:p,consoleHistory:k,consoleLoading:R,login:I,loginAsGuest:F,refreshPane:b,loadAll:M,sendConsoleCommand:Y,sendZeroHopAdvert:K,sendFloodAdvert:Q,rebootRepeater:x,syncClock:S}=ke(t,{hasAdvertLocation:T}),_=xe(n,"contact",t.id),d=Object.values(p).some(g=>g.loading);return e.jsxs("div",{className:"flex-1 flex flex-col min-h-0",children:[e.jsxs("header",{className:"flex justify-between items-start px-4 py-2.5 border-b border-border gap-2",children:[e.jsx("span",{className:"flex min-w-0 flex-1 flex-col",children:e.jsxs("span",{className:"flex min-w-0 flex-wrap items-baseline gap-x-2 gap-y-0.5",children:[e.jsxs("span",{className:"flex min-w-0 flex-1 items-baseline gap-2",children:[e.jsx("span",{className:"min-w-0 flex-shrink truncate font-semibold text-base",children:t.name}),e.jsx("span",{className:"min-w-0 flex-1 truncate font-mono text-[11px] text-muted-foreground transition-colors hover:text-primary",role:"button",tabIndex:0,onKeyDown:he,onClick:()=>{navigator.clipboard.writeText(t.id),Z.success("Contact key copied!")},title:"Click to copy",children:t.id})]}),N&&e.jsx("span",{className:"min-w-0 flex-none text-[11px] text-muted-foreground max-sm:basis-full",children:e.jsx(pe,{contact:N,ourLat:i,ourLon:u})})]})}),e.jsxs("div",{className:"flex items-center gap-0.5 flex-shrink-0",children:[W&&e.jsx(B,{variant:"outline",size:"sm",onClick:M,disabled:d,className:"h-7 px-2 text-[11px] leading-none border-success text-success hover:bg-success/10 hover:text-success sm:h-8 sm:px-3 sm:text-xs",children:d?"Loading...":"Load All"}),N&&e.jsx("button",{className:"p-1 rounded hover:bg-accent text-lg leading-none transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",onClick:()=>v(!0),title:"Path Discovery. Send a routed probe and inspect the forward and return paths","aria-label":"Path Discovery",children:e.jsx(ge,{className:"h-4 w-4 text-muted-foreground","aria-hidden":"true"})}),e.jsx("button",{className:"p-1 rounded hover:bg-accent text-lg leading-none transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",onClick:y,title:"Direct Trace","aria-label":"Direct Trace",children:e.jsx(be,{className:"h-4 w-4 text-muted-foreground"})}),r&&e.jsxs("button",{className:"flex items-center gap-1 rounded px-1 py-1 hover:bg-accent text-lg leading-none transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",onClick:D,title:o?"Disable desktop notifications for this conversation":l==="denied"?"Notifications blocked by the browser":"Enable desktop notifications for this conversation","aria-label":o?"Disable notifications for this conversation":"Enable notifications for this conversation",children:[e.jsx(ve,{className:`h-4 w-4 ${o?"text-status-connected":"text-muted-foreground"}`,fill:o?"currentColor":"none","aria-hidden":"true"}),o&&e.jsx("span",{className:"hidden md:inline text-[11px] font-medium text-status-connected",children:"Notifications On"})]}),e.jsx("button",{className:"p-1 rounded hover:bg-accent text-lg leading-none transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",onClick:()=>L("contact",t.id),title:_?"Remove from favorites. Favorite contacts stay loaded on the radio for ACK support.":"Add to favorites. Favorite contacts stay loaded on the radio for ACK support.","aria-label":_?"Remove from favorites":"Add to favorites",children:_?e.jsx(ee,{className:"h-4 w-4 fill-current text-favorite","aria-hidden":"true"}):e.jsx(ee,{className:"h-4 w-4 text-muted-foreground","aria-hidden":"true"})}),e.jsx("button",{className:"p-1 rounded hover:bg-destructive/10 text-muted-foreground hover:text-destructive text-lg leading-none transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",onClick:()=>j(t.id),title:"Delete","aria-label":"Delete",children:e.jsx(je,{className:"h-4 w-4","aria-hidden":"true"})})]}),N&&e.jsx(Ne,{open:A,onClose:()=>v(!1),contact:N,contacts:s,radioName:m,onDiscover:w})]}),e.jsx("div",{className:"flex-1 overflow-y-auto p-4",children:W?e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"grid grid-cols-1 gap-4 md:grid-cols-2 md:items-stretch",children:[e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsx(ze,{data:h.nodeInfo,state:p.nodeInfo,onRefresh:()=>b("nodeInfo"),disabled:d}),e.jsx(Fe,{data:h.status,state:p.status,onRefresh:()=>b("status"),disabled:d}),e.jsx(Oe,{data:h.radioSettings,state:p.radioSettings,onRefresh:()=>b("radioSettings"),disabled:d,advertData:h.advertIntervals,advertState:p.advertIntervals,onRefreshAdvert:()=>b("advertIntervals")}),e.jsx(We,{data:h.lppTelemetry,state:p.lppTelemetry,onRefresh:()=>b("lppTelemetry"),disabled:d})]}),e.jsx("div",{className:"flex min-h-0 flex-col gap-4",children:e.jsx(Ee,{data:h.neighbors,state:p.neighbors,onRefresh:()=>b("neighbors"),disabled:d,repeaterContact:N,contacts:s,nodeInfo:h.nodeInfo,nodeInfoState:p.nodeInfo,repeaterName:t.name})})]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[e.jsx(He,{data:h.acl,state:p.acl,onRefresh:()=>b("acl"),disabled:d}),e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsx(Ge,{data:h.ownerInfo,state:p.ownerInfo,onRefresh:()=>b("ownerInfo"),disabled:d}),e.jsx(qe,{onSendZeroHopAdvert:K,onSendFloodAdvert:Q,onSyncClock:S,onReboot:x,consoleLoading:R})]})]}),e.jsx(Ue,{history:k,loading:R,onSend:Y})]}):e.jsx(Ce,{repeaterName:t.name,loading:G,error:c,onLogin:I,onLoginAsGuest:F})})]})}export{Ve as RepeaterDashboard,De as formatClockDrift,J as formatDuration}; //# sourceMappingURL=RepeaterDashboard-BVkivKK9.js.map