mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-13 20:36:35 +00:00
Add HTML 5 push notifcations support (#89)
* Add push notification handling to service worker * Add push registration to sidebar * Whitelist manifest.json * Remove unused property * Catch if no url specified * Fix eslint * Fix bug * Fix some bugs * More Firefox proof * Moar fixes * Fix semi
This commit is contained in:
parent
474366c536
commit
5efe930d6c
@ -1 +1 @@
|
||||
Subproject commit 4f22ce18a788888bff1cbdafb3586edc715ba29e
|
||||
Subproject commit bf4adea64549d0adb95597f1846d90bc47648c0e
|
@ -9,7 +9,7 @@
|
||||
"scripts": {
|
||||
"setup_js_dev": "git submodule init && git submodule update && cd home-assistant-js && npm install",
|
||||
"clean": "rm -rf build/* build-temp/*",
|
||||
"js_dev": "script/sw-dev.js && npm run watch_ru_all",
|
||||
"js_dev": "script/sw-precache.js && npm run watch_ru_all",
|
||||
"js_dev_demo": "BUILD_DEMO=1 npm run watch_ru_all",
|
||||
"js_prod": "BUILD_DEV=0 npm run ru_all",
|
||||
"js_demo": "BUILD_DEV=0 BUILD_DEMO=1 npm run ru_all",
|
||||
|
@ -1,10 +0,0 @@
|
||||
#! /usr/bin/env node
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
var content = `
|
||||
console.warn('Service worker disabled in dev mode');
|
||||
`;
|
||||
|
||||
fs.writeFileSync(path.join('build', 'service_worker.js'), content);
|
@ -15,9 +15,10 @@ var path = require('path');
|
||||
var swPrecache = require('sw-precache');
|
||||
var uglifyJS = require('uglify-js');
|
||||
|
||||
const DEV = !!JSON.parse(process.env.BUILD_DEV || 'true');
|
||||
|
||||
var rootDir = '..';
|
||||
var panelDir = rootDir + '/panels';
|
||||
// var panels = fs.readdirSync(panelDir);
|
||||
|
||||
var dynamicUrlToDependencies = {
|
||||
'/': [rootDir + '/frontend.html', rootDir + '/core.js'],
|
||||
@ -55,9 +56,9 @@ panelsFingerprinted.forEach(panel => {
|
||||
dynamicUrlToDependencies[url] = [fpath];
|
||||
});
|
||||
|
||||
var options = {
|
||||
const options = {
|
||||
navigateFallback: '/',
|
||||
navigateFallbackWhitelist: [/^((?!(static|api|local|service_worker.js)).)*$/],
|
||||
navigateFallbackWhitelist: [/^((?!(static|api|local|service_worker.js|manifest.json)).)*$/],
|
||||
dynamicUrlToDependencies: dynamicUrlToDependencies,
|
||||
staticFileGlobs: [
|
||||
rootDir + '/icons/favicon.ico',
|
||||
@ -74,9 +75,55 @@ var options = {
|
||||
verbose: true,
|
||||
};
|
||||
|
||||
var genPromise = swPrecache.generate(options);
|
||||
const devBase = 'console.warn("Service worker caching disabled in development")';
|
||||
|
||||
if (true) {
|
||||
const notify = `
|
||||
self.addEventListener("push", function(event) {
|
||||
var data;
|
||||
if (event.data) {
|
||||
data = event.data.json();
|
||||
event.waitUntil(self.registration.showNotification(data.title, data));
|
||||
}
|
||||
});
|
||||
self.addEventListener('notificationclick', function(event) {
|
||||
var url;
|
||||
|
||||
if (!event.notification.data || !event.notification.data.url) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.notification.close();
|
||||
url = event.notification.data.url;
|
||||
|
||||
if (!url) return;
|
||||
|
||||
event.waitUntil(
|
||||
clients.matchAll({
|
||||
type: 'window',
|
||||
})
|
||||
.then(function (windowClients) {
|
||||
var i;
|
||||
var client;
|
||||
for (i = 0; i < windowClients.length; i++) {
|
||||
client = windowClients[i];
|
||||
if (client.url === url && 'focus' in client) {
|
||||
return client.focus();
|
||||
}
|
||||
}
|
||||
if (clients.openWindow) {
|
||||
return clients.openWindow(url);
|
||||
}
|
||||
return undefined;
|
||||
})
|
||||
);
|
||||
});
|
||||
`;
|
||||
|
||||
let genPromise = DEV ? Promise.resolve(devBase) : swPrecache.generate(options);
|
||||
|
||||
genPromise = genPromise.then(swString => swString + '\n' + notify);
|
||||
|
||||
if (!DEV) {
|
||||
genPromise = genPromise.then(
|
||||
swString => uglifyJS.minify(swString, { fromString: true }).code);
|
||||
}
|
||||
|
@ -78,7 +78,7 @@
|
||||
opacity: var(--dark-divider-opacity)
|
||||
}
|
||||
|
||||
.streaming {
|
||||
.setting {
|
||||
@apply(--sidebar-text);
|
||||
}
|
||||
|
||||
@ -120,8 +120,18 @@
|
||||
<div>
|
||||
<div class='divider'></div>
|
||||
|
||||
<template is='dom-if' if='[[supportPush]]'>
|
||||
<paper-item class='horizontal layout justified'>
|
||||
<div class='setting'>Push Notifications</div>
|
||||
<paper-toggle-button
|
||||
on-change='handlePushChange'
|
||||
checked='{{pushToggleChecked}}'
|
||||
></paper-toggle-button>
|
||||
</paper-item>
|
||||
</template>
|
||||
|
||||
<paper-item class='horizontal layout justified'>
|
||||
<div class='streaming'>Streaming updates</div>
|
||||
<div class='setting'>Streaming updates</div>
|
||||
<stream-status hass='[[hass]]'></stream-status>
|
||||
</paper-item>
|
||||
|
||||
@ -180,20 +190,6 @@ Polymer({
|
||||
},
|
||||
},
|
||||
|
||||
hasHistoryComponent: {
|
||||
type: Boolean,
|
||||
bindNuclear: function (hass) {
|
||||
return hass.configGetters.isComponentLoaded('history');
|
||||
},
|
||||
},
|
||||
|
||||
hasLogbookComponent: {
|
||||
type: Boolean,
|
||||
bindNuclear: function (hass) {
|
||||
return hass.configGetters.isComponentLoaded('logbook');
|
||||
},
|
||||
},
|
||||
|
||||
panels: {
|
||||
type: Array,
|
||||
bindNuclear: function (hass) {
|
||||
@ -203,6 +199,19 @@ Polymer({
|
||||
];
|
||||
},
|
||||
},
|
||||
|
||||
supportPush: {
|
||||
type: Boolean,
|
||||
value: 'PushManager' in window &&
|
||||
(document.location.protocol === 'https:' ||
|
||||
document.location.hostname === 'localhost'),
|
||||
},
|
||||
|
||||
pushToggleChecked: {
|
||||
type: Boolean,
|
||||
value: 'Notification' in window &&
|
||||
Notification.permission === 'granted',
|
||||
},
|
||||
},
|
||||
|
||||
created: function () {
|
||||
@ -283,6 +292,56 @@ Polymer({
|
||||
this.debounce('updateStyles', this._boundUpdateStyles, 1);
|
||||
},
|
||||
|
||||
handlePushChange: function (ev) {
|
||||
var subscribe = ev.target.checked;
|
||||
|
||||
// MVP, will move later.
|
||||
var promise = navigator.serviceWorker.getRegistration().then(function (reg) {
|
||||
if (!reg) {
|
||||
throw new Error('No service worker registered');
|
||||
}
|
||||
|
||||
return reg.pushManager.subscribe({
|
||||
userVisibleOnly: true,
|
||||
});
|
||||
});
|
||||
|
||||
if (!subscribe) {
|
||||
promise.then(function (sub) {
|
||||
sub.unsubscribe();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
promise.then(function (sub) {
|
||||
var browserName;
|
||||
if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1) {
|
||||
browserName = 'firefox';
|
||||
} else {
|
||||
browserName = 'chrome';
|
||||
}
|
||||
|
||||
return this.hass.callApi('POST', 'notify.html5', {
|
||||
subscription: sub,
|
||||
browser: browserName,
|
||||
});
|
||||
}.bind(this)).catch(function (err) {
|
||||
var message;
|
||||
|
||||
if (err.message && err.message.indexOf('gcm_sender_id') !== -1) {
|
||||
message = 'Please setup the notify.html5 platform.';
|
||||
} else {
|
||||
message = 'Notification registration failed.';
|
||||
}
|
||||
|
||||
/* eslint-disable no-console */
|
||||
console.error(err);
|
||||
/* eslint-enable no-console */
|
||||
this.hass.notificationActions.createNotification(message);
|
||||
this.pushToggleChecked = false;
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
handleLogOut: function () {
|
||||
this.hass.authActions.logOut();
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user