diff --git a/meshuser.js b/meshuser.js index 5a5de462..7fd28435 100644 --- a/meshuser.js +++ b/meshuser.js @@ -907,6 +907,22 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } break; } + case 'webpush': { + if (parent.parent.webpush == null) { + r = "Web push not supported."; + } else { + if (cmdargs['_'].length != 1) { + r = "Usage: WebPush \"Message\""; + } else { + const pushSubscription = { "endpoint": "https://updates.push.services.mozilla.com/wpush/v2/gAAAAABgIkO9hjXHWhMPiuk-ppNRw7r_pUZitddwCEK4ykdzeIxOIjFnYhIt_nr-qUca2mpZziwQsSEhYTUCiuYrhWnVDRweMtiUj16yJJq8V5jneaEaUYjEIe5jp3DOMNpoTm1aHgX74gCR8uTXSITcM97bNi-hRxcQ4f6Ie4WSAmoXpd89B_g", "keys": { "auth": "UB2sbLVK7ALnSHw5P1dahg", "p256dh": "BIoRbcNSxBuTjN39CCCUCHo1f4NxBJ1YDdu_k4MbPW_q3NK1_RufnydUzLPDp8ibBVItSI72-s48QJvOjQ_S8Ok" } } + parent.parent.webpush.sendNotification(pushSubscription, cmdargs['_'][0]).then( + function (value) { try { ws.send(JSON.stringify({ action: 'OK', value: r, tag: command.tag })); } catch (ex) { } }, + function (error) { try { ws.send(JSON.stringify({ action: 'Error', value: r, tag: command.tag })); } catch (ex) { } } + ); + } + } + break; + } case 'amtmanager': { if (parent.parent.amtManager == null) { r = 'Intel AMT Manager not active.'; } else { r = parent.parent.amtManager.getStatusString(); } break; @@ -5275,6 +5291,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use }); break; } + case 'webpush': { + //console.log(command); + break; + } case 'print': { console.log(command.value); break; diff --git a/public/serviceworker.js b/public/serviceworker.js index d34b3fc2..f9c6f3d4 100644 --- a/public/serviceworker.js +++ b/public/serviceworker.js @@ -1,25 +1,6 @@ -// "BMWzSl5zZPWw_lAKVvQb8NZBQwCs83jQJc68cj04yQTYt_kAIvuCMte0wU7BXjODXuGn8ut5qwU0pR_44dZuAmQ" - -self.addEventListener('install', event => { - console.log('Service Worker install', event); -}); - - -// This will be called only once when the service worker is activated. -self.addEventListener('activate', async() => { -try { - const applicationServerKey = urlB64ToUint8Array('BMWzSl5zZPWw_lAKVvQb8NZBQwCs83jQJc68cj04yQTYt_kAIvuCMte0wU7BXjODXuGn8ut5qwU0pR_44dZuAmQ') - const options = { applicationServerKey, userVisibleOnly: true } - const subscription = await self.registration.pushManager.subscribe(options) - console.log(JSON.stringify(subscription)) - } catch (err) { - console.log('Error', err) - } -}) - self.addEventListener('push', function (event) { - console.log('Service Worker push', event); + console.log('Service Worker push', JSON.stringify(event)); if (event.data) { console.log("Push event!! ", event.data.text()); showLocalNotification("Yolo", event.data.text(), self.registration); @@ -28,38 +9,10 @@ self.addEventListener('push', function (event) { } }); - -self.addEventListener('message', function(event) { - console.log('Service Worker message', event); - if (isObject(event.data)) { - if (event.data.type === 'sync') { - // in this way, you can decide your tag - //const id = event.data.id || uuid() - // pass the port into the memory stor - //syncStore[id] = Object.assign({ port: event.ports[0] }, event.data) - //self.registration.sync.register(id) - } - } -}) - -self.addEventListener('sync', function(event) { - console.log('Service Worker sync', event); -}) - const showLocalNotification = function(title, body, swRegistration) { const options = { body // here you can add more properties like icon, image, vibrate, etc. }; swRegistration.showNotification(title, options); -}; - -// Used to convert Base64 public VAPID key to bytearray. -function urlBase64ToUint8Array(base64String) { - const padding = '='.repeat((4 - base64String.length % 4) % 4); - const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/'); - const rawData = window.atob(base64); - const outputArray = new Uint8Array(rawData.length); - for (let i = 0; i < rawData.length; ++i) { outputArray[i] = rawData.charCodeAt(i); } - return outputArray; -} \ No newline at end of file +}; \ No newline at end of file diff --git a/views/default.handlebars b/views/default.handlebars index 0eac16b0..bd36368f 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -354,7 +354,6 @@
Localization Settings
Notification Settings
@@ -1360,37 +1359,6 @@
// Fix links if a loginKey is used
if (urlargs.key) { Q('termsLinkFooter').href += '?key=' + urlargs.key; }
- /*
- // Register the service worker
- if ('serviceWorker' in navigator) {
- navigator.serviceWorker.addEventListener('message', function(event) {
- console.log("Client message from service worker: " + event);
- });
-
- navigator.serviceWorker.register('serviceworker.js')
- .then(function(reg) {
- // Registration worked
- console.log('Registration succeeded. Scope is ' + reg.scope);
-
- reg.pushManager.getSubscription().then(function(sub) {
- if (sub === null) {
- // Update UI to ask user to register for Push
- console.log('Not subscribed to push service.');
- } else {
- // We have a subscription, update the database
- console.log('Subscription object: ', sub);
-
- navigator.serviceWorker.controller.postMessage({type: 'sync', text: 'Hello!'})
- }
- });
-
- }).catch((error) => {
- // Registration failed
- console.log('Registration failed with ' + error);
- });
- }
- */
-
// Check if we are in debug mode
args = parseUriArgs();
if (args.key && (isAlphaNumeric(args.key) == false)) { delete args.key; }
@@ -2098,7 +2066,7 @@
serverinfo = message.serverinfo;
if (serverinfo.timeout) { setInterval(checkIdleSessionTimeout, 10000); checkIdleSessionTimeout(); }
if (debugmode == 1) { console.log('Server time: ', printDateTime(new Date(serverinfo.serverTime))); }
- //console.log(serverinfo);
+ setupServiceWorker();
break;
}
case 'userinfo': {
@@ -9692,13 +9660,8 @@
}
}
- function account_enablePushNotifications() {
- if ((serverinfo == null) || (serverinfo.vapidpublickey == null)) return;
- return false;
- }
-
function account_enableNotifications() {
- if (Notification) { Notification.requestPermission().then(function (permission) { QV('accountEnableNotificationsSpan', permission != 'granted'); }); }
+ if (Notification) { Notification.requestPermission().then(function (permission) { QV('accountEnableNotificationsSpan', permission != 'granted'); setupServiceWorker(); }); }
return false;
}
@@ -13873,6 +13836,30 @@
return false;
}
+
+ //
+ // SERVICE WORKER
+ //
+
+ function setupServiceWorker() {
+ if ((typeof serverinfo.vapidpublickey != 'string') || (Notification == null) || (Notification.permission != 'granted')) return;
+ // Register the service worker
+ if ('serviceWorker' in navigator) {
+ navigator.serviceWorker.register('serviceworker.js')
+ .then(function(reg) {
+ // Subscribe to push notifications
+ navigator.serviceWorker.ready.then(function(reg) {
+ reg.pushManager.subscribe({ applicationServerKey: urlBase64ToUint8Array(serverinfo.vapidpublickey), userVisibleOnly: true }).then(function(sub) {
+ meshserver.send({ action: 'webpush', sub: sub });
+ }).catch(function(e) { console.error('Unable to subscribe to push', e); });
+ })
+ }).catch(function(error) {
+ // Registration failed
+ console.log('Registration failed', error);
+ });
+ }
+ }
+
//
// POPUP DIALOG
//
@@ -14081,7 +14068,6 @@
// Setup web notifications
if ((x == 2) && Notification) { QV('accountEnableNotificationsSpan', Notification.permission != 'granted'); }
- //QV('accountEnablePushNotificationsSpan', true);
// Fetch the server timeline stats if needed
if ((x == 40) && (serverTimelineStats == null)) { refreshServerTimelineStats(); }
@@ -14416,6 +14402,16 @@
if (typeof Symbol!=='undefined')TextEncoder.prototype[Symbol.toStringTag]='TextEncoder';
}
+ // Used to convert Base64 public VAPID key to bytearray.
+ function urlBase64ToUint8Array(base64String) {
+ const padding = '='.repeat((4 - base64String.length % 4) % 4);
+ const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
+ const rawData = atob(base64);
+ const outputArray = new Uint8Array(rawData.length);
+ for (let i = 0; i < rawData.length; ++i) { outputArray[i] = rawData.charCodeAt(i); }
+ return outputArray;
+ }
+
function joinPaths() { var x = []; for (var i in arguments) { var w = arguments[i]; if ((w != null) && (w != '')) { while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); } while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); } x.push(w); } } return x.join('/'); }
function putstore(name, val) {
try {