147 lines
4.3 KiB
JavaScript
147 lines
4.3 KiB
JavaScript
const VER = 6
|
|
|
|
self.addEventListener('message', async (event) => {
|
|
event.waitUntil(debug(event.source, Object.assign({ answer: true }, event.data)))
|
|
})
|
|
|
|
self.addEventListener('install', (event) => {
|
|
console.log('install event:', event)
|
|
// The promise that skipWaiting() returns can be safely ignored.
|
|
event.waitUntil(self.skipWaiting().then(() => debug(event.source, { installed: true })))
|
|
|
|
// Perform any other actions required for your
|
|
// service worker to install, potentially inside
|
|
// of event.waitUntil();
|
|
})
|
|
|
|
self.addEventListener('activate', (event) => {
|
|
event.waitUntil(
|
|
// Привязка нового сервис-воркера к текущим клиентам
|
|
clients.claim().then(() => debug(event.source, { activated: true })),
|
|
)
|
|
})
|
|
|
|
self.addEventListener('push', (event) => {
|
|
// PushData keys structure standart https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/showNotification
|
|
let pushData = event.data.json()
|
|
if (!pushData || !pushData.notification.title) {
|
|
console.error('Received WebPush with an empty title. Received body: ', pushData)
|
|
}
|
|
self.registration
|
|
.showNotification(pushData.notification.title, pushData.notification.options)
|
|
.then(function () {
|
|
// You can save to your analytics fact that push was shown
|
|
// fetch('https://your_backend_server.com/track_show?message_id=' + pushData.data.message_id);
|
|
})
|
|
})
|
|
|
|
async function handleNotificationClick(event) {
|
|
event.notification.close()
|
|
|
|
if (!event.notification.data) {
|
|
await debug(null, {
|
|
error: 'Click on WebPush with empty data, where url should be. Notification',
|
|
})
|
|
console.error(
|
|
'Click on WebPush with empty data, where url should be. Notification: ',
|
|
event.notification,
|
|
)
|
|
return
|
|
}
|
|
if (!event.notification.data.url) {
|
|
await debug(null, { error: 'Click on WebPush without url. Notification' })
|
|
console.error('Click on WebPush without url. Notification: ', event.notification)
|
|
return
|
|
}
|
|
|
|
await openURL(event.notification.data.url)
|
|
}
|
|
|
|
self.addEventListener('notificationclick', (event) => {
|
|
event.waitUntil(handleNotificationClick(event))
|
|
})
|
|
|
|
async function openURL(urlToOpen) {
|
|
let matchedClients
|
|
try {
|
|
const urlToOpenObj = new URL(urlToOpen, location.origin)
|
|
|
|
matchedClients = await clients.matchAll({ type: 'window', includeUncontrolled: true })
|
|
|
|
try {
|
|
for (const client of matchedClients) {
|
|
const clientUrlObj = new URL(client.url)
|
|
try {
|
|
if (
|
|
urlToOpenObj.pathname + urlToOpenObj.search !==
|
|
clientUrlObj.pathname + clientUrlObj.search
|
|
) {
|
|
await debug(client, {
|
|
urlToOpenObj: urlToOpenObj.pathname + urlToOpenObj.search,
|
|
clientUrlObj: clientUrlObj.pathname + clientUrlObj.search,
|
|
})
|
|
continue
|
|
}
|
|
|
|
if (client.focused) {
|
|
return
|
|
}
|
|
|
|
await client.focus()
|
|
return
|
|
} catch (error) {
|
|
await debug({ error: error.message })
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('get client error', error)
|
|
}
|
|
} catch (error) {
|
|
console.error('openURL error', error)
|
|
}
|
|
|
|
try {
|
|
const client = await clients.openWindow(urlToOpen)
|
|
if (!client) {
|
|
await debug(client, { error: 'client is null' })
|
|
throw new Error('client is null')
|
|
}
|
|
} catch (error) {
|
|
await debug(matchedClients && matchedClients[0], { error: error.message })
|
|
console.error(error)
|
|
}
|
|
}
|
|
|
|
async function debug(client, data) {
|
|
try {
|
|
if (!client) {
|
|
const matchedClients = await clients.matchAll({ type: 'window', includeUncontrolled: true })
|
|
for (const matchedClient of matchedClients) {
|
|
if (matchedClient.focused) {
|
|
client = matchedClient
|
|
break
|
|
}
|
|
}
|
|
if (!client && matchedClients.length) {
|
|
return Promise.all(matchedClients.map((client) => debug(client, data)))
|
|
}
|
|
}
|
|
|
|
if (!client) {
|
|
throw new Error('not found client for debug')
|
|
}
|
|
|
|
if (!client.postMessage) {
|
|
console.error('not found client.postMessage for debug', client)
|
|
return
|
|
}
|
|
|
|
await client.postMessage({
|
|
type: 'debug',
|
|
debug: Object.assign({ VER }, data || {}),
|
|
})
|
|
} catch (error) {
|
|
console.error(error)
|
|
}
|
|
}
|