From da580353cae4f0f7e80817de6b053093366aff72 Mon Sep 17 00:00:00 2001 From: Maya Date: Mon, 9 Mar 2026 22:55:40 +0300 Subject: [PATCH] feat: CTA to try next converter --- messages/en.json | 6 ++ .../functional/popups/FallbackToast.svelte | 37 ++++++++++ src/lib/types/file.svelte.ts | 73 +++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 src/lib/components/functional/popups/FallbackToast.svelte diff --git a/messages/en.json b/messages/en.json index 644fb3d..224582b 100644 --- a/messages/en.json +++ b/messages/en.json @@ -145,6 +145,12 @@ }, "errors": { "cant_convert": "We can't convert this file.", + "converter_fallback": { + "body": "Conversion failed for {filename}. Would you like to try the next compatible converter {converter}?", + "yes": "Next converter", + "no": "Cancel conversion", + "all_failed": "All compatible converters failed for {filename}. Conversion has been cancelled." + }, "vertd_server": "what are you doing..? you're supposed to run the vertd server!", "vertd_generic_view": "View error details", "vertd_generic_body": "An error occurred whilst whilst trying convert your video. Would you like to submit this video to the developers to help fix this bug? Only your video file will be sent. No identifiers will be uploaded.", diff --git a/src/lib/components/functional/popups/FallbackToast.svelte b/src/lib/components/functional/popups/FallbackToast.svelte new file mode 100644 index 0000000..3f27151 --- /dev/null +++ b/src/lib/components/functional/popups/FallbackToast.svelte @@ -0,0 +1,37 @@ + + +
+

+ {m["convert.errors.converter_fallback.body"]({ + filename: additional.fileName, + converter: additional.nextConverter, + })} +

+
+ + +
+
diff --git a/src/lib/types/file.svelte.ts b/src/lib/types/file.svelte.ts index 25c31ba..b767033 100644 --- a/src/lib/types/file.svelte.ts +++ b/src/lib/types/file.svelte.ts @@ -4,6 +4,7 @@ import { m } from "$lib/paraglide/messages"; import { ToastManager } from "$lib/util/toast.svelte"; import type { Component } from "svelte"; import { MAX_ARRAY_BUFFER_SIZE } from "$lib/store/index.svelte"; +import FallbackToast from "$lib/components/functional/popups/FallbackToast.svelte"; import type { ConversionSettings, SettingDefinition, @@ -37,6 +38,9 @@ export class VertFile { public cancelled = $state(false); public converters: Converter[] = []; + private fallbackToastId: number | null = null; + private attemptedConverters = new Set(); + private retryingFallback = false; public isZip = $state(() => this.from === ".zip"); @@ -137,6 +141,8 @@ export class VertFile { // eslint-disable-next-line @typescript-eslint/no-explicit-any public async convert(...args: any[]) { + if (!this.retryingFallback) this.attemptedConverters.clear(); + if (!this.converters.length) throw new Error("No converters found"); const customConverter = this.converters.find( @@ -162,6 +168,7 @@ export class VertFile { } if (!converter) throw new Error("No converter found"); + this.attemptedConverters.add(converter.name); log(["file", "convert"], `using converter: ${converter.name}`); this.result = null; @@ -181,8 +188,74 @@ export class VertFile { ...args, ); this.result = res; + if (this.fallbackToastId !== null) { + ToastManager.remove(this.fallbackToastId); + this.fallbackToastId = null; + } } catch (err) { if (!this.cancelled) this.toastErr(err); + + const compatibleConverters = this.findConverters([ + this.from, + this.to, + ]); + const nextConverter = compatibleConverters.find( + (c) => !this.attemptedConverters.has(c.name), + ); + + // TODO: clean up languages file, then migrate all languages to new structure + + // TODO: should figure out a cleaner way to do this + if (!this.cancelled && nextConverter) { + if (this.fallbackToastId !== null) + ToastManager.remove(this.fallbackToastId); + + this.fallbackToastId = ToastManager.add({ + type: "warning", + disappearing: false, + message: FallbackToast, + additional: { + fileName: this.file.name, + nextConverter: nextConverter.name, + onNext: async () => { + if (this.fallbackToastId !== null) + ToastManager.remove(this.fallbackToastId); + this.fallbackToastId = null; + + log( + ["file", "convert"], + `retrying ${this.name} with next compatible converter: ${nextConverter.name}`, + ); + + this.conversionSettings = { + ...this.conversionSettings, + converter: nextConverter.name, + }; + this.retryingFallback = true; + try { + await this.convert(...args); + } finally { + this.retryingFallback = false; + } + }, + onCancel: () => { + if (this.fallbackToastId !== null) + ToastManager.remove(this.fallbackToastId); + this.fallbackToastId = null; + this.cancelled = true; + }, + }, + }); + } else if (!this.cancelled) { + this.cancelled = true; + ToastManager.add({ + type: "error", + message: m["convert.errors.converter_fallback.all_failed"]({ + filename: this.file.name, + }), + }); + } + this.result = null; } this.processing = false;