3x-ui/web
MHSanaei f4f0af576a
feat(ws): live updates on inbounds/xray/nodes pages, drop polling + manual refresh
Replaces the legacy polling + manual-refresh model with WebSocket pushes
across the three live-data pages. The hub already broadcast traffic /
client_stats / outbounds; this wires the frontend to consume them and
adds a new `nodes` channel for the heartbeat job's snapshot.

Frontend
- new useWebSocket composable: page-scoped singleton WebSocketClient,
  lifecycle-managed on/off, leaves disconnect to page-unload
- inbounds: useInbounds gains applyTrafficEvent / applyClientStatsEvent
  / applyInvalidate that merge counters and online/lastOnline in place;
  InboundsPage subscribes; InboundList drops the auto-refresh popover,
  the refresh button, and the now-unused refreshing prop
- xray outbounds: useXraySetting gains applyOutboundsEvent; XrayPage
  subscribes; OutboundsTab drops the refresh button + emit
- nodes: useNodes gains applyNodesEvent and stops the 5s
  setInterval/visibilitychange polling; NodesPage subscribes;
  NodeList drops the refresh button and ReloadOutlined import

Backend
- web/websocket: new MessageTypeNodes + BroadcastNodes notifier
- node_heartbeat_job: after wg.Wait(), reload the table once and
  BroadcastNodes(updated). Gated on websocket.HasClients() so a panel
  with no open browser doesn't spend the DB read

Bug fixes spotted in this pass
- websocket.js #buildUrl defaulted basePath to '' when the global was
  missing (dev mode), producing `ws://host:portws` and a SyntaxError
  on the WebSocket constructor. Fall back to '/' and ensure leading
  slash.
- vite.config.js: forward /ws to ws://localhost:2053 with ws:true so
  dev (5173) reaches the Go backend's WebSocket
- NodeFormModal: a-input-password's visibilityToggle is Boolean in
  AntD Vue 4; the v3-era object form (`{ visible, 'onUpdate:visible' }`)
  triggered a Vue prop-type warning. Drop the override (default true
  shows the eye icon and toggles internally) and remove the orphaned
  tokenVisible ref

Translations
- pages.inbounds.autoRefresh / autoRefreshInterval: removed from all
  13 locales (UI gone)
- pages.nodes.refresh: removed from all 13 locales (UI gone)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 17:30:31 +02:00
..
controller feat(stats): system history modal + per-node CPU/Mem trends across all locales 2026-05-09 16:24:57 +02:00
entity feat: add configurable auto-restart on client auto-disable 2026-05-04 23:19:25 +02:00
global Refactor code and fix linter warnings (#3627) 2026-01-05 05:54:56 +01:00
job feat(ws): live updates on inbounds/xray/nodes pages, drop polling + manual refresh 2026-05-09 17:30:31 +02:00
locale i18n: collapse two translation databases into a single web/translation/<lang>.json set 2026-05-08 18:05:56 +02:00
middleware feat(nodes): multi-node panel orchestration (CRUD, deployment, traffic sync, sub per-node) 2026-05-09 15:25:29 +02:00
network docs: add comments for all functions 2025-09-20 09:35:50 +02:00
runtime feat(nodes): multi-node panel orchestration (CRUD, deployment, traffic sync, sub per-node) 2026-05-09 15:25:29 +02:00
service feat(stats): system history modal + per-node CPU/Mem trends across all locales 2026-05-09 16:24:57 +02:00
session feat(nodes): multi-node panel orchestration (CRUD, deployment, traffic sync, sub per-node) 2026-05-09 15:25:29 +02:00
translation feat(ws): live updates on inbounds/xray/nodes pages, drop polling + manual refresh 2026-05-09 17:30:31 +02:00
websocket feat(ws): live updates on inbounds/xray/nodes pages, drop polling + manual refresh 2026-05-09 17:30:31 +02:00
web.go fix(embed): include underscore-prefixed Vite chunks in dist FS 2026-05-09 16:44:15 +02:00