feat: CTA to try next converter

This commit is contained in:
Maya 2026-03-09 22:55:40 +03:00
parent 95210e84eb
commit da580353ca
No known key found for this signature in database
3 changed files with 116 additions and 0 deletions

View File

@ -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.",

View File

@ -0,0 +1,37 @@
<script lang="ts">
import { m } from "$lib/paraglide/messages";
type Additional = {
fileName: string;
nextConverter: string;
onNext: () => void | Promise<void>;
onCancel: () => void;
};
let { additional }: { additional: Additional } = $props();
export const title = "An error occurred";
</script>
<div class="flex flex-col gap-4">
<p class="text-black">
{m["convert.errors.converter_fallback.body"]({
filename: additional.fileName,
converter: additional.nextConverter,
})}
</p>
<div class="flex gap-4">
<button
class="btn rounded-lg h-fit py-2 w-full"
onclick={() => additional.onCancel()}
>
{m["convert.errors.converter_fallback.no"]()}
</button>
<button
class="btn rounded-lg h-fit py-2 w-full bg-accent-blue text-black"
onclick={() => additional.onNext()}
>
{m["convert.errors.converter_fallback.yes"]()}
</button>
</div>
</div>

View File

@ -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<string>();
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;