From cb37383ccdc81e7fd54e64c10a1bd2344682f129 Mon Sep 17 00:00:00 2001 From: viettranx Date: Mon, 23 Mar 2026 14:00:00 +0700 Subject: [PATCH] feat(ui): show server version in sidebar connection status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace hardcoded "0.2.0" in WS connect response with the actual build-injected version. Wire server version through WS client → auth store → sidebar footer so it displays next to connection status. --- internal/gateway/router.go | 4 ++-- ui/web/src/api/ws-client.ts | 3 +++ ui/web/src/components/layout/connection-status.tsx | 8 +++++++- ui/web/src/components/providers/ws-provider.tsx | 9 +++++++-- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/internal/gateway/router.go b/internal/gateway/router.go index c0c06b28..2f938eea 100644 --- a/internal/gateway/router.go +++ b/internal/gateway/router.go @@ -272,7 +272,7 @@ func (r *MethodRouter) handleConnect(ctx context.Context, client *Client, req *p "sender_id": client.id, "server": map[string]any{ "name": "goclaw", - "version": "0.2.0", + "version": r.server.version, }, })) return @@ -301,7 +301,7 @@ func (r *MethodRouter) sendConnectResponse(ctx context.Context, client *Client, "cross_tenant": client.crossTenant, "server": map[string]any{ "name": "goclaw", - "version": "0.2.0", + "version": r.server.version, }, } diff --git a/ui/web/src/api/ws-client.ts b/ui/web/src/api/ws-client.ts index eb289b49..3b0d74af 100644 --- a/ui/web/src/api/ws-client.ts +++ b/ui/web/src/api/ws-client.ts @@ -31,6 +31,7 @@ export class WsClient { tenantName = ""; tenantSlug = ""; crossTenant = false; + serverVersion = ""; private readonly maxReconnectDelay = 30_000; private readonly baseReconnectDelay = 1_000; @@ -206,6 +207,7 @@ export class WsClient { tenant_name?: string; tenant_slug?: string; cross_tenant?: boolean; + server?: { name?: string; version?: string }; }>("connect", { token: this.getToken(), user_id: this.getUserId(), @@ -238,6 +240,7 @@ export class WsClient { this.tenantName = res?.tenant_name ?? ""; this.tenantSlug = res?.tenant_slug ?? ""; this.crossTenant = res?.cross_tenant ?? false; + this.serverVersion = res?.server?.version ?? ""; this.onStateChange("connected"); } catch (e) { if (this.connectGeneration === generation) { diff --git a/ui/web/src/components/layout/connection-status.tsx b/ui/web/src/components/layout/connection-status.tsx index 6c6d1f05..adc38cb8 100644 --- a/ui/web/src/components/layout/connection-status.tsx +++ b/ui/web/src/components/layout/connection-status.tsx @@ -5,6 +5,7 @@ import { cn } from "@/lib/utils"; export function ConnectionStatus({ collapsed }: { collapsed?: boolean }) { const { t } = useTranslation("common"); const connected = useAuthStore((s) => s.connected); + const serverVersion = useAuthStore((s) => s.serverInfo?.version); return (
@@ -15,7 +16,12 @@ export function ConnectionStatus({ collapsed }: { collapsed?: boolean }) { )} /> {!collapsed && ( - {connected ? t("connected") : t("disconnected")} + + {connected ? t("connected") : t("disconnected")} + {connected && serverVersion && ( + · {serverVersion} + )} + )}
); diff --git a/ui/web/src/components/providers/ws-provider.tsx b/ui/web/src/components/providers/ws-provider.tsx index 7c8ea06c..b946a9f3 100644 --- a/ui/web/src/components/providers/ws-provider.tsx +++ b/ui/web/src/components/providers/ws-provider.tsx @@ -30,8 +30,13 @@ export function WsProvider({ children }: { children: React.ReactNode }) { () => useAuthStore.getState().senderID, (state: ConnectionState) => { const store = useAuthStore.getState(); - store.setConnected(state === "connected"); - if (state === "connected" && wsRef.current) { + const isConnected = state === "connected"; + if (isConnected && wsRef.current) { + store.setConnected(true, { version: wsRef.current.serverVersion }); + } else { + store.setConnected(false); + } + if (isConnected && wsRef.current) { const client = wsRef.current; store.setRole(client.role || ""); store.setTenant(client.tenantId, client.tenantName, client.tenantSlug, client.crossTenant);