From b336ed5b732d56e7c6196f688578045822fea1bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Mon, 15 Jun 2026 01:28:12 +0200 Subject: [PATCH] fix(settings): confirm VAPID regenerate in-app; let labs subtitle wrap The VAPID regenerate overwrite guard used a native window.confirm for a subscription-invalidating destructive action, where the rest of the release uses the project's AlertDialog. Drive the overwrite confirm through an AlertDialog (calm in-app dialog, destructive action variant) and retry with force from its action. The /labs header subtitle used truncate, clipping mid-word in longer locales on a 375px viewport. Drop truncate so it wraps; the add button stays shrink-0 and the row aligns to the top. --- messages/de.json | 2 + messages/en.json | 2 + messages/es.json | 2 + messages/fr.json | 2 + messages/it.json | 2 + messages/pl.json | 2 + src/app/labs/page.tsx | 4 +- .../admin/web-push-vapid-section.tsx | 50 ++++++++++++++++--- 8 files changed, 58 insertions(+), 8 deletions(-) diff --git a/messages/de.json b/messages/de.json index 1d1ba962d..b847bccee 100644 --- a/messages/de.json +++ b/messages/de.json @@ -4932,6 +4932,8 @@ "webPushVapidGenerated": "VAPID-Schlüssel erzeugt. Betreff speichern, um abzuschließen.", "webPushVapidGenerateFailed": "VAPID-Schlüssel konnten nicht erzeugt werden.", "webPushVapidGenerateConfirm": "VAPID-Schlüssel sind bereits konfiguriert. Ein neues Schlüsselpaar macht alle Browser-Push-Abos ungültig — jedes Gerät muss sich neu anmelden. Fortfahren?", + "webPushVapidGenerateConfirmTitle": "VAPID-Schlüssel neu erzeugen?", + "webPushVapidRegenerate": "Neu erzeugen", "configured": "Konfiguriert", "monitoringTestSuccess": "Testevent wurde gesendet", "monitoringTestFailed": "Monitoring-Test fehlgeschlagen", diff --git a/messages/en.json b/messages/en.json index 3a8b08b12..3613256a8 100644 --- a/messages/en.json +++ b/messages/en.json @@ -4932,6 +4932,8 @@ "webPushVapidGenerated": "VAPID keys generated. Save the subject to finish.", "webPushVapidGenerateFailed": "Could not generate VAPID keys.", "webPushVapidGenerateConfirm": "VAPID keys are already configured. Generating a new pair invalidates every browser push subscription — each device must re-subscribe. Continue?", + "webPushVapidGenerateConfirmTitle": "Regenerate VAPID keys?", + "webPushVapidRegenerate": "Regenerate", "configured": "Configured", "monitoringTestSuccess": "Test event sent", "monitoringTestFailed": "Monitoring test failed", diff --git a/messages/es.json b/messages/es.json index 210c603ad..fde506b9e 100644 --- a/messages/es.json +++ b/messages/es.json @@ -4932,6 +4932,8 @@ "webPushVapidGenerated": "Claves VAPID generadas. Guarda el asunto para terminar.", "webPushVapidGenerateFailed": "No se pudieron generar las claves VAPID.", "webPushVapidGenerateConfirm": "Las claves VAPID ya están configuradas. Generar un par nuevo invalida todas las suscripciones push del navegador: cada dispositivo debe volver a suscribirse. ¿Continuar?", + "webPushVapidGenerateConfirmTitle": "¿Regenerar las claves VAPID?", + "webPushVapidRegenerate": "Regenerar", "configured": "Configurado", "monitoringTestSuccess": "Evento de prueba enviado", "monitoringTestFailed": "La prueba de monitorización falló", diff --git a/messages/fr.json b/messages/fr.json index e73f56d89..e34333cd1 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -4932,6 +4932,8 @@ "webPushVapidGenerated": "Clés VAPID générées. Enregistrez le sujet pour terminer.", "webPushVapidGenerateFailed": "Impossible de générer les clés VAPID.", "webPushVapidGenerateConfirm": "Les clés VAPID sont déjà configurées. Générer une nouvelle paire invalide tous les abonnements push du navigateur — chaque appareil doit se réabonner. Continuer ?", + "webPushVapidGenerateConfirmTitle": "Régénérer les clés VAPID ?", + "webPushVapidRegenerate": "Régénérer", "configured": "Configuré", "monitoringTestSuccess": "Événement de test envoyé", "monitoringTestFailed": "Échec du test de surveillance", diff --git a/messages/it.json b/messages/it.json index 5e20abdb5..e21d8c410 100644 --- a/messages/it.json +++ b/messages/it.json @@ -4932,6 +4932,8 @@ "webPushVapidGenerated": "Chiavi VAPID generate. Salva l'oggetto per completare.", "webPushVapidGenerateFailed": "Impossibile generare le chiavi VAPID.", "webPushVapidGenerateConfirm": "Le chiavi VAPID sono già configurate. Generare una nuova coppia invalida tutte le sottoscrizioni push del browser: ogni dispositivo deve ri-sottoscriversi. Continuare?", + "webPushVapidGenerateConfirmTitle": "Rigenerare le chiavi VAPID?", + "webPushVapidRegenerate": "Rigenera", "configured": "Configurato", "monitoringTestSuccess": "Evento di prova inviato", "monitoringTestFailed": "Test di monitoraggio non riuscito", diff --git a/messages/pl.json b/messages/pl.json index f62178eb5..58998f833 100644 --- a/messages/pl.json +++ b/messages/pl.json @@ -4932,6 +4932,8 @@ "webPushVapidGenerated": "Klucze VAPID wygenerowane. Zapisz temat, aby zakończyć.", "webPushVapidGenerateFailed": "Nie udało się wygenerować kluczy VAPID.", "webPushVapidGenerateConfirm": "Klucze VAPID są już skonfigurowane. Wygenerowanie nowej pary unieważnia wszystkie subskrypcje push w przeglądarce — każde urządzenie musi zasubskrybować ponownie. Kontynuować?", + "webPushVapidGenerateConfirmTitle": "Wygenerować nowe klucze VAPID?", + "webPushVapidRegenerate": "Wygeneruj ponownie", "configured": "Skonfigurowano", "monitoringTestSuccess": "Wysłano zdarzenie testowe", "monitoringTestFailed": "Test monitorowania nie powiódł się", diff --git a/src/app/labs/page.tsx b/src/app/labs/page.tsx index 524e903e2..2030d0510 100644 --- a/src/app/labs/page.tsx +++ b/src/app/labs/page.tsx @@ -50,12 +50,12 @@ export default function LabsPage() { return (
-
+

