From 73b17d70ec3a9b1d73789c236601628bfa8c498b Mon Sep 17 00:00:00 2001 From: Egor Kislitsyn Date: Sun, 9 Dec 2018 19:25:43 +0700 Subject: [PATCH] improve push notifications code --- src/modules/pushNotifications.js | 15 ++++++-- src/services/push/push.js | 65 +++++++++++--------------------- static/sw.js | 33 ++++++++-------- 3 files changed, 48 insertions(+), 65 deletions(-) diff --git a/src/modules/pushNotifications.js b/src/modules/pushNotifications.js index 43143b1f..ea92f811 100644 --- a/src/modules/pushNotifications.js +++ b/src/modules/pushNotifications.js @@ -12,16 +12,23 @@ const subscribe = { setVapidPublicKey (state, vapidPublicKey) { state.vapidPublicKey = vapidPublicKey } - }, actions: { setInstanceOption (store, { name, value }) { - store.commit('setVapidPublicKey', value) - if (store.state.token) registerPushNotifications(this) + if (name === 'vapidPublicKey') { + store.commit('setVapidPublicKey', value) + + if (store.state.token) { + registerPushNotifications(store.rootState.config.webPushNotifications, value, store.state.token) + } + } }, setCurrentUser (store, user) { store.commit('setApiToken', user.credentials) - if (store.state.vapidPublicKey) registerPushNotifications(this) + + if (store.state.vapidPublicKey) { + registerPushNotifications(store.rootState.config.webPushNotifications, store.state.vapidPublicKey, user.credentials) + } } } } diff --git a/src/services/push/push.js b/src/services/push/push.js index ffab5918..4a03a73d 100644 --- a/src/services/push/push.js +++ b/src/services/push/push.js @@ -14,58 +14,42 @@ function isPushSupported () { function registerServiceWorker () { return navigator.serviceWorker.register('/static/sw.js') - .then(function (registration) { - console.log('Service worker successfully registered.') - return registration - }) - .catch(function (err) { - console.error('Unable to register service worker.', err) - }) + .catch((err) => console.error('Unable to register service worker.', err)) } function askPermission () { - return new Promise(function (resolve, reject) { - if (!window.Notification) return reject(new Error('Notifications disabled')) + return new Promise((resolve, reject) => { + const Notification = window.Notification - if (window.Notification.permission !== 'default') { - return resolve(window.Notification.permission) - } + if (!Notification) return reject(new Error('Notifications disabled')) + if (Notification.permission !== 'default') return resolve(Notification.permission) - const permissionResult = window.Notification.requestPermission(function (result) { - resolve(result) - }) + const permissionResult = Notification.requestPermission(resolve) if (permissionResult) permissionResult.then(resolve, reject) - }).then(function (permissionResult) { - if (permissionResult !== 'granted') { - throw new Error('We weren\'t granted permission.') - } + }).then((permissionResult) => { + if (permissionResult !== 'granted') throw new Error('We weren\'t granted permission.') return permissionResult }) } -function subscribe (registration, store) { - if (!store.rootState.config.webPushNotifications) { - return Promise.reject(new Error('Web Push is disabled in config')) - } - - if (!store.rootState.instance.vapidPublicKey) { - return Promise.reject(new Error('VAPID public key is not found')) - } +function subscribe (registration, isEnabled, vapidPublicKey) { + if (!isEnabled) return Promise.reject(new Error('Web Push is disabled in config')) + if (!vapidPublicKey) return Promise.reject(new Error('VAPID public key is not found')) const subscribeOptions = { userVisibleOnly: true, - applicationServerKey: urlBase64ToUint8Array(store.rootState.instance.vapidPublicKey) + applicationServerKey: urlBase64ToUint8Array(vapidPublicKey) } return registration.pushManager.subscribe(subscribeOptions) } -function sendSubscriptionToBackEnd (subscription, store) { +function sendSubscriptionToBackEnd (subscription, token) { return window.fetch('/api/v1/push/subscription/', { method: 'POST', headers: { 'Content-Type': 'application/json', - 'Authorization': `Bearer ${store.rootState.oauth.token}` + 'Authorization': `Bearer ${token}` }, body: JSON.stringify({ subscription, @@ -79,28 +63,23 @@ function sendSubscriptionToBackEnd (subscription, store) { } }) }) - .then(function (response) { - if (!response.ok) { - throw new Error('Bad status code from server.') - } - + .then((response) => { + if (!response.ok) throw new Error('Bad status code from server.') return response.json() }) - .then(function (responseData) { - if (!responseData.id) { - throw new Error('Bad response from server.') - } + .then((responseData) => { + if (!responseData.id) throw new Error('Bad response from server.') return responseData }) } -export default function registerPushNotifications (store) { +export default function registerPushNotifications (isEnabled, vapidPublicKey, token) { if (isPushSupported()) { registerServiceWorker() - .then(function (registration) { + .then((registration) => { return askPermission() - .then(() => subscribe(registration, store)) - .then((subscription) => sendSubscriptionToBackEnd(subscription, store)) + .then(() => subscribe(registration, isEnabled, vapidPublicKey)) + .then((subscription) => sendSubscriptionToBackEnd(subscription, token)) .catch((e) => console.warn(`Failed to setup Web Push Notifications: ${e.message}`)) }) } diff --git a/static/sw.js b/static/sw.js index 0402a220..d51870d5 100644 --- a/static/sw.js +++ b/static/sw.js @@ -1,32 +1,29 @@ /* eslint-env serviceworker */ -self.addEventListener('push', function (event) { + +function getWindowClients () { + return clients.matchAll({ includeUncontrolled: true }) + .then((clientList) => clientList.filter(({ type }) => type === 'window')) +} + +self.addEventListener('push', (event) => { if (event.data) { - const data = event.data.json() + event.waitUntil(getWindowClients().then((list) => { + const data = event.data.json() - const promiseChain = clients.matchAll({ - includeUncontrolled: true - }).then(function (clientList) { - const list = clientList.filter((item) => item.type === 'window') - if (list.length) return - return self.registration.showNotification(data.title, data) - }) - - event.waitUntil(promiseChain) + if (list.length === 0) return self.registration.showNotification(data.title, data) + })) } }) -self.addEventListener('notificationclick', function (event) { +self.addEventListener('notificationclick', (event) => { event.notification.close() - event.waitUntil(clients.matchAll({ - includeUncontrolled: true - }).then(function (clientList) { - const list = clientList.filter((item) => item.type === 'window') - + event.waitUntil(getWindowClients().then((list) => { for (var i = 0; i < list.length; i++) { var client = list[i] if (client.url === '/' && 'focus' in client) { return client.focus() } } - if (clients.openWindow) { return clients.openWindow('/') } + + if (clients.openWindow) return clients.openWindow('/') })) })