From f62b6eb75e0a6e8fafbebf3a41b913cd2cb929ed Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Tue, 24 Jan 2023 01:59:39 +0300 Subject: Web Push --- .gitignore | 1 + src/main/assets/scripts.js | 37 +++++++++++++++++++--- src/main/resources/static/sw.js | 29 +++++++++++++++++ .../db/specific/mariadb/V1.22__schema.sql | 2 +- vnext/server/middleware/event.js | 4 +-- 5 files changed, 65 insertions(+), 8 deletions(-) create mode 100644 src/main/resources/static/sw.js diff --git a/.gitignore b/.gitignore index 4ba5a066..cc9da567 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ **/out/** target/** src/main/resources/static/*.js +!src/main/resources/static/sw.js src/main/resources/static/*.css src/main/resources/static/*.svg src/main/resources/static/*.map diff --git a/src/main/assets/scripts.js b/src/main/assets/scripts.js index eecb3372..20d32fd9 100644 --- a/src/main/assets/scripts.js +++ b/src/main/assets/scripts.js @@ -195,11 +195,6 @@ function wsIncomingReply(msg) { document.getElementById('replies').appendChild(li); updateRepliesCounter(); - var notify = new Notification(msg.user.uname, { - body: `${msg.replyQuote}\n${msg.body}`, - icon: msg.user.avatar - }); - notify.onerror = console.log; } function newReply(e) { @@ -530,12 +525,44 @@ function fetchUserUri(dataUri, callback) { }); } +const registerServiceWorker = () => { + const publicKey = 'BPU0LniKKR0QiaUvILPd9AystmSOU8rWDZobxKm7IJN5HYxOSQdktRdc74TZvyRS9_kyUz7LDN6gUAmAVOmObAU'; + navigator.serviceWorker.register('/sw.js', { scope: '/' }); + navigator.serviceWorker.ready.then(reg => { + reg.pushManager.subscribe({ + userVisibleOnly: true, + applicationServerKey: publicKey + }).then( + sub => { + const body = [ + { + type: 'web', + token: JSON.stringify(sub) + } + ]; + fetch('/api/notifications?hash=' + document.getElementById('body').getAttribute('data-hash'), { + method: 'PUT', + headers: { + 'Content-Type': 'application/json' + }, + credentials: 'same-origin', + body: JSON.stringify(body) + }).then(response => { + console.log(response.status); + }); + }, + err => console.error(err) + ); + }); +}; + function notificationsCheckPermissions(button) { console.log(Notification.permission); switch (Notification.permission.toLowerCase()) { case 'granted': button.innerHTML = `${i18n('settings.notifications.granted')}`; button.disabled = true; + registerServiceWorker(); break; case 'denied': diff --git a/src/main/resources/static/sw.js b/src/main/resources/static/sw.js new file mode 100644 index 00000000..48fe7787 --- /dev/null +++ b/src/main/resources/static/sw.js @@ -0,0 +1,29 @@ +/// +/// +/// + +var sw = /** @type {ServiceWorkerGlobalScope & typeof self} */ (self); +sw.addEventListener('install', function() { + sw.skipWaiting(); +}); +sw.addEventListener('activate', function() { + sw.clients.claim(); +}); +sw.addEventListener('push', function(evt) { + if (evt.data) { + const data = evt.data.json(); + console.log('Push', data); + if (data.body) { + sw.registration.showNotification(data.title, { + body: data.body, + icon: data.custom.message.user.avatar + }); + } + } +}); +sw.addEventListener('notificationclick', function(evt) { + evt.notification.close(); + evt.waitUntil( + sw.clients.openWindow('https://juick.com/') + ); +}); diff --git a/src/test/resources/db/specific/mariadb/V1.22__schema.sql b/src/test/resources/db/specific/mariadb/V1.22__schema.sql index d767b23b..9d5e2ff0 100644 --- a/src/test/resources/db/specific/mariadb/V1.22__schema.sql +++ b/src/test/resources/db/specific/mariadb/V1.22__schema.sql @@ -24,7 +24,7 @@ DROP TABLE IF EXISTS `android`; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `android` ( `user_id` int(10) unsigned NOT NULL, - `regid` char(1024) NOT NULL, + `regid` text NOT NULL, `ts` timestamp NOT NULL DEFAULT current_timestamp(), UNIQUE KEY `regid` (`regid`), KEY `user_id` (`user_id`) diff --git a/vnext/server/middleware/event.js b/vnext/server/middleware/event.js index 838ea8b1..5ea855dd 100644 --- a/vnext/server/middleware/event.js +++ b/vnext/server/middleware/event.js @@ -27,8 +27,8 @@ function processMessageEvent(msg) { users.forEach(user => { log(`${user.uname}: ${user.unreadCount}`); let [sandboxTokens, productionTokens] = (user.tokens || []) - .filter(t => ['mpns', 'apns', 'fcm'].includes(t.type)) - .map(t => t.token) + .filter(t => ['mpns', 'apns', 'fcm', 'web'].includes(t.type)) + .map(t => t.type === 'web' ? JSON.parse(t.token) : t.token) .reduce((result, element, i) => { allSandboxIds.includes(user.uid) ? result[0].push(element) -- cgit v1.2.3