dsh-mesh-ui 0.0.15 → 0.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/client.js +51 -3
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -120,6 +120,8 @@ function nodeLabel(name) { return NODE_LABELS[String(name || '').toLowerCase()]
|
|
|
120
120
|
// [layout-helpers-end]
|
|
121
121
|
// [relay-helpers-begin] 2026-11-09 架构层:识别公网中转站(frps)与通信方式(纯函数,可单测)
|
|
122
122
|
// 2026-11-10 隐私:默认不展示公网 IP/域名;局域网/回环地址保留。
|
|
123
|
+
// 用户在页头打开「显示公网地址」后,maskHost/maskText 直接返回原值。
|
|
124
|
+
var showPublicAddresses = false
|
|
123
125
|
function isPrivateNetworkHost(raw) {
|
|
124
126
|
var h = String(raw || '').trim().toLowerCase().replace(/^\[|\]$/g, '')
|
|
125
127
|
h = h.replace(/^https?:\/\//, '').split('/')[0].replace(/:\d+$/, '')
|
|
@@ -135,6 +137,7 @@ function nodeLabel(name) { return NODE_LABELS[String(name || '').toLowerCase()]
|
|
|
135
137
|
}
|
|
136
138
|
function maskHost(raw) {
|
|
137
139
|
var s = String(raw || '').trim()
|
|
140
|
+
if (showPublicAddresses) return s || '—'
|
|
138
141
|
if (!s) return '—'
|
|
139
142
|
var port = ''
|
|
140
143
|
var m = /^(.*):(\d+)$/.exec(s)
|
|
@@ -142,6 +145,7 @@ function nodeLabel(name) { return NODE_LABELS[String(name || '').toLowerCase()]
|
|
|
142
145
|
return (isPrivateNetworkHost(s) ? s : '公网地址已隐藏') + port
|
|
143
146
|
}
|
|
144
147
|
function maskText(value) {
|
|
148
|
+
if (showPublicAddresses) return value
|
|
145
149
|
if (typeof value !== 'string') return value
|
|
146
150
|
return value
|
|
147
151
|
.replace(/https?:\/\/[^\s"'<>]+/gi, function (u) {
|
|
@@ -559,10 +563,24 @@ body.light .dm-edge-label { stroke: rgba(255,255,255,.92); }
|
|
|
559
563
|
var s0 = useState({ scale: 1, x: 0, y: 0 }); var view = s0[0]; var setView = s0[1]
|
|
560
564
|
var s1 = useState(false); var dragging = s1[0]; var setDragging = s1[1]
|
|
561
565
|
// 2026-11-09:三通道筛选(局域网/公网/樱花)
|
|
562
|
-
|
|
566
|
+
// 2026-11-10:筛选状态持久化;刷新/切页面后不再丢。
|
|
567
|
+
var FILTER_STORE_KEY = 'dsh-mesh-ui.filters.v1'
|
|
568
|
+
var filterState = useState(function () {
|
|
569
|
+
try {
|
|
570
|
+
var saved = JSON.parse(window.localStorage.getItem(FILTER_STORE_KEY) || '{}') || {}
|
|
571
|
+
return { lan: saved.lan !== false, public: saved.public !== false, sakura: saved.sakura !== false }
|
|
572
|
+
} catch (_) { return { lan: true, public: true, sakura: true } }
|
|
573
|
+
})
|
|
563
574
|
var showFilters = filterState[0]
|
|
564
575
|
var setShowFilters = filterState[1]
|
|
565
|
-
function toggleFilter(k) {
|
|
576
|
+
function toggleFilter(k) {
|
|
577
|
+
setShowFilters(function (prev) {
|
|
578
|
+
var n = Object.assign({}, prev)
|
|
579
|
+
n[k] = !n[k]
|
|
580
|
+
try { window.localStorage.setItem(FILTER_STORE_KEY, JSON.stringify(n)) } catch (_) { /* ignore */ }
|
|
581
|
+
return n
|
|
582
|
+
})
|
|
583
|
+
}
|
|
566
584
|
// fit 用最新布局的 ref(拖拽中不重算视角;只有初始化 / 窗口变化 / ⟲ 重置 / ⤢ 自适应才重算)
|
|
567
585
|
var effRef = useRef(effLayout)
|
|
568
586
|
effRef.current = effLayout
|
|
@@ -1408,7 +1426,20 @@ function deviceLinkState(data, peer, lanMap) {
|
|
|
1408
1426
|
}
|
|
1409
1427
|
|
|
1410
1428
|
function Details(props) {
|
|
1411
|
-
|
|
1429
|
+
var storeKey = 'dsh-mesh-ui.details.' + encodeURIComponent(String(props.title || ''))
|
|
1430
|
+
var sOpen = useState(function () {
|
|
1431
|
+
try {
|
|
1432
|
+
var saved = window.localStorage.getItem(storeKey)
|
|
1433
|
+
return saved == null ? Boolean(props.open) : saved === '1'
|
|
1434
|
+
} catch (_) { return Boolean(props.open) }
|
|
1435
|
+
})
|
|
1436
|
+
var open = sOpen[0]; var setOpen = sOpen[1]
|
|
1437
|
+
function onToggle(event) {
|
|
1438
|
+
var next = Boolean(event.currentTarget.open)
|
|
1439
|
+
setOpen(next)
|
|
1440
|
+
try { window.localStorage.setItem(storeKey, next ? '1' : '0') } catch (_) { /* ignore */ }
|
|
1441
|
+
}
|
|
1442
|
+
return h('details', { className: 'dm-details', open: open, onToggle: onToggle },
|
|
1412
1443
|
h('summary', null, props.title, props.badge != null ? h('span', { className: 'dm-pill muted' }, String(props.badge)) : null),
|
|
1413
1444
|
h('div', { className: 'dm-body' }, props.children)
|
|
1414
1445
|
)
|
|
@@ -1543,6 +1574,17 @@ function deviceLinkState(data, peer, lanMap) {
|
|
|
1543
1574
|
var verdictState = useState(''); var verdictShown = verdictState[0]; var setVerdictShown = verdictState[1]
|
|
1544
1575
|
var verdictRef = useRef({ raw: '', streak: 0 })
|
|
1545
1576
|
var s5 = useState('local'); var selectedKey = s5[0]; var setSelectedKey = s5[1]
|
|
1577
|
+
var sPublic = useState(function () {
|
|
1578
|
+
try { return window.localStorage.getItem('dsh-mesh.show-public-addresses') === '1' } catch (error) { return false }
|
|
1579
|
+
})
|
|
1580
|
+
var showPublic = sPublic[0]; var setShowPublic = sPublic[1]
|
|
1581
|
+
showPublicAddresses = showPublic
|
|
1582
|
+
function toggleShowPublic(event) {
|
|
1583
|
+
var next = Boolean(event && event.target && event.target.checked)
|
|
1584
|
+
setShowPublic(next)
|
|
1585
|
+
showPublicAddresses = next
|
|
1586
|
+
try { window.localStorage.setItem('dsh-mesh.show-public-addresses', next ? '1' : '0') } catch (error) { /* ignore */ }
|
|
1587
|
+
}
|
|
1546
1588
|
// 双栏宽度:拖动分隔条调整并记忆,窄屏由 CSS 媒体查询自动堆叠。
|
|
1547
1589
|
var dragState = useState(function () {
|
|
1548
1590
|
try { var saved = Number(window.localStorage.getItem('dsh-mesh-split-w')); return Number.isFinite(saved) && saved > 0 ? saved : 0 } catch (error) { return 0 }
|
|
@@ -1684,6 +1726,10 @@ function deviceLinkState(data, peer, lanMap) {
|
|
|
1684
1726
|
}, data.warming ? '预热中' : (verdictShown || data.verdict || '?')),
|
|
1685
1727
|
h('span', { className: 'dm-sub' }, (data.meshVersion ? 'mesh ' + data.meshVersion + ' · ' : '') + (data.at ? ago(data.at) : '')),
|
|
1686
1728
|
h('span', { style: { flex: 1 } }),
|
|
1729
|
+
h('label', { className: 'dm-toggle', title: '默认隐藏公网 IP/域名;勾选后显示真实地址并记住选择' },
|
|
1730
|
+
h('input', { type: 'checkbox', checked: Boolean(showPublic), onChange: toggleShowPublic }),
|
|
1731
|
+
h('span', null, '显示公网地址')
|
|
1732
|
+
),
|
|
1687
1733
|
h('a', { className: 'dm-btn', href: API, target: '_blank', rel: 'noreferrer', style: { textDecoration: 'none' } }, '原始 JSON'),
|
|
1688
1734
|
h('button', { className: 'dm-btn', onClick: copyJson }, copied || '复制诊断'),
|
|
1689
1735
|
h('button', { className: 'dm-btn primary', onClick: function () { load(true) }, title: '立即采集一次并等待新快照(8s 冷却)' }, loading ? '采集中…' : '刷新'),
|
|
@@ -2419,6 +2465,8 @@ body[data-ds-dark-theme] .dm-dg-fs-item.active { background:rgba(88,166,255,.28)
|
|
|
2419
2465
|
.dm-lan-node { display:flex; gap:8px; align-items:center; border-top:1px solid rgba(128,128,128,.16); padding:7px 0; font-size:12px; }
|
|
2420
2466
|
.dm-lan-node:first-child { border-top:none; }
|
|
2421
2467
|
.dm-lan-code { font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; font-size:12px; padding:6px 8px; border-radius:8px; background:rgba(88,166,255,.1); border:1px solid rgba(88,166,255,.35); word-break:break-all; }
|
|
2468
|
+
.dm-toggle { display:inline-flex; align-items:center; gap:5px; font-size:11.5px; opacity:.8; cursor:pointer; user-select:none; white-space:nowrap; }
|
|
2469
|
+
.dm-toggle input { margin:0; }
|
|
2422
2470
|
|
|
2423
2471
|
.dm-pane { min-width:0; display:flex; flex-direction:column; gap:12px; }
|
|
2424
2472
|
.dm-divider { cursor:col-resize; align-self:stretch; min-height:120px; border-radius:4px; position:relative; }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-mesh-ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17",
|
|
4
4
|
"description": "DSH sidebar page for dsh-mesh: AI network topology, peer health, and delegation panel. Read-only; data is collected from the installed dsh-mesh-node package.",
|
|
5
5
|
"icon": "icon.svg",
|
|
6
6
|
"type": "module",
|