Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove a Web Push Notification

Is there a way to remove a Web Push Notification once shown? To remove it from the notification list on the device - or mark it as "read"?

I assume this can't be done from the server, and I've been hunting around for a Javascript API - but I haven't found anything.

(The wider problem that I'm trying to crack is how to synchronise notifications on multiple screens/browsers/devices.)

like image 997
Daniel Freeman Avatar asked Mar 26 '18 09:03

Daniel Freeman


People also ask

Can you cancel a push notification?

How to Disable Push Notifications on Android. You can disable push notifications on Android by going into the Settings > Notifications options. Similar to iOS, Android lets you turn off push notifications for individual apps or use a 'Do not disturb' mode.

How do I turn off Chrome push notifications?

Disable Chrome notifications on AndroidHit the three dots in the right-hand corner. Tap Settings. Choose Notifications. To block all notifications from Chrome on Android, toggle the switch to the right of Show notifications to the off position.


2 Answers

Even though it's not possble to revoke push messages, it is possible to close one, using:

// app.js
navigator.serviceWorker.ready.then(reg => {
  reg.getNotifications().then(notifications => {
    for (let i = 0; i < notifications.length; i += 1) {
      notifications[i].close();
    }
  });
});

You could even send a new WebPush message from the back-end with a special action in the payload, for example data: { action: 'close', id: 123 } to trigger messages to be closed. The 'push' eventListener can relay a 'message' event to all clients to close the given (or all) open notifications.

// sw.js
self.addEventListener('push', event => {
  let opts = event.data.json();

  if (opts.data && opts.data.action) {
    event.waitUntil(clients.matchAll().then(windowClients => {
      for (let i = 0; i < windowClients.length; i += 1) {
        windowsClients[i].postMessage(opts.data);
      }
    });
  }
});

// app.js
navigator.serviceWorker.addEventListener('message', event => {
  if (event.data && event.data.action && event.data.action === 'close') {
    closeNotification(event.data.id);
  }
});

function closeNotification(id) {
  navigator.serviceWorker.ready.then(reg => {
    reg.getNotifications().then(n => {
      for (let i = 0; i < n.length; i += 1) {
        if (n[i].data && n[i].data.id && n[i].data.id === id) {
          n[i].close();
        }
      }
    });
  });
}

The biggest downside is that this method only works for active / open clients. I haven't found a way around that.

Used sources:

  • https://developer.mozilla.org/en-US/docs/Web/API/Client/postMessage
  • https://web-push-book.gauntface.com/common-notification-patterns/#merging-notifications
  • https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/getNotifications
like image 135
royarisse Avatar answered Jan 02 '23 20:01

royarisse


I think might be impossible. As you can show and hide a notification. And this can be a workaround for default browser action as described here

Chrome will only show the "This site has been updated in the background." notification when a push message is received and the push event in the service worker does not show a notification after the promise passed to event.waitUntil() has finished.

like image 30
Kitsor Avatar answered Jan 02 '23 22:01

Kitsor