Instantly share code, notes, and snippets.
Last active
August 14, 2024 17:54
-
Star
(0)
0
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save maiconcarraro/0845af1acc7490fb57e4c119815f50fc to your computer and use it in GitHub Desktop.
PWABuilder iOS shell + React example
This file contains 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
export default function SubscribeButton() { | |
const [subscribing, setSubscribing] = useState<boolean>(true); | |
const [token, setToken] = useState<string | null>(null); | |
const [iOSPushCapability, setiOSPushCapability] = useState(false); | |
const saveFCMToken = api.user.saveFCMToken.useMutation({ // I'm using tRPC | |
onSuccess() { | |
setSubscribing(false); | |
toast.success("Success."); | |
}, | |
onError() { | |
toast.error("Error."); | |
}, | |
}); | |
useEffect(() => { | |
if (typeof window !== "object") { | |
return; | |
} | |
// For iOS shell | |
if ( | |
window.webkit && | |
window.webkit.messageHandlers && | |
window.webkit.messageHandlers["push-permission-request"] && | |
window.webkit.messageHandlers["push-permission-state"] | |
) { | |
setiOSPushCapability(true); | |
return; | |
} | |
// Below this is for Web and android shell only | |
const granted = Notification?.permission === "granted"; | |
if (granted) { | |
getToken(getMessaging(firebaseApp), { | |
vapidKey: process.env.NEXT_PUBLIC_WEB_PUSH_PUBLIC_KEY, | |
}) | |
.then((token) => { | |
setToken(token); | |
setSubscribing(false); | |
}) | |
.catch((err) => console.error(err)); | |
} else { | |
setSubscribing(false); | |
} | |
}, []); | |
const subscribeButtonOnClick = async () => { | |
setSubscribing(true); | |
const messaging = getMessaging(firebaseApp); | |
// Request notification permission | |
const permission = await Notification.requestPermission(); | |
if (permission === "granted") { | |
const currentToken = await getToken(messaging, { | |
vapidKey: process.env.NEXT_PUBLIC_WEB_PUSH_PUBLIC_KEY, // I'm using Next.js | |
}).catch((err) => { | |
console.error(err); | |
return ""; | |
}); | |
setToken(currentToken); | |
if (currentToken) { | |
await saveFCMToken.mutateAsync({ fcmToken: currentToken }); | |
} | |
} else { | |
setSubscribing(false); | |
toast.error("Error."); | |
} | |
}; | |
const onTokenChange = useCallback((token: string) => { | |
return saveFCMToken | |
.mutateAsync({ fcmToken: token }) | |
.then(() => setToken(token)); | |
}, []); | |
return ( | |
<div> | |
{iOSPushCapability ? ( | |
<SubscribeButtonIOS | |
loading={saveFCMToken.isPending} | |
onTokenChange={onTokenChange} | |
> | |
Subscribe (iOS) | |
</SubscribeButtonIOS> | |
) : ( | |
<Button | |
loading={saveFCMToken.isPending || subscribing} | |
onClick={subscribeButtonOnClick} | |
> | |
Subscribe (Web) | |
</Button> | |
)} | |
</div> | |
); | |
} |
This file contains 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
declare global { | |
interface Window { | |
webkit?: { | |
messageHandlers: { | |
[x: string]: { | |
postMessage: (data: string) => void; | |
}; | |
}; | |
}; | |
} | |
} | |
export default function SubscribeButtonIOS({ | |
onTokenChange, | |
...props | |
}: ButtonProps & { | |
onTokenChange: (token: string) => void; | |
}) { | |
const [synced, setSynced] = useState(false); | |
const [token, setToken] = useState<string | null>(null); | |
const webkitPushTokenRequest = useCallback(() => { | |
window.webkit?.messageHandlers["push-token"]?.postMessage("push-token"); | |
}, []); | |
const webkitPushPermissionRequest = useCallback(() => { | |
window.webkit?.messageHandlers["push-permission-request"]?.postMessage( | |
"push-permission-request", | |
); | |
}, []); | |
const webkitPushPermissionState = useCallback(() => { | |
window.webkit?.messageHandlers["push-permission-state"]?.postMessage( | |
"push-permission-state", | |
); | |
}, []); | |
useEffect(() => { | |
if (typeof window !== "object") { | |
return; | |
} | |
const pushPermissionRequest = (event: CustomEvent) => { | |
if (event && event.detail) { | |
switch (event.detail) { | |
case "granted": | |
webkitPushTokenRequest(); | |
break; | |
default: | |
toast.error("Denied."); | |
break; | |
} | |
} | |
}; | |
// @ts-ignore | |
window.addEventListener("push-permission-state", (event: CustomEvent) => { | |
setSynced(true); | |
if (event && event.detail) { | |
switch (event.detail) { | |
case "notDetermined": | |
// permission not asked | |
break; | |
case "denied": | |
toast.error("Denied."); | |
// permission denied | |
break; | |
case "authorized": | |
case "ephemeral": | |
case "provisional": | |
webkitPushTokenRequest(); | |
break; | |
case "unknown": | |
default: | |
// something wrong | |
break; | |
} | |
} | |
}); | |
// Sync state | |
webkitPushPermissionState(); | |
// sendPushToWebView | |
const pushNotification = (event: CustomEvent) => { | |
if (event && event.detail) { | |
// logMessage(JSON.stringify(event.detail)); | |
} | |
}; | |
const pushToken = (event: CustomEvent) => { | |
if (event && event.detail) { | |
setToken(event.detail); | |
} | |
}; | |
// @ts-ignore | |
window.addEventListener("push-permission-request", pushPermissionRequest); | |
// @ts-ignore | |
window.addEventListener("push-notification", pushNotification); | |
// @ts-ignore | |
window.addEventListener("push-token", pushToken); | |
return () => { | |
// @ts-ignore | |
window.removeEventListener( | |
"push-permission-request", | |
pushPermissionRequest, | |
); | |
// @ts-ignore | |
window.removeEventListener("push-notification", pushNotification); | |
// @ts-ignore | |
window.removeEventListener("push-token", pushToken); | |
}; | |
}, []); | |
useEffect(() => { | |
if (token) { | |
onTokenChange(token); | |
} | |
}, [token, onTokenChange]); | |
return ( | |
<Button | |
{...props} | |
loading={!synced || props.loading} | |
onClick={() => { | |
setToken(""); | |
webkitPushPermissionRequest(); | |
}} | |
/> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment