mirror of https://github.com/VERT-sh/VERT.git
fix: revoke generated object URLs
This commit is contained in:
parent
49821e51cb
commit
8ff1632b49
|
|
@ -2,6 +2,7 @@
|
|||
import { m } from "$lib/paraglide/messages";
|
||||
import type { DialogProps } from "$lib/store/DialogProvider";
|
||||
import { link, sanitize } from "$lib/store/index.svelte";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
interface VertdErrorDetailsProps {
|
||||
jobId: string;
|
||||
|
|
@ -13,6 +14,19 @@
|
|||
type Props = DialogProps<VertdErrorDetailsProps>;
|
||||
|
||||
let { additional }: Props = $props();
|
||||
let errorMessageUrl = $state("#");
|
||||
|
||||
onMount(() => {
|
||||
const url = URL.createObjectURL(
|
||||
new Blob([additional.errorMessage], {
|
||||
type: "text/plain",
|
||||
}),
|
||||
);
|
||||
|
||||
errorMessageUrl = url;
|
||||
|
||||
return () => URL.revokeObjectURL(url);
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
|
|
@ -41,13 +55,7 @@
|
|||
{@html sanitize(link(
|
||||
["view_link"],
|
||||
m["convert.errors.vertd_details_error_message"](),
|
||||
[
|
||||
URL.createObjectURL(
|
||||
new Blob([additional.errorMessage], {
|
||||
type: "text/plain",
|
||||
}),
|
||||
),
|
||||
],
|
||||
[errorMessageUrl],
|
||||
[true],
|
||||
["text-blue-500 font-normal"],
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -90,53 +90,67 @@ class Files {
|
|||
const mediaElement = isVideo
|
||||
? document.createElement("video")
|
||||
: new Image();
|
||||
mediaElement.src = URL.createObjectURL(file);
|
||||
const mediaUrl = URL.createObjectURL(file);
|
||||
mediaElement.src = mediaUrl;
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
if (isVideo) {
|
||||
const video = mediaElement as HTMLVideoElement;
|
||||
// seek to 10% of video time or 2 seconds in
|
||||
video.onloadeddata = () => {
|
||||
const seekTime = Math.min(video.duration * 0.1, 2);
|
||||
video.currentTime = seekTime;
|
||||
};
|
||||
video.onseeked = resolve;
|
||||
video.onerror = reject;
|
||||
} else {
|
||||
(mediaElement as HTMLImageElement).onload = resolve;
|
||||
(mediaElement as HTMLImageElement).onerror = reject;
|
||||
try {
|
||||
await new Promise((resolve, reject) => {
|
||||
if (isVideo) {
|
||||
const video = mediaElement as HTMLVideoElement;
|
||||
// seek to 10% of video time or 2 seconds in
|
||||
video.onloadeddata = () => {
|
||||
const seekTime = Math.min(video.duration * 0.1, 2);
|
||||
video.currentTime = seekTime;
|
||||
};
|
||||
video.onseeked = resolve;
|
||||
video.onerror = reject;
|
||||
} else {
|
||||
(mediaElement as HTMLImageElement).onload = resolve;
|
||||
(mediaElement as HTMLImageElement).onerror = reject;
|
||||
}
|
||||
});
|
||||
|
||||
const canvas = document.createElement("canvas");
|
||||
const ctx = canvas.getContext("2d");
|
||||
if (!ctx) return undefined;
|
||||
|
||||
const width = isVideo
|
||||
? (mediaElement as HTMLVideoElement).videoWidth
|
||||
: (mediaElement as HTMLImageElement).width;
|
||||
const height = isVideo
|
||||
? (mediaElement as HTMLVideoElement).videoHeight
|
||||
: (mediaElement as HTMLImageElement).height;
|
||||
|
||||
const scale = Math.max(maxSize / width, maxSize / height);
|
||||
canvas.width = width * scale;
|
||||
canvas.height = height * scale;
|
||||
ctx.drawImage(mediaElement, 0, 0, canvas.width, canvas.height);
|
||||
|
||||
// check if completely transparent
|
||||
const imageData = ctx.getImageData(
|
||||
0,
|
||||
0,
|
||||
canvas.width,
|
||||
canvas.height,
|
||||
);
|
||||
const isTransparent = Array.from(imageData.data).every(
|
||||
(value, index) => {
|
||||
return (index + 1) % 4 !== 0 || value === 0;
|
||||
},
|
||||
);
|
||||
if (isTransparent) {
|
||||
canvas.remove();
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
|
||||
const canvas = document.createElement("canvas");
|
||||
const ctx = canvas.getContext("2d");
|
||||
if (!ctx) return undefined;
|
||||
|
||||
const width = isVideo
|
||||
? (mediaElement as HTMLVideoElement).videoWidth
|
||||
: (mediaElement as HTMLImageElement).width;
|
||||
const height = isVideo
|
||||
? (mediaElement as HTMLVideoElement).videoHeight
|
||||
: (mediaElement as HTMLImageElement).height;
|
||||
|
||||
const scale = Math.max(maxSize / width, maxSize / height);
|
||||
canvas.width = width * scale;
|
||||
canvas.height = height * scale;
|
||||
ctx.drawImage(mediaElement, 0, 0, canvas.width, canvas.height);
|
||||
|
||||
// check if completely transparent
|
||||
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
const isTransparent = Array.from(imageData.data).every((value, index) => {
|
||||
return (index + 1) % 4 !== 0 || value === 0;
|
||||
});
|
||||
if (isTransparent) {
|
||||
const url = canvas.toDataURL();
|
||||
canvas.remove();
|
||||
return undefined;
|
||||
return url;
|
||||
} finally {
|
||||
URL.revokeObjectURL(mediaUrl);
|
||||
mediaElement.removeAttribute("src");
|
||||
if (isVideo) (mediaElement as HTMLVideoElement).load();
|
||||
}
|
||||
|
||||
const url = canvas.toDataURL();
|
||||
canvas.remove();
|
||||
return url;
|
||||
}
|
||||
|
||||
private async _handleZipFile(file: File): Promise<void> {
|
||||
|
|
|
|||
Loading…
Reference in New Issue