shellphone.app/app/core/hooks/use-notifications.ts

72 lines
2.1 KiB
TypeScript
Raw Normal View History

2021-08-01 16:28:47 +00:00
import { getConfig, useMutation } from "blitz";
import { useEffect, useMemo, useState } from "react";
2021-08-01 16:28:47 +00:00
import setNotificationSubscription from "../mutations/set-notification-subscription";
2021-08-05 17:07:15 +00:00
import useCurrentPhoneNumber from "./use-current-phone-number";
2021-08-01 16:28:47 +00:00
const { publicRuntimeConfig } = getConfig();
export default function useNotifications() {
const isServiceWorkerSupported = useMemo(() => "serviceWorker" in navigator, []);
2021-08-01 16:28:47 +00:00
const [subscription, setSubscription] = useState<PushSubscription | null>(null);
const [setNotificationSubscriptionMutation] = useMutation(setNotificationSubscription);
2021-08-05 17:07:15 +00:00
const phoneNumber = useCurrentPhoneNumber();
2021-08-01 16:28:47 +00:00
useEffect(() => {
(async () => {
if (!isServiceWorkerSupported) {
return;
}
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.getSubscription();
setSubscription(subscription);
})();
}, [isServiceWorkerSupported]);
async function subscribe() {
2021-08-05 17:07:15 +00:00
if (!isServiceWorkerSupported || !phoneNumber) {
2021-08-01 16:28:47 +00:00
return;
}
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(publicRuntimeConfig.webPush.publicKey),
});
setSubscription(subscription);
2021-08-05 17:07:15 +00:00
await setNotificationSubscriptionMutation({
phoneNumberId: phoneNumber.id,
subscription: subscription.toJSON() as any,
}); // TODO remove as any
2021-08-01 16:28:47 +00:00
}
async function unsubscribe() {
if (!isServiceWorkerSupported) {
return;
}
return subscription?.unsubscribe();
}
return {
isServiceWorkerSupported,
subscription,
subscribe,
unsubscribe,
};
}
function urlBase64ToUint8Array(base64String: string) {
const padding = "=".repeat((4 - (base64String.length % 4)) % 4);
const base64 = (base64String + padding).replace(/\-/g, "+").replace(/_/g, "/");
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}