diff options
Diffstat (limited to 'client-web/source/sw/worker.ts')
-rw-r--r-- | client-web/source/sw/worker.ts | 115 |
1 files changed, 76 insertions, 39 deletions
diff --git a/client-web/source/sw/worker.ts b/client-web/source/sw/worker.ts index a06f3db..442f08a 100644 --- a/client-web/source/sw/worker.ts +++ b/client-web/source/sw/worker.ts @@ -4,9 +4,12 @@ Copyright (C) 2022 metamuffin <metamuffin@disroot.org> */ /// <reference no-default-lib="true"/> - /// <reference lib="esnext" /> /// <reference lib="webworker" /> + +import { handle_download_request, port_to_readable, streams } from "./download.ts"; +import { SWMessage } from "./protocol.ts"; + declare const self: ServiceWorkerGlobalScope; export { }; console.log("hello from the keks-meet service worker"); @@ -25,53 +28,87 @@ self.addEventListener("unload", () => { console.log("unload") }) -const streams = new Map<string, { readable: ReadableStream, size: number }>() - -self.addEventListener("message", ev => { - const { path, size } = ev.data, port = ev.ports[0] - const readable = port_to_readable(port) - streams.set(path, { readable, size }) +self.addEventListener("message", async ev => { + const message: SWMessage = ev.data; + console.log("incoming message", message); + if (message.download) { + const { path, size } = message.download, port = ev.ports[0] + const readable = port_to_readable(port) + streams.set(path, { readable, size }) + } + if (message.check_version) { + broadcast_response(await check_for_updates()) + } + if (message.update) { + broadcast_response(await update()) + } }) -function port_to_readable(port: MessagePort): ReadableStream { - return new ReadableStream({ - start(controller) { - console.log("ReadableStream started"); - port.onmessage = event => { - if (event.data === "end") controller.close() - else if (event.data === "abort") controller.error("aborted") - else controller.enqueue(event.data) - } - }, - cancel() { console.log("ReadableStream cancelled"); port.postMessage({ abort: true }) }, - }) +async function broadcast_response(message: SWMessage) { + const clients = await self.clients.matchAll({}) + console.log(clients); + clients.forEach(c => c.postMessage(message)) } -self.addEventListener("fetch", event => { +self.addEventListener("fetch", async event => { const { request } = event; if (!request.url.startsWith(self.origin)) return const path = request.url.substring(self.origin.length) console.log(request.method, path); - const stream = streams.get(path) - if (stream) { - streams.delete(path) - console.log(`-> stream response`); - return event.respondWith( - new Response( - stream.readable, - { - headers: new Headers({ - "content-type": "application/octet-stream; charset=utf-8", // TODO transmit and set accordingly - "content-security-policy": "default-src 'none'", - "content-length": `${stream.size}`, - }) - } - ) - ) - } - + if (path.startsWith("/download")) return handle_download_request(path, event) + if (path.startsWith("/signaling")) return event.respondWith(fetch(request)) if (path == "/swtest") return event.respondWith(new Response("works!", { headers: new Headers({ "content-type": "text/plain" }) })) - event.respondWith(fetch(request)) + const cache = await caches.open("v1") + // const cached = await cache.match(request) + // if (cached) { + // console.log("-> cached"); + // return cached + // } + console.log("-> forwarding to the server"); + const response = await fetch(request); + cache.put(request, response.clone()) + event.respondWith(response.clone()) }) + + +async function update(): Promise<SWMessage> { + console.log("updating..."); + await caches.delete("v1") + await Promise.all( + [ + "/", + "/room", + "/config.json", + "/assets/bundle.js", + "/favicon.ico" + ] + .map(cache_preload) + ) + return { updated: true } +} + +async function cache_preload(path: string) { + const cache = await caches.open("v1") + const req = new Request(path) + const res = await fetch(req) + await cache.put(req, res) +} + +async function check_for_updates(): Promise<SWMessage> { + console.log("checking for updates"); + const cache = await caches.open("v1") + const res = await fetch("/version") + const res2 = await cache.match(new Request("/version")); + const available_version = await res.text() + const installed_version = res2 ? await res2.text() : "none"; + console.log({ available_version, installed_version }); + return { + version_info: { + available_version, + installed_version + } + } +} + |