Last active
November 19, 2024 06:18
-
-
Save achadha235/e986363348eabfb5191dbe392c90bf36 to your computer and use it in GitHub Desktop.
React hook for managing web push notifications
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { useEffect, useState } from "react"; | |
| enum NotificationError { | |
| ServiceWorkerAndPushManagerNotSupported = "ServiceWorkerAndPushManagerNotSupported", | |
| PushManagerUnavailable = "PushManagerUnavailable", | |
| ExistingSubscription = "ExistingSubscription", | |
| PermissionNotGranted = "PermissionNotGranted", | |
| } | |
| export function useNotifications() { | |
| const [loading, setLoading] = useState(true); | |
| const [subscription, setSubscription] = useState<PushSubscription | null>( | |
| null | |
| ); | |
| const isNotificationSupported = | |
| "serviceWorker" in navigator && "PushManager" in window; | |
| async function useServiceWorkerRegistration() { | |
| return navigator.serviceWorker.ready; | |
| } | |
| useEffect(() => { | |
| if (!isNotificationSupported) { | |
| setLoading(false); | |
| return; | |
| } | |
| async function checkExistingSubscription() { | |
| try { | |
| const registration = await useServiceWorkerRegistration(); | |
| const pushManager = registration.pushManager; | |
| if (pushManager) { | |
| const existingSubscription = await pushManager.getSubscription(); | |
| if (existingSubscription) { | |
| setSubscription(existingSubscription); | |
| } | |
| } | |
| } catch (error) { | |
| console.error("Error checking subscription:", error); | |
| } finally { | |
| setLoading(false); | |
| } | |
| } | |
| checkExistingSubscription(); | |
| }, []); | |
| async function subscribe(options: PushSubscriptionOptionsInit) { | |
| setLoading(true); | |
| try { | |
| if (!isNotificationSupported) { | |
| throw new Error( | |
| NotificationError.ServiceWorkerAndPushManagerNotSupported | |
| ); | |
| } | |
| const permission = await Notification.requestPermission(); | |
| if (permission !== "granted") { | |
| throw new Error(NotificationError.PermissionNotGranted); | |
| } | |
| const registration = await useServiceWorkerRegistration(); | |
| const pushManager = registration.pushManager; | |
| if (!pushManager) { | |
| throw new Error(NotificationError.PushManagerUnavailable); | |
| } | |
| const existingSubscription = await pushManager.getSubscription(); | |
| if (existingSubscription) { | |
| throw new Error(NotificationError.ExistingSubscription); | |
| } | |
| const subscription = await pushManager.subscribe(options); | |
| console.debug("subscription", subscription); | |
| setSubscription(subscription); | |
| } finally { | |
| setLoading(false); | |
| } | |
| } | |
| async function unsubscribe() { | |
| setLoading(true); | |
| try { | |
| if (!isNotificationSupported) { | |
| throw new Error( | |
| NotificationError.ServiceWorkerAndPushManagerNotSupported | |
| ); | |
| } | |
| const registration = await useServiceWorkerRegistration(); | |
| const pushManager = registration.pushManager; | |
| if (!pushManager) { | |
| throw new Error(NotificationError.PushManagerUnavailable); | |
| } | |
| const existingSubscription = await pushManager.getSubscription(); | |
| if (!existingSubscription) { | |
| return false; | |
| } | |
| const success = await existingSubscription.unsubscribe(); | |
| if (success) { | |
| setSubscription(null); | |
| } | |
| return success; | |
| } finally { | |
| setLoading(false); | |
| } | |
| } | |
| return { | |
| subscription, | |
| isNotificationSupported, | |
| subscribe, | |
| unsubscribe, | |
| loading, | |
| }; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment