import React, { createContext, FC, useCallback, useEffect, useMemo, useRef } from 'react' import { apolloClient } from '../apollo-client' import { gql_Channel, useCreateChannelMutation } from '../graphql' import { urlBase64ToUint8Array } from '../utils' export type HNSProviderProps = { serviceWorkerPath?: string publicKey?: string children?: React.ReactNode getUserToken: () => Promise } export type HNSContextResult = { // isWebPushSupported: boolean isWebPushSubscribed: boolean subscribeToWebPush: () => Promise serviceWorkerPath?: string publicKey?: string getUserToken: () => Promise } export const HNSContext = createContext({ // isWebPushSupported: false, isWebPushSubscribed: false, subscribeToWebPush: () => Promise.reject(), getUserToken: () => Promise.reject(), }) export const HNSProviderInner: FC = ({ serviceWorkerPath = '/hns-webpush-sw.js', publicKey, children, getUserToken, }) => { const serviceWorkerRegistration = useRef() // const isWebPushSupported = useMemo(() => { // return 'serviceWorker' in navigator && 'PushManager' in window // }, []) const [isWebPushSubscribed, setIsWebPushSubscribed] = React.useState(false) const [createChannel, { data }] = useCreateChannelMutation({ client: apolloClient }) const subscribeToWebPush = useCallback(async () => { if (!serviceWorkerRegistration.current || !publicKey) { return } const subscription = await serviceWorkerRegistration.current.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: publicKey ? urlBase64ToUint8Array(publicKey) : undefined, }) if (subscription) { try { const jwt = await getUserToken() const { data, errors } = await createChannel({ context: { headers: { authorization: `Bearer ${jwt}`, }, }, variables: { channel: gql_Channel.WebPush, details: subscription.toJSON(), }, }) if (errors) { throw new Error(errors[0].message) } if (data?.hc_createChannel?.id) { setIsWebPushSubscribed(true) } } catch (e) { console.error('error', e) } } }, [createChannel, getUserToken, publicKey]) const contextValue = useMemo( () => ({ // isWebPushSupported, isWebPushSubscribed, subscribeToWebPush, serviceWorkerPath, publicKey, getUserToken, }), [isWebPushSubscribed, subscribeToWebPush, serviceWorkerPath, publicKey, getUserToken] ) useEffect(() => { let changed = false if ('serviceWorker' in navigator && publicKey && !changed) { navigator.serviceWorker .getRegistration(serviceWorkerPath) .then((registration) => { if (!registration) { navigator.serviceWorker.register(serviceWorkerPath).then((registration) => { serviceWorkerRegistration.current = registration registration.pushManager .getSubscription() .then((subscription) => { if (subscription) { setIsWebPushSubscribed(true) } }) .catch((err) => console.error('Service Worker registration failed: ', err)) }) } else { serviceWorkerRegistration.current = registration registration?.pushManager .getSubscription() .then((subscription) => { if (subscription) { setIsWebPushSubscribed(true) } }) .catch((err) => console.error('Service Worker registration failed: ', err)) } }) .catch((e) => { console.error('error', e) }) } // eslint-disable-next-line react-hooks/exhaustive-deps }, []) return {children} } export const HNSProvider: FC = (props) => { // if (typeof window === 'undefined') { // return {props.children} // } return } export function useHNSContext() { return React.useContext(HNSContext) }