I have a service worker that has a event listener for push messages.
Here is the code
self.addEventListener('push', (event) => {
event.waitUntil(clients.matchAll({ type: 'window' }).then((clients) => {
console.log('Push event 3', event.data.json())
for (let i = 0; i < clients.length; ++i) {
if (clients[i].visibilityState === 'visible') return // there is a visible window
}
// continue with showing a notification
const data = notification.data || {}
data.click_action = notification.click_action
return registration.showNotification(notification.title + " test ", {
body: notification.body,
icon: notification.icon,
badge: notification.badge,
data: data,
requireInteraction: true,
actions: notification.actions,
image: notification.image,
click_action: notification.click_action
})
}))
})
async function checkClientIsVisible() {
const windowClients = await clients.matchAll({
type: 'window',
includeUncontrolled: true
})
for (var i = 0; i < windowClients.length; i++) {
if (windowClients[i].visibilityState === 'visible') {
return true
}
}
return false
}
The listener function checks if there are any windows/tabs showing the website in the scope of the sw.
It works fine on desktops pwa (windows/mac) and on android pwa too, but on IOS the push notification is showing even if the pwa window is in the foreground, what I want is that the notifications DO NOT appear when the pwa is in the foreground, only closed/background.
Thank you!
Well, after a 3 days research, seems like is not possible what I want, the PWA in IOS will always show the notification if the server has sent one.
Apple developer site stats (https://developer.apple.com/documentation/usernotifications/sending_web_push_notifications_in_web_apps_and_browsers) Safari doesn’t support invisible push notifications. Present push notifications to the user immediately after your service worker receives them. If you don’t, Safari revokes the push notification permission for your site.
With this in mind, I've "resolved" the issue keeping track of the browser visibility in the server side via websocket (since I was using signalr already):
Doing this way, when I need to send a push notification, I filter out the device tokens that are registered as visible on the server side and I never send a notificaiton to those devices.