import { useEffect, useState } from "react"; import { useAppName } from "@/lib/brand"; import { useSettings } from "@/store/settings"; import { Switch } from "@/ui/misc"; import { requestNotificationPermission, showNotification, playNewMailSound } from "@/lib/notify/notify"; import { useSession } from "@/store/session"; import { disableWebPush, enableWebPush, webPushActive } from "@/lib/notify/webpushEnable"; import { supportsEmailPush, webPushAvailable } from "@/lib/notify/webpush"; import { toast } from "@/ui/toast"; import { t } from "@/lib/i18n"; import { isEnforced } from "@/lib/settingsPolicy"; export function NotificationsSettings() { const appName = useAppName(); const s = useSettings((st) => st.settings); const update = useSettings((st) => st.update); const pushConnected = useSession((st) => st.pushConnected); const [perm, setPerm] = useState("Notification" in window ? Notification.permission : "unsupported"); const [background, setBackground] = useState(false); const [busy, setBusy] = useState(false); const canBackground = webPushAvailable(); useEffect(() => { void webPushActive().then(setBackground); }, []); useEffect(() => { if ("Notification" in window) setPerm(Notification.permission); }, [s.desktopNotifications]); return (

{t("Notifications")}

{t("Live updates are delivered via JMAP push ({state}).", { state: pushConnected ? t("connected") : t("reconnecting…") })}

{ if (v) { const p = await requestNotificationPermission(); setPerm(p); if (p !== "granted") return; } update({ desktopNotifications: v }); }} label={t("Desktop notifications while {app} is open", { app: appName })} hint={perm === "denied" ? t("Notifications are blocked in your browser settings.") : perm === "unsupported" ? t("Not supported in this browser.") : t("Shows a system notification when new mail arrives in your Inbox while the tab is in the background.")} disabled={perm === "denied" || perm === "unsupported"} /> {/* The distinction worth drawing for the user: the switch above needs a tab open, this one does not. Everything before this shipped only the first kind, while calling it "desktop notifications". */} { setBusy(true); try { if (v) { const p = await requestNotificationPermission(); setPerm(p); if (p !== "granted") return; const res = await enableWebPush(); if (!res.ok) { toast.error(res.reason); return; } setBackground(true); toast.success(t("Background notifications are on")); } else { await disableWebPush(); setBackground(false); } } finally { setBusy(false); } }} label={t("Notify me even when {app} is closed", { app: appName })} hint={ !canBackground ? t("Needs a browser with the Push API and a mail server that publishes a push key.") : supportsEmailPush() ? t("Your mail server delivers these straight to your browser, so they arrive with no {app} tab open, naming the sender and subject. Your browser still has to be running — if you quit it completely, notifications wait and arrive when you open it again.", { app: appName }) : t("Your mail server can wake this browser, but will not include the sender or subject. Your browser still has to be running.") } /> update({ notificationSound: v })} label={t("Play a sound for new mail")} />

{t("The tab title and favicon always show your unread Inbox count.")}

); }