()
| 77 | * ("blocked", "unsupported", "subscribed") off the returned view. |
| 78 | */ |
| 79 | export function useWebPush(): IUseWebPushView { |
| 80 | const isSupported = isApiSupported(); |
| 81 | const isConfigured = env.VITE_VAPID_PUBLIC_KEY !== ""; |
| 82 | |
| 83 | const [permission, setPermission] = |
| 84 | useState<IWebPushPermission>(currentPermission); |
| 85 | const [isSubscribed, setIsSubscribed] = useState(false); |
| 86 | const [isPending, setIsPending] = useState(false); |
| 87 | |
| 88 | useEffect(() => { |
| 89 | if (!isSupported) { |
| 90 | return undefined; |
| 91 | } |
| 92 | |
| 93 | let cancelled = false; |
| 94 | |
| 95 | const refreshSubscription = async (): Promise<void> => { |
| 96 | try { |
| 97 | const registration = await navigator.serviceWorker.ready; |
| 98 | const sub = await registration.pushManager.getSubscription(); |
| 99 | |
| 100 | if (!cancelled) { |
| 101 | setIsSubscribed(sub !== null); |
| 102 | } |
| 103 | } catch (error: unknown) { |
| 104 | if (!cancelled) { |
| 105 | logger.warn({ |
| 106 | event: "notifications.web_push.subscribe_failed", |
| 107 | phase: "initial_check", |
| 108 | error: getErrorMessage(error) |
| 109 | }); |
| 110 | } |
| 111 | } |
| 112 | }; |
| 113 | |
| 114 | void refreshSubscription(); |
| 115 | |
| 116 | return () => { |
| 117 | cancelled = true; |
| 118 | }; |
| 119 | }, [isSupported]); |
| 120 | |
| 121 | const subscribe = useCallback(async (): Promise<void> => { |
| 122 | if (!isSupported || !isConfigured) { |
| 123 | return; |
| 124 | } |
| 125 | |
| 126 | setIsPending(true); |
| 127 | |
| 128 | try { |
| 129 | const requested = await Notification.requestPermission(); |
| 130 | |
| 131 | setPermission(normalizePermission(requested)); |
| 132 | |
| 133 | if (requested !== "granted") { |
| 134 | return; |
| 135 | } |
| 136 |
no test coverage detected