PageSourceSearch

https://www.niteflirt.com/service-worker.js

js niteflirt.com collected 2026-09-24 10:05:49 UTC 4,465 bytes, 137 lines download raw bytes

1const BUILD_ID = '0.0.1-260921.1750';
2self.build = BUILD_ID;
3
4function logEvent(data = {}) {
5  const url = '/client_api/log';
6  const headers = { 'Content-Type': 'application/json' };
7
8  // Telemetry is best-effort: a failed log must never reject a waitUntil chain.
9  return fetch(url, {
10    method: 'POST',
11    body: JSON.stringify(data),
12    headers,
13  }).catch(() => {});
14}
15
16const updateServiceWorker = async () => {
17  try {
18    await self.registration.update();
19    logEvent({ log: { message: 'Checking for updates', event: 'update', build: self.build } });
20    self.skipWaiting(); // Optional: Force the waiting service worker to become the active service worker.
21  } catch (err) {
22    logEvent({ log: { message: 'Update failed', event: 'error', build: self.build, error: err } });
23  }
24};
25
26const updateAppOnEvent = (e) => {
27  if (e.data && e.data.command === 'UPDATE_APP') {
28    updateServiceWorker();
29  }
30}
31
32function onInstall(event) {
33  console.log('[Serviceworker]', `Installing! ${self.build}`, event);
34  logEvent({ log: { message: 'Installing', event: 'install', build: self.build } });
35}
36
37function onActivate(event) {
38  console.log('[Serviceworker]', "Activating!", event);
39  logEvent({ log: { message: 'Activating', event: 'activate', build: self.build } });
40}
41
42function onFetch(event) {
43  // console.log('[Serviceworker]', "Fetching!", event);
44  // logEvent({ log: { message: 'Fetching', event: 'fetch', build: self.build } });
45}
46
47const showMessageNotification = async function(payload) {
48  if ('setAppBadge' in self.navigator && payload.badge_count != null) {
49    try {
50      await self.navigator.setAppBadge(payload.badge_count);
51    } catch (e) {
52      // A badge failure must never block the notification.
53    }
54  }
55
56  if (Notification.permission !== 'granted') {
57    return logEvent({ log: { message: 'push_suppressed', event: 'push_suppressed', reason: 'permission_not_granted', build: self.build } });
58  }
59
60  const badge = "https://www.niteflirt.com/niteflirt/images/favicon/push-notification-icon.png";
61
62  const options = {
63    body: payload.body_text || 'You have new activity on NiteFlirt',
64    badge,
65    vibrate: [100, 50, 100],
66    data: {
67      dateOfArrival: Date.now(),
68      primaryKey: '2',
69      url: payload.notification_url || '/',
70    },
71  };
72
73  const title = payload.title || 'New activity on NiteFlirt';
74
75  try {
76    await self.registration.showNotification(title, options);
77  } catch (e) {
78    return logEvent({ log: { message: 'push_suppressed', event: 'push_suppressed', reason: 'show_notification_failed', build: self.build, error: e.message } });
79  }
80
81  return logEvent({ log: { message: 'push_shown', event: 'push_shown', build: self.build } });
82};
83
84const handlePush = async function(event) {
85  let payload = null;
86
87  try {
88    payload = event.data ? event.data.json() : null;
89  } catch (e) {
90    console.error('Error parsing event data', e);
91    logEvent({ log: { message: 'Error parsing event data', event: 'error', build: self.build, error: e.message } });
92  }
93
94  if (payload && payload.type === 'UPDATE_APP') {
95    // Silent by design; must not be sent until the follow-up to NF-26656 lands.
96    return updateServiceWorker();
97  }
98
99  // Always show a notification: the subscription promises userVisibleOnly, and
100  // iOS Safari/Firefox revoke subscriptions after repeated silent pushes (NF-26656).
101  return showMessageNotification(payload || {});
102};
103
104function onPush(event) {
105  console.log('[Serviceworker]', "Pushing!", event, "With build", self.build);
106  logEvent({ log: { message: 'Pushing', event: 'push', build: self.build } });
107  event.waitUntil(handlePush(event));
108};
109
110async function onNotificationClick(event) {
111  logEvent({ log: { message: 'Notification clicked', event: 'notification_click', build: self.build } });
112  const url = event.notification.data.url;
113  event.notification.close();
114  event.waitUntil(
115    clients.matchAll({ type: "window" }).then((clientList) => {
116      for (const client of clientList) {
117        if ("focus" in client) {
118          client.focus();
119          client.navigate(url);
120          return
121        }
122      }
123
124      if (clients.openWindow) {
125        return clients.openWindow(url);
126      }
127    })
128  );
129};
130
131self.addEventListener('install', onInstall);
132self.addEventListener('activate', onActivate);
133self.addEventListener('fetch', onFetch);
134self.addEventListener('push', onPush);
135self.addEventListener('message', updateAppOnEvent);
136
137self.onnotificationclick = onNotificationClick;

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.