diff --git a/messages/en.json b/messages/en.json index a6a31a7..4cee4ac 100644 --- a/messages/en.json +++ b/messages/en.json @@ -47,6 +47,11 @@ } }, "convert": { + "zip_file": { + "extracting": "Detected ZIP archive: {filename}", + "extracted": "Extracted {extract_count} files from {filename}. {ignore_count} items were ignored.", + "extract_error": "Error extracting {filename}: {error}" + }, "external_warning": { "title": "External server warning", "text": "If you choose to convert into a video format, those files will be uploaded to an external server to be converted. Do you want to continue?", @@ -247,7 +252,8 @@ "general": "Error converting {file}: {message}", "cancel": "Error canceling conversion for {file}: {message}", "magick": "Error in Magick worker, image conversion may not work as expected.", - "ffmpeg": "Error loading ffmpeg, some features may not work.", + "ffmpeg": "Error loading FFmpeg, some features may not work as expected.", + "pandoc": "Error loading Pandoc worker, document conversion may not work as expected.", "no_audio": "No audio stream found.", "invalid_rate": "Invalid sample rate specified: {rate}Hz" } diff --git a/src/lib/converters/pandoc.svelte.ts b/src/lib/converters/pandoc.svelte.ts index 1f3fb68..a7c955c 100644 --- a/src/lib/converters/pandoc.svelte.ts +++ b/src/lib/converters/pandoc.svelte.ts @@ -26,9 +26,13 @@ export class PandocConverter extends Converter { this.status = "ready"; } catch (err) { this.status = "error"; + error( + ["converters", this.name], + `Failed to load Pandoc worker: ${err}`, + ); ToastManager.add({ type: "error", - message: `Failed to load Pandoc worker: ${err}`, // TODO: i18n + message: m["workers.errors.pandoc"](), }); } })(); diff --git a/src/lib/store/index.svelte.ts b/src/lib/store/index.svelte.ts index 5a14aa0..5c897a2 100644 --- a/src/lib/store/index.svelte.ts +++ b/src/lib/store/index.svelte.ts @@ -10,6 +10,7 @@ import { getLocale, setLocale } from "$lib/paraglide/runtime"; import { m } from "$lib/paraglide/messages"; import sanitizeHtml from "sanitize-html"; import { unzip } from "fflate"; +import { ToastManager } from "$lib/toast/index.svelte"; class Files { public files = $state([]); @@ -144,6 +145,12 @@ class Files { private async _handleZipFile(file: File): Promise { try { log(["files"], `extracting zip file: ${file.name}`); + ToastManager.add({ + type: "info", + message: m["convert.zip_file.extracting"]({ + filename: file.name, + }), + }); const arrayBuffer = await file.arrayBuffer(); const uint8Array = new Uint8Array(arrayBuffer); @@ -158,18 +165,20 @@ class Files { return; } - log( - ["files"], - `extracted ${Object.keys(unzipped).length} files from zip`, - ); + const itemCount = Object.keys(unzipped).length; + let ignoreCount = 0; + + log(["files"], `extracted ${itemCount} files from zip`); for (const [filename, data] of Object.entries(unzipped)) { if ( filename.startsWith(".") || filename.includes("/__MACOSX/") || filename.endsWith("/") - ) + ) { + ignoreCount++; continue; + } const buffer = Array.from(data); const extractedFile = new File( @@ -180,6 +189,15 @@ class Files { this._add(extractedFile); } + ToastManager.add({ + type: "success", + message: m["convert.zip_file.extracted"]({ + filename: file.name, + extract_count: itemCount - ignoreCount, + ignore_count: ignoreCount, + }), + }); + resolve(); }); }); @@ -200,8 +218,20 @@ class Files { file.type === "application/x-zip-compressed"; if (isZip) { - await this._handleZipFile(file); - return; + try { + await this._handleZipFile(file); + return; + } catch (err) { + error(["files"], `error extracting zip file: ${err}`); + ToastManager.add({ + type: "error", + message: m["convert.zip_file.extract_error"]({ + filename: file.name, + error: String(err), + }), + }); + return; + } } // regular files