mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 21:10:59 +00:00
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.
This commit is contained in:
1 parent
790fecddb8
commit
b336ed5b73
8 files changed
+58
-8
No files matched your search
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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ó",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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ę",
|
||||
|
||||
@@ -50,12 +50,12 @@ export default function LabsPage() {
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<PullToRefreshIndicator {...pull} />
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<div className="min-w-0">
|
||||
<h1 className="text-2xl font-bold tracking-tight">
|
||||
{t("labs.title")}
|
||||
</h1>
|
||||
<p className="text-muted-foreground truncate text-xs sm:text-sm">
|
||||
<p className="text-muted-foreground text-xs sm:text-sm">
|
||||
{t("labs.subtitle")}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -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")}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<AlertDialog
|
||||
open={overwriteConfirmOpen}
|
||||
onOpenChange={setOverwriteConfirmOpen}
|
||||
>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>
|
||||
{t("admin.webPushVapidGenerateConfirmTitle")}
|
||||
</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
{t("admin.webPushVapidGenerateConfirm")}
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>{t("common.cancel")}</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
variant="destructive"
|
||||
onClick={() => void generateVapidKeys(true)}
|
||||
>
|
||||
{t("admin.webPushVapidRegenerate")}
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user