mirror of
https://github.com/dmduran12/pymc_console-dist.git
synced 2026-03-28 17:43:04 +01:00
2 lines
53 KiB
JavaScript
2 lines
53 KiB
JavaScript
import{r as e,j as s}from"./vendor-react-alRNW2nb.js";import{u as t,U as a,S as n,c as l,d as i,e as o,f as r,h as c,j as d,k as m,m as u,n as x,o as h,p as f,q as p,T as g,L as b,B as j,r as v,t as y,v as N,D as w,w as k,x as M,y as C,z as S,A as L,E as T,F as B,G as F,H as _,J as R,K as D,M as $,N as H,O as P,P as A,Q as I,R as z,V as E,W,X as q,Y as O,_ as G,$ as V,a0 as U,a1 as J,a2 as K}from"./index-CkRTgHHA.js";import{C as X,P as Q,a as Y,B as Z}from"./PageLayout-BWMUVZgC.js";import{u as ee,r as se,h as te,a as ae,b as ne,i as le}from"./consumer-registry-BUFl6buY.js";import{A as ie,m as oe}from"./vendor-motion-DNp0Qg4F.js";import{c as re,d as ce,q as de,a as me,o as ue,L as xe,r as he,s as fe,A as pe,R as ge,t as be,u as je,v as ve,w as ye,x as Ne,y as we,z as ke,Z as Me,g as Ce,B as Se,D as Le,C as Te,H as Be,J as Fe,K as _e,N as Re,O as De,Q as $e}from"./vendor-icons-TO0PZKGR.js";import{u as He}from"./vendor-charts-C916_-gs.js";import{A as Pe}from"./AnimatedNumber-DACuG-ay.js";import{c as Ae}from"./node-types-DRVunROD.js";import{b as Ie,c as ze,a as Ee,d as We,F as qe}from"./meshcore-tx-constants-BDLT5LMb.js";import{u as Oe,P as Ge,C as Ve}from"./PacketList-BJFBF77t.js";import{u as Ue,a as Je}from"./usePipelineStore-CLEA3Bev.js";import{T as Ke}from"./TimeRangeStepper-CsLZzi5t.js";import{L as Xe}from"./LightSparkline-BAD3v4m9.js";import{c as Qe}from"./link-scoring-C0BjaK96.js";import{b as Ye,c as Ze}from"./vendor-core-FtpmsTnh.js";import{N as es}from"./NodeInformationCard-tOZNdmfP.js";import{g as ss,e as ts,a as as,f as ns}from"./chat-utils-mqGCinix.js";import{C as ls}from"./ChatBubble-OmHlf-X1.js";import{R as is,C as os}from"./Grid-m53vqd2Y.js";import"./vendor-virt-BytWoLhu.js";import"./cosmograph-DqYT4sUA.js";import"./vendor-fonts-CRZaZSFf.js";import"./primitives-Bgn6Ik6L.js";import"./payload-decoders-_TRhCJrs.js";import"./badge-colors-BxLppqaF.js";import"./SignalIndicator-Bdj3-1hL.js";import"./DataBox-DpDXI-WX.js";import"./useMapViewStore-sFZdb1_p.js";import"./geo-utils-DJn8DnxF.js";const rs=[{target:"ReceivedChart",fn:"type",minStage:1},{target:"ReceivedChart",fn:"airtime",minStage:1,when:te}];function cs({packets:l,rangeMinutes:i,bucketCount:o}){ee(rs);const r=t(),[c,d]=e.useState(null),[m,u]=e.useState(null),[x,h]=e.useState(null),{buckets:f,activeTypes:p,totalByType:g}=e.useMemo(()=>function(e,s,t){const a=Date.now()/1e3,n=60*s,l=a-n,i=n/t,o=[];for(let c=0;c<t;c++)o.push({start:l+c*i,end:l+(c+1)*i,bytesByType:{},totalBytes:0});const r={};for(const c of e){if(c.transmitted)continue;const e=c.timestamp;if(e<l||e>a)continue;const s=Math.min(t-1,Math.floor((e-l)/i)),n=c.type??c.payload_type??0,d=c.length??c.payload_length??0,m=o[s];m.bytesByType[n]=(m.bytesByType[n]??0)+d,m.totalBytes+=d,r[n]=(r[n]??0)+d}return{buckets:o,activeTypes:Object.keys(r).map(e=>parseInt(e,10)).filter(e=>r[e]>0).sort((e,s)=>r[s]-r[e]),totalByType:r}}(l,i,o),[l,i,o]),b=e.useCallback((e,s,t)=>{d(s),u(t)},[]),j=f.length>0&&p.length>0,v=c?function(e){const s=new Date(1e3*e).getHours();return s>=6&&s<18}(c.start):null,y=c?(N=c.start,new Date(1e3*N).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",hour12:!1})):"";var N;const w=null!==x&&null!==v&&x!==v;return v!==x&&h(v),s.jsxs("div",{className:"flex flex-col h-full relative",children:[s.jsx("div",{className:"h-5 relative mb-1 shrink-0",children:c&&null!==m&&s.jsxs("div",{className:"absolute flex items-center gap-1.5 type-data-sm -translate-x-1/2",style:{left:`calc(48px + ${100*m}% * (1 - 48px / 100%))`},children:[s.jsx(ie,{mode:"wait",children:s.jsx(oe.span,{initial:!!w&&{opacity:0,scale:.5,rotate:-90},animate:{opacity:1,scale:1,rotate:0},exit:{opacity:0,scale:.5,rotate:90},transition:{duration:.25,ease:"easeOut"},children:v?s.jsx(re,{className:"w-4 h-4 text-sys-amber"}):s.jsx(ce,{className:"w-4 h-4 text-sys-blue"})},v?"sun":"moon")}),s.jsx("span",{className:"text-fg-secondary",children:y})]})}),s.jsx("div",{className:"flex-1 min-h-0",children:j&&s.jsx(a,{buckets:f,activeTypes:p,gridColor:r.grid,axisTickColor:r.axisTick,onHover:b})}),s.jsx("div",{className:"pt-2 px-1 pb-2 shrink-0",children:j&&s.jsx(n,{activeTypes:p,totalByType:g})})]})}se(rs);const ds=e.memo(function({buckets:t,activeTypes:a}){const n=e.useRef(null),o=e.useRef(t),r=e.useRef(a);o.current=t,r.current=a;const c=e.useMemo(()=>[t.map(e=>e.start),t.map(()=>1)],[t]);return e.useEffect(()=>{if(!n.current||0===t.length)return;const e=n.current,s=e.getBoundingClientRect(),a=Math.floor(s.width)||200,d=Math.floor(s.height)||60,m=new He({width:a,height:d,padding:[0,0,0,0],cursor:{show:!1},scales:{x:{time:!1},y:{range:[0,1]}},axes:[{show:!1},{show:!1}],series:[{},{show:!1}],legend:{show:!1},hooks:{draw:[e=>{const s=e.ctx,{left:t,top:a,width:n,height:c}=e.bbox;!function(e,s,t,a,n,o,r){if(0===s.length)return;const c=function(e,s,t){var a,n;if(e.length<=t)return e;const l=e.length/t,i=[];for(let o=0;o<t;o++){const t=Math.floor(o*l),r=Math.floor((o+1)*l),c=e.slice(t,r),d={start:(null==(a=c[0])?void 0:a.start)??0,end:(null==(n=c.at(-1))?void 0:n.end)??0,bytesByType:{},totalBytes:0};for(const e of c){d.totalBytes+=e.totalBytes;for(const t of s){const s=e.bytesByType[t]??0;s>0&&(d.bytesByType[t]=(d.bytesByType[t]??0)+s)}}i.push(d)}return i}(s,t,i.statsCard),d=c.length,m=o/d,u=c.map(e=>e.totalBytes),x=Math.max(...u);if(0!==x){for(let s=0;s<d;s++){const i=c[s],o=a+s*m,d=i.totalBytes;if(0===d)continue;const u=d/x*r;let h=n+r-u+u;for(const s of t){const t=i.bytesByType[s]??0;if(0===t)continue;const a=t/d*u,n=h-a;e.fillStyle=l(s),e.globalAlpha=.85,e.fillRect(o,n,m,a),h=n}}e.globalAlpha=1}}(s,o.current,r.current,t,a,n,c)}]}},c,e),u=new ResizeObserver(()=>{const s=e.getBoundingClientRect();s.width>0&&s.height>0&&m.setSize({width:Math.floor(s.width),height:Math.floor(s.height)})});return u.observe(e),()=>{u.disconnect(),m.destroy()}},[c,t.length]),0===t.length?s.jsx("div",{className:"h-full flex items-center justify-center",children:s.jsx("div",{className:"w-full h-0.5 rounded-full bg-fg-muted/15"})}):s.jsx("div",{ref:n,className:"w-full h-full"})}),ms=[{target:"ForwardedCard",fn:"type",minStage:1}];function us({value:t,receivedCount:a,packets:n,rangeMinutes:l,bucketCount:i,timeRangeLabel:d,icon:m,isLoaded:u=!0}){ee(ms);const{buckets:x,activeTypes:h,ratePerHour:f}=e.useMemo(()=>function(e,s,t){const a=Date.now()/1e3,n=60*s,l=a-n,i=n/t,o=[];for(let m=0;m<t;m++)o.push({start:l+m*i,end:l+(m+1)*i,bytesByType:{},totalBytes:0});const r={};let c=0;for(const m of e){if(!("tx_forward"===m.packet_origin||m.transmitted&&"tx_local"!==m.packet_origin))continue;const e=m.timestamp;if(e<l||e>a)continue;const s=Math.min(t-1,Math.floor((e-l)/i)),n=m.type??m.payload_type??0,d=m.length??m.payload_length??0,u=o[s];u.bytesByType[n]=(u.bytesByType[n]??0)+d,u.totalBytes+=d,r[n]=(r[n]??0)+d,c++}const d=s/60;return{buckets:o,activeTypes:Object.keys(r).map(e=>parseInt(e,10)).filter(e=>r[e]>0).sort((e,s)=>r[s]-r[e]),ratePerHour:d>0?Math.round(c/d):0}}(n,l,i),[n,l,i]),p=a>0?(t/a*100).toFixed(1):null;return u?s.jsxs(o,{children:[s.jsxs("div",{className:"flex items-center gap-1.5 sm:gap-2 mb-2 sm:mb-3",children:[m&&s.jsx("span",{className:"icon-sm text-icon-card-title",children:m}),s.jsx("span",{className:"type-micro",children:"FORWARDED"}),d&&s.jsx(c,{color:"zinc",className:"hidden sm:inline-flex",children:d})]}),s.jsx("div",{className:"type-data-xl text-fg-primary",children:s.jsx(Pe,{value:t,className:"font-mono tabular-nums",priority:"high"})}),s.jsx("div",{className:"flex-1 mt-1 overflow-hidden min-h-[40px] sm:min-h-[60px]",children:h.length>0?s.jsx(ds,{buckets:x,activeTypes:h}):s.jsx("div",{className:"w-full h-full flex items-center justify-center",children:s.jsx("div",{className:"w-full h-0.5 rounded-full bg-fg-muted/15"})})}),s.jsx("div",{className:"pt-1.5 sm:pt-2 mt-1",children:s.jsxs("div",{className:"flex gap-2 sm:gap-3",children:[s.jsxs("div",{className:"flex-1 min-w-0",children:[s.jsx("div",{className:"data-box-label",children:"Rate"}),s.jsxs("div",{className:"data-box data-box-fill data-box-left",children:[f,"/hr"]})]}),null!==p&&s.jsxs("div",{className:"flex-1 min-w-0",children:[s.jsx("div",{className:"data-box-label",children:"Ratio"}),s.jsxs("div",{className:"data-box data-box-fill data-box-left",children:[p,"%"]})]})]})})]}):s.jsx(o,{children:s.jsx(r,{})})}se(ms);const xs=[{target:"DroppedCard",fn:"type",minStage:1}];function hs({value:t,receivedCount:a,packets:n,rangeMinutes:l,bucketCount:i,timeRangeLabel:d,icon:m,isLoaded:u=!0}){ee(xs);const{buckets:x,activeTypes:h,ratePerHour:f}=e.useMemo(()=>function(e,s,t){const a=Date.now()/1e3,n=60*s,l=a-n,i=n/t,o=[];for(let m=0;m<t;m++)o.push({start:l+m*i,end:l+(m+1)*i,bytesByType:{},totalBytes:0});const r={};let c=0;for(const m of e){if(!m.drop_reason)continue;const e=m.timestamp;if(e<l||e>a)continue;const s=Math.min(t-1,Math.floor((e-l)/i)),n=m.type??m.payload_type??0,d=m.length??m.payload_length??0,u=o[s];u.bytesByType[n]=(u.bytesByType[n]??0)+d,u.totalBytes+=d,r[n]=(r[n]??0)+d,c++}const d=s/60;return{buckets:o,activeTypes:Object.keys(r).map(e=>parseInt(e,10)).filter(e=>r[e]>0).sort((e,s)=>r[s]-r[e]),ratePerHour:d>0?Math.round(c/d):0}}(n,l,i),[n,l,i]),p=a>0?(t/a*100).toFixed(1):null;return u?s.jsxs(o,{children:[s.jsxs("div",{className:"flex items-center gap-1.5 sm:gap-2 mb-2 sm:mb-3",children:[m&&s.jsx("span",{className:"icon-sm text-icon-card-title",children:m}),s.jsx("span",{className:"type-micro",children:"DROPPED"}),d&&s.jsx(c,{color:"zinc",className:"hidden sm:inline-flex",children:d})]}),s.jsx("div",{className:"type-data-xl text-fg-primary",children:s.jsx(Pe,{value:t,className:"font-mono tabular-nums",priority:"high"})}),s.jsx("div",{className:"flex-1 mt-1 overflow-hidden min-h-[40px] sm:min-h-[60px]",children:h.length>0?s.jsx(ds,{buckets:x,activeTypes:h}):s.jsx("div",{className:"w-full h-full flex items-center justify-center",children:s.jsx("div",{className:"w-full h-0.5 rounded-full bg-fg-muted/15"})})}),s.jsx("div",{className:"pt-1.5 sm:pt-2 mt-1",children:s.jsxs("div",{className:"flex gap-2 sm:gap-3",children:[s.jsxs("div",{className:"flex-1 min-w-0",children:[s.jsx("div",{className:"data-box-label",children:"Rate"}),s.jsxs("div",{className:"data-box data-box-fill data-box-left",children:[f,"/hr"]})]}),null!==p&&s.jsxs("div",{className:"flex-1 min-w-0",children:[s.jsx("div",{className:"data-box-label",children:"Drop %"}),s.jsxs("div",{className:"data-box data-box-fill data-box-left",children:[p,"%"]})]})]})})]}):s.jsx(o,{children:s.jsx(r,{})})}se(xs);const fs={",":"punc",".":"punc-period",":":"punc-colon","/":"punc-slash"},ps=/([,\.:\/])/g,gs=e.memo(function({children:t,className:a="",as:n="span"}){const l=e.useMemo(()=>{let e;return e="number"==typeof t?t.toLocaleString():Array.isArray(t)?t.join(""):String(t??""),ps.test(e)?(ps.lastIndex=0,e.split(ps).map((e,t)=>{const a=fs[e];return a?s.jsx("span",{className:a,children:e},t):e})):e},[t]);return s.jsx(n,{className:`data-tight ${a}`.trim(),children:l})});function bs(e,s,t){return Ee(Math.max(s,Math.min(t,e)))}function js({stats:t,receivedBuckets:a,droppedBuckets:n,forwardedBuckets:l,bucketDurationSeconds:i,timeRangeLabel:u,isLoaded:x=!0}){var h,f,p,g;const[b,j]=e.useState(!1),[v,y]=e.useState("idle"),N=d(),w=e.useCallback(async(e,s)=>{if("applying"!==v){y("applying");try{const t=await m({tx_delay_factor:e,direct_tx_delay_factor:s});(null==t?void 0:t.success)?(y("success"),setTimeout(()=>y("idle"),2e3)):(y("error"),setTimeout(()=>y("idle"),2500))}catch{y("error"),setTimeout(()=>y("idle"),2500)}}},[v]);if(!x)return s.jsx(o,{children:s.jsx(r,{})});const k=Math.floor(Date.now()/1e3)-604800,M=Object.values((null==t?void 0:t.neighbors)??{}).filter(e=>e.zero_hop&&e.last_seen>=k&&Ae(e).isRepeater).length,C=N.filter(e=>"active"===e.status||e.lastSeen>=k).length,S=Math.max(M,C),L=function(e,s,t){const a=e=>(null==e?void 0:e.reduce((e,s)=>e+s.count,0))??0,n=a(s),l=a(t),i=n||(null==e?void 0:e.rx_count)||1,o=l||(null==e?void 0:e.dropped_count)||0;return i>0?o/(i+o)*100:0}(t,a,n),T=function(e,s,t){if((null==s?void 0:s.length)&&t){const e=100;return((null==(a=s)?void 0:a.reduce((e,s)=>e+s.count,0))??0)*e/(s.length*t*1e3)*100}var a;if(e){const s=1e3*(e.uptime_seconds||1);return(e.total_airtime_ms||e.airtime_used_ms||0)/s*100}return 0}(t,l,i),B=(null==(f=null==(h=null==t?void 0:t.config)?void 0:h.delays)?void 0:f.tx_delay_factor)??null,F=(null==(g=null==(p=null==t?void 0:t.config)?void 0:p.delays)?void 0:g.direct_tx_delay_factor)??null,_=function(e,s,t,a){let n=Ie(e);s>20?n+=2*qe:s>12&&(n+=qe),t>8&&(n+=qe);const l=bs(n,0,2);let i=We(e);t>8&&(i+=qe);const o=bs(i,0,1),r=ze(l),c=ze(o),d=null!==a?ze(a):null;let m="stable";return null!==d&&(r>d?m="increase":r<d&&(m="decrease")),{floodFactor:l,directFactor:o,floodSlots:r,directSlots:c,adjustment:m,duplicateRate:Math.round(100*s)/100,txUtilization:Math.round(1e3*t)/1e3,zeroHopCount:e}}(S,L,T,B),R=1!==S,D=Ie(S),$=[`${S} repeater${R?"s":""} heard in the last 7 days (base ×${D.toFixed(1)}).`];_.floodFactor===D&&L<=12&&T<=8?$.push("No modifiers applied — network looks healthy."):(L>20?$.push(`High duplicate rate (${L.toFixed(1)}%) suggests frequent collisions — window widened.`):L>12&&$.push(`Elevated duplicate rate (${L.toFixed(1)}%) — window widened one step.`),T>8&&$.push(`Channel is busy (${T.toFixed(1)}% TX util) — extra spacing added.`));const H=[`Direct uses one forwarder — ×${_.directFactor.toFixed(1)} backoff for channel contention.`];T>8&&H.push("Busy channel — small extra backoff.");const P=[`Flood ×${_.floodFactor.toFixed(1)} (${_.floodSlots} slot${1!==_.floodSlots?"s":""})`,...$,"",`Direct ×${_.directFactor.toFixed(1)}`,...H,"","Click to copy CLI commands"].join("\n"),A=null!==B?ze(B):null,I=null!==F?ze(F):null,z=null!==A&&_.floodSlots!==A,E=null!==I&&_.directSlots!==I,W=z||E;return s.jsxs(o,{children:[s.jsxs("div",{className:"flex items-center gap-1.5 sm:gap-2 mb-2 sm:mb-3 flex-wrap",children:[s.jsx(de,{className:"w-4 h-4 text-icon-card-title flex-shrink-0"}),s.jsx("span",{className:"type-micro",children:"DELAY DOCTOR"}),u&&s.jsx(c,{color:"zinc",className:"hidden sm:inline-flex",children:u})]}),s.jsxs("button",{onClick:async()=>{const e=`set txdelay ${_.floodFactor.toFixed(1)}\nset direct.txdelay ${_.directFactor.toFixed(1)}`;try{await navigator.clipboard.writeText(e),j(!0),setTimeout(()=>j(!1),1500)}catch{const s=document.createElement("textarea");s.value=e,s.style.position="fixed",s.style.opacity="0",document.body.appendChild(s),s.select();try{document.execCommand("copy"),j(!0),setTimeout(()=>j(!1),1500)}catch{console.error("Failed to copy commands")}document.body.removeChild(s)}},className:"flex gap-3 mb-2 sm:mb-3 w-full text-left hover:bg-subtle-fill radius-inner transition-base p-1 -m-1 group",title:P,children:[s.jsxs("div",{className:"flex-1 flex flex-col",children:[s.jsx("span",{className:"type-data-xl text-fg-primary",children:s.jsxs(gs,{children:["×",_.floodFactor.toFixed(1)]})}),s.jsx("span",{className:"type-micro text-fg-muted mt-0.5 sm:mt-1",children:"Flood"})]}),s.jsxs("div",{className:"flex-1 flex flex-col",children:[s.jsx("span",{className:"type-data-xl text-sys-blue",children:s.jsxs(gs,{children:["×",_.directFactor.toFixed(1)]})}),s.jsx("span",{className:"type-micro text-fg-muted mt-0.5 sm:mt-1",children:"Direct"})]}),s.jsx("div",{className:"flex items-center self-center opacity-0 group-hover:opacity-100 transition-opacity",children:b?s.jsx(me,{className:"w-4 h-4 text-sys-green"}):s.jsx(ue,{className:"w-4 h-4 text-fg-muted"})})]}),s.jsx("div",{className:"flex-1 py-2",children:s.jsxs("div",{className:"flex gap-3",children:[s.jsxs("div",{className:"flex-1",children:[s.jsx("div",{className:"data-box-label",children:"Dupe"}),s.jsxs("div",{className:"data-box data-box-fill data-box-left "+(_.duplicateRate>8?"text-status-warning":""),children:[_.duplicateRate.toFixed(1),"%"]})]}),s.jsxs("div",{className:"flex-1",children:[s.jsx("div",{className:"data-box-label",children:"TX Util"}),s.jsxs("div",{className:"data-box data-box-fill data-box-left",children:[_.txUtilization.toFixed(2),"%"]})]})]})}),s.jsx("div",{className:"pt-2 mt-auto",children:s.jsxs("div",{className:"flex items-end justify-between gap-2",children:[s.jsxs("div",{className:"flex-1 min-w-0",children:[s.jsx("div",{className:"data-box-label",children:"Current"}),s.jsx("div",{className:"flex gap-2",children:null!==B?s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:"data-box",children:["×",B.toFixed(2)]}),s.jsxs("div",{className:"data-box",style:{color:"var(--sys-blue)"},children:["×",(null==F?void 0:F.toFixed(2))??"—"]})]}):s.jsx("span",{className:"text-sm text-fg-muted",children:"No config"})})]}),W&&s.jsxs("button",{onClick:()=>w(_.floodFactor,_.directFactor),disabled:"applying"===v||"success"===v,className:"flex items-center gap-1.5 px-2.5 py-1.5 radius-inner type-micro font-medium transition-base\n "+("success"===v?"bg-sys-green/15 text-sys-green":"error"===v?"bg-sys-red/15 text-sys-red":"applying"===v?"bg-subtle-fill text-fg-muted":"bg-sys-blue/10 text-sys-blue hover:bg-sys-blue/20"),title:`Apply ×${_.floodFactor.toFixed(1)} flood, ×${_.directFactor.toFixed(1)} direct`,children:["success"===v?"Rx'd":"error"===v?"Failed":"Apply","applying"===v?s.jsx(xe,{className:"w-3.5 h-3.5 animate-spin"}):"success"===v?s.jsx(me,{className:"w-3.5 h-3.5"}):s.jsxs("span",{className:"relative inline-flex items-end w-6 h-3.5",children:[s.jsx(he,{className:"w-3.5 h-3.5 absolute left-0 bottom-0"}),s.jsx(fe,{className:"w-3 h-3 absolute right-0 bottom-0"})]})]})]})})]})}const vs=[{target:"RecentPackets",fn:"rssi",minStage:1},{target:"RecentPackets",fn:"snr",minStage:1}];function ys(){ee(vs);const t=u(),a=x(),n=h(),l=f(),i=Ue(),r=Oe(e=>e.requestChannel),[c,d]=e.useState(!0),m=e.useCallback(e=>d(e),[]),v=e.useMemo(()=>[...t.length<=100?t:t.slice(-100)].sort((e,s)=>(s.timestamp??0)-(e.timestamp??0)),[t]),y=null==l?void 0:l.local_hash,N=null==l?void 0:l.neighbors,w=Je();return s.jsxs(o,{noPadding:!0,className:"!overflow-visible",children:[s.jsx(p,{listHeader:!0,icon:s.jsx(ge,{}),title:"Recent Packets",actions:s.jsxs("div",{className:"flex items-center gap-3",children:[s.jsx(g,{enabled:c,onChange:m,label:"Hide Dupes",size:"sm"}),n&&s.jsx(b,{showLabel:!0}),s.jsxs(j,{color:"primary",outline:!0,href:"/packets",children:["View all",s.jsx(pe,{"data-slot":"icon"})]})]})}),s.jsx("div",{className:"flex-1 min-h-0 overflow-y-auto px-1",children:s.jsx(Ge,{packets:v,allPackets:t,localHash:y,neighbors:N,resolveSource:w,getDecodedContent:i,onChannelClick:r,loading:a,maxPackets:25,showPagination:!1,flashNewest:!0,hideDupes:c,emptyMessage:"No packets received",footerAction:s.jsxs(j,{color:"primary",outline:!0,href:"/packets",children:["View all",s.jsx(pe,{"data-slot":"icon"})]})})})]})}se(vs);const Ns={stable:"M5 12h14",up:"M5 15l7-7 7 7",down:"M19 9l-7 7-7-7"};function ws({trend:e}){return s.jsx("span",{className:`mini-widget-trend ${e}`,children:s.jsx("svg",{className:"w-3 h-3",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:s.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:Ns[e]})})})}function ks(){return s.jsx("div",{className:"mini-widget-loading",children:s.jsx("div",{className:"mini-widget-loading-spinner"})})}function Ms({message:e}){return s.jsx("div",{className:"mini-widget-error",children:s.jsx("span",{title:e,children:"No data"})})}function Cs({title:e,icon:t,value:a,unit:n,valueSize:l="md",status:i,subtitle:r,trend:c,children:d,isLoading:m=!1,error:u,className:x="",onClick:h}){const f=["mini-widget-value","lg"===l&&"mini-widget-value-lg","sm"===l&&"mini-widget-value-sm"].filter(Boolean).join(" "),p=["mini-widget",x].filter(Boolean).join(" ");return s.jsxs(o,{noPadding:!0,className:p,onClick:h,children:[s.jsxs("div",{className:"mini-widget-header",children:[t,s.jsx("span",{className:"mini-widget-title",children:e}),i&&"unknown"!==i&&s.jsx("div",{className:`mini-widget-status-dot ${i}`}),c&&s.jsx(ws,{trend:c})]}),m?s.jsx(ks,{}):u?s.jsx(Ms,{message:u}):s.jsxs(s.Fragment,{children:[void 0!==a&&s.jsxs("div",{className:f,children:["number"==typeof a?s.jsx(Pe,{value:a,className:"font-mono tabular-nums",priority:"medium",format:Number.isInteger(a)?void 0:{minimumFractionDigits:1,maximumFractionDigits:1}}):s.jsx(gs,{children:a}),n&&s.jsx("span",{className:"mini-widget-unit",children:n})]}),r&&s.jsx("div",{className:"mini-widget-subtitle",children:r}),d]})]})}const Ss={DELTA_CRITICAL:10,SLOPE_CRITICAL:4,JITTER_CRITICAL:6,DELTA_WARNING:5,SLOPE_WARNING:2,JITTER_WARNING:4},Ls={baselineMedian:null,baselineP10:null,baselineP90:null,currentMedian:null,currentSampleCount:0,delta:0,slope:0,jitter:0,penalty:0,penaltyReason:null,computedAt:0,isReliable:!1};function Ts(e,s){if(0===e.length)return null;const t=[...e].sort((e,s)=>e-s),a=s/100*(t.length-1),n=Math.floor(a),l=Math.ceil(a);return n===l?t[n]:t[n]+(t[l]-t[n])*(a-n)}function Bs(e){return Ts(e,50)}const Fs={lbtStats:null,noiseFloor:null,sparklineNoiseFloor:[],noiseFloorWindowHistory:[],linkQuality:null,channelHealth:null,nfTrend:Ls,radioConfig:null,trends:null,stats:null,recentPackets:[],quickNeighbors:[],isLoading:!0,error:null,refresh:async()=>{}},_s=e.createContext(Fs);function Rs({children:t}){var a;const n=f(),l=u(),i=v(),o=y(),r=N(),c=w[r],d=Math.max(1,c.minutes/60),m=null===n,x=e.useMemo(()=>k(l,d),[l,d]),h=(null==n?void 0:n.noise_floor_dbm)??null,p=e.useMemo(()=>M(h)?h:null,[h]),g=e.useMemo(()=>{var e;const s=null==(e=null==n?void 0:n.config)?void 0:e.radio;return s?{sf:s.spreading_factor??7,bwHz:s.bandwidth??125e3}:null},[null==(a=null==n?void 0:n.config)?void 0:a.radio]),b=C(d),j=S(d),F=null==n?void 0:n.neighbors,_=e.useMemo(()=>{const e=F??{};return Object.fromEntries(Object.entries(e).filter(([e])=>!o.has(e)))},[F,o]),R=e.useMemo(()=>i.filter(e=>!o.has(e.hash)),[i,o]),D=e.useMemo(()=>function(e){if(0===e.length)return{...Ls,computedAt:Math.floor(Date.now()/1e3)};const s=Math.floor(Date.now()/1e3),t=e.filter(e=>Number.isFinite(e)),a=e.length>0?[e[e.length-1]]:[],n=e.slice(-4).filter(e=>Number.isFinite(e)),l=Bs(t),i=Ts(t,10),o=Ts(t,90),r=Bs(a),c=null!==r&&null!==i?r-i:0,d=function(e){if(e.length<2)return 0;const s=e.length;let t=0,a=0,n=0,l=0;const i=e[0].timestamp;for(const r of e){const e=(r.timestamp-i)/3600,s=r.value;t+=e,a+=s,n+=e*s,l+=e*e}const o=s*l-t*t;return Math.abs(o)<1e-4?0:(s*n-t*a)/o}(n.map((e,t)=>({timestamp:s-3600*(n.length-1-t),value:e}))),m=function(e){if(e.length<2)return 0;const s=e.reduce((e,s)=>e+s,0)/e.length,t=e.map(e=>Math.pow(e-s,2)).reduce((e,s)=>e+s,0)/e.length;return Math.sqrt(t)}(n),u=t.length>=12,[x,h]=u?function(e,s,t){const a=Ss;return e>=a.DELTA_CRITICAL?[2,`Noise floor ${e.toFixed(1)} dB above baseline`]:s>=a.SLOPE_CRITICAL?[2,`Noise floor rising ${s.toFixed(1)} dB/hour`]:t>=a.JITTER_CRITICAL?[2,`Noise floor unstable (±${t.toFixed(1)} dB)`]:e>=a.DELTA_WARNING?[1,`Noise floor ${e.toFixed(1)} dB above baseline`]:s>=a.SLOPE_WARNING?[1,`Noise floor rising ${s.toFixed(1)} dB/hour`]:t>=a.JITTER_WARNING?[1,`Noise floor variable (±${t.toFixed(1)} dB)`]:[0,null]}(c,d,m):[0,null];return{baselineMedian:l,baselineP10:i,baselineP90:o,currentMedian:r,currentSampleCount:a.length,delta:c,slope:d,jitter:m,penalty:x,penaltyReason:h,computedAt:s,isReliable:u}}(b),[b]),$=e.useMemo(()=>L(R,_,g),[R,_,g]),H=e.useMemo(()=>T(x,p,$),[x,p,$]),[P,A]=e.useState({noiseFloor:null,networkScore:null,channelHealth:null}),I=e.useRef(0);e.useEffect(()=>{const e=()=>{const e=Date.now();e-I.current>3e4&&(I.current=e,A({noiseFloor:p,networkScore:(null==$?void 0:$.networkScore)??null,channelHealth:(null==H?void 0:H.score)??null}))};e();const s=setInterval(e,5e3);return()=>clearInterval(s)},[p,null==$?void 0:$.networkScore,null==H?void 0:H.score]);const z=e.useMemo(()=>({noiseFloor:{current:p,previous:P.noiseFloor,trend:null!==p?B(p,P.noiseFloor,2,!0):"stable"},networkScore:{current:(null==$?void 0:$.networkScore)??0,previous:P.networkScore,trend:B((null==$?void 0:$.networkScore)??0,P.networkScore,3,!1)},channelHealth:{current:(null==H?void 0:H.score)??0,previous:P.channelHealth,trend:B((null==H?void 0:H.score)??0,P.channelHealth,3,!1)}}),[p,null==$?void 0:$.networkScore,null==H?void 0:H.score,P]),E={lbtStats:x,noiseFloor:p,sparklineNoiseFloor:b,noiseFloorWindowHistory:j,linkQuality:$,channelHealth:H,nfTrend:D,radioConfig:g,trends:z,stats:n,recentPackets:l,quickNeighbors:i,isLoading:m,error:null,refresh:async()=>{}};return s.jsx(_s.Provider,{value:E,children:t})}function Ds(){const s=e.useContext(_s);if(void 0===s)throw new Error("useLBTData must be used within an LBTDataProvider");return s}function $s(e,s){return 0===e?"No backoffs":`${s.toFixed(0)}% retry rate`}function Hs(){const{lbtStats:t,isLoading:a,error:n}=Ds(),l=Ye(),i=(null==t?void 0:t.avgBackoffMs)??0,o=(null==t?void 0:t.retryRate)??0,r=t?(c=i)<100?"excellent":c<250?"good":c<500?"fair":c<1e3?"congested":"critical":"unknown";var c;const d=null==t?void 0:t.sparklineBackoff,m=e.useMemo(()=>!d||d.length<2?[]:d.map((e,s)=>({timestamp:Date.now()-36e5*(d.length-1-s),count:e})),[d]);return s.jsx(Cs,{title:"LBT Backoff",icon:s.jsx(be,{className:"mini-widget-icon"}),value:Math.round(i),unit:"ms",status:r,subtitle:t?$s(i,o):void 0,isLoading:a,error:n,onClick:()=>l("/packets"),children:s.jsx("div",{className:"mini-widget-sparkline w-full",children:s.jsx(Xe,{data:m,width:9999,height:24,color:"var(--sys-blue)",isLoading:a,className:"w-full"})})})}function Ps(e){return 0===e?"—":e<1?"<1":Math.round(e).toString()}function As(){const{lbtStats:e,isLoading:t,error:a}=Ds(),n=Ye(),l=(null==e?void 0:e.channelBusyCount)??0,i=(null==e?void 0:e.totalPacketsWithLBT)??0,o=(null==e?void 0:e.channelBusyRate)??0,r=(null==e?void 0:e.retryRate)??0,c=(null==e?void 0:e.avgBackoffMs)??0,d=(null==e?void 0:e.minBackoffMs)??0,m=(null==e?void 0:e.maxBackoffMs)??0,u=r>0?Math.max(0,(r-o)/r*100):100;return s.jsx(Cs,{title:"Ch. Busy",icon:s.jsx(je,{className:"mini-widget-icon"}),isLoading:t,error:a,onClick:()=>n("/packets"),children:s.jsx("div",{className:"flex-1 flex items-end",children:s.jsxs("div",{className:"grid grid-cols-[auto_minmax(0,1fr)] sm:grid-cols-[auto_minmax(0,1fr)_auto_minmax(0,1fr)] gap-x-2 gap-y-1 sm:gap-y-2 w-full items-baseline",children:[s.jsx("span",{className:"data-box-label mb-0 text-[10px] sm:text-sm",title:`${l} packets exceeded max CAD attempts (5) out of ${i} total transmissions.`,children:"Failed:"}),s.jsxs("div",{className:"data-box data-box-compact sm:data-box justify-self-start",title:`${l} packets exceeded max CAD attempts (5) out of ${i} total transmissions.`,children:[s.jsx(gs,{children:l}),s.jsx("span",{className:"text-fg-muted punc-slash",children:"/"}),s.jsx(gs,{children:i})]}),s.jsx("span",{className:"data-box-label mb-0 text-[10px] sm:text-sm",title:`${u.toFixed(1)}% of packets that needed LBT retries were sent successfully.`,children:"Sent:"}),s.jsx("div",{className:"data-box data-box-compact sm:data-box justify-self-start",title:`${u.toFixed(1)}% of packets that needed LBT retries were sent successfully.`,children:s.jsxs(gs,{children:[u.toFixed(0),"%"]})}),s.jsx("span",{className:"data-box-label mb-0 text-[10px] sm:text-sm",title:`Average LBT backoff delay: ${c.toFixed(0)}ms.`,children:"Mean:"}),s.jsxs("div",{className:"data-box data-box-compact sm:data-box justify-self-start",title:`Average LBT backoff delay: ${c.toFixed(0)}ms.`,children:[s.jsx(gs,{children:Ps(c)}),s.jsx("span",{className:"text-fg-muted text-xs",children:"ms"})]}),s.jsx("span",{className:"data-box-label mb-0 text-[10px] sm:text-sm",title:`Backoff range: ${d.toFixed(0)}ms min, ${m.toFixed(0)}ms max.`,children:"Range:"}),s.jsxs("div",{className:"data-box data-box-compact sm:data-box justify-self-start",title:`Backoff range: ${d.toFixed(0)}ms min, ${m.toFixed(0)}ms max.`,children:[s.jsx(gs,{children:Ps(d)}),s.jsx("span",{className:"text-fg-muted punc-slash",children:"/"}),s.jsx(gs,{children:Ps(m)})]})]})})})}function Is(e){return null===e?"No reading":e<-115?"Very quiet":e<-105?"Quiet":e<-95?"Moderate":e<-85?"Elevated":"High interference"}function zs(){const{noiseFloor:t,noiseFloorWindowHistory:a,trends:n,isLoading:l,error:i}=Ds(),o=null===(r=t)||r<-110?"excellent":r<-100?"good":r<-90?"fair":r<-80?"congested":"critical";var r;const c=null==n?void 0:n.noiseFloor.trend,d=e.useMemo(()=>{if(!a||a.length<2)return[];return function(e,s,t,a){const n=e.length;if(0===n)return[];if(1===n)return new Array(a).fill(s[0]);if(2===n){const e=new Array(a);for(let t=0;t<a;t++)e[t]=s[0]+(s[1]-s[0])*(t/47);return e}const l=Math.max(2,Math.ceil(.25*n)),i=e[0],o=e[n-1]-i||1,r=new Array(a),c=new Array(n);for(let d=0;d<a;d++){const t=i+d/47*o;for(let s=0;s<n;s++)c[s]=Math.abs(e[s]-t);const a=c.slice().sort((e,s)=>e-s),m=Math.max(a[l-1],1e-10);let u=0,x=0,h=0,f=0,p=0;for(let l=0;l<n;l++){const a=c[l]/m;if(a>=1)continue;const n=a*a*a,i=(1-n)*(1-n)*(1-n),o=e[l]-t;u+=i,x+=i*o,h+=i*s[l],f+=i*o*o,p+=i*o*s[l]}if(0===u){r[d]=s[Math.round(d/47*(n-1))];continue}const g=u*f-x*x;r[d]=Math.abs(g)<1e-10?h/u:(f*h-x*p)/g}return r}(a.map(e=>e.timestamp),a.map(e=>-e.noise_floor_dbm),0,48).map((e,s)=>({timestamp:Date.now()-36e5*(47-s),count:e}))},[a]),m=null!==t?Math.round(t):"—";return s.jsx(Cs,{title:"Noise Floor",icon:s.jsx(ve,{className:"mini-widget-icon"}),value:m,unit:null!==t?"dBm":void 0,status:o,trend:c,subtitle:Is(t),isLoading:l,error:i,children:s.jsx("div",{className:"mini-widget-sparkline w-full",children:s.jsx(Xe,{data:d,width:9999,height:22,color:"var(--sys-blue)",isLoading:l,className:"w-full"})})})}const Es=[{target:"LinkLeaders",fn:"path",minStage:1,when:ae},{target:"LinkLeaders",fn:"src_hash",minStage:1,when:ne}];function Ws(){ee(Es);const t=Ye(),a=v(),n=u(),l=f(),i=N(),o=60*w[i].minutes,r=F(),c=e.useMemo(()=>{if(0===r)return n;const e=r-o;return n.filter(s=>s.timestamp>=e)},[n,o,r]),d=null===l,m=(null==l?void 0:l.local_hash)?_(l.local_hash):"",x=(null==l?void 0:l.neighbors)??{},{neighborHashes:h,neighborNames:p}=e.useMemo(()=>{const e=new Set,s=new Map;for(const t of a){e.add(t.hash);const a=x[t.hash],n=(null==a?void 0:a.name)||(null==a?void 0:a.node_name)||t.prefix;s.set(t.hash,n)}return{neighborHashes:e,neighborNames:s}},[a,x]),g=e.useMemo(()=>{if(0===h.size||0===c.length||!m)return{champion:null,listener:null,loudest:null};const{scores:e}=Qe(c,h,m),s=[];for(const[l,i]of e)0!==i.blendedScore&&s.push({...i,name:p.get(l)??_(l)});let t=null,a=null,n=null;for(const l of s)(!t||l.blendedScore>t.blendedScore)&&(t=l),(!a||l.listenerScore>a.listenerScore)&&(a=l),(!n||l.loudScore>n.loudScore)&&(n=l);return{champion:t,listener:a,loudest:n}},[c,h,m,p]),{champion:b,listener:j,loudest:y}=g,k=b||j||y?s.jsxs("div",{className:"flex flex-col gap-0 sm:gap-0.5 mt-auto",children:[b&&s.jsx(R,{content:(M=b,s.jsxs("div",{className:"max-w-[220px]",children:[s.jsxs("div",{className:"font-semibold mb-1",children:["🏆 Champion: ",M.name]}),s.jsxs("div",{className:"text-fg-muted mb-1",children:["Blended Score: ",M.blendedScore,s.jsx("span",{className:"text-fg-muted/60 ml-1",children:"(Listener + Loud)"})]}),s.jsxs("div",{className:"border-t border-edge-subtle pt-1 mt-1 space-y-0.5",children:[s.jsxs("div",{children:["Listener: ",M.listenerScore,"/100 (",M.listenerCount," shared paths)"]}),s.jsxs("div",{children:["Loud: ",M.loudScore,"/100 (",M.loudCount," packets relayed)"]})]})]})),children:s.jsxs("div",{className:"flex items-center gap-1 text-xs sm:text-sm radius-badge px-1 -mx-1 hover-bg transition-base cursor-default",children:[s.jsx(ye,{className:"w-2.5 h-2.5 sm:w-3 sm:h-3 text-map-neighbor-color flex-shrink-0"}),s.jsx("span",{className:"font-semibold text-map-neighbor-color font-mono truncate flex-1 min-w-0",children:b.name}),s.jsx("span",{className:"text-map-neighbor-color pl-1 sm:pl-2 tabular-nums flex-shrink-0 w-7 sm:w-9 text-right",children:b.blendedScore})]})}),j&&s.jsx(R,{content:(e=>s.jsxs("div",{className:"max-w-[220px]",children:[s.jsxs("div",{className:"font-semibold mb-1",children:["👂 Best Listener: ",e.name]}),s.jsxs("div",{className:"text-fg-muted mb-1",children:["Score: ",e.listenerScore,"/100"]}),s.jsx("div",{className:"border-t border-edge-subtle pt-1 mt-1",children:s.jsxs("div",{children:[e.listenerCount," packets where they heard your transmissions"]})})]}))(j),children:s.jsxs("div",{className:"flex items-center gap-1 text-xs sm:text-sm radius-badge px-1 -mx-1 hover-bg transition-base cursor-default",children:[s.jsx(Ne,{className:"w-2.5 h-2.5 sm:w-3 sm:h-3 text-fg-muted flex-shrink-0"}),s.jsx("span",{className:"text-fg-muted font-mono truncate flex-1 min-w-0",children:j.name}),s.jsx("span",{className:"text-fg-muted pl-1 sm:pl-2 tabular-nums flex-shrink-0 w-7 sm:w-9 text-right",children:j.listenerScore})]})}),y&&s.jsx(R,{content:(e=>s.jsxs("div",{className:"max-w-[220px]",children:[s.jsxs("div",{className:"font-semibold mb-1",children:["📢 Loudest: ",e.name]}),s.jsxs("div",{className:"text-fg-muted mb-1",children:["Score: ",e.loudScore,"/100"]}),s.jsx("div",{className:"border-t border-edge-subtle pt-1 mt-1",children:s.jsxs("div",{children:[e.loudCount," packets they relayed directly to you"]})})]}))(y),children:s.jsxs("div",{className:"flex items-center gap-1 text-xs sm:text-sm radius-badge px-1 -mx-1 hover-bg transition-base cursor-default",children:[s.jsx(we,{className:"w-2.5 h-2.5 sm:w-3 sm:h-3 text-fg-muted flex-shrink-0"}),s.jsx("span",{className:"text-fg-muted font-mono truncate flex-1 min-w-0",children:y.name}),s.jsx("span",{className:"text-fg-muted pl-1 sm:pl-2 tabular-nums flex-shrink-0 w-7 sm:w-9 text-right",children:y.loudScore})]})})]}):0===a.length?s.jsx("div",{className:"flex items-center justify-center text-xs sm:text-sm text-fg-muted mt-auto",children:"No direct neighbors"}):s.jsx("div",{className:"flex items-center justify-center text-xs sm:text-sm text-fg-muted mt-auto",children:"No routing data yet"});var M;return s.jsx(Cs,{title:"Link Leaders",icon:s.jsx(ke,{className:"mini-widget-icon"}),isLoading:d,onClick:()=>t("/contacts"),children:k})}function qs(){const{lbtStats:t,isLoading:a,error:n}=Ds(),l=t?function(e){const{retryRate:s,channelBusyCount:t,totalPacketsWithLBT:a,avgBackoffMs:n,maxBackoffMs:l}=e;if(0===a)return 0;const i=Math.min(a/10,1),o=Math.log(1+.15*s)/Math.log(16)*40,r=t/a*100,c=Math.min(.5*r,25);let d=0;n>100&&(d=Math.min(8*Math.log10(n/100),15));let m=0;l>500&&n>0&&l>2*n&&(m=Math.min((l-500)/200,5));const u=(o+c+d+m)*i;return Math.min(u,85)}(t):0,i=t?(o=l)<15?"excellent":o<30?"good":o<45?"fair":o<60?"congested":"critical":"unknown";var o;const r=(null==t?void 0:t.maxBackoffMs)??0,c=t?r>200?`Max backoff: ${Math.round(r)}ms`:function(e){return e<15?"Clear channel":e<30?"Light traffic":e<45?"Moderate traffic":e<60?"Heavy traffic":e<75?"Congested":"Severe congestion"}(l):void 0,d=null==t?void 0:t.sparklineCollisionRisk,m=e.useMemo(()=>!d||d.length<2?[]:d.map((e,s)=>({timestamp:Date.now()-36e5*(d.length-1-s),count:e})),[d]),u=Math.round(10*l)/10;return s.jsx(Cs,{title:"Collision Risk",icon:s.jsx(Me,{className:"mini-widget-icon"}),value:u,unit:"%",status:i,subtitle:c,isLoading:a,error:n,children:s.jsx("div",{className:"mini-widget-sparkline w-full",children:s.jsx(Xe,{data:m,width:9999,height:24,color:"var(--sys-blue)",isLoading:a,className:"w-full"})})})}function Os(){const[t,a]=e.useState(!1),[n]=e.useState(0),{stats:l,lbtStats:i,isLoading:o}=Ds(),r=e.useMemo(()=>{if(!l)return null;const e=l.airtime_used_ms??0,s=l.max_airtime_ms??1;return{usedMs:e,maxMs:s,remainingMs:l.airtime_remaining_ms??0,utilizationPercent:l.utilization_percent??(s>0?e/s*100:0)}},[l]),c=e.useMemo(()=>i&&0!==i.totalPacketsWithLBT?(i.totalPacketsWithLBT-i.packetsWithRetries)/i.totalPacketsWithLBT*100:100,[i]),d=(null==r?void 0:r.utilizationPercent)??0,m=(u=d)<30?"excellent":u<50?"good":u<70?"fair":u<90?"congested":"critical";var u;const x=(null==r?void 0:r.remainingMs)??0,h=c<95?`${c.toFixed(0)}% clean TX`:((f=x)<1e3?`${Math.round(f)}ms`:f<6e4?`${(f/1e3).toFixed(1)}s`:`${(f/6e4).toFixed(1)}m`)+" remaining";var f;const p=r?s.jsx("div",{className:"mini-widget-progress mt-auto",children:s.jsx("div",{className:`mini-widget-progress-bar ${m}`,style:{width:`${Math.min(d,100)}%`}})}):null;return s.jsx(Cs,{title:"Duty Cycle",icon:s.jsx(ge,{className:"mini-widget-icon"}),value:d.toFixed(1),unit:"%",status:m,subtitle:h,isLoading:o,children:p})}function Gs(){return s.jsxs("div",{className:"mini-widget",children:[s.jsxs("div",{className:"mini-widget-header",children:[s.jsx(D,{className:"w-4 h-4"}),s.jsx(D,{className:"h-3 w-16"})]}),s.jsx(D,{className:"h-7 w-12 mt-2"}),s.jsx(D,{className:"h-3 w-20 mt-2"})]})}function Vs(){return s.jsx("div",{className:"widget-row",children:Array.from({length:6}).map((e,t)=>s.jsx(Gs,{},t))})}se(Es);const Us=[{target:"MeshHealth",fn:"type",minStage:1}];function Js({className:e="",isLoaded:t=!0}){return ee(Us),s.jsxs("div",{className:`mesh-health-container relative ${e}`,children:[s.jsxs("div",{className:"mesh-health-header",children:[s.jsx(Ce,{className:"w-4 h-4 text-sys-blue"}),s.jsx("span",{className:"type-label text-fg-muted",children:"MESH HEALTH"})]}),t?s.jsx(Rs,{children:s.jsxs("div",{className:"widget-row",children:[s.jsx(Hs,{}),s.jsx(qs,{}),s.jsx(zs,{}),s.jsx(Os,{}),s.jsx(As,{}),s.jsx(Ws,{})]})}):s.jsx(Vs,{})]})}se(Us);const Ks=[{target:"PublicChannel",fn:"decrypt",minStage:2,when:le}];se(Ks);let Xs="",Qs="",Ys="";function Zs(e){!function(){const e=new Date,s=e.toDateString();if(s!==Ys){Ys=s,Xs=s;const t=new Date(e);t.setDate(t.getDate()-1),Qs=t.toDateString()}}();const s=new Date(1e3*e).toDateString();return s===Xs?"Today":s===Qs?"Yesterday":new Date(1e3*e).toLocaleDateString([],{weekday:"short",month:"short",day:"numeric"})}function et(e,s,t){return`${e||""}|${s}|${t}`}const st=e.memo(function({message:e,onChannelClick:t,isChannelSelected:a}){const n=e.channelName||e.channelHash.slice(0,6);return s.jsx("div",{style:{transform:"translateZ(0)",willChange:"transform"},children:s.jsx(ls,{senderName:e.senderName||"Unknown",text:e.text,timestamp:e.timestamp,nameAccessory:s.jsx(Ve,{channelName:n,active:a,onClick:()=>null==t?void 0:t(e.channelHash)})})})},function(e,s){const t=e.message,a=s.message;return t.timestamp===a.timestamp&&t.text===a.text&&t.senderName===a.senderName&&t.channelHash===a.channelHash&&t.channelName===a.channelName&&e.isChannelSelected===s.isChannelSelected&&e.onChannelClick===s.onChannelClick});function tt({open:t,onClose:a,messages:n,onLoadMore:l,hasMoreToLoad:i,isDecoding:o,initialChannel:r}){const c=e.useRef(null),d=e.useRef(!0),m=N(),u=W(),x=e.useRef(!1);e.useEffect(()=>{t?(x.current=!0,q.resume()):x.current&&q.pause()},[t]);const h=e.useMemo(()=>{const e=Date.now()/1e3-60*w[m].minutes;return[...n].filter(s=>s.timestamp>=e).sort((e,s)=>e.timestamp-s.timestamp)},[n,m]),f=e.useCallback(()=>{const e=c.current;e&&(d.current=e.scrollTop>=-50)},[]),p=e.useMemo(()=>{const e=new Map;for(const s of h){const t=s.channelHash,a=e.get(t);a?a.count++:e.set(t,{name:s.channelName||s.channelHash.slice(0,6),hash:s.channelHash,count:1})}return Array.from(e.values()).sort((e,s)=>s.count-e.count)},[h]),g=p.length,[b,j]=e.useState(null),[v,y]=e.useState(!1);e.useEffect(()=>{t&&r&&j(r)},[t,r]);const k=e.useCallback(()=>{l(b,p)},[l,b,p]),M=e.useMemo(()=>b?h.filter(e=>e.channelHash===b):h,[h,b]),C=e.useMemo(()=>{const e=[];let s="";for(const t of M){const a=Zs(t.timestamp);a!==s&&(e.push({type:"date",date:a}),s=a),e.push({type:"message",message:t})}return e},[M]);e.useLayoutEffect(()=>{const e=c.current;e&&d.current&&(e.scrollTop=0)},[M.length]);const S=p.slice(0,19),L=p.slice(19),T=L.length>0;return s.jsx(O,{open:t,onClose:a,size:"lg",motionPlus:!0,solid:!0,children:s.jsxs(G,{className:"p-0 flex flex-col h-[80vh] max-h-[700px] rounded-2xl",children:[s.jsx("div",{className:"flex-shrink-0 px-4 sm:px-5 py-3 sm:py-4",children:s.jsxs("div",{className:"flex items-center justify-between gap-3",children:[s.jsxs("div",{className:"flex items-center gap-3",children:[s.jsx(Se,{className:"size-5 text-icon-card-title flex-shrink-0"}),s.jsx("h2",{className:"type-micro",children:"Public Channels"})]}),s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(Ke,{ranges:w,selectedIndex:m,onSelect:u,size:"sm"}),s.jsx("button",{onClick:a,className:"sm:hidden min-h-[44px] min-w-[44px] px-3 flex items-center justify-center text-[15px] font-medium text-sys-blue active:text-sys-blue/70 transition-base radius-inner active:bg-subtle-fill",children:"Done"}),s.jsx("button",{onClick:a,className:"hidden sm:flex items-center justify-center p-2 text-fg-muted hover:text-fg-primary transition-base radius-inner hover:bg-subtle","aria-label":"Close",children:s.jsx("svg",{className:"w-5 h-5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:s.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M6 18L18 6M6 6l12 12"})})})]})]})}),s.jsx("div",{className:"flex-shrink-0 px-3 pb-2 relative z-10 isolate",style:{minHeight:g>0?void 0:0},children:g>0&&s.jsxs("div",{className:"flex flex-wrap gap-1",children:[s.jsxs("button",{onClick:()=>j(null),className:Ze("px-2 py-0.5 rounded text-xs font-medium transition-all","ring-1 ring-inset",null===b?"bg-sys-blue/20 text-sys-blue ring-sys-blue/30":"bg-subtle-fill text-fg-secondary ring-edge-subtle hover:bg-subtle-fill-strong"),children:["All ",g]}),S.map(e=>s.jsx("button",{onClick:()=>j(e.hash),className:Ze("flex items-center gap-1 px-2 py-0.5 rounded text-xs font-medium transition-all","ring-1 ring-inset",b===e.hash?"bg-sys-blue/20 text-sys-blue ring-sys-blue/30":"bg-subtle-fill text-fg-secondary ring-edge-subtle hover:bg-subtle-fill-strong"),children:s.jsx("span",{className:"truncate max-w-[80px]",children:e.name})},e.hash)),T&&s.jsxs("div",{className:"relative",children:[s.jsxs("button",{onClick:()=>y(!v),className:Ze("flex items-center gap-0.5 px-2 py-0.5 rounded text-xs font-medium transition-all","ring-1 ring-inset",v||L.some(e=>e.hash===b)?"bg-sys-blue/20 text-sys-blue ring-sys-blue/30":"bg-subtle-fill text-fg-secondary ring-edge-subtle hover:bg-subtle-fill-strong"),children:["+",L.length,s.jsx(Te,{className:Ze("size-3 transition-transform",v&&"rotate-180")})]}),v&&s.jsx("div",{className:Ze("absolute top-full left-0 mt-1 z-50","min-w-[140px] max-h-[200px] overflow-y-auto","p-1 rounded-lg","bg-elevated backdrop-blur-xl","ring-1 ring-edge-subtle shadow-xl"),children:L.map(e=>s.jsxs("button",{onClick:()=>{j(e.hash),y(!1)},className:Ze("w-full flex items-center gap-1.5 px-2 py-1 rounded text-xs font-medium transition-all text-left",b===e.hash?"bg-sys-blue/20 text-sys-blue":"text-fg-secondary hover:bg-subtle-fill-strong"),children:[s.jsx(Be,{className:"size-2.5 opacity-60 flex-shrink-0"}),s.jsx("span",{className:"truncate",children:e.name}),s.jsxs("span",{className:"opacity-60 ml-auto",children:["(",e.count,")"]})]},e.hash))})]})]})}),s.jsx("div",{ref:c,onScroll:f,className:Ze("flex-1 overflow-y-auto overflow-x-hidden","mx-3 mb-3 rounded-md","bg-body","ring-1 ring-inset ring-edge-subtle","flex flex-col-reverse"),children:o&&0===M.length?s.jsxs("div",{className:"flex flex-col items-center justify-center h-full min-h-[300px] text-fg-muted px-4 py-4",children:[s.jsx(xe,{className:"size-12 mb-4 text-sys-indigo animate-spin"}),s.jsx("p",{className:"text-lg font-medium",children:"Loading messages..."})]}):0===M.length?s.jsxs("div",{className:"flex flex-col items-center justify-center h-full min-h-[300px] text-fg-muted px-4 py-4",children:[s.jsx(Fe,{className:"size-16 mb-4 opacity-20"}),s.jsx("p",{className:"text-lg font-medium",children:"No messages yet"}),s.jsx("p",{className:"text-sm mt-1 opacity-70",children:b?"No messages in this channel":"Public channel messages will appear here"})]}):s.jsxs("div",{className:"px-4 py-4",children:[i&&s.jsx("div",{className:"flex justify-center mb-4",children:s.jsx("button",{onClick:k,disabled:o,className:Ze("px-4 py-1.5 rounded-full","text-[11px] font-medium","ring-1 ring-inset",o?"bg-subtle-fill text-fg-muted ring-edge-subtle cursor-wait":"bg-sys-blue/10 text-sys-blue ring-sys-blue/20 hover:bg-sys-blue/20 hover:ring-sys-blue/30"),children:o?s.jsxs("span",{className:"flex items-center gap-1.5",children:[s.jsx(xe,{className:"size-3 animate-spin"}),"Loading..."]}):"Load older messages"})}),C.map((e,t)=>{if("date"===e.type)return s.jsx("div",{className:"flex justify-center my-4",children:s.jsx("span",{className:Ze("px-3.5 py-1.5 rounded-full","bg-subtle-fill backdrop-blur-sm","text-[11px] text-fg-muted/80 font-medium","ring-1 ring-edge-subtle"),children:e.date})},`date-${e.date}-${t}`);const a=`msg-${e.message.timestamp}-${e.message.senderName||"anon"}-${e.message.channelHash}`;return s.jsx("div",{className:"mb-3",children:s.jsx(st,{message:e.message,onChannelClick:j,isChannelSelected:b===e.message.channelHash})},a)})]})}),s.jsx("div",{className:"flex-shrink-0 px-5 py-2 text-center",children:s.jsxs("p",{className:"text-[11px] text-fg-muted",children:[M.length," messages · ",g," ",1===g?"channel":"channels",o&&s.jsxs("span",{className:"ml-2 text-sys-indigo",children:[s.jsx(xe,{className:"inline size-3 animate-spin mr-1"}),"Decrypting..."]})]})})]})})}function at({isLoaded:t=!0}){ee(Ks);const a=u(),[n,l]=e.useState(!1),[i,o]=e.useState(null),r=N(),c=e.useCallback(()=>{o(null),l(!0),$.getState().queueDecryption(a)},[a]),d=Oe(e=>e.requestedHash),m=Oe(e=>e.clearRequest);e.useEffect(()=>{d&&(o(d),l(!0),$.getState().queueDecryption(a),m())},[d,m,a]);const x=H(),h=P(),f=A(),p=e.useMemo(()=>function(e){const s=[],t=new Set;for(const a of e.values()){const e=a.decoded;if(!e||!e.decrypted||e.macCorrupted||!e.text)continue;const n=et(e.senderName,e.channelHash,e.text);t.has(n)||(t.add(n),s.push({timestamp:a.timestamp,channelName:e.channelName,channelHash:e.channelHash,senderName:e.senderName,text:e.text,rssi:a.rssi,snr:a.snr}))}return s}(x),[x]),g=e.useMemo(()=>{const e=Date.now()/1e3-60*w[r].minutes;return p.filter(s=>s.timestamp>=e)},[p,r]),b=e.useMemo(()=>0===g.length?null:g.reduce((e,s)=>s.timestamp>e.timestamp?s:e),[g]),j=h.isDecoding,v=e.useMemo(()=>{const e=Date.now()/1e3-60*w[r].minutes,s=new Set;let t=0;for(const n of a)(n.type??n.payload_type)===I.GRP_TXT&&((n.timestamp??0)<e||s.has(n.packet_hash)||(s.add(n.packet_hash),t++));return t},[a,r]),y=z(),k=e.useMemo(()=>{const e=Date.now()/1e3-60*w[r].minutes;for(const s of a)if((s.type??s.payload_type)===I.GRP_TXT&&!((s.timestamp??0)<e||y.has(s.packet_hash)))return!0;return!1},[a,y,r]),M=e.useCallback((e,s)=>{if(!j){if(e){const t=s.find(s=>s.hash===e);if(t)return t.name,void $.getState().queueChannelDecryption(a,t.name)}$.getState().queueDecryption(a)}},[a,j]);return t?s.jsxs(s.Fragment,{children:[s.jsx("div",{onClick:c,className:Ze("group cursor-pointer rounded-2xl transition-all duration-150","bg-surface/80 backdrop-blur-lg depth-raised","hover:bg-subtle-fill","px-3 py-2.5 sm:px-4 sm:py-3"),children:s.jsxs("div",{className:"flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between",children:[s.jsxs("div",{className:"flex items-center gap-2 sm:gap-3 flex-shrink-0",children:[s.jsx(Se,{className:"size-4 text-icon-card-title flex-shrink-0"}),s.jsx("span",{className:"type-micro",children:"CHAT ACTIVITY"}),v>0&&s.jsx("span",{className:"inline-flex items-center px-2 py-1 rounded-md bg-subtle-fill ring-1 ring-inset ring-edge-subtle text-sm tabular-nums text-fg-secondary",children:v}),s.jsx(Le,{className:"size-4 text-fg-muted group-hover:text-sys-indigo transition-colors ml-auto sm:hidden"})]}),s.jsxs("div",{className:"flex items-center gap-2 sm:gap-1.5 min-w-0 overflow-hidden",children:[s.jsx(ie,{mode:"wait",initial:!1,children:b?s.jsxs(oe.div,{initial:{opacity:0,y:16},animate:{opacity:1,y:0},exit:{opacity:0,y:-16},transition:{duration:.2,ease:[.4,0,.2,1]},className:"flex items-center gap-2 sm:gap-1.5 min-w-0",children:[b.channelName&&s.jsx("span",{className:"hidden sm:inline-flex",children:s.jsx(Ve,{channelName:b.channelName})}),s.jsx("div",{className:"hidden sm:flex w-[30px] h-[30px] rounded-full items-center justify-center flex-shrink-0 ring-1 ring-edge-subtle",style:{backgroundColor:ss(ts(b.senderName||"").cleanName)},children:ts(b.senderName||"").emoji?s.jsx("span",{className:"text-base",children:ts(b.senderName||"").emoji}):s.jsx("span",{className:"text-white text-xs font-bold tracking-tighter",children:as(b.senderName||"")})}),s.jsx("div",{className:"inline-flex items-center px-3 py-1.5 rounded-2xl rounded-tr-md bg-[#007AFF] shadow-sm min-w-0 flex-1 sm:flex-initial sm:max-w-xs sm:-ml-px",children:s.jsx("span",{className:"text-sm text-white truncate tracking-wide",children:ns(b.text)})}),s.jsx("span",{className:"inline-flex items-center px-2 py-1 rounded-md bg-subtle-fill ring-1 ring-inset ring-edge-subtle text-sm tabular-nums text-fg-secondary flex-shrink-0",children:E(b.timestamp)})]},`msg-${b.timestamp}-${b.senderName}-${b.channelHash}`):f?s.jsx(oe.span,{initial:{opacity:0},animate:{opacity:1},className:"text-sm text-fg-muted italic",children:"No messages yet"},"empty"):s.jsxs(oe.div,{initial:{opacity:0},animate:{opacity:1},exit:{opacity:0,y:-16},transition:{duration:.15},className:"flex items-center gap-2 sm:gap-1.5",children:[s.jsx("div",{className:"hidden sm:block w-8 h-4 rounded bg-subtle-fill-strong animate-pulse"}),s.jsx("div",{className:"hidden sm:block w-[30px] h-[30px] rounded-full bg-subtle-fill-strong animate-pulse"}),s.jsx("div",{className:"h-8 w-32 sm:w-48 rounded-2xl bg-subtle-fill-strong animate-pulse"}),s.jsx("div",{className:"w-12 h-6 rounded-md bg-subtle-fill-strong animate-pulse"})]},"skeleton")}),s.jsx(Le,{className:"size-4 text-fg-muted group-hover:text-sys-indigo transition-colors flex-shrink-0 hidden sm:block ml-1"})]})]})}),s.jsx(tt,{open:n,onClose:()=>l(!1),messages:p,onLoadMore:M,hasMoreToLoad:k,isDecoding:j,initialChannel:i})]}):s.jsx("div",{className:"h-14 rounded-xl bg-elevated/50 animate-pulse"})}function nt(){var t,a;const n=f(),l=V(),i=u(),o=U(),r=e.useRef(!1);o&&!r.current&&(r.current=!0);const d=r.current,m=N(),x=W(),h=J(),g=w[m]??w[4],b=h.isBackgroundLoading&&m>=5,j=null==(t=null==n?void 0:n.config)?void 0:t.radio,v=e.useMemo(()=>j?{sf:j.spreading_factor??10,bw:j.bandwidth??25e4,cr:j.coding_rate??5,preamble:j.preamble_length??8}:null,[j]),y=i.length,k=e.useMemo(()=>y?K(g.minutes,g.buckets,i,n):null,[y,g.minutes,g.buckets,v]),M=e.useMemo(()=>{const e=e=>(null==e?void 0:e.reduce((e,s)=>e+s.count,0))??0,s=e(null==k?void 0:k.received),t=e(null==k?void 0:k.unique_received),a=e(null==k?void 0:k.forwarded),n=e(null==k?void 0:k.dropped),l=e(null==k?void 0:k.transmitted),i=((null==k?void 0:k.time_range_minutes)??g.minutes)/60;return{received:s,uniqueReceived:t,forwarded:a,dropped:n,transmitted:l,rxPerHour:i>0?Math.round(s/i):0,fwdPerHour:i>0?Math.round(a/i):0}},[k,g.minutes]),C=e.useMemo(()=>{if(!i.length)return{totalBytes:0,kbPerHour:0};const e=Date.now()/1e3,s=e-60*g.minutes;let t=0;for(const n of i)n.transmitted||n.timestamp<s||n.timestamp>e||(t+=n.length??n.payload_length??0);const a=g.minutes/60;return{totalBytes:t,kbPerHour:a>0?Math.round(t/1024/a):0}},[i,g.minutes]),S=(null==n?void 0:n.node_name)??(null==(a=null==n?void 0:n.config)?void 0:a.node_name)??"Unknown Node";return e.useEffect(()=>{S&&"Unknown Node"!==S&&(document.title=`pyMC: ${S}`)},[S]),l?s.jsxs(X,{neomorphic:!0,className:"p-8 text-center",children:[s.jsx("p",{className:"type-subheading text-sys-red mb-2",children:"Failed to connect to backend"}),s.jsx("p",{className:"type-body text-fg-muted",children:l}),s.jsx("p",{className:"type-data-sm text-fg-muted mt-4",children:"Make sure the backend is running on port 8000"})]}):s.jsxs(Q,{children:[s.jsx(Y,{title:S,icon:s.jsx(_e,{}),controls:s.jsx(Ke,{ranges:w,selectedIndex:m,onSelect:x,isPending:b})}),s.jsxs(Z,{children:[s.jsx(at,{isLoaded:d}),s.jsx(is,{template:"hero-auto",children:s.jsxs(X,{neomorphic:!0,children:[s.jsx(p,{icon:s.jsx(Re,{}),title:"PACKETS RECEIVED",badge:g.label,badgeColor:"zinc",actions:d?s.jsxs("div",{className:"data-box",children:[C.kbPerHour," KB/hr"]}):s.jsx("div",{className:"data-box opacity-0",children:"0 KB/hr"})}),s.jsxs("div",{className:"flex flex-wrap gap-4 sm:gap-8",children:[s.jsxs("div",{className:"flex items-end gap-2",children:[s.jsx("div",{className:"type-data-xl text-fg-primary",children:d?s.jsx(Pe,{value:M.received,className:"font-mono tabular-nums",priority:"high"}):s.jsx("span",{className:"opacity-30",children:"—"})}),s.jsx(c,{color:"zinc",className:"mb-0.5 sm:mb-1",children:"Total Rx"})]}),s.jsxs("div",{className:"flex items-end gap-2",children:[s.jsx("div",{className:"type-data-xl text-fg-primary",children:d?s.jsx(Pe,{value:M.uniqueReceived,className:"font-mono tabular-nums",priority:"high"}):s.jsx("span",{className:"opacity-30",children:"—"})}),s.jsx(c,{color:"zinc",className:"mb-0.5 sm:mb-1",children:"Unique"})]})]}),s.jsxs("div",{className:"mt-2 flex-1 min-h-0 relative",children:[s.jsx("div",{className:"absolute inset-0 flex items-end gap-1 transition-opacity duration-300 "+(d?"opacity-0 pointer-events-none":"opacity-100"),"aria-hidden":d,children:[45,72,33,58,80,42,65,28,55,75,38,62].map((e,t)=>s.jsx("div",{className:"flex-1 bg-subtle-fill rounded-sm animate-pulse",style:{height:`${e}%`}},t))}),s.jsx("div",{className:"h-full transition-opacity duration-300 "+(d?"opacity-100":"opacity-0"),children:s.jsx(cs,{packets:i,rangeMinutes:g.minutes,bucketCount:g.buckets})})]})]})}),s.jsxs(is,{template:"compact",children:[s.jsx(os,{span:6,lg:4,children:s.jsx(us,{value:M.forwarded,receivedCount:M.received,packets:i,rangeMinutes:g.minutes,bucketCount:g.buckets,timeRangeLabel:g.label,icon:s.jsx(De,{className:"w-4 h-4"}),isLoaded:d})}),s.jsx(os,{span:6,lg:4,children:s.jsx(hs,{value:M.dropped,receivedCount:M.received,packets:i,rangeMinutes:g.minutes,bucketCount:g.buckets,timeRangeLabel:g.label,icon:s.jsx($e,{className:"w-4 h-4"}),isLoaded:d})}),s.jsx(os,{span:12,lg:4,children:s.jsx(js,{stats:n,localHash:null==n?void 0:n.local_hash,receivedBuckets:null==k?void 0:k.received,droppedBuckets:null==k?void 0:k.dropped,forwardedBuckets:null==k?void 0:k.forwarded,bucketDurationSeconds:null==k?void 0:k.bucket_duration_seconds,timeRangeLabel:g.label,isLoaded:d})})]}),s.jsx(Js,{isLoaded:d}),s.jsx(ys,{}),n&&s.jsx(is,{template:"auto",children:s.jsx(es,{nodeName:S,repeaterVersion:n.version,coreVersion:n.core_version,localHash:n.local_hash,publicKey:n.public_key})})]})]})}export{nt as default};
|