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,19 +19,40 @@ self.addEventListener("push", function (event) {
break; break;
} }
const notificationOptions = {
body: data.message,
icon: "/images/maskable-icon.png",
image: data.image,
badge: "/images/maskable-badge.png",
tag: data.id,
data: { id: data.id, link: data.direct_url },
actions,
};
// 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 // event.waitUntil is required on iOS Safari — without it, the browser
// may consider this a "silent push" and revoke the subscription after 3 occurrences. // may consider this a "silent push" and revoke the subscription after 3 occurrences.
event.waitUntil( event.waitUntil(
// @ts-expect-error we know this exists isIOS
self.registration.showNotification(data.title, { ? // @ts-expect-error we know this exists
body: data.message, self.registration
icon: "/images/maskable-icon.png", .getNotifications({ tag: data.id })
image: data.image, .then((existing) => {
badge: "/images/maskable-badge.png", for (const n of existing) {
tag: data.id, n.close();
data: { id: data.id, link: data.direct_url }, }
actions, })
}), // eslint-disable-line comma-dangle .then(show)
: show(), // eslint-disable-line comma-dangle
); );
} else { } else {
// pass // pass