wip: add support for WEBPUSH

This commit is contained in:
Simon Ser 2021-05-20 20:03:44 +02:00
parent 32012bbea5
commit dc6614e4ff
5 changed files with 70 additions and 0 deletions

View file

@ -23,6 +23,7 @@ import { SERVER_BUFFER, BufferType, ReceiptType, ServerStatus, Unread, BufferEve
import commands from "../commands.js"; import commands from "../commands.js";
import { setup as setupKeybindings } from "../keybindings.js"; import { setup as setupKeybindings } from "../keybindings.js";
import * as store from "../store.js"; import * as store from "../store.js";
import * as webpush from "../webpush.js";
const baseConfig = { const baseConfig = {
server: {}, server: {},
@ -1095,6 +1096,10 @@ export default class App extends Component {
switch (msg.command) { switch (msg.command) {
case irc.RPL_WELCOME: case irc.RPL_WELCOME:
this.fetchBacklog(serverID); this.fetchBacklog(serverID);
if (client.enabledCaps["soju.im/webpush"]) {
// TODO: check if notifications are enabled
webpush.register(client);
}
break; break;
case irc.RPL_ENDOFMOTD: case irc.RPL_ENDOFMOTD:
case irc.ERR_NOMOTD: case irc.ERR_NOMOTD:

View file

@ -24,6 +24,7 @@ const permanentCaps = [
"draft/read-marker", "draft/read-marker",
"soju.im/bouncer-networks", "soju.im/bouncer-networks",
"soju.im/webpush",
]; ];
const RECONNECT_MIN_DELAY_MSEC = 10 * 1000; // 10s const RECONNECT_MIN_DELAY_MSEC = 10 * 1000; // 10s

View file

@ -1,4 +1,6 @@
import { html, render } from "./lib/index.js"; import { html, render } from "./lib/index.js";
import App from "./components/app.js"; import App from "./components/app.js";
navigator.serviceWorker.register("./service-worker.js");
render(html`<${App}/>`, document.body); render(html`<${App}/>`, document.body);

6
service-worker.js Normal file
View file

@ -0,0 +1,6 @@
self.addEventListener("push", (event) => {
var payload = event.data ? event.data.text() : "no payload";
event.waitUntil(self.registration.showNotification("gamja service worker", {
body: payload,
}));
});

56
webpush.js Normal file
View file

@ -0,0 +1,56 @@
import * as irc from "./lib/irc.js";
async function register(client) {
let encodedVapidPubkey = client.isupport.get("VAPID");
if (!encodedVapidPubkey) {
throw new Error("Server is missing VAPID public key");
}
let vapidPubKey = urlBase64ToUint8Array(encodedVapidPubkey);
let registration = await navigator.serviceWorker.ready;
let subscription = registration.pushManager.getSubscription();
if (subscription && !compareVapidPubkeys(subscription.options.applicationServerKey, vapidPubKey)) {
await subscription.unsubscribe();
subscription = null;
}
if (!subscription) {
subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: vapidPubKey,
});
}
var data = subscription.toJSON();
var keysStr = irc.formatTags(data.keys);
client.send({
command: "WEBPUSH",
params: ["REGISTER", data.endpoint, keysStr],
});
}
function urlBase64ToUint8Array(base64String) {
var padding = '='.repeat((4 - base64String.length % 4) % 4);
var base64 = (base64String + padding)
.replace(/\-/g, '+')
.replace(/_/g, '/');
var rawData = window.atob(base64);
var outputArray = new Uint8Array(rawData.length);
for (var i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
function compareVapidPubkeys(a, b) {
if (a.length !== b.length) {
return false;
}
for (let i = 0; i < a.length; i++) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
}