From 88bd1f91a89c2b5368cf355281e75c2956a499bb Mon Sep 17 00:00:00 2001 From: Eduard Gert Date: Mon, 1 Jun 2026 17:50:21 +0200 Subject: [PATCH] update session expire dialog to account for hours, days etc. --- .../session/SessionAboutToExpireDialog.tsx | 31 ++++++++++++++----- client/ui/i18n/locales/de/common.json | 2 ++ client/ui/i18n/locales/en/common.json | 2 ++ client/ui/i18n/locales/hu/common.json | 2 ++ 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/client/ui/frontend/src/modules/session/SessionAboutToExpireDialog.tsx b/client/ui/frontend/src/modules/session/SessionAboutToExpireDialog.tsx index 6571d8a58..232c3062a 100644 --- a/client/ui/frontend/src/modules/session/SessionAboutToExpireDialog.tsx +++ b/client/ui/frontend/src/modules/session/SessionAboutToExpireDialog.tsx @@ -20,12 +20,24 @@ import { formatErrorMessage } from "@/lib/errors.ts"; const DEFAULT_SECONDS = 360; const WINDOW_WIDTH = 360; +// Below this, the situation is genuinely "soon" and the title/description +// uses the urgent wording. Above it (e.g. opened with hours remaining), the +// "later" variant drops the urgency cue so it doesn't read absurdly. +const SOON_THRESHOLD_SECONDS = 60 * 60; -function formatMMSS(seconds: number): string { +// Renders the countdown with only the units that matter: mm:ss under an +// hour, hh:mm:ss under a day, dd:hh:mm:ss otherwise. Two-digit zero pad +// throughout so columns don't jump as digits roll over. +function formatRemaining(seconds: number): string { const s = Math.max(0, seconds | 0); - const m = Math.floor(s / 60); - const r = s % 60; - return `${String(m).padStart(2, "0")}:${String(r).padStart(2, "0")}`; + const days = Math.floor(s / 86400); + const hours = Math.floor((s % 86400) / 3600); + const minutes = Math.floor((s % 3600) / 60); + const secs = s % 60; + const pad = (n: number) => String(n).padStart(2, "0"); + if (days > 0) return `${pad(days)}:${pad(hours)}:${pad(minutes)}:${pad(secs)}`; + if (hours > 0) return `${pad(hours)}:${pad(minutes)}:${pad(secs)}`; + return `${pad(minutes)}:${pad(secs)}`; } export default function SessionAboutToExpireDialog() { @@ -42,6 +54,7 @@ export default function SessionAboutToExpireDialog() { const [remaining, setRemaining] = useState(initialSeconds); const [busy, setBusy] = useState(false); const expired = remaining <= 0; + const soon = remaining <= SOON_THRESHOLD_SECONDS; useEffect(() => { setRemaining(initialSeconds); @@ -127,10 +140,14 @@ export default function SessionAboutToExpireDialog() { {expired ? t("sessionAboutToExpire.expired") - : t("sessionAboutToExpire.title")} + : soon + ? t("sessionAboutToExpire.title") + : t("sessionAboutToExpire.titleLater")} - {t("sessionAboutToExpire.description")} + {soon + ? t("sessionAboutToExpire.description") + : t("sessionAboutToExpire.descriptionLater")} @@ -140,7 +157,7 @@ export default function SessionAboutToExpireDialog() { } aria-live={"polite"} > - {formatMMSS(remaining)} + {formatRemaining(remaining)} diff --git a/client/ui/i18n/locales/de/common.json b/client/ui/i18n/locales/de/common.json index 09dbaf42a..f7586e3c0 100644 --- a/client/ui/i18n/locales/de/common.json +++ b/client/ui/i18n/locales/de/common.json @@ -320,7 +320,9 @@ "sessionExpired.signIn": "Anmelden", "sessionAboutToExpire.title": "Sitzung läuft bald ab", + "sessionAboutToExpire.titleLater": "Sitzung läuft ab", "sessionAboutToExpire.description": "Ihre NetBird-Sitzung läuft in Kürze ab. Bleiben Sie verbunden, damit Ihre Geräte online bleiben.", + "sessionAboutToExpire.descriptionLater": "Ihre NetBird-Sitzung läuft ab. Verlängern Sie jetzt, damit Ihre Geräte online bleiben.", "sessionAboutToExpire.stay": "Verbunden bleiben", "sessionAboutToExpire.logout": "Abmelden", "sessionAboutToExpire.expired": "Sitzung abgelaufen", diff --git a/client/ui/i18n/locales/en/common.json b/client/ui/i18n/locales/en/common.json index bf1850575..e830be5e1 100644 --- a/client/ui/i18n/locales/en/common.json +++ b/client/ui/i18n/locales/en/common.json @@ -337,7 +337,9 @@ "sessionExpired.signIn": "Sign in", "sessionAboutToExpire.title": "Session expiring soon", + "sessionAboutToExpire.titleLater": "Session will expire", "sessionAboutToExpire.description": "Your NetBird session will expire shortly. Stay connected to keep your devices online.", + "sessionAboutToExpire.descriptionLater": "Your NetBird session will expire. Extend now to keep your devices online.", "sessionAboutToExpire.stay": "Stay connected", "sessionAboutToExpire.logout": "Logout", "sessionAboutToExpire.expired": "Session expired", diff --git a/client/ui/i18n/locales/hu/common.json b/client/ui/i18n/locales/hu/common.json index b82d5dcc9..eb55dd61e 100644 --- a/client/ui/i18n/locales/hu/common.json +++ b/client/ui/i18n/locales/hu/common.json @@ -320,7 +320,9 @@ "sessionExpired.signIn": "Bejelentkezés", "sessionAboutToExpire.title": "A munkamenet hamarosan lejár", + "sessionAboutToExpire.titleLater": "A munkamenet lejár", "sessionAboutToExpire.description": "A NetBird munkamenete hamarosan lejár. Maradjon csatlakoztatva, hogy az eszközei elérhetők maradjanak.", + "sessionAboutToExpire.descriptionLater": "A NetBird munkamenete lejár. Hosszabbítsa meg most, hogy az eszközei elérhetők maradjanak.", "sessionAboutToExpire.stay": "Maradjon csatlakoztatva", "sessionAboutToExpire.logout": "Kijelentkezés", "sessionAboutToExpire.expired": "Munkamenet lejárt",