Skip to content

Instantly share code, notes, and snippets.

@tomfa
Last active June 16, 2024 11:25
Show Gist options
  • Save tomfa/59a99400cd2d6bc8bff6dcd0a570e138 to your computer and use it in GitHub Desktop.
Save tomfa/59a99400cd2d6bc8bff6dcd0a570e138 to your computer and use it in GitHub Desktop.
iOS push notifications
{
"name": "Notification app",
"short_name": "Notifs",
"start_url": ".",
"display": "standalone",
"background_color": "#1f2937",
"orientation": "portrait",
"description": "Notifications made easy.",
"icons": [{
"src": "img/logo_144.png",
"sizes": "144x144"
},{
"src": "img/logo_512.png",
"sizes": "512x512"
}, {
"src": "img/logo.svg",
"sizes": "48x48 72x72 96x96 128x128 256x256"
}],
"related_applications": [{
"platform": "web"
}]
}
/*
Apple (finally) added support for push notifications by PWAs in iOS 16.4.
There are some caviats:
- The app must be installed to iOS as a PWA (Share -> Add to home screen)
- The notifications must be sent from a service worker through showNotification.
new Notification() does not work.
- The app must be served over HTTPS (so use e.g. localtunnel.me during development)
Note that ⬆️ is not consistent what is documented on MDN.
Related links:
- https://developer.mozilla.org/en-US/docs/Web/API/Notification/Notification
- https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/showNotification
- https://github.com/mdn/browser-compat-data/issues/19318
*/
const isInstalledAsPWA = typeof window !== 'undefined' &&
!!window.matchMedia('(display-mode: standalone)').matches;
const serviceWorkerSupported =
typeof navigator !== "undefined" &&
"serviceWorker" in navigator;
const notificationsSupported = typeof Notification !== "undefined";
let worker = null;
if (serviceWorkerSupported) {
navigator.serviceWorker.ready
.then(w => { worker = w })
.catch(err => console.error(err));
}
const registerServiceWorker = () => {
if (!serviceWorkerSupported) {
return null;
}
if (worker) {
return worker
}
return navigator.serviceWorker.register("/sw.js");
}
const requestNotificationPermission = () => notificationsSupported && Notification.requestPermission();
const hasNotificationPermission = () => notificationsSupported && Notification.permission === "granted";
/**
* Show notification.
*
* @param {Object} event - The event object
* @param {Object} event.title - Title in notification
* @param {Object} [event.body] - Optional notification body
*/
const showNotification = async ({ title, body }) => {
if (!isInstalledAsPWA) {
console.error(`Must install as PWA first`);
return;
}
if (!serviceWorkerSupported || !notificationsSupported) {
console.error(`Not supported in your browser`)
return;
}
if (!hasNotificationPermission) {
await requestNotificationPermission();
}
const sw = await registerServiceWorker();
if (!sw) {
console.error('Unable to register service worker');
return;
}
await sw.showNotification(title, body ? { body } : undefined);
}
// sendEventToServiceWorker function below is unrelated to
// notifications, but sends message to the dummy event handler in sw.js
const sendEventToServiceWorker = (data) => {
postMessage(data);
}
/**
* Dummy service worker event handler
* @param {MessageEvent<any>} event - The event object
* @param {Object} event.data - The data sent to the worker.
*/
addEventListener("message", (event) => {
console.log(`Message received: ${event.data}`);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment