Add browser notification support for new videos
- Settings: Notifications section with toggle that requests browser permission and stores preference in localStorage - Layout: fires a Notification when new_count increases and user isn't on /following - Works whenever the tab is open (foreground or background) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -600,6 +600,62 @@ function OAuth2Section({ s, qc }) {
|
||||
);
|
||||
}
|
||||
|
||||
function NotificationsSection() {
|
||||
const [permission, setPermission] = useState(() =>
|
||||
"Notification" in window ? Notification.permission : "unsupported"
|
||||
);
|
||||
const [enabled, setEnabled] = useState(() => localStorage.getItem("notifications_enabled") === "true");
|
||||
|
||||
const requestPermission = async () => {
|
||||
if (!("Notification" in window)) return;
|
||||
const result = await Notification.requestPermission();
|
||||
setPermission(result);
|
||||
if (result === "granted") {
|
||||
setEnabled(true);
|
||||
localStorage.setItem("notifications_enabled", "true");
|
||||
new Notification("YTContinue notifications on", {
|
||||
body: "You'll be notified when new videos arrive from channels you follow.",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const toggle = () => {
|
||||
if (permission !== "granted") {
|
||||
requestPermission();
|
||||
return;
|
||||
}
|
||||
const next = !enabled;
|
||||
setEnabled(next);
|
||||
localStorage.setItem("notifications_enabled", next ? "true" : "false");
|
||||
};
|
||||
|
||||
if (permission === "unsupported") return null;
|
||||
|
||||
return (
|
||||
<Section title="Notifications">
|
||||
<Row
|
||||
label="New video alerts"
|
||||
hint={
|
||||
permission === "denied"
|
||||
? "Blocked by browser — allow notifications for this site in browser settings"
|
||||
: "Get a browser notification when followed channels upload new videos"
|
||||
}
|
||||
>
|
||||
{permission === "denied" ? (
|
||||
<span className="text-xs text-zinc-600">Blocked</span>
|
||||
) : (
|
||||
<button
|
||||
onClick={toggle}
|
||||
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${enabled && permission === "granted" ? "bg-accent" : "bg-zinc-700"}`}
|
||||
>
|
||||
<span className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${enabled && permission === "granted" ? "translate-x-6" : "translate-x-1"}`} />
|
||||
</button>
|
||||
)}
|
||||
</Row>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
export default function SettingsPage() {
|
||||
const { user } = useAuth();
|
||||
const qc = useQueryClient();
|
||||
@@ -823,6 +879,9 @@ export default function SettingsPage() {
|
||||
</Row>
|
||||
</Section>
|
||||
|
||||
{/* Notifications */}
|
||||
<NotificationsSection />
|
||||
|
||||
{/* Data */}
|
||||
<Section title="Data">
|
||||
<div className="px-5 py-4 flex items-center justify-between">
|
||||
|
||||
Reference in New Issue
Block a user