I’ve carried out the Push and Notification API following this tutorial. It really works completely positive in Chrome on Mac OS.
However now I’m attempting to get it to work on Safari on iOS (16.4.3).
I’ve added my utility to the house display screen to make it a PWA.
I’ve a button #enable-notifications
to execute the next code:
JS code of my app
doc.getElementById("enable-notifications").addEventListener("click on", () => {
predominant();
});
const test = () => {
if (!('serviceWorker' in navigator)) {
throw new Error('No Service Employee assist!')
}
if (!('PushManager' in window)) {
throw new Error('No Push API Assist!')
}
}
const registerServiceWorker = async () => {
const swRegistration = await navigator.serviceWorker.register('/property/js/order-dashboard/serviceworker.js');
return swRegistration;
}
const requestNotificationPermission = async () => {
Promise.resolve(Notification.requestPermission()).then(operate(permission) {
if (permission !== 'granted') {
throw new Error('Permission not granted for Notification')
}
});
}
const predominant = async () => {
test();
const swRegistration = await registerServiceWorker();
const permission = await requestNotificationPermission();
}
const showLocalNotification = (title, physique, swRegistration) => {
const choices = {
physique,
};
swRegistration.showNotification(title, choices);
}
That is serviceworker.js:
// urlB64ToUint8Array is a magic operate that may encode the base64 public key
// to Array buffer which is required by the subscription possibility
const urlB64ToUint8Array = base64String => {
const padding = '='.repeat((4 - (base64String.size % 4)) % 4)
const base64 = (base64String + padding).substitute(/-/g, '+').substitute(/_/g, "https://stackoverflow.com/")
const rawData = atob(base64)
const outputArray = new Uint8Array(rawData.size)
for (let i = 0; i < rawData.size; ++i) {
outputArray[i] = rawData.charCodeAt(i)
}
return outputArray
}
// saveSubscription saves the subscription to the backend
const saveSubscription = async subscription => {
const SERVER_URL = 'https://good-months-invite-109-132-150-239.loca.lt/save-subscription'
const response = await fetch(SERVER_URL, {
technique: 'put up',
headers: {
'Content material-Sort': 'utility/json',
},
physique: JSON.stringify(subscription),
})
console.log(response);
return response.json()
}
self.addEventListener('activate', async () => {
// This will likely be referred to as solely as soon as when the service employee is activated.
strive {
const applicationServerKey = urlB64ToUint8Array(
'BDLVKNq32B-Dr3HRd4wQ2oNZL9mw5JAGhB1XGCdKlDE9_KDEw7uTOLuPKH-374RRolaa0rr7UyfrJd7tvRvp304'
)
const choices = { applicationServerKey, userVisibleOnly: true }
const subscription = await self.registration.pushManager.subscribe(choices)
const response = await saveSubscription(subscription)
console.log(response)
} catch (err) {
console.log('Error', err)
}
})
self.addEventListener("push", operate(occasion) {
if (occasion.information) {
console.log("Push occasion!!! ", occasion.information.textual content());
showLocalNotification("Yolo", occasion.information.textual content(), self.registration);
} else {
console.log("Push occasion however no information");
}
});
const showLocalNotification = (title, physique, swRegistration) => {
const choices = {
physique
// right here you possibly can add extra properties like icon, picture, vibrate, and so on.
};
swRegistration.showNotification(title, choices);
};
And that is my node.js back-end:
const categorical = require('categorical')
const cors = require('cors')
const bodyParser = require('body-parser')
const webpush = require('web-push')
const app = categorical()
app.use(cors())
app.use(bodyParser.json())
const port = 4000
app.get("https://stackoverflow.com/", (req, res) => res.ship('Howdy World!'))
const dummyDb = { subscription: null } //dummy in reminiscence retailer
const saveToDatabase = async subscription => {
// Since it is a demo app, I'm going to save lots of this in a dummy in reminiscence retailer. Don't do that in your apps.
// Right here you ought to be writing your db logic to reserve it.
dummyDb.subscription = subscription
}
// The brand new /save-subscription endpoint
app.put up('/save-subscription', async (req, res) => {
const subscription = req.physique
await saveToDatabase(subscription) //Technique to save lots of the subscription to Database
console.log("saved");
res.json({ message: 'success' })
})
const vapidKeys = {
publicKey:
'BDLVKNq32B-Dr3HRd4wQ2oNZL9mw5JAGhB1XGCdKlDE9_KDEw7uTOLuPKH-374RRolaa0rr7UyfrJd7tvRvp304',
privateKey: 'BGbNIt2twl1XsbDHPNe_w6FrKsWcZrys6anByEKyCGo',
}
//setting our beforehand generated VAPID keys
webpush.setVapidDetails(
'mailto:[email protected]',
vapidKeys.publicKey,
vapidKeys.privateKey
)
//operate to ship the notification to the subscribed gadget
const sendNotification = (subscription, dataToSend) => {
webpush.sendNotification(subscription, dataToSend)
}
//route to check ship notification
app.get('/send-notification', (req, res) => {
const subscription = dummyDb.subscription //get subscription out of your databse right here.
const message="Howdy World"
sendNotification(subscription, message)
res.json({ message: 'message despatched' })
})
app.hear(port, () => console.log(`Instance app listening on port ${port}!`))
Once I click on #enable-notifications
on iOS I get the pop-up to permit notifications. However then nothing occurs. My back-end additionally doesn’t get referred to as.
What appears to be the difficulty right here?