diff --git a/messages/en.json b/messages/en.json index 2f34788..f9fc37e 100644 --- a/messages/en.json +++ b/messages/en.json @@ -31,7 +31,11 @@ "status": { "text": "Status: {status}", "ready": "ready", - "not_ready": "not ready" + "not_ready": "not ready", + "not_initialized": "not initialized", + "downloading": "downloading...", + "initializing": "initializing...", + "unknown": "unknown status" }, "supported_formats": "Supported formats:" }, diff --git a/src/lib/converters/converter.svelte.ts b/src/lib/converters/converter.svelte.ts index f321b56..a530b62 100644 --- a/src/lib/converters/converter.svelte.ts +++ b/src/lib/converters/converter.svelte.ts @@ -1,5 +1,11 @@ import type { VertFile } from "$lib/types"; +export type WorkerStatus = + | "not-ready" + | "downloading" + | "ready" + | "error"; + export class FormatInfo { public name: string; @@ -32,14 +38,15 @@ export class Converter { * List of supported formats. */ public supportedFormats: FormatInfo[] = []; + + public status: WorkerStatus = $state("not-ready"); + public readonly reportsProgress: boolean = false; + /** * Convert a file to a different format. * @param input The input file. * @param to The format to convert to. Includes the dot. */ - public ready: boolean = $state(false); - public readonly reportsProgress: boolean = false; - public async convert( // eslint-disable-next-line @typescript-eslint/no-unused-vars input: VertFile, diff --git a/src/lib/converters/ffmpeg.svelte.ts b/src/lib/converters/ffmpeg.svelte.ts index e9ccebc..7d16a15 100644 --- a/src/lib/converters/ffmpeg.svelte.ts +++ b/src/lib/converters/ffmpeg.svelte.ts @@ -83,14 +83,19 @@ export class FFmpegConverter extends Converter { (async () => { const baseURL = "https://cdn.jsdelivr.net/npm/@ffmpeg/core@0.12.10/dist/esm"; + + this.status = "downloading"; + await this.ffmpeg.load({ coreURL: `${baseURL}/ffmpeg-core.js`, wasmURL: `${baseURL}/ffmpeg-core.wasm`, }); - this.ready = true; + + this.status = "ready"; })(); } catch (err) { error(["converters", this.name], `error loading ffmpeg: ${err}`); + this.status = "error"; addToast("error", m["workers.errors.ffmpeg"]()); } } diff --git a/src/lib/converters/magick.svelte.ts b/src/lib/converters/magick.svelte.ts index 2183915..244328e 100644 --- a/src/lib/converters/magick.svelte.ts +++ b/src/lib/converters/magick.svelte.ts @@ -86,19 +86,22 @@ export class MagickConverter extends Converter { super(); log(["converters", this.name], `created converter`); if (!browser) return; + + this.status = "downloading"; + log(["converters", this.name], `loading worker @ ${MagickWorker}`); this.worker.onmessage = (e) => { const message: WorkerMessage = e.data; log(["converters", this.name], `received message ${message.type}`); if (message.type === "loaded") { - this.ready = true; + this.status = "ready"; } else if (message.type === "error") { error( ["converters", this.name], `error in worker: ${message.error}`, ); + this.status = "error"; addToast("error", m["workers.errors.magick"]()); - throw new Error(message.error); } }; } diff --git a/src/lib/converters/pandoc.svelte.ts b/src/lib/converters/pandoc.svelte.ts index bbf08ec..b4c9a7b 100644 --- a/src/lib/converters/pandoc.svelte.ts +++ b/src/lib/converters/pandoc.svelte.ts @@ -2,6 +2,7 @@ import { VertFile } from "$lib/types"; import { Converter, FormatInfo } from "./converter.svelte"; import { browser } from "$app/environment"; import PandocWorker from "$lib/workers/pandoc?worker&url"; +import { addToast } from "$lib/store/ToastProvider"; export class PandocConverter extends Converter { public name = "pandoc"; @@ -12,10 +13,17 @@ export class PandocConverter extends Converter { super(); if (!browser) return; (async () => { - this.wasm = await fetch("/pandoc.wasm").then((r) => - r.arrayBuffer(), - ); - this.ready = true; + try { + this.status = "downloading"; + this.wasm = await fetch("/pandoc.wasm").then((r) => + r.arrayBuffer(), + ); + + this.status = "ready"; + } catch (err) { + this.status = "error"; + addToast("error", `Failed to load Pandoc worker: ${err}`); + } })(); } diff --git a/src/lib/converters/vertd.svelte.ts b/src/lib/converters/vertd.svelte.ts index 1ea3fe2..d0e1ecf 100644 --- a/src/lib/converters/vertd.svelte.ts +++ b/src/lib/converters/vertd.svelte.ts @@ -237,7 +237,7 @@ export class VertdConverter extends Converter { this.log = (msg) => log(["converters", this.name], msg); this.log("created converter"); this.log("not rly sure how to implement this :P"); - this.ready = true; + this.status = "ready"; } public async convert(input: VertFile, to: string): Promise { diff --git a/src/lib/sections/settings/Vertd.svelte b/src/lib/sections/settings/Vertd.svelte index d19546b..7963177 100644 --- a/src/lib/sections/settings/Vertd.svelte +++ b/src/lib/sections/settings/Vertd.svelte @@ -8,6 +8,7 @@ import { vertdLoaded } from "$lib/store/index.svelte"; import { m } from "$lib/paraglide/messages"; import { link } from "$lib/store/index.svelte"; + //import { converters } from "$lib/converters"; let vertdCommit = $state(null); let abortController: AbortController | null = null; @@ -35,12 +36,16 @@ if (err.name !== "AbortError") { vertdCommit = null; vertdLoaded.set(false); + // const converter = converters.find((c) => c.name === "vertd"); + // if (converter) converter.status = "not-ready"; } }); } else { if (abortController) abortController.abort(); vertdCommit = null; vertdLoaded.set(false); + // const converter = converters.find((c) => c.name === "vertd"); + // if (converter) converter.status = "not-ready"; } return () => { diff --git a/src/lib/store/index.svelte.ts b/src/lib/store/index.svelte.ts index fb5bb16..52d123a 100644 --- a/src/lib/store/index.svelte.ts +++ b/src/lib/store/index.svelte.ts @@ -18,7 +18,7 @@ class Files { public ready = $derived( this.files.length === 0 ? false - : this.requiredConverters.every((f) => f?.ready) && + : this.requiredConverters.every((f) => f?.status === "ready") && this.files.every((f) => !f.processing), ); public results = $derived( diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index d81fc4d..fb98968 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -10,6 +10,7 @@ import { browser } from "$app/environment"; import "overlayscrollbars/overlayscrollbars.css"; import { onMount } from "svelte"; + import type { WorkerStatus } from "$lib/converters/converter.svelte"; const getSupportedFormats = (name: string) => converters @@ -20,41 +21,44 @@ ) .join(", ") || "none"; - const status: { + const worker: { [key: string]: { - ready: boolean; formats: string; icon: typeof Image; title: string; + status: WorkerStatus; }; } = $derived({ Images: { - ready: - converters.find((c) => c.name === "imagemagick")?.ready || - false, formats: getSupportedFormats("imagemagick"), icon: Image, title: m["upload.cards.images"](), + status: + converters.find((c) => c.name === "imagemagick")?.status || + "not-ready", }, Audio: { - ready: converters.find((c) => c.name === "ffmpeg")?.ready || false, formats: getSupportedFormats("ffmpeg"), icon: AudioLines, title: m["upload.cards.audio"](), + status: + converters.find((c) => c.name === "ffmpeg")?.status || + "not-ready", }, Documents: { - ready: converters.find((c) => c.name === "pandoc")?.ready || false, formats: getSupportedFormats("pandoc"), icon: BookText, title: m["upload.cards.documents"](), + status: + converters.find((c) => c.name === "pandoc")?.status || + "not-ready", }, Video: { - ready: - converters.find((c) => c.name === "vertd")?.ready || - (false && $vertdLoaded), formats: getSupportedFormats("vertd"), icon: Film, title: m["upload.cards.video"](), + status: + $vertdLoaded === true ? "ready" : "not-ready", // not using converter.status for this }, }); @@ -76,9 +80,21 @@ return ""; }; + const getStatusText = (status: WorkerStatus) => { + switch (status) { + case "downloading": + return m["upload.cards.status.downloading"](); + case "ready": + return m["upload.cards.status.ready"](); + default: + // "not-ready", "error" and other statuses (somehow) + return m["upload.cards.status.not_ready"](); + } + }; + let scrollContainers: HTMLElement[] = $state([]); // svelte-ignore state_referenced_locally - let showBlur = $state(Array(Object.keys(status).length).fill(false)); + let showBlur = $state(Array(Object.keys(worker).length).fill(false)); onMount(() => { const handleResize = () => { @@ -129,7 +145,7 @@ {#if browser} - {#each Object.entries(status) as [key, s], i} + {#each Object.entries(worker) as [key, s], i} {@const Icon = s.icon} @@ -201,16 +217,12 @@ {/if} {@html m["upload.cards.status.text"]({ - status: s.ready - ? m[ - "upload.cards.status.ready" - ]() - : m[ - "upload.cards.status.not_ready" - ](), + status: getStatusText(s.status), })} - + {m[ "upload.cards.supported_formats"
{@html m["upload.cards.status.text"]({ - status: s.ready - ? m[ - "upload.cards.status.ready" - ]() - : m[ - "upload.cards.status.not_ready" - ](), + status: getStatusText(s.status), })}