diff options
author | metamuffin <metamuffin@disroot.org> | 2023-04-10 14:15:33 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2023-04-10 14:15:33 +0200 |
commit | 4b026c618ed6b40a22c0bf601b45e1da96d5bc5e (patch) | |
tree | 34ea874d40407f8f318d66d8935cbdbbf3fbb42d /client-web/source/download_stream.ts | |
parent | fe36a0640f2e36baad1f08033f09b49bdd0f1062 (diff) | |
download | keks-meet-4b026c618ed6b40a22c0bf601b45e1da96d5bc5e.tar keks-meet-4b026c618ed6b40a22c0bf601b45e1da96d5bc5e.tar.bz2 keks-meet-4b026c618ed6b40a22c0bf601b45e1da96d5bc5e.tar.zst |
new (useless) sw
Diffstat (limited to 'client-web/source/download_stream.ts')
-rw-r--r-- | client-web/source/download_stream.ts | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/client-web/source/download_stream.ts b/client-web/source/download_stream.ts new file mode 100644 index 0000000..5aafde1 --- /dev/null +++ b/client-web/source/download_stream.ts @@ -0,0 +1,85 @@ +/* + This file is part of keks-meet (https://codeberg.org/metamuffin/keks-meet) + which is licensed under the GNU Affero General Public License (version 3); see /COPYING. + Copyright (C) 2022 metamuffin <metamuffin@disroot.org> +*/ +/// <reference lib="dom" /> +import { log } from "./logger.ts" +import { send_sw_message, SW_ENABLED } from "./sw/client.ts" + +function FallbackStreamDownload(size: number, filename?: string, progress?: (position: number) => void) { + log({ scope: "*", warn: true }, "downloading to memory because serviceworker is not available") + let position = 0 + let buffer = new Uint8Array(size) + return { + close() { + const a = document.createElement("a") + a.href = URL.createObjectURL(new Blob([buffer], { type: "text/plain" })) + a.download = filename ?? "file" + a.click() + }, + abort() { buffer = new Uint8Array(); /* have fun gc */ }, + write(chunk: Blob) { + const reader = new FileReader(); + reader.onload = function (event) { + const arr = new Uint8Array(event.target!.result as ArrayBuffer); + for (let i = 0; i < arr.length; i++, position++) { + buffer[position] = arr[i] + } + if (progress) progress(position) + }; + reader.readAsArrayBuffer(chunk); + } + } +} + +export function StreamDownload({ size, filename, cancel, progress }: { + size: number, + filename: string, + cancel: () => void, + progress: (position: number) => void +}) { + if (!SW_ENABLED) FallbackStreamDownload(size, filename, progress) + let position = 0 + + // the sw will handle this download + const path = `/download/${encodeURIComponent(filename ?? "file")}` + + const { port1, port2 } = new MessageChannel() + send_sw_message({ download: { path, size } }, [port2]) + + const a = document.createElement("a") + a.href = path + a.download = filename ?? "file" + a.target = "_blank" + // TODO this delay is part of a race condition btw + setTimeout(() => { + a.click() + }, 100) + + port1.onmessage = ev => { + if (ev.data.abort) { + cancel() + port1.close() + } + } + + return { + close() { + port1.postMessage("end") + }, + abort() { + port1.postMessage("abort") + }, + write(chunk: Blob) { + const reader = new FileReader(); + reader.onload = function (event) { + const arr = new Uint8Array(event.target!.result as ArrayBuffer); + port1.postMessage(arr) + position += arr.length + if (progress) progress(position) + }; + reader.readAsArrayBuffer(chunk); + } + } +} |