frigate/web/src/views/settings/NotificationsSettingsView.tsx

115 lines
3.8 KiB
TypeScript
Raw Normal View History

2024-07-10 20:25:35 +03:00
import { Button } from "@/components/ui/button";
import Heading from "@/components/ui/heading";
import { Toaster } from "@/components/ui/sonner";
import { FrigateConfig } from "@/types/frigateConfig";
import axios from "axios";
2024-07-20 22:19:34 +03:00
import { useCallback, useEffect, useState } from "react";
import useSWR from "swr";
2024-07-10 20:25:35 +03:00
2024-07-20 18:14:38 +03:00
const NOTIFICATION_SERVICE_WORKER = "notifications-worker.ts";
2024-07-10 20:25:35 +03:00
export default function NotificationView() {
2024-07-20 22:19:34 +03:00
const { data: config } = useSWR<FrigateConfig>("config", {
revalidateOnFocus: false,
});
2024-07-10 20:25:35 +03:00
2024-07-20 20:25:44 +03:00
// notification key handling
const { data: publicKey } = useSWR(
config?.notifications?.enabled ? "notifications/pubkey" : null,
2024-07-20 22:19:34 +03:00
{ revalidateOnFocus: false },
);
const subscribeToNotifications = useCallback(
(registration: ServiceWorkerRegistration) => {
if (registration) {
registration.pushManager
.subscribe({
userVisibleOnly: true,
applicationServerKey: publicKey,
})
.then((pushSubscription) => {
axios.post("notifications/register", {
sub: pushSubscription,
});
});
}
},
[publicKey],
2024-07-20 20:25:44 +03:00
);
2024-07-20 18:14:38 +03:00
// notification state
2024-07-20 22:19:34 +03:00
const [registration, setRegistration] =
useState<ServiceWorkerRegistration | null>();
2024-07-20 18:14:38 +03:00
useEffect(() => {
navigator.serviceWorker
.getRegistration(NOTIFICATION_SERVICE_WORKER)
.then((worker) => {
2024-07-20 22:19:34 +03:00
if (worker) {
setRegistration(worker);
} else {
setRegistration(null);
}
})
.catch(() => {
setRegistration(null);
2024-07-20 18:14:38 +03:00
});
}, []);
2024-07-10 20:25:35 +03:00
return (
<>
<div className="flex size-full flex-col md:flex-row">
<Toaster position="top-center" closeButton={true} />
<div className="scrollbar-container order-last mb-10 mt-2 flex h-full w-full flex-col overflow-y-auto rounded-lg border-[1px] border-secondary-foreground bg-background_alt p-2 md:order-none md:mb-0 md:mr-2 md:mt-0">
<Heading as="h3" className="my-2">
Notification Settings
</Heading>
{config?.notifications.enabled && (
<div className="mt-2 space-y-6">
<div className="space-y-3">
{
// TODO need to register the worker before enabling the notifications button
// TODO make the notifications button show enable / disable depending on current state
}
<Button
2024-07-20 22:19:34 +03:00
disabled={publicKey == undefined}
onClick={() => {
2024-07-20 22:19:34 +03:00
if (registration == null) {
Notification.requestPermission().then((permission) => {
if (permission === "granted") {
navigator.serviceWorker
.register(NOTIFICATION_SERVICE_WORKER)
.then((registration) => {
setRegistration(registration);
if (registration.active) {
subscribeToNotifications(registration);
} else {
setTimeout(
() => subscribeToNotifications(registration),
1000,
);
}
});
}
});
} else {
registration.unregister();
setRegistration(null);
}
}}
>
2024-07-20 22:19:34 +03:00
{`${registration != null ? "Unregister" : "Register"} for Notifications`}
</Button>
</div>
</div>
)}
</div>
</div>
</>
2024-07-10 20:25:35 +03:00
);
}