This commit is contained in:
@@ -1,189 +1,146 @@
|
||||
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.
|
||||
self.skipWaiting()
|
||||
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();
|
||||
})
|
||||
|
||||
const isIOS = /iPhone|iPad|iPod/i.test(navigator.userAgent)
|
||||
|
||||
self.addEventListener('activate', (event) => {
|
||||
event.waitUntil(
|
||||
clients.claim(), // Привязка нового сервис-воркера к текущим клиентам
|
||||
// Привязка нового сервис-воркера к текущим клиентам
|
||||
clients.claim().then(() => debug(event.source, { activated: true })),
|
||||
)
|
||||
})
|
||||
|
||||
self.addEventListener('push', (event) => {
|
||||
const data = event.data.json()
|
||||
console.log('Push событие получено:', data.type)
|
||||
|
||||
// Отображение уведомления
|
||||
if (data.type === 'notification') {
|
||||
event.waitUntil(
|
||||
self.registration
|
||||
.showNotification(data.notification.title, data.notification.options)
|
||||
.then(() => {
|
||||
console.log('Notification создан', data.notification.options.tag)
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Notification ошибка создания', error)
|
||||
}),
|
||||
)
|
||||
} else if (data.type === 'cancelNotification') {
|
||||
event.waitUntil(
|
||||
self.registration
|
||||
.getNotifications({ tag: data.notification.options.tag })
|
||||
.then((notifications) => {
|
||||
notifications.forEach((notification) => {
|
||||
if (
|
||||
notification.tag === data.notification.options.tag ||
|
||||
notification.data.payload.tag === data.notification.options.data.payload.tag // удалить, если notification.tag поддерживают все
|
||||
) {
|
||||
notification.close()
|
||||
console.log('Notification удален')
|
||||
}
|
||||
})
|
||||
}),
|
||||
)
|
||||
// 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);
|
||||
})
|
||||
})
|
||||
|
||||
self.addEventListener('notificationclose', function (event) {
|
||||
const dismissedNotification = event.notification
|
||||
|
||||
console.log('dismissedNotification', dismissedNotification)
|
||||
})
|
||||
|
||||
self.addEventListener('notificationclick', (event) => {
|
||||
console.log('click to notification', event.notification)
|
||||
|
||||
async function handleNotificationClick(event) {
|
||||
event.notification.close()
|
||||
|
||||
// const urlToOpen = new URL(event.notification.data.url, self.location.origin).href
|
||||
|
||||
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) {
|
||||
console.log('no urlToOpen')
|
||||
await debug(null, { error: 'Click on WebPush without url. Notification' })
|
||||
console.error('Click on WebPush without url. Notification: ', event.notification)
|
||||
return
|
||||
}
|
||||
|
||||
function getNotificationUrl(urlToOpen) {
|
||||
return urlToOpen
|
||||
// return fetch(urlToOpen, {
|
||||
// redirect: 'manual',
|
||||
// method: 'HEAD',
|
||||
// cache: 'no-cache',
|
||||
// })
|
||||
// .then((response) => {
|
||||
// console.log('response.url', response.url)
|
||||
// console.log('response.type', response.url)
|
||||
// if (response && response.type === 'opaqueredirect') {
|
||||
// const location = response.headers.get('location')
|
||||
// console.log('headers location', location)
|
||||
// return location
|
||||
// }
|
||||
// return response.url
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// console.debug('erro in getNotificationUrl', error)
|
||||
// return urlToOpen
|
||||
// })
|
||||
}
|
||||
await openURL(event.notification.data.url)
|
||||
}
|
||||
|
||||
// Открытие URL из данных уведомления
|
||||
event.waitUntil(
|
||||
Promise.all([
|
||||
getNotificationUrl(event.notification.data.url),
|
||||
self.addEventListener('notificationclick', (event) => {
|
||||
event.waitUntil(handleNotificationClick(event))
|
||||
})
|
||||
|
||||
clients.matchAll({ type: 'window', includeUncontrolled: true }),
|
||||
])
|
||||
.then(([urlToOpen, clientList]) => {
|
||||
const urlToOpenObj = new URL(urlToOpen, location.origin)
|
||||
for (const client of clientList) {
|
||||
console.log('client.url', client.url)
|
||||
const clientUrlObj = new URL(client.url)
|
||||
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 ===
|
||||
urlToOpenObj.pathname + urlToOpenObj.search !==
|
||||
clientUrlObj.pathname + clientUrlObj.search
|
||||
) {
|
||||
console.log('focus')
|
||||
|
||||
return Promise.all([
|
||||
'focus' in client && client.focus(),
|
||||
client.postMessage({
|
||||
type: 'notificationClick',
|
||||
tag: event.notification.tag,
|
||||
payload: event.notification.payload,
|
||||
url: urlToOpen,
|
||||
matchUrl: true,
|
||||
isIOS,
|
||||
}),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
if (isIOS && clientList.length > 0) {
|
||||
const client = clientList[0]
|
||||
return Promise.all([
|
||||
client.focus(),
|
||||
client.postMessage({
|
||||
type: 'notificationClick',
|
||||
tag: event.notification.tag,
|
||||
payload: event.notification.payload,
|
||||
url: urlToOpen,
|
||||
matchUrl: false,
|
||||
isIOS,
|
||||
}),
|
||||
])
|
||||
}
|
||||
|
||||
if (clients.openWindow) {
|
||||
console.log('open new window', urlToOpen)
|
||||
|
||||
return clients.openWindow(urlToOpen).then((client) => {
|
||||
if (client) {
|
||||
return client.postMessage({
|
||||
type: 'notificationClick',
|
||||
tag: event.notification.tag,
|
||||
payload: event.notification.payload,
|
||||
url: urlToOpen,
|
||||
matchUrl: true,
|
||||
isIOS,
|
||||
})
|
||||
} else {
|
||||
console.log('new window not opened')
|
||||
for (const client of clientList) {
|
||||
return client.postMessage({
|
||||
type: 'notificationClick',
|
||||
tag: event.notification.tag,
|
||||
payload: event.notification.payload,
|
||||
url: urlToOpen,
|
||||
matchUrl: false,
|
||||
isIOS,
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
console.log('clients.openWindow not available')
|
||||
|
||||
for (const client of clientList) {
|
||||
return client.postMessage({
|
||||
type: 'notificationClick',
|
||||
tag: event.notification.tag,
|
||||
payload: event.notification.payload,
|
||||
url: urlToOpen,
|
||||
matchUrl: false,
|
||||
isIOS,
|
||||
await debug(client, {
|
||||
urlToOpenObj: urlToOpenObj.pathname + urlToOpenObj.search,
|
||||
clientUrlObj: clientUrlObj.pathname + clientUrlObj.search,
|
||||
})
|
||||
continue
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
.catch((error) => {
|
||||
console.error(error)
|
||||
}),
|
||||
)
|
||||
})
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user