PageSourceSearch

https://cases.media/notification-sw.js

js cases.media collected 2026-10-02 17:47:06 UTC 3,879 bytes, 110 lines download raw bytes

1self.addEventListener("install", (event) => {
2    // Force the waiting service worker to become the active service worker.
3    self.skipWaiting();
4});
5
6const showLocalNotification = (payload, swRegistration) => {
7    const defTitle = 'Default title';
8    const defOptions = {
9        body: "",
10        icon: "https://cdn.cases.media/image/original/apple-touch-icon-512x512-26.png",
11        badge: "https://cdn.cases.media/image/original/android-chrome-badge-97x97-maskable.png"
12    }
13
14    let options = Object.assign({}, defOptions, payload.options);
15    let title = payload.title || defTitle;
16
17    // Close same notification
18    if (options && options.data && options.tag && options.data.total) {
19        return swRegistration.getNotifications()
20        .then((notifications) => {
21            let maxTotal = 0;
22
23            for (let notification of notifications) {
24                if (!notification.data || !notification.tag || !notification.data.total) continue;
25                if (notification.tag !== options.tag) continue;
26
27                maxTotal = maxTotal > notification.data.total ? maxTotal : notification.data.total;
28
29                if (notification.data.total < options.data.total) {
30                    notification.close();
31                }
32            }
33
34            // Show notification only if total is greater then previous one
35            if (maxTotal < options.data.total)  {
36                return swRegistration.showNotification(title, options)
37            }
38        });
39    }
40
41    return swRegistration.showNotification(title, options)
42}
43
44const determineBadgeCount = (payload) => {
45    if (!payload || !payload.options || !payload.options.data) return undefined;
46    return payload.options.data.badgeCount;
47}
48
49self.addEventListener('push', function (event) {
50    if (event.data) {
51        try {
52            let promises = [];
53            let data = event.data.json();
54
55            if (self.navigator && 'setAppBadge' in self.navigator) {
56                const badgeCount = determineBadgeCount(data);
57
58                if (typeof badgeCount !== 'undefined') {
59                    // Promise to set the badge
60                    promises.push(self.navigator.setAppBadge(badgeCount));
61                }
62            }
63
64            // Promise to show a notification
65            promises.push(showLocalNotification(data, self.registration));
66
67            event.waitUntil(Promise.all(promises));
68        } catch (e) {
69            console.log(e)
70        }
71    }
72})
73
74self.addEventListener('notificationclick', function (event) {
75    if (!event.notification.data || !event.notification.data.url) return true;
76
77    const urlToOpen = new URL(event.notification.data.url, self.location.origin).href;
78
79    const promiseChain = clients.matchAll({
80        type: 'window',
81        includeUncontrolled: true
82    })
83    .then(async (windowClients) => {
84        // If the PWA is already running (including backgrounded iOS mode),
85        // try to bring the existing window forward and navigate it.
86        const clientToFocus = windowClients.find((client) => client.visibilityState === 'visible') || windowClients[0];
87
88        if (clientToFocus) {
89            try {
90                const isSamePage = clientToFocus.url === urlToOpen;
91                if (isSamePage) {
92                    await clientToFocus.focus();
93                    return;
94                }
95
96                const navigatedClient = await clientToFocus.navigate(urlToOpen);
97                await (navigatedClient || clientToFocus).focus();
98                return;
99            } catch (error) {
100                // Navigate/focus can fail on some platforms for backgrounded clients.
101                // Fall through to openWindow as a reliable fallback.
102            }
103        }
104
105        await clients.openWindow(urlToOpen);
106    });
107
108    event.waitUntil(promiseChain);
109    event.notification.close();
110})

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.