From a903e84278fbbaf3f01221adb79363bec129a8cc Mon Sep 17 00:00:00 2001 From: VirusAlex Date: Fri, 1 May 2026 16:07:02 +0300 Subject: [PATCH] feat(ui): show NetCopy version in topbar (local + peer) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The /api/peer/info endpoint returns the running NetCopy version on each side, but the UI never read or displayed it. Reported by VirusAlex — "надо бы ещё в ui где-то отображать версию". Two compact version chips in the topbar: - Brand area, next to the hostname: local version (e.g. "v0.4.2"), populated on a successful Connect. - Peer section, next to the peer status pill: peer version on a successful Connect peer. Both are hidden until populated so first-load doesn't show "v?". Hover-title carries the same value plus context for narrow viewports. The peer status pill also gains a richer title that shows "NetCopy v0.4.2 on hostname" once the connection succeeds — useful for spotting "peer is running a different build than me" mismatches at a glance during a release. Pure client-side, no API changes (the version field has been on /api/peer/info since v0.2.x). Co-Authored-By: Claude Opus 4.7 (1M context) --- src/main/resources/web/app.js | 7 +++++++ src/main/resources/web/index.html | 20 +++++++++++++++++++- src/main/resources/web/style.css | 14 ++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/main/resources/web/app.js b/src/main/resources/web/app.js index 53ec9ff..a2474fe 100644 --- a/src/main/resources/web/app.js +++ b/src/main/resources/web/app.js @@ -31,6 +31,11 @@ document.addEventListener('alpine:init', () => { localTcpPort: 0, peerTcpPort: 0, peerHostname: null, + // NetCopy version reported by each side's /api/peer/info. Populated + // on successful Connect; null until then. Helpful for "is the peer + // running the same build as me" sanity checks during a release. + localVersion: null, + peerVersion: null, // ---- transfers + ws --------------------------------------------- transfers: [], // [{ id, host, state, protocol, bytesDone, totalBytes, ... }] @@ -96,6 +101,7 @@ document.addEventListener('alpine:init', () => { const info = await r.json(); this.localTcpPort = info.tcpPort || 0; this.hostname = info.hostname || this.hostname; + this.localVersion = info.version || null; this.localOk = true; this.localStatus = 'ok'; this.openWs(); @@ -142,6 +148,7 @@ document.addEventListener('alpine:init', () => { const info = await r.json(); this.peerTcpPort = info.tcpPort || 0; this.peerHostname = info.hostname || null; + this.peerVersion = info.version || null; this.peerOk = true; this.peerStatus = 'ok'; this.openPeerWs(); diff --git a/src/main/resources/web/index.html b/src/main/resources/web/index.html index 5c67d2c..d9c9507 100644 --- a/src/main/resources/web/index.html +++ b/src/main/resources/web/index.html @@ -26,6 +26,13 @@
NetCopy + +
@@ -82,7 +89,18 @@ x-text="$store.app.peerStatus === 'connecting' ? 'connecting…' : $store.app.peerStatus === 'ok' ? 'peer ok' : $store.app.peerStatus === 'error' ? 'error' - : 'no peer'"> + : 'no peer'" + :title="$store.app.peerStatus === 'ok' + ? ('NetCopy v' + ($store.app.peerVersion || '?') + + ' on ' + ($store.app.peerHostname || '?')) + : ''"> + +