From fc14d5bbcd153f161eaabc1f9525ce69c965aaa3 Mon Sep 17 00:00:00 2001 From: kazeyukiro Date: Fri, 2 Oct 2026 03:40:06 +0000 Subject: [PATCH] ui(dashboard): mono total-rate chart; drop username from share URI names Speed chart is a single muted total (up+down) series; metric sparklines use secondary text color only. HY2/AnyTLS share fragments use node name without appending the panel username. --- backend/internal/node/uri_builders.go | 14 ++---- frontend/src/pages/Dashboard.tsx | 69 +++++++++++---------------- 2 files changed, 33 insertions(+), 50 deletions(-) diff --git a/backend/internal/node/uri_builders.go b/backend/internal/node/uri_builders.go index bf521a7..4a85817 100644 --- a/backend/internal/node/uri_builders.go +++ b/backend/internal/node/uri_builders.go @@ -410,12 +410,9 @@ func hysteria2URIs(name, host, port string, cfg map[string]interface{}) ([]strin if v, ok := cfg["down"].(string); ok && v != "" { params["down"] = v } - display := name - if username != "" && username != name { - display = name + " - " + username - } + _ = username userinfo := url.User(password).String() - result = append(result, addName(query("hysteria2://"+userinfo+"@"+netutil.JoinHostPort(host, port), params), display)) + result = append(result, addName(query("hysteria2://"+userinfo+"@"+netutil.JoinHostPort(host, port), params), name)) } return result, nil } @@ -544,11 +541,8 @@ func anytlsURIs(name, host, port string, cfg map[string]interface{}) ([]string, if v, ok := cfg["min-idle-session"].(string); ok && v != "" { params["min_idle_session"] = v } - display := name - if username != "" && username != name { - display = name + " - " + username - } - result = append(result, addName(query("anytls://"+url.User(password).String()+"@"+netutil.JoinHostPort(host, port), params), display)) + _ = username + result = append(result, addName(query("anytls://"+url.User(password).String()+"@"+netutil.JoinHostPort(host, port), params), name)) } return result, nil } diff --git a/frontend/src/pages/Dashboard.tsx b/frontend/src/pages/Dashboard.tsx index 59fd6e7..c3e4a9d 100644 --- a/frontend/src/pages/Dashboard.tsx +++ b/frontend/src/pages/Dashboard.tsx @@ -60,50 +60,49 @@ const Sparkline: React.FC<{ // Straight segments only (no smooth curve) โ€” reads like a real counter strip. const line = coords.map(([x, y]) => `${x.toFixed(1)},${y.toFixed(1)}`).join(' '); const baseline = coords.map(([x]) => `${x.toFixed(1)},${(h - 1).toFixed(1)}`).join(' '); - const last = coords[coords.length - 1]; return ( - + - ); }; -/** Dual-series rate chart โ€” solid grid, hairline strokes, no gradient wash. */ +/** Single-series total rate chart โ€” one muted stroke, plain grid. */ const SpeedChart: React.FC<{ up: number[]; down: number[]; - upColor: string; - downColor: string; + color: string; height?: number; -}> = ({ up, down, upColor, downColor, height = 168 }) => { +}> = ({ up, down, color, height = 160 }) => { const w = 480; const h = height; const n = Math.max(up.length, down.length, 2); - const all = [...up, ...down]; - const max = Math.max(...all, 1); - const toPts = (series: number[]) => { - const pad = series.length < n ? Array(n - series.length).fill(0).concat(series) : series.slice(-n); - return pad.map((v, i) => { + const total: number[] = []; + for (let i = 0; i < n; i++) { + const u = up[up.length - n + i] ?? 0; + const d = down[down.length - n + i] ?? 0; + total.push(Math.max(0, u) + Math.max(0, d)); + } + const max = Math.max(...total, 1); + const line = total + .map((v, i) => { const x = (i / (n - 1)) * w; - const y = h - (Math.max(0, v) / max) * (h - 12) - 6; + const y = h - (v / max) * (h - 12) - 6; return `${x.toFixed(1)},${y.toFixed(1)}`; - }).join(' '); - }; - const upLine = toPts(up); - const downLine = toPts(down); + }) + .join(' '); return ( - {[0, 0.25, 0.5, 0.75, 1].map((p) => ( + {[0, 0.5, 1].map((p) => ( ))} - { detail={undefined} peak={hist.cpu.length ? `${t('dashboard.peak')} ${Math.max(...hist.cpu)}%` : undefined} series={hist.cpu} - color={cpuPct >= 80 ? token.colorError : accent} + color={token.colorTextSecondary} isMobile={isMobile} /> @@ -382,7 +372,7 @@ const Dashboard: React.FC = () => { detail={`${formatBytes(sys?.memory?.used || 0)} / ${formatBytes(sys?.memory?.total || 0)}`} peak={hist.mem.length ? `${t('dashboard.avg')} ${Math.round((hist.mem.reduce((a, b) => a + b, 0) / hist.mem.length) * 10) / 10}%` : undefined} series={hist.mem} - color={memPct >= 80 ? token.colorError : accent} + color={token.colorTextSecondary} isMobile={isMobile} /> @@ -394,7 +384,7 @@ const Dashboard: React.FC = () => { detail={`${formatBytes(sys?.disk?.used || 0)} / ${formatBytes(sys?.disk?.total || 0)}`} peak={sys?.disk?.total ? `${t('dashboard.free')} ${formatBytes(Math.max(0, (sys?.disk?.total || 0) - (sys?.disk?.used || 0)))}` : undefined} series={hist.disk} - color={diskPct >= 90 ? token.colorError : accent} + color={token.colorTextSecondary} isMobile={isMobile} /> @@ -406,7 +396,7 @@ const Dashboard: React.FC = () => { detail={`${t('dashboard.totalUsers')}: ${users?.total ?? 0} ยท ${t('dashboard.enabledUsers')}: ${users?.enabled ?? 0}`} peak={`${t('dashboard.listeners')}: ${data?.listeners?.enabled ?? 0}/${data?.listeners?.total ?? 0}`} series={hist.conns.length ? hist.conns : [0, online]} - color={success} + color={token.colorTextSecondary} isMobile={isMobile} /> @@ -448,9 +438,8 @@ const Dashboard: React.FC = () => { @@ -519,7 +508,7 @@ const Dashboard: React.FC = () => {
- +