Files
op-packages/luci-app-honk/root/etc/honk/dashboard/assets/Nodes-CF-Y3hZu.js
T

6 lines
29 KiB
JavaScript

import{r as j,j as t}from"./vendor-react-Bf71BWbF.js";import{u as V,aM as Ye,B as F,cx as ve,aP as q,a5 as _e,a8 as Se,a7 as ee,a9 as Ke,a as ie,aB as Xe,E as Te,j as Ze,af as en,aT as H,bt as Ce,bu as nn,bw as sn,aG as an,cr as Le,b1 as tn,$ as De,aE as ne,aH as on,bj as Re,aC as rn,bz as ln,ae as $e,T as Q,b2 as me,y as Ge,N as dn,q as se,Q as cn,P as ke,C as un,d1 as Ae,d2 as mn,d3 as Fe,as as pn,aY as bn,am as vn,an as hn,a0 as Ne,aq as fn,ap as ce,a1 as ae,b3 as gn,cs as xn,a2 as he,bb as C,cB as pe,cO as fe,b as ge,cN as jn,bc as yn,J as We,d4 as kn,cH as Nn,d5 as we,cA as wn,aa as Pn,d6 as Mn,d7 as _n,cy as Sn,d8 as Tn,be as Cn,bf as Ln,d9 as Dn,cC as Rn,bn as $n,ac as Gn,I as An,cw as Fn,cW as Wn}from"./index-CXHBmSa5.js";import{F as Bn}from"./FactStrip-BgQ_tYB6.js";import{u as In,C as En,p as On}from"./layout-BRLew_nj.js";import{D as Be,c as Hn}from"./Table-D0NFHHNQ.js";import{T as qn}from"./TimeCell-gSIuLEFc.js";import{A as Vn}from"./AddCircle-Db3HxlxQ.js";import{u as zn}from"./outbounds-f8QoVoCV.js";import{p as Un,b as Qn}from"./policyText-CAFy3qpo.js";import{a as Ie}from"./setup-B5f1cfyO.js";import{$ as Jn}from"./useFilter-DZ8TXqn_.js";import{p as Yn}from"./probe-C8ejAKwA.js";import{P as Kn}from"./PolicyPicker-DSSmYroN.js";import"./useGridSelectionCheckbox-BV96yL-N.js";import"./Virtualizer--Vfl8O3n.js";import"./ListLayout-CPapuywx.js";function Pe({kind:e,color:s}){return t.jsx("i",{className:"rp-marker "+e,style:s?{color:s}:void 0,"aria-hidden":"true"})}function Xn({label:e,groups:s,legend:n,max:a,fmt:l,limit:o=10,showAll:c}){const r=V(),u=Ye(),{ref:d,tip:p,show:m,hide:h}=In(),[k,b]=j.useState(new Set),i=[0,a/4,a/2,3*a/4,a],v=g=>Math.min(100,g/a*100);return t.jsxs("div",{className:"rp-markerplot rp-chart-hover",ref:d,onPointerLeave:h,role:"group","aria-label":e,"aria-describedby":u,children:[t.jsx("ul",{className:"legend",children:n.map(g=>t.jsxs("li",{children:[t.jsx(Pe,{kind:g.kind}),g.label]},g.kind))}),t.jsxs("div",{className:"axis","aria-hidden":"true",children:[t.jsx("span",{}),t.jsx("div",{className:"scale",children:i.map(g=>t.jsx("span",{style:{insetInlineStart:`${v(g)}%`},children:l(g)},g))}),t.jsx("span",{})]}),s.map(g=>t.jsxs("section",{"aria-label":g.label,children:[s.length>1&&t.jsx("h4",{className:"rp-label",children:g.label}),(k.has(g.id)?g.rows:g.rows.slice(0,o)).map(x=>{const N=Object.values(x.values).filter(M=>M!==void 0),T=v(Math.min(...N)),D=v(Math.max(...N));return t.jsxs("div",{className:"row",onPointerMove:M=>m(M,[x.label,...x.details]),children:[t.jsx("span",{className:"name",children:x.label}),t.jsxs("div",{className:"track",role:"img","aria-label":x.label+r("ui.separator")+x.description,children:[i.map(M=>t.jsx("i",{className:"grid",style:{insetInlineStart:`${v(M)}%`}},M)),D>T&&t.jsx("i",{className:"span",style:{insetInlineStart:`${T}%`,width:`${D-T}%`}}),["tick","diamond","dot"].map(M=>x.values[M]===void 0?null:t.jsx("span",{className:"at "+M+(x.values[M]>a?" over":""),style:{insetInlineStart:`${v(x.values[M])}%`},children:t.jsx(Pe,{kind:M,color:M==="dot"?x.tone:void 0})},M))]}),t.jsx("span",{className:"value",children:x.text})]},x.id)}),!k.has(g.id)&&g.rows.length>o&&t.jsx("div",{className:"row more",children:t.jsx(F,{quiet:!0,small:!0,onPress:()=>b(x=>new Set([...x,g.id])),children:c(g.rows.length)})}),g.notes.map(x=>t.jsx("p",{className:"rp-note note",children:x},x))]},g.id)),t.jsx(En,{tip:p})]})}function Zn(e,s,n){const a=new Map((s??[]).map(r=>[r.id,r.name])),l=new Map,o=(r,u)=>{let d=l.get(r);return d||l.set(r,d={id:r,label:u,rows:[],missing:[]}),d};for(const r of e){const u=ve(r),d=n==="protocol"?[["protocol:"+(r.protocol??""),r.protocol??null]]:r.group_ids.length?r.group_ids.map(p=>["group:"+p,a.get(p)??p]):[["group:",null]];for(const[p,m]of d){const h=o(p,m);u?.state==="healthy"&&u.latency_ms!==null?h.rows.push({id:r.id,name:r.name,latest:u.latency_ms,moving:u.moving_avg_ms,avg10:u.avg10_ms}):h.missing.push({id:r.id,name:r.name,state:u?.state==="unavailable"?"unavailable":"unmeasured"})}}const c=[...l.values()];for(const r of c)r.rows.sort((u,d)=>u.latest-d.latest||q(u.name,d.name)),r.missing.sort((u,d)=>q(u.name,d.name));return c.sort((r,u)=>(r.label===null?1:0)-(u.label===null?1:0)||q(r.label??"",u.label??""))}function es(e){const s=e.flatMap(n=>n.rows);return{moving:s.some(n=>n.moving!==null),avg10:s.some(n=>n.avg10!==null)}}function ns(e){const s=e.flatMap(l=>l.rows.flatMap(o=>[o.latest,o.moving??o.latest])).sort((l,o)=>l-o),n=Math.max(10,(On(s,90)??0)*1.25),a=n<=100?20:n<=500?100:n<=2e3?500:1e3;return Math.ceil(n/a)*a}function ss(){const e=_e().data?.resources,s=Se(ee(e,"nodes",{whileLoading:!0})),n=Ke(ee(e,"groups",{whileLoading:!1})),[a,l]=j.useState("group"),o=j.useMemo(()=>Zn(s.data??[],n.data,a),[s.data,n.data,a]);return{nodes:s,by:a,setBy:l,view:o}}const ue=6;function as(){const e=V(),s=ie(),n=Xe(),{nodes:a,by:l,setBy:o,view:c}=ss();if(a.error&&!a.data)return t.jsx(Te,{error:a.error,onRetry:a.refetch});if(!a.data)return t.jsx(Ze,{});if(!a.data.length)return t.jsx(en,{children:e("ui.empty")});const r={ok:n.positive,warn:n.notice,err:n.negative},u=es(c),d=[...new Map(c.flatMap(b=>b.rows).map(b=>[b.id,b])).values()].sort((b,i)=>b.latest-i.latest),p=new Set(c.flatMap(b=>b.missing.filter(i=>i.state==="unavailable").map(i=>i.id))).size,m=d.length?[{label:e("nodes.latency.lowest"),icon:t.jsx(Ce,{}),tint:"c2",value:d[0].name,caption:H(d[0].latest,e)},{label:e("nodes.latency.highest"),icon:t.jsx(nn,{}),tint:"c4",value:d[d.length-1].name,caption:H(d[d.length-1].latest,e)},{label:e("nodes.latency.unavailable"),value:e("nodes.latency.count",{n:p}),icon:t.jsx(sn,{}),tint:"c5",tone:p?"negative":void 0}]:[],h=b=>{const i=De(s,b.slice(0,ue).map(v=>v.name));return b.length>ue?`${i} ${e("nodes.latency.andMore",{n:b.length-ue})}`:i},k=b=>{const i=b.filter(g=>g.state==="unavailable"),v=b.filter(g=>g.state==="unmeasured");return[...i.length?[e("nodes.latency.unavailableList",{n:i.length,names:h(i)})]:[],...v.length?[e("nodes.latency.unmeasuredList",{n:v.length,names:h(v)})]:[]]};return t.jsxs("div",{className:"rp-chart-page",children:[t.jsx(Bn,{facts:m}),t.jsx(an,{title:e("ui.nodeLatency"),note:e("nodes.latency.sample",{n:a.data.length}),aside:t.jsx(tn,{label:e("nodes.latency.by"),value:l,onChange:b=>o(b),items:[["group",e("nodes.latency.byGroup")],["protocol",e("nodes.latency.byProtocol")]]}),children:t.jsx(Xn,{label:e("ui.nodeLatency"),max:ns(c),fmt:b=>H(b,e),showAll:b=>e("nodes.latency.showAll",{n:b}),legend:[{kind:"dot",label:e("nodes.latency.latest")},...u.moving?[{kind:"diamond",label:e("nodes.latency.moving")}]:[],...u.avg10?[{kind:"tick",label:e("nodes.latency.avg10")}]:[]],groups:c.map(b=>({id:b.id,label:b.label??e(l==="group"?"nodes.latency.noGroup":"nodes.latency.noProtocol"),rows:b.rows.map(i=>{const v=[e("ui.valuePair",{label:e("nodes.latency.latest"),value:H(i.latest,e)}),...u.moving?[e("ui.valuePair",{label:e("nodes.latency.moving"),value:H(i.moving,e)})]:[],...u.avg10?[e("ui.valuePair",{label:e("nodes.latency.avg10"),value:H(i.avg10,e)})]:[]];return{id:i.id,label:i.name,values:{dot:i.latest,diamond:i.moving??void 0,tick:i.avg10??void 0},text:H(i.latest,e),tone:r[Le(i.latest)],description:v.join(e("ui.separator")),details:v}}),notes:k(b.missing)}))})})]})}function ts({model:e}){const s=V();return t.jsxs(t.Fragment,{children:[e.canManage&&t.jsxs("div",{className:"rp-toolbar",children:[t.jsx("span",{className:"rp-grow"}),t.jsx(F,{small:!0,onPress:e.onAdd,children:s("nodes.addProvider")})]}),t.jsx(Be,{label:s("nodes.providers"),loading:e.loading,rows:e.rows,height:280,fit:!0,selected:e.selected,onSelect:e.onSelect,selectOnFocus:!0,empty:s("nodes.noProviders"),cols:[{id:"name",label:s("nodes.provider"),minWidth:140,grow:2,isRowHeader:!0,render:n=>t.jsx("span",{className:"rp-chain",children:t.jsx(ne,{text:n.url,children:n.name})})},{id:"kind",label:s("nodes.kindLabel"),minWidth:150,grow:0,drop:5,render:n=>t.jsx(on,{children:n.kind})},{id:"count",label:s("nodes.count"),minWidth:80,grow:0,align:"end",drop:6,render:n=>n.count},{id:"usage",label:s("nodes.usage"),minWidth:200,drop:2,render:n=>n.usage},{id:"updated",label:s("nodes.updated"),minWidth:140,drop:3,render:n=>t.jsx(qn,{at:n.updatedAt})},{id:"interval",label:s("nodes.interval"),minWidth:130,grow:0,drop:4,render:n=>n.hasInterval&&e.writable?t.jsx(ne,{text:e.sourceTip,children:t.jsx(Re,{quiet:!0,label:n.intervalLabel,value:n.intervalValue,isDisabled:e.sourceBusy,onChange:n.setInterval,items:n.intervals,children:n.interval})}):n.interval},{id:"expires",label:s("nodes.expires"),minWidth:140,drop:1,render:n=>n.expires},{id:"status",label:s("ui.state"),minWidth:96,grow:0,drop:7,render:n=>n.status?t.jsx(rn,{small:!0,tone:n.tone,children:t.jsx(ne,{text:n.error,children:n.status})}):"—"},{id:"actions",label:s("ui.actions"),minWidth:e.canManage?112:88,grow:0,render:n=>t.jsxs("span",{className:"rp-chain",children:[n.refreshable&&t.jsx(F,{small:!0,quiet:!0,icon:!0,isPending:n.refreshing,isDisabled:n.refreshDisabled,label:n.refreshLabel,onPress:n.refresh,children:t.jsx(ln,{className:"rp-spin-on-press"})}),n.removable&&t.jsx(F,{small:!0,quiet:!0,icon:!0,isDisabled:e.busy,label:n.removeLabel,onPress:n.remove,children:t.jsx($e,{})})]})}]})]})}const Ee=j.createContext(null);function os({row:e}){const s=j.useContext(Ee);return t.jsx(F,{small:!0,quiet:!0,icon:!0,isPending:s===e.id,isDisabled:!!s,label:e.probeLabel,onPress:e.probe,children:t.jsx(Ce,{})})}function rs({model:e}){const s=V(),{canManage:n,writable:a,sourceBusy:l,busy:o}=e,c=j.useMemo(()=>[{id:"name",label:s("nodes.node"),minWidth:150,grow:2,isRowHeader:!0,sortable:!0,render:r=>t.jsx("span",{className:"rp-chain",children:t.jsx(ne,{children:r.name})})},{id:"protocol",label:s("nodes.protocol"),minWidth:144,grow:0,drop:2,sortable:!0,render:r=>r.protocol},{id:"latency",label:s("nodes.latency"),minWidth:96,grow:0,align:"end",sortable:!0,render:r=>t.jsx("span",{className:r.latencyClass,children:r.latency})},{id:"groups",label:s("nodes.groups"),minWidth:200,drop:1,render:r=>t.jsx(ne,{children:r.groups})},{id:"actions",label:s("ui.actions"),minWidth:n?108:72,grow:0,render:r=>t.jsxs("span",{className:"rp-chain",children:[r.canProbe&&t.jsx(os,{row:r}),a&&t.jsx(Re,{quiet:!0,chevron:!1,label:r.joinLabel,isDisabled:l,items:r.menu,onAction:r.join,children:t.jsx(Vn,{})}),r.removable&&t.jsx(F,{small:!0,quiet:!0,icon:!0,isDisabled:o,label:r.removeLabel,onPress:r.remove,children:t.jsx($e,{})})]})}],[s,n,a,l,o]);return t.jsxs(t.Fragment,{children:[e.writable&&e.sourceTip&&t.jsx("p",{className:"rp-note",children:e.sourceTip}),t.jsxs("div",{className:"rp-toolbar",children:[t.jsx(Q,{label:s("nodes.search"),search:!0,value:e.search,width:240,onChange:e.setSearch}),t.jsx(me,{label:s("nodes.group"),side:!0,value:e.group,onChange:e.setGroup,items:e.groups}),t.jsx(me,{label:s("nodes.protocol"),side:!0,value:e.protocol,onChange:e.setProtocol,items:e.protocols}),t.jsx("span",{className:"rp-label",children:e.shown}),t.jsx("span",{className:"rp-grow"}),e.canManage&&t.jsx(F,{small:!0,onPress:e.onAdd,children:s("nodes.addNode")})]}),t.jsx(Ee.Provider,{value:e.probeBusy,children:t.jsx(Be,{label:e.label,loading:e.loading,rows:e.rows,height:520,empty:s("nodes.empty"),sort:e.sort,onSort:e.setSort,cols:c})})]})}function is(e){const s=/^(\d+(?:\.\d+)?)(ms|s|m|h)?$/.exec(e.trim());if(!s)return null;const n={ms:1/1e3,s:1,m:60,h:3600};return Math.ceil(Number(s[1])*(n[s[2]??"s"]??1))}function re(e){if(!e)return null;try{return new URL(e).hostname||null}catch{return null}}function ls(e){const s=un(e).trim(),{tokens:n}=Ge(s),a=n[0];if(!a)return null;const l=s.slice(a.from,a.to),o=n[1],c=o&&s.slice(o.from,o.to)===":"&&!s.slice(o.to).startsWith("//"),r=c?o.to:0,u=n.find(b=>b.from>=r);if(!u)return null;const d=u.kind==="quoted";let p=d?se(s.slice(u.from,u.to)):s.slice(r).trim(),m=c?se(l):null;if(!m){const b=p.indexOf(":");b!==-1&&!p.startsWith("://",b)?(m=p.slice(0,b).trim(),p=p.slice(b+1)):m=re(p)}const h=d?s.slice(u.to).trim():"",k=h.startsWith("(")&&h.endsWith(")")?se(h.slice(1,-1)):null;return h&&k===null?null:m?{tag:m,url:p,ua:k}:null}function Oe(e){const{blocks:s,tokens:n}=Ge(e),a=[];for(const l of s.filter(o=>o.name==="subscription"))for(let o=0;o<n.length;o++){const c=n[o];if(c.from<=l.open||c.from>=l.close||c.depth!==l.depth+1||c.kind==="comment")continue;const r=e.lastIndexOf(`
`,c.from-1)+1,u=/^[ \t]*$/.test(e.slice(r,c.from))?r:c.from,d=l.children.find(i=>i.from===c.from);if(d){for(;n[o+1]?.from<d.to;)o++;if(d.line===d.endLine)continue;const i=dn(e,d,n),v=i.find(x=>x.name==="url"),g=i.find(x=>x.name==="interval");a.push({from:u,to:d.to,block:d,tag:d.name,host:v?re(se(v.value)):null,interval:g?is(se(g.value)):null,fields:i,parts:null});continue}const p=n[o+1];p&&e.slice(p.from,p.to)===":"&&!e.slice(p.to).startsWith("//")&&(o+=2);const m=n[o];if(!m||m.from>=l.close)break;if(m.kind!=="quoted")for(;n[o+1]?.from===n[o].to&&!/[(){}]/.test(e.slice(n[o+1].from,n[o+1].to));)o++;if(e[n[o+1]?.from]==="(")for(o++;n[o+1]&&!(e[n[o].from]===")"&&n[o].parens===1);)o++;let h=n[o].to,k;n[o+1]?.kind==="comment"&&n[o+1].line===n[o].line&&(k=e.slice(n[o+1].from,n[o+1].to),h=n[++o].to);const b=ls(e.slice(u,h));b&&a.push({from:u,to:h,tag:b.tag,host:re(b.url),interval:null,fields:[],parts:b,comment:k})}return a}function ds(e){return Oe(e).map(({tag:s,host:n,interval:a})=>({tag:s,host:n,interval:a}))}function cs(e,s,n){const a=Oe(e).find(u=>u.tag===s);if(!a||a.interval===n)return e;const l=e.slice(a.from,a.to).match(/^[ \t]*/)?.[0]??" ",o=l+(l.includes(" ")?" ":" ");if(a.parts){const u=[`${l}${cn(s)}: {`,`${o}url: ${ke(a.parts.url)}`];return a.parts.ua!==null&&u.push(`${o}ua: ${ke(a.parts.ua)}`),u.push(`${o}interval: '${n}s'`,`${l}}${a.comment?" "+a.comment:""}`),e.slice(0,a.from)+u.join(`
`)+e.slice(a.to)}const c=a.fields.find(u=>u.name==="interval");if(c)return e.slice(0,c.valueFrom)+` '${n}s'`+e.slice(c.valueTo);if(!a.block)return e;const r=e.lastIndexOf(`
`,a.block.close-1)+1;return e.slice(0,r)+`${o}interval: '${n}s'
`+e.slice(r)}function us(e,s,n,a){const l=ve(e),o=l?.state==="healthy"&&l.latency_ms!=null;return{id:e.id,name:e.name,protocol:e.protocol??"—",latency:o?H(l.latency_ms,a):l?.state==="unavailable"?a("ui.unavailable"):"—",latencyClass:o?`ms ${Le(l.latency_ms)}`:l?.state==="unavailable"?"ms err":"ms",groups:e.group_ids.length?De(n,e.group_ids.map(c=>s.get(c)??c)):"—",probeLabel:a("nodes.probe",{name:e.name}),joinLabel:a("nodes.joinGroup",{name:e.name}),removeLabel:a("nodes.remove",{name:e.name})}}const ms=e=>gn(ve(e));function ps(e,s,n,a){const l=new Map;for(const i of s){if(!i.provider_id||!i.subscription_tag)continue;const v=l.get(i.provider_id)??new Set;v.add(i.subscription_tag),l.set(i.provider_id,v)}const o=i=>{const v=l.get(i);return v?.size===1?[...v][0]:void 0},c=i=>{const v=re(i.url_redacted),g=v?n.filter(x=>x.host===v):[];return g.length===1?g[0].tag:void 0},r=new Map,u=e.filter(i=>i.kind==="subscription");for(const i of u){const v=o(i.id)??c(i);v&&r.set(i.id,v)}const d=u.filter(i=>!r.has(i.id)),p=new Set(r.values()),m=n.filter(i=>!p.has(i.tag));d.length===1&&m.length===1&&r.set(d[0].id,m[0].tag);const h=e.map(i=>{const v=o(i.id);return{...i,displayName:r.get(i.id)??i.name,configTag:i.kind==="subscription"&&v&&n.filter(g=>g.tag===v).length===1?v:void 0}}),k={builtin:0,unattributed:0};for(const i of s)i.provider_id==null&&k[Ae(i)]++;const b=[];for(const i of["builtin","unattributed"]){const v=k[i];v&&b.push({id:mn(i,e),name:a(i==="builtin"?"nodes.kind.builtin":"nodes.kind.unattributed"),kind:i,url_redacted:null,node_count:v,updated_at:null,expires_at:null,traffic:null,status:"ok",last_error:null})}return{list:[...b,...h]}}function bs(e,s){return s!==null&&e.some(n=>n.id===s)?s:(e.find(n=>n.kind!=="builtin"&&n.kind!=="unattributed")??e[0])?.id??null}function vs(e,s,n){return e.filter(a=>s===void 0||(s===null?a.provider_id==null&&Ae(a)==="builtin"==(n==="builtin"):a.provider_id===s))}function hs(e,s,n,a,l,o){const c=s.trim(),r=e.filter(m=>(!c||o(m.name,c))&&(!n||m.group_ids.includes(n))&&(!a||m.protocol===a)),u=l.direction==="ascending"?1:-1,d=l.column==="latency"?new Map(r.map(m=>[m.id,ms(m)])):new Map,p={name:(m,h)=>q(m.name,h.name),protocol:(m,h)=>q(m.protocol??"",h.protocol??""),latency:(m,h)=>xn(d.get(m.id),d.get(h.id))||q(m.name,h.name)};return r.sort((m,h)=>u*(p[l.column]??p.name)(m,h))}const be=[3600,21600,43200,86400];function xe(e,s,n){return e===0?n("nodes.manualOnly"):be.includes(e)?n("nodes.everyHours",{n:e/3600}):pn(String(e),s)}function He(e,s,n){return[0,...be,...e===null||e===0||be.includes(e)?[]:[e]].map(a=>({id:String(a),label:xe(a,s,n)}))}function fs(e,s){const n={name:e.name.trim(),kind:"subscription",url:e.value.trim()},a=Number(e.interval);s?.update_interval!==void 0&&e.interval&&a!==s.update_interval&&(n.update_interval=a);const l=e.agent.trim();return s?.user_agent!==void 0&&l&&l!==s.user_agent&&(n.user_agent=l),s?.cache!==void 0&&e.cache!==null&&e.cache!==s.cache&&(n.cache=e.cache),n}function gs(e,s,n,a){const l={subscription:"nodes.kind.subscription",file:"nodes.kind.file",inline:"nodes.kind.inline",builtin:"nodes.kind.builtin",unattributed:"nodes.kind.unattributed"},o={ok:"nodes.status.ok",stale:"nodes.status.stale",error:"nodes.status.error"},c={ok:"ok",stale:"warn",error:"err"},r=e.kind==="builtin"||e.kind==="unattributed",u=e.traffic?bn(e.traffic.upload_bytes,e.traffic.download_bytes):null,d=e.kind==="subscription"?s:void 0,p=e.displayName??e.name;return{id:e.id,name:p,url:e.url_redacted??void 0,kind:Ne(l,e.kind,a),count:ae(e.node_count,n),usage:u===null?"—":e.traffic?.total_bytes?a("ui.fraction",{part:ce(u,n),whole:ce(e.traffic.total_bytes,n)}):ce(u,n),updatedAt:r?null:e.updated_at,expires:e.expires_at?fn(e.expires_at,n):"—",interval:d==null?"—":xe(d,n,a),intervalValue:d==null?"":String(d),hasInterval:d!==void 0,intervalLabel:a("nodes.intervalOf",{name:p}),intervals:d===void 0?[]:He(d,n,a),status:r?null:Ne(o,e.status,a),tone:c[e.status],error:e.last_error?vn(hn(e.last_error.code,e.last_error.message,a),a):void 0,refreshLabel:a("nodes.refresh",{name:p}),removeLabel:a("nodes.remove",{name:p})}}const qe=e=>/^[a-z][a-z0-9+.-]*:\/\/\S+$/i.test(e.trim());function xs(e,s,n,a){const l=s.trim();return e!=="provider"&&e!=="node"||!l&&!n.trim()?null:l?e==="node"?qe(n)?null:a("nodes.linkInvalid"):Fe(l)?Ie(n)?null:a("nodes.urlInvalid"):a("nodes.nameInvalid"):a("nodes.nameMissing")}function js(e){const s=V(),n=he[ie()],{refresh:a}=e,l=new Map(e.entries.map(c=>[c.tag,c.interval]));return{rows:e.rows.map(c=>({...gs(c,c.configTag?l.get(c.configTag):void 0,n,s),refreshable:c.kind==="subscription"&&e.canRefresh,refreshing:a.busy===c.id,refreshDisabled:!!a.busy,refresh:()=>void a.refresh(c.id).then(r=>{r&&("degraded"in r?C("info",s("nodes.refreshedDegraded",{name:c.name})):C("positive",s("nodes.refreshed",{name:c.name,n:ae(r.node_count,n)})))},r=>fe(r,s,s("nodes.refreshFailed",{name:c.name}))),removable:e.canManage&&(c.kind==="subscription"||c.kind==="file"),remove:()=>{(c.kind==="subscription"||c.kind==="file")&&e.onRemove(c)},setInterval:r=>{if(!c.configTag)return;const u=Number(r);e.source.apply(d=>cs(d,c.configTag,u)).then(d=>{d.kind==="ok"&&C("positive",s("nodes.intervalSet",{name:c.name,interval:xe(u,n,s)}));const p=pe(d,s);p&&C(p.kind,p.text,{detail:p.detail})})}})),loading:e.loading,selected:e.selected,onSelect:e.onSelect,canManage:e.canManage,busy:e.busy,writable:e.source.writable,sourceBusy:e.source.busy||!e.source.main,sourceTip:e.source.error?ge(e.source.error,s):void 0,onAdd:e.onAdd}}function ys(e){const{nodes:s,names:n,providers:a,source:l,query:o,reload:c,joinGroup:r,onNewGroup:u,onRemove:d,canManage:p}=e,m=V(),h=ie(),k=he[h],b=jn(c),[i,v]=j.useState(o??"");yn(o,f=>v(f??""));const[g,x]=j.useState(""),[N,T]=j.useState(""),[D,M]=j.useState({column:"name",direction:"ascending"}),W=j.useMemo(()=>[...new Set(s.flatMap(f=>f.group_ids))].sort((f,P)=>q(n.get(f)??f,n.get(P)??P)).map(f=>({id:f,label:n.get(f)??f})),[s,n]),$=j.useMemo(()=>[...new Set(s.map(f=>f.protocol??""))].filter(Boolean).sort(q).map(f=>({id:f,label:f})),[s]),S=W.some(f=>f.id===g)?g:"",B=$.some(f=>f.id===N)?N:"",{contains:L}=Jn({sensitivity:"base"}),G=j.useMemo(()=>hs(s,i,S,B,D,L),[s,i,S,B,D,L]),w=j.useMemo(()=>We(l.main?.content??"").map(f=>({...f,names:new Set(kn(f))})),[l.main?.content]),I=j.useMemo(()=>new Map(s.map(f=>[f.id,new Set(f.group_ids.map(P=>n.get(P)??P))])),[s,n]),K=j.useMemo(()=>new Set(a.filter(f=>f.kind==="inline").map(f=>f.id)),[a]),{probe:z,canProbe:J,busy:le}=b,Y=j.useCallback(f=>({...us(f,n,h,m),canProbe:J&&!Nn(f.protocol),probe:()=>void z(f.id).then(P=>{if(!P)return;const{kind:de,text:oe}=Yn(P,f.id,f.name,m);C(de,oe)},P=>fe(P,m,m("nodes.probeError",{name:f.name}))),menu:()=>[...w.filter(P=>!P.names.has(f.name)&&!I.get(f.id)?.has(P.name)).map(P=>({id:P.name,label:P.name,desc:Un(P.policy,m)})),{id:"/new",label:m("nodes.newGroup")}],join:P=>P==="/new"?u(f):r(f,P),removable:p&&typeof f.provider_id=="string"&&K.has(f.provider_id),remove:()=>d(f)}),[n,h,J,z,m,w,I,u,r,p,K,d]),X=j.useMemo(()=>({build:Y,rows:new WeakMap}),[Y]),te=j.useMemo(()=>Hn(X.rows,G,X.build),[X,G]);return{rows:te,probeBusy:le,search:i,setSearch:v,group:S,setGroup:x,protocol:B,setProtocol:T,sort:D,setSort:M,groups:[{id:"",label:m("nodes.anyGroup")},...W],protocols:[{id:"",label:m("nodes.anyProtocol")},...$],shown:m("ui.fraction",{part:ae(te.length,k),whole:ae(s.length,k)}),loading:e.loading,label:e.label,canManage:p,busy:e.busy,writable:l.writable,sourceBusy:l.busy||!l.main,sourceTip:l.error?ge(l.error,m):void 0,onAdd:e.onAdd}}const Me={name:"",value:"",interval:"",agent:"",cache:null};function ks({go:e,query:s}){const n=V(),[a,l]=j.useState(null),[o,c]=j.useState(Me),[r,u]=j.useState(we[0].id),d=j.useRef(0),p=j.useRef(null),[m,h]=j.useState(null),[k,b]=j.useState(null),i=wn(!!a&&!!(o.name||o.value),()=>{d.current++,l(null)}),v=j.useCallback(y=>{d.current++,c(Me),u(we[0].id),b(null),l(y)},[]),g=he[ie()],x=_e().data?.resources,N=Pn(ee(x,"providers",{whileLoading:!0})),T=Se(ee(x,"nodes",{whileLoading:!0})),D=zn(),{refetch:M}=N,{refetch:W}=T,$=j.useCallback(()=>{M(),W()},[M,W]),S=Mn($),B=_n($),L=Sn(),G=j.useMemo(()=>ds(L.main?.content??""),[L.main?.content]),w=j.useMemo(()=>new Set(We(L.main?.content??"").map(y=>y.name)),[L.main?.content]),{list:I}=j.useMemo(()=>ps(N.data?.providers??[],T.data??[],G,n),[N.data,T.data,G,n]),K=j.useMemo(()=>new URLSearchParams(s),[s]),z=bs(I,K.get("provider")),J=I.find(y=>y.id===z)??null,le=j.useMemo(()=>{const y=I.find(R=>R.id===z);return vs(T.data??[],y?.kind==="builtin"||y?.kind==="unattributed"?null:y?.id,y?.kind)},[T.data,I,z]),{apply:Y}=L,X=j.useCallback((y,R)=>{Y(U=>Tn(U,R,[y.name])).then(U=>{U.kind==="ok"&&C("positive",n("nodes.joined",{name:y.name,group:R}));const _=pe(U,n);_&&C(_.kind,_.text,{detail:_.detail})})},[Y,n]),te=j.useCallback(()=>v({kind:"node"}),[v]),f=j.useCallback(y=>v({kind:"group",item:y}),[v]),P=j.useCallback(y=>v({kind:"removeNode",item:y}),[v]),de=async y=>{if(!a||p.current)return;p.current=a,h(a);const R=d.current,U=_=>{d.current===R?b(A=>({id:(A?.id??0)+1,text:_})):C("negative",_)};try{if(a.kind==="provider"){const _=await S.addProvider(fs(o,E));if(!_)return;const A=o.name.trim();if(x?.providers.can_refresh){d.current===R&&(i.clear(),y());const Z=()=>void B.refresh(_.id).then(O=>{O&&("degraded"in O?C("info",n("nodes.refreshedDegraded",{name:A})):C("positive",n("nodes.addedRefreshed",{name:A,n:ae(O.node_count,g)})))},O=>fe(O,n,n("nodes.addedRefreshFailed",{name:A}),{label:n("ui.retry"),onAction:Z,closeOnAction:!0}));Z();return}C("positive",n("nodes.added",{name:A}))}else if(a.kind==="node"){const _=await S.addNode({name:o.name.trim(),link:o.value.trim()});if(!_)return;C("positive",n("nodes.added",{name:_.name}))}else if(a.kind==="group"){const _=o.name.trim(),A=a.item.name,Z=await Y(Je=>Dn(Je,[{kind:"createGroup",group:_,policy:r},{kind:"addNode",group:_,value:A}])),O=pe(Z,n);if(O&&U(Rn(O,n)),Z.kind!=="ok")return;C("positive",n("nodes.joined",{name:A,group:_}))}else if(a.kind==="removeProvider"){if(!await S.removeProvider(a.item.id))return;C("positive",n("nodes.removed",{name:a.item.name}))}else{if(!await S.removeNode(a.item.id))return;C("positive",n("nodes.removed",{name:a.item.name}))}d.current===R&&(i.clear(),y())}catch(_){U(ge(_,n))}finally{p.current=null,h(null)}},oe=a?.kind==="removeProvider"||a?.kind==="removeNode",Ve=a===null?"":a.kind==="provider"?n("nodes.addProvider"):a.kind==="node"?n("nodes.addNode"):a.kind==="group"?n("nodes.newGroup"):n(a.kind==="removeProvider"?"nodes.removeProviderTitle":"nodes.removeNodeTitle",{name:a.item.name}),je=a?.kind==="group"?Qn(o.name.trim(),w,n):null,E=x?.providers.create_options,ye=/^[\x20-\x7E]{0,256}$/.test(o.agent.trim())?null:n("nodes.agentInvalid"),ze=a?.kind==="provider"?Fe(o.name.trim())&&Ie(o.value)&&!ye:a?.kind==="node"?o.name.trim()!==""&&qe(o.value):a?.kind==="group"?je===null:!0,Ue=js({rows:I,loading:N.loading&&!N.data,selected:z,onSelect:y=>{if(!y)return;const R=new URLSearchParams(s);R.set("provider",y),e("nodes",R.toString(),{replace:!0})},canManage:!!x?.providers.can_manage,canRefresh:!!x?.providers.can_refresh,busy:!!S.busy,source:L,entries:G,reload:$,refresh:B,onAdd:()=>v({kind:"provider"}),onRemove:y=>v({kind:"removeProvider",item:y})}),Qe=ys({nodes:le,providers:N.data?.providers??[],names:D,loading:T.loading&&!T.data,label:J?n("nodes.of",{name:J.displayName??J.name}):n("nav.nodes"),query:K.get("q"),source:L,canManage:!!x?.nodes.can_manage,busy:!!S.busy,reload:W,joinGroup:X,onAdd:te,onNewGroup:f,onRemove:P});return{measured:ee(x,"nodes",{whileLoading:!0}),tab:Ln(s,["list","latency"],"list"),setTab:y=>e("nodes",Cn(s,y,"list")),providerTable:Ue,nodeTable:Qe,error:N.error??T.error,reload:$,dialog:a,setDialog:y=>{d.current++,b(null),l(y)},problem:k,form:o,setForm:y=>{p.current!==a&&c(y)},removing:oe,dialogTitle:Ve,formValid:ze,formReason:xs(a?.kind,o.name,o.value,n),submit:de,pending:a!==null&&m===a,submitting:m!==null,submitLabel:oe?n("nodes.remove",{name:a.item.name}):a?.kind==="group"?n("nodes.join"):n("nodes.add"),groupHelp:a?.kind==="group"?n("nodes.newGroupHelp",{name:a.item.name}):"",groupNameError:o.name.trim()?je:null,agentError:ye,options:E&&{intervals:E.update_interval===void 0?null:He(E.update_interval,g,n),interval:o.interval||String(E.update_interval),agent:E.user_agent,cache:E.cache===void 0?null:o.cache??E.cache},policy:r,setPolicy:y=>{p.current!==a&&u(y)}}}function Is(e){const s=V(),{measured:n,tab:a,setTab:l,providerTable:o,nodeTable:c,error:r,reload:u,dialog:d,setDialog:p,problem:m,form:h,setForm:k,removing:b,dialogTitle:i,formValid:v,formReason:g,submit:x,pending:N,submitting:T,submitLabel:D,groupHelp:M,groupNameError:W,agentError:$,options:S,policy:B,setPolicy:L}=ks(e),G=t.jsxs(t.Fragment,{children:[t.jsx("p",{className:"rp-note",children:s("nodes.note")}),t.jsx(Te,{error:r,onRetry:u}),t.jsx(ts,{model:o}),t.jsx(rs,{model:c})]});return t.jsxs("div",{className:"rp-page",children:[n?t.jsx($n,{keepMounted:!0,label:s("nav.nodes"),value:a,onChange:l,items:[{id:"list",label:s("nodes.tab.list"),content:G},{id:"latency",label:s("nodes.tab.latency"),content:t.jsx(as,{})}]}):G,t.jsxs(Gn,{title:i,narrow:!0,isOpen:d!==null&&!b,reason:N?null:g,onOpenChange:w=>{w||p(null)},footer:w=>t.jsxs(t.Fragment,{children:[t.jsx(F,{onPress:w,children:s("ui.cancel")}),t.jsx(F,{accent:!0,isDisabled:!v||T,isPending:N,onPress:()=>void x(w),children:D})]}),children:[m&&t.jsx(An,{takeFocus:!0,children:m.text},m.id),d?.kind==="provider"&&t.jsxs("div",{className:"rp-list",children:[t.jsx("span",{className:"rp-label",children:s("nodes.addProviderHelp")}),t.jsx(Q,{isDisabled:N,label:s("nodes.name"),value:h.name,placeholder:"sub-a",onChange:w=>k({...h,name:w})}),t.jsx(Q,{isDisabled:N,label:s("nodes.url"),value:h.value,placeholder:"https://example.org/sub?token=…",onChange:w=>k({...h,value:w})}),S?.intervals&&t.jsx(me,{label:s("nodes.interval"),items:S.intervals,value:S.interval,isDisabled:N,onChange:w=>k({...h,interval:w})}),S?.agent!==void 0&&t.jsx(Q,{isDisabled:N,label:s("nodes.agent"),value:h.agent,placeholder:S.agent,error:$??void 0,spellCheck:!1,onChange:w=>k({...h,agent:w})}),S?.cache!=null&&t.jsxs(t.Fragment,{children:[t.jsx(Fn,{isSelected:S.cache,isDisabled:N,onChange:w=>k({...h,cache:w}),children:s("nodes.cache")}),t.jsx("span",{className:"rp-label",children:s("nodes.cacheHelp")})]})]}),d?.kind==="group"&&t.jsxs("div",{className:"rp-list",children:[t.jsx("span",{className:"rp-label",children:M}),t.jsx(Q,{isDisabled:N,label:s("nodes.name"),value:h.name,placeholder:"hk",spellCheck:!1,description:s("arrange.groupNameHint"),error:W??void 0,onChange:w=>k({...h,name:w})}),t.jsx(Kn,{value:B,onChange:L,isDisabled:N})]}),d?.kind==="node"&&t.jsxs("div",{className:"rp-list",children:[t.jsx("span",{className:"rp-label",children:s("nodes.addNodeHelp")}),t.jsx(Q,{isDisabled:N,label:s("nodes.name"),value:h.name,placeholder:"hk-03",onChange:w=>k({...h,name:w})}),t.jsx(Q,{isDisabled:N,label:s("nodes.link"),value:h.value,placeholder:"vless://…",onChange:w=>k({...h,value:w})})]})]}),t.jsx(Wn,{title:i,isOpen:b,onCancel:()=>p(null),confirmLabel:D,isPending:N,isDisabled:T,error:m,onConfirm:()=>void x(()=>p(null)),children:t.jsx("p",{className:"rp-label",children:s(d?.kind==="removeProvider"?"nodes.removeProviderHelp":"nodes.removeNodeHelp")})})]})}export{Is as Nodes};