From 622e5e140fb0fe3ca7c767ef6d06207b76785307 Mon Sep 17 00:00:00 2001 From: Eduard Gert Date: Wed, 17 Jun 2026 14:06:38 +0200 Subject: [PATCH] add overlay if daemon not compatible --- .../empty-state/DaemonOutdatedOverlay.tsx | 52 +++++++++++++++++++ .../frontend/src/contexts/StatusContext.tsx | 25 ++++++++- client/ui/i18n/locales/de/common.json | 6 +++ client/ui/i18n/locales/en/common.json | 8 +++ client/ui/i18n/locales/es/common.json | 6 +++ client/ui/i18n/locales/fr/common.json | 6 +++ client/ui/i18n/locales/hu/common.json | 6 +++ client/ui/i18n/locales/it/common.json | 6 +++ client/ui/i18n/locales/pt/common.json | 6 +++ client/ui/i18n/locales/ru/common.json | 6 +++ client/ui/i18n/locales/zh-CN/common.json | 6 +++ 11 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 client/ui/frontend/src/components/empty-state/DaemonOutdatedOverlay.tsx diff --git a/client/ui/frontend/src/components/empty-state/DaemonOutdatedOverlay.tsx b/client/ui/frontend/src/components/empty-state/DaemonOutdatedOverlay.tsx new file mode 100644 index 000000000..b18f83d52 --- /dev/null +++ b/client/ui/frontend/src/components/empty-state/DaemonOutdatedOverlay.tsx @@ -0,0 +1,52 @@ +import { useTranslation } from "react-i18next"; +import { AlertTriangleIcon, DownloadIcon } from "lucide-react"; +import { Browser } from "@wailsio/runtime"; +import { Button } from "@/components/buttons/Button"; +import { useStatus } from "@/contexts/StatusContext.tsx"; + +const RELEASES_URL = "https://github.com/netbirdio/netbird/releases/latest"; + +function openUrl(url: string) { + Browser.OpenURL(url).catch(() => globalThis.open(url, "_blank")); +} + +export const DaemonOutdatedOverlay = () => { + const { t } = useTranslation(); + const { isDaemonOutdated } = useStatus(); + + if (!isDaemonOutdated) return null; + + return ( +
+
+
+ +
+ +
+

+ {t("daemon.outdated.title")} +

+

+ {t("daemon.outdated.description")} +

+
+ +
+ +
+
+
+ ); +}; diff --git a/client/ui/frontend/src/contexts/StatusContext.tsx b/client/ui/frontend/src/contexts/StatusContext.tsx index 0164d892e..0ad9c7875 100644 --- a/client/ui/frontend/src/contexts/StatusContext.tsx +++ b/client/ui/frontend/src/contexts/StatusContext.tsx @@ -10,7 +10,9 @@ import { import { Events } from "@wailsio/runtime"; import { DaemonFeed } from "@bindings/services"; import { Status } from "@bindings/services/models.js"; +import { DaemonOutdatedOverlay } from "@/components/empty-state/DaemonOutdatedOverlay.tsx"; import { DaemonUnavailableOverlay } from "@/components/empty-state/DaemonUnavailableOverlay.tsx"; +import { isDaemonCompatible } from "@/lib/compat"; const EVENT_STATUS = "netbird:status"; @@ -21,6 +23,7 @@ type StatusContextValue = { isReady: boolean; isDaemonUnavailable: boolean; isDaemonAvailable: boolean; + isDaemonOutdated: boolean; }; const StatusContext = createContext(null); @@ -36,6 +39,7 @@ export const useStatus = () => { export const StatusProvider = ({ children }: { children: ReactNode }) => { const [status, setStatus] = useState(null); const [error, setError] = useState(null); + const [isDaemonOutdated, setIsDaemonOutdated] = useState(false); const refresh = useCallback(async () => { try { @@ -64,6 +68,21 @@ export const StatusProvider = ({ children }: { children: ReactNode }) => { const isDaemonUnavailable = isReady && status.status === "DaemonUnavailable"; const isDaemonAvailable = isReady && !isDaemonUnavailable; + useEffect(() => { + if (!isDaemonAvailable) return; + let cancelled = false; + isDaemonCompatible() + .then((ok) => { + if (!cancelled) setIsDaemonOutdated(!ok); + }) + .catch((err) => { + console.error("[StatusContext] daemon compatible error", err); + }); + return () => { + cancelled = true; + }; + }, [isDaemonAvailable]); + const value = useMemo( () => ({ status, @@ -72,14 +91,16 @@ export const StatusProvider = ({ children }: { children: ReactNode }) => { isReady, isDaemonUnavailable, isDaemonAvailable, + isDaemonOutdated, }), - [status, error, refresh, isReady, isDaemonUnavailable, isDaemonAvailable], + [status, error, refresh, isReady, isDaemonUnavailable, isDaemonAvailable, isDaemonOutdated], ); return ( - {isDaemonAvailable && children} + {isDaemonAvailable && !isDaemonOutdated && children} + ); }; diff --git a/client/ui/i18n/locales/de/common.json b/client/ui/i18n/locales/de/common.json index 66249250e..c1751acd8 100644 --- a/client/ui/i18n/locales/de/common.json +++ b/client/ui/i18n/locales/de/common.json @@ -1250,6 +1250,12 @@ "daemon.unavailable.docsLink": { "message": "Dokumentation" }, + "daemon.outdated.title": { + "message": "NetBird-Dienst ist veraltet" + }, + "daemon.outdated.description": { + "message": "Aktualisieren Sie den NetBird-Dienst, um diese App zu verwenden." + }, "error.jwt_clock_skew": { "message": "Anmeldung fehlgeschlagen: Die Uhr dieses Geräts ist nicht mit dem Server synchron. Bitte synchronisieren Sie die Systemuhr und versuchen Sie es erneut." }, diff --git a/client/ui/i18n/locales/en/common.json b/client/ui/i18n/locales/en/common.json index 0d64b2657..a8dff2e29 100644 --- a/client/ui/i18n/locales/en/common.json +++ b/client/ui/i18n/locales/en/common.json @@ -1667,6 +1667,14 @@ "message": "Documentation", "description": "Documentation link on the daemon-unavailable overlay." }, + "daemon.outdated.title": { + "message": "NetBird Service Is Outdated", + "description": "Title of the overlay shown when the NetBird background service is too old to drive this UI." + }, + "daemon.outdated.description": { + "message": "Update the NetBird service to use this app.", + "description": "Body of the daemon-outdated overlay telling the user to upgrade the service." + }, "error.jwt_clock_skew": { "message": "Sign-in failed: this device's clock is out of sync with the server. Please sync your system clock and try again.", "description": "Sign-in error shown to the user: the device clock is out of sync with the server." diff --git a/client/ui/i18n/locales/es/common.json b/client/ui/i18n/locales/es/common.json index bafddb096..87ae60460 100644 --- a/client/ui/i18n/locales/es/common.json +++ b/client/ui/i18n/locales/es/common.json @@ -1250,6 +1250,12 @@ "daemon.unavailable.docsLink": { "message": "Documentación" }, + "daemon.outdated.title": { + "message": "El servicio de NetBird está desactualizado" + }, + "daemon.outdated.description": { + "message": "Actualice el servicio de NetBird para usar esta aplicación." + }, "error.jwt_clock_skew": { "message": "Error al iniciar sesión: el reloj de este dispositivo no está sincronizado con el servidor. Sincronice el reloj del sistema e inténtelo de nuevo." }, diff --git a/client/ui/i18n/locales/fr/common.json b/client/ui/i18n/locales/fr/common.json index 2b76863df..1ec0f9356 100644 --- a/client/ui/i18n/locales/fr/common.json +++ b/client/ui/i18n/locales/fr/common.json @@ -1250,6 +1250,12 @@ "daemon.unavailable.docsLink": { "message": "Documentation" }, + "daemon.outdated.title": { + "message": "Le service NetBird est obsolète" + }, + "daemon.outdated.description": { + "message": "Mettez à jour le service NetBird pour utiliser cette application." + }, "error.jwt_clock_skew": { "message": "Échec de la connexion : l’horloge de cet appareil n’est pas synchronisée avec le serveur. Veuillez synchroniser l’horloge de votre système et réessayer." }, diff --git a/client/ui/i18n/locales/hu/common.json b/client/ui/i18n/locales/hu/common.json index 20d596453..7cab54828 100644 --- a/client/ui/i18n/locales/hu/common.json +++ b/client/ui/i18n/locales/hu/common.json @@ -1250,6 +1250,12 @@ "daemon.unavailable.docsLink": { "message": "Dokumentáció" }, + "daemon.outdated.title": { + "message": "A NetBird szolgáltatás elavult" + }, + "daemon.outdated.description": { + "message": "Frissítsd a NetBird szolgáltatást az alkalmazás használatához." + }, "error.jwt_clock_skew": { "message": "A bejelentkezés sikertelen: az eszköz órája eltér a szerverétől. Kérjük, szinkronizálja a rendszer óráját, majd próbálja újra." }, diff --git a/client/ui/i18n/locales/it/common.json b/client/ui/i18n/locales/it/common.json index b75b85eef..bff7c4ce6 100644 --- a/client/ui/i18n/locales/it/common.json +++ b/client/ui/i18n/locales/it/common.json @@ -1250,6 +1250,12 @@ "daemon.unavailable.docsLink": { "message": "Documentazione" }, + "daemon.outdated.title": { + "message": "Il servizio NetBird è obsoleto" + }, + "daemon.outdated.description": { + "message": "Aggiorna il servizio NetBird per usare questa app." + }, "error.jwt_clock_skew": { "message": "Accesso non riuscito: l'orologio di questo dispositivo non è sincronizzato con il server. Sincronizzi l'orologio di sistema e riprovi." }, diff --git a/client/ui/i18n/locales/pt/common.json b/client/ui/i18n/locales/pt/common.json index f2ce6471c..aa95540b2 100644 --- a/client/ui/i18n/locales/pt/common.json +++ b/client/ui/i18n/locales/pt/common.json @@ -1250,6 +1250,12 @@ "daemon.unavailable.docsLink": { "message": "Documentação" }, + "daemon.outdated.title": { + "message": "O serviço NetBird está desatualizado" + }, + "daemon.outdated.description": { + "message": "Atualize o serviço NetBird para usar este aplicativo." + }, "error.jwt_clock_skew": { "message": "Falha no login: o relógio deste dispositivo está fora de sincronia com o servidor. Sincronize o relógio do sistema e tente novamente." }, diff --git a/client/ui/i18n/locales/ru/common.json b/client/ui/i18n/locales/ru/common.json index 866e1e495..8c548818f 100644 --- a/client/ui/i18n/locales/ru/common.json +++ b/client/ui/i18n/locales/ru/common.json @@ -1250,6 +1250,12 @@ "daemon.unavailable.docsLink": { "message": "Документация" }, + "daemon.outdated.title": { + "message": "Служба NetBird устарела" + }, + "daemon.outdated.description": { + "message": "Обновите службу NetBird, чтобы использовать это приложение." + }, "error.jwt_clock_skew": { "message": "Не удалось войти: часы этого устройства рассинхронизированы с сервером. Синхронизируйте системные часы и повторите попытку." }, diff --git a/client/ui/i18n/locales/zh-CN/common.json b/client/ui/i18n/locales/zh-CN/common.json index 848e497b5..9e68efef0 100644 --- a/client/ui/i18n/locales/zh-CN/common.json +++ b/client/ui/i18n/locales/zh-CN/common.json @@ -1250,6 +1250,12 @@ "daemon.unavailable.docsLink": { "message": "文档" }, + "daemon.outdated.title": { + "message": "NetBird 服务版本过旧" + }, + "daemon.outdated.description": { + "message": "请更新 NetBird 服务以使用此应用。" + }, "error.jwt_clock_skew": { "message": "登录失败:此设备的时钟与服务器不同步。请同步您的系统时钟后重试。" },