Files
spsays-training/components/push/push-toggle.tsx
T
2026-06-11 00:32:04 +05:30

121 lines
3.5 KiB
TypeScript

"use client";
/**
* PushToggle — the settings control for browser push notifications. Reads the
* current state on mount (supported? permission? server-configured?
* subscribed?) and lets the user enable/disable. Renders as a settings row
* matching the rest of /settings.
*/
import { useEffect, useState } from "react";
import { toast } from "sonner";
import { SettingRow, ToggleSwitch } from "@/components/settings/setting-row";
import {
disablePush,
enablePush,
isPushEnabled,
needsIOSInstall,
pushConfigured,
pushPermission,
pushSupported,
} from "@/lib/push";
type State =
| "loading"
| "unsupported"
| "ios-install" // iOS: must add to Home Screen first
| "unavailable" // server has no VAPID keys
| "denied" // browser permission blocked
| "on"
| "off";
export function PushToggle() {
const [state, setState] = useState<State>("loading");
const [busy, setBusy] = useState(false);
useEffect(() => {
let cancelled = false;
(async () => {
if (!pushSupported()) {
return finish(needsIOSInstall() ? "ios-install" : "unsupported");
}
if (pushPermission() === "denied") return finish("denied");
if (!(await pushConfigured())) return finish("unavailable");
finish((await isPushEnabled()) ? "on" : "off");
function finish(s: State) {
if (!cancelled) setState(s);
}
})();
return () => {
cancelled = true;
};
}, []);
async function toggle() {
setBusy(true);
try {
if (state === "on") {
await disablePush();
setState("off");
toast.success("Push notifications turned off");
} else {
await enablePush();
setState("on");
toast.success("Push notifications turned on");
}
} catch (err) {
const msg =
err instanceof Error ? err.message : "Something went wrong.";
// A fresh block surfaces as a permission error — reflect it.
if (pushPermission() === "denied") setState("denied");
toast.error(msg);
} finally {
setBusy(false);
}
}
return (
<SettingRow
label="Push notifications"
description={describe(state)}
control={
state === "on" || state === "off" ? (
<ToggleSwitch
checked={state === "on"}
disabled={busy}
onToggle={toggle}
label="Push notifications"
/>
) : (
<span className="text-xs text-muted-foreground">
{state === "loading"
? "…"
: state === "ios-install"
? null
: "Unavailable"}
</span>
)
}
/>
);
}
function describe(state: State): string {
switch (state) {
case "on":
return "On — you'll be notified about follow requests and more, even when the app is closed.";
case "off":
return "Get notified about follow requests and more, even when the app is closed.";
case "denied":
return "Blocked in your browser. Enable notifications for this site in your browser settings, then reload.";
case "ios-install":
return "On iPhone & iPad, notifications work only from the Home Screen app. Tap the Share icon in Safari, choose “Add to Home Screen”, then open Prabhupāda Says from the new icon and turn this on.";
case "unsupported":
return "This browser doesn't support push notifications.";
case "unavailable":
return "Push notifications aren't available right now.";
default:
return "Checking…";
}
}