2017-07-10 19:47:03 +00:00
|
|
|
"use strict";
|
|
|
|
|
|
|
|
const $ = require("jquery");
|
|
|
|
const storage = require("./localStorage");
|
|
|
|
const socket = require("./socket");
|
2019-02-20 09:10:18 +00:00
|
|
|
const {vueApp} = require("./vue");
|
2017-07-10 19:47:03 +00:00
|
|
|
|
2017-11-07 20:22:16 +00:00
|
|
|
let pushNotificationsButton;
|
2017-07-10 19:47:03 +00:00
|
|
|
let clientSubscribed = null;
|
|
|
|
let applicationServerKey;
|
|
|
|
|
2017-12-24 14:06:23 +00:00
|
|
|
if ("serviceWorker" in navigator) {
|
|
|
|
navigator.serviceWorker.addEventListener("message", (event) => {
|
|
|
|
if (event.data && event.data.type === "open") {
|
2019-07-17 09:33:59 +00:00
|
|
|
$("#sidebar")
|
|
|
|
.find(`.chan[data-target="#${event.data.channel}"]`)
|
|
|
|
.trigger("click");
|
2017-12-24 14:06:23 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-09-28 08:53:32 +00:00
|
|
|
module.exports.hasServiceWorker = false;
|
|
|
|
|
2017-07-10 19:47:03 +00:00
|
|
|
module.exports.configurePushNotifications = (subscribedOnServer, key) => {
|
|
|
|
applicationServerKey = key;
|
|
|
|
|
|
|
|
// If client has push registration but the server knows nothing about it,
|
|
|
|
// this subscription is broken and client has to register again
|
|
|
|
if (clientSubscribed === true && subscribedOnServer === false) {
|
2018-01-30 09:38:33 +00:00
|
|
|
pushNotificationsButton.prop("disabled", true);
|
2017-07-10 19:47:03 +00:00
|
|
|
|
2017-09-28 08:53:32 +00:00
|
|
|
navigator.serviceWorker.ready
|
2017-07-10 19:47:03 +00:00
|
|
|
.then((registration) => registration.pushManager.getSubscription())
|
|
|
|
.then((subscription) => subscription && subscription.unsubscribe())
|
|
|
|
.then((successful) => {
|
|
|
|
if (successful) {
|
2018-01-30 09:38:33 +00:00
|
|
|
alternatePushButton().prop("disabled", false);
|
2017-07-10 19:47:03 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-11-07 20:22:16 +00:00
|
|
|
module.exports.initialize = () => {
|
|
|
|
pushNotificationsButton = $("#pushNotifications");
|
|
|
|
|
|
|
|
if (!isAllowedServiceWorkersHost()) {
|
2019-02-20 09:10:18 +00:00
|
|
|
vueApp.pushNotificationState = "nohttps";
|
2017-11-07 20:22:16 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-07-10 19:47:03 +00:00
|
|
|
if ("serviceWorker" in navigator) {
|
2019-07-17 09:33:59 +00:00
|
|
|
navigator.serviceWorker
|
|
|
|
.register("service-worker.js")
|
|
|
|
.then((registration) => {
|
|
|
|
module.exports.hasServiceWorker = true;
|
2017-09-28 08:53:32 +00:00
|
|
|
|
2019-07-17 09:33:59 +00:00
|
|
|
if (!registration.pushManager) {
|
|
|
|
return;
|
|
|
|
}
|
2017-07-10 19:47:03 +00:00
|
|
|
|
2019-07-17 09:33:59 +00:00
|
|
|
return registration.pushManager.getSubscription().then((subscription) => {
|
2019-02-20 09:10:18 +00:00
|
|
|
vueApp.pushNotificationState = "supported";
|
2017-07-10 19:47:03 +00:00
|
|
|
|
2019-07-17 09:33:59 +00:00
|
|
|
clientSubscribed = !!subscription;
|
2017-07-10 19:47:03 +00:00
|
|
|
|
2019-07-17 09:33:59 +00:00
|
|
|
if (clientSubscribed) {
|
|
|
|
alternatePushButton();
|
|
|
|
}
|
|
|
|
});
|
2019-08-02 12:53:31 +00:00
|
|
|
})
|
|
|
|
.catch(() => {
|
|
|
|
vueApp.pushNotificationState = "unsupported";
|
|
|
|
});
|
2017-07-10 19:47:03 +00:00
|
|
|
}
|
2017-11-07 20:22:16 +00:00
|
|
|
};
|
2017-07-10 19:47:03 +00:00
|
|
|
|
2019-08-02 12:53:31 +00:00
|
|
|
module.exports.onPushButton = () => {
|
|
|
|
// TODO: move dom logic to Settings.vue
|
|
|
|
pushNotificationsButton = $("#pushNotifications");
|
2018-01-30 09:38:33 +00:00
|
|
|
pushNotificationsButton.prop("disabled", true);
|
2017-07-10 19:47:03 +00:00
|
|
|
|
2019-07-17 09:33:59 +00:00
|
|
|
navigator.serviceWorker.ready
|
|
|
|
.then((registration) =>
|
|
|
|
registration.pushManager
|
|
|
|
.getSubscription()
|
|
|
|
.then((existingSubscription) => {
|
|
|
|
if (existingSubscription) {
|
|
|
|
socket.emit("push:unregister");
|
|
|
|
|
|
|
|
return existingSubscription.unsubscribe();
|
|
|
|
}
|
|
|
|
|
|
|
|
return registration.pushManager
|
|
|
|
.subscribe({
|
|
|
|
applicationServerKey: urlBase64ToUint8Array(applicationServerKey),
|
|
|
|
userVisibleOnly: true,
|
|
|
|
})
|
|
|
|
.then((subscription) => {
|
|
|
|
const rawKey = subscription.getKey ? subscription.getKey("p256dh") : "";
|
|
|
|
const key = rawKey
|
|
|
|
? window.btoa(String.fromCharCode(...new Uint8Array(rawKey)))
|
|
|
|
: "";
|
|
|
|
const rawAuthSecret = subscription.getKey
|
|
|
|
? subscription.getKey("auth")
|
|
|
|
: "";
|
|
|
|
const authSecret = rawAuthSecret
|
|
|
|
? window.btoa(String.fromCharCode(...new Uint8Array(rawAuthSecret)))
|
|
|
|
: "";
|
|
|
|
|
|
|
|
socket.emit("push:register", {
|
|
|
|
token: storage.get("token"),
|
|
|
|
endpoint: subscription.endpoint,
|
|
|
|
keys: {
|
|
|
|
p256dh: key,
|
|
|
|
auth: authSecret,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.then((successful) => {
|
|
|
|
if (successful) {
|
|
|
|
alternatePushButton().prop("disabled", false);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
)
|
2019-08-03 19:03:45 +00:00
|
|
|
.catch(() => {
|
2019-02-20 09:10:18 +00:00
|
|
|
vueApp.pushNotificationState = "unsupported";
|
2019-07-17 09:33:59 +00:00
|
|
|
});
|
2017-07-10 19:47:03 +00:00
|
|
|
|
|
|
|
return false;
|
2019-08-02 12:53:31 +00:00
|
|
|
};
|
2017-07-10 19:47:03 +00:00
|
|
|
|
|
|
|
function alternatePushButton() {
|
|
|
|
const text = pushNotificationsButton.text();
|
|
|
|
|
|
|
|
return pushNotificationsButton
|
|
|
|
.text(pushNotificationsButton.data("text-alternate"))
|
|
|
|
.data("text-alternate", text);
|
|
|
|
}
|
|
|
|
|
|
|
|
function urlBase64ToUint8Array(base64String) {
|
2019-07-17 09:33:59 +00:00
|
|
|
const padding = "=".repeat((4 - (base64String.length % 4)) % 4);
|
|
|
|
const base64 = (base64String + padding).replace(/-/g, "+").replace(/_/g, "/");
|
2017-07-10 19:47:03 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
function isAllowedServiceWorkersHost() {
|
2019-07-17 09:33:59 +00:00
|
|
|
return (
|
|
|
|
location.protocol === "https:" ||
|
|
|
|
location.hostname === "localhost" ||
|
|
|
|
location.hostname === "127.0.0.1"
|
|
|
|
);
|
2017-07-10 19:47:03 +00:00
|
|
|
}
|