{t("labs.title")}

-

+

{t("labs.subtitle")}

diff --git a/src/components/admin/web-push-vapid-section.tsx b/src/components/admin/web-push-vapid-section.tsx index e409d96f8..d67d49bc6 100644 --- a/src/components/admin/web-push-vapid-section.tsx +++ b/src/components/admin/web-push-vapid-section.tsx @@ -6,6 +6,16 @@ import { toast } from "sonner"; import { BellRing, KeyRound, Loader2 } from "lucide-react"; import { SettingsCardHeader } from "@/components/settings/_card-header"; import { Button } from "@/components/ui/button"; +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogTitle, +} from "@/components/ui/alert-dialog"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { useTranslations } from "@/lib/i18n/context"; @@ -32,6 +42,11 @@ export function WebPushVapidSection() { string | null >(null); const [generating, setGenerating] = useState(false); + // Overwrite guard: the first generate returns 409 when keys already exist; + // we surface the project's AlertDialog (not a native window.confirm) before + // retrying with force, since regenerating invalidates every live Web-Push + // subscription. + const [overwriteConfirmOpen, setOverwriteConfirmOpen] = useState(false); const webPushVapidPublicKeyValue = webPushVapidPublicKeyDraft ?? settings?.webPushVapidPublicKey ?? ""; @@ -71,12 +86,10 @@ export function WebPushVapidSection() { ); if (res.status === 409) { - // Overwrite guard — existing keys would be replaced. Confirm with - // the operator (regenerating invalidates current subscriptions), - // then retry with force. - if (window.confirm(t("admin.webPushVapidGenerateConfirm"))) { - await generateVapidKeys(true); - } + // Overwrite guard — existing keys would be replaced. Surface the + // in-app confirm dialog (regenerating invalidates current + // subscriptions); the dialog action retries with force. + setOverwriteConfirmOpen(true); return; } @@ -201,6 +214,31 @@ export function WebPushVapidSection() { {t("common.save")}
+ + + + + + {t("admin.webPushVapidGenerateConfirmTitle")} + + + {t("admin.webPushVapidGenerateConfirm")} + + + + {t("common.cancel")} + void generateVapidKeys(true)} + > + {t("admin.webPushVapidRegenerate")} + + + +
); }