Try to handle iOS stacked notifications

This commit is contained in:
Nicolas Mowen 2026-03-23 17:49:33 -06:00
parent fb4b37c337
commit b1cbedc195

View File

@ -19,11 +19,7 @@ self.addEventListener("push", function (event) {
break; break;
} }
// event.waitUntil is required on iOS Safari — without it, the browser const notificationOptions = {
// may consider this a "silent push" and revoke the subscription after 3 occurrences.
event.waitUntil(
// @ts-expect-error we know this exists
self.registration.showNotification(data.title, {
body: data.message, body: data.message,
icon: "/images/maskable-icon.png", icon: "/images/maskable-icon.png",
image: data.image, image: data.image,
@ -31,7 +27,32 @@ self.addEventListener("push", function (event) {
tag: data.id, tag: data.id,
data: { id: data.id, link: data.direct_url }, data: { id: data.id, link: data.direct_url },
actions, actions,
}), // eslint-disable-line comma-dangle };
// iOS Safari does not auto-coalesce notifications by tag (WebKit bug #258922).
// On iOS 18.3+ close() works, so we manually close duplicates before showing.
// On other platforms, tag-based replacement works natively — skip the extra work.
const isIOS =
/iPad|iPhone|iPod/.test(navigator.userAgent) && !self.MSStream;
const show = () =>
// @ts-expect-error we know this exists
self.registration.showNotification(data.title, notificationOptions);
// event.waitUntil is required on iOS Safari — without it, the browser
// may consider this a "silent push" and revoke the subscription after 3 occurrences.
event.waitUntil(
isIOS
? // @ts-expect-error we know this exists
self.registration
.getNotifications({ tag: data.id })
.then((existing) => {
for (const n of existing) {
n.close();
}
})
.then(show)
: show(), // eslint-disable-line comma-dangle
); );
} else { } else {
// pass // pass