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",