I’ve applied the Push and Notification API following this tutorial. It really works completely high-quality in Chrome on Mac OS.
However now I’m making an attempt to get it to work on Safari on iOS (16.4.3).
I’ve added my utility to the house display 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", () => {
fundamental();
});
const verify = () => {
if (!('serviceWorker' in navigator)) {
throw new Error('No Service Employee help!')
}
if (!('PushManager' in window)) {
throw new Error('No Push API Assist!')
}
}
const registerServiceWorker = async () => {
const swRegistration = await navigator.serviceWorker.register('/belongings/js/order-dashboard/serviceworker.js');
return swRegistration;
}
const requestNotificationPermission = async () => {
Promise.resolve(Notification.requestPermission()).then(perform(permission) {
if (permission !== 'granted') {
throw new Error('Permission not granted for Notification')
}
});
}
const fundamental = async () => {
verify();
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 perform that may encode the base64 public key
// to Array buffer which is required by the subscription choice
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, {
methodology: 'submit',
headers: {
'Content material-Kind': 'utility/json',
},
physique: JSON.stringify(subscription),
})
console.log(response);
return response.json()
}
self.addEventListener('activate', async () => {
// This might be known 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", perform(occasion) {
if (occasion.knowledge) {
console.log("Push occasion!!! ", occasion.knowledge.textual content());
showLocalNotification("Yolo", occasion.knowledge.textual content(), self.registration);
} else {
console.log("Push occasion however no knowledge");
}
});
const showLocalNotification = (title, physique, swRegistration) => {
const choices = {
physique
// right here you may add extra properties like icon, picture, vibrate, and so on.
};
swRegistration.showNotification(title, choices);
};
And that is my node.js back-end:
const specific = require('specific')
const cors = require('cors')
const bodyParser = require('body-parser')
const webpush = require('web-push')
const app = specific()
app.use(cors())
app.use(bodyParser.json())
const port = 4000
app.get("https://stackoverflow.com/", (req, res) => res.ship('Good day 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 have to be writing your db logic to reserve it.
dummyDb.subscription = subscription
}
// The brand new /save-subscription endpoint
app.submit('/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:myuserid@e mail.com',
vapidKeys.publicKey,
vapidKeys.privateKey
)
//perform to ship the notification to the subscribed machine
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="Good day World"
sendNotification(subscription, message)
res.json({ message: 'message despatched' })
})
app.pay attention(port, () => console.log(`Instance app listening on port ${port}!`))
After 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 known as.
What appears to be the difficulty right here?