mirror of https://github.com/VERT-sh/VERT.git
feat: basic functionality
This commit is contained in:
parent
9952d1563a
commit
b5ac70a015
|
|
@ -1,7 +1,18 @@
|
||||||
import type { IFile, OmitBetterStrict } from "$lib/types";
|
import type { IFile, OmitBetterStrict } from "$lib/types";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for all converters.
|
||||||
|
*/
|
||||||
export class Converter {
|
export class Converter {
|
||||||
|
/**
|
||||||
|
* List of supported formats.
|
||||||
|
*/
|
||||||
public supportedFormats: string[] = [];
|
public supportedFormats: string[] = [];
|
||||||
|
/**
|
||||||
|
* Convert a file to a different format.
|
||||||
|
* @param input The input file.
|
||||||
|
* @param to The format to convert to. Includes the dot.
|
||||||
|
*/
|
||||||
public async convert(
|
public async convert(
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
input: OmitBetterStrict<IFile, "extension">,
|
input: OmitBetterStrict<IFile, "extension">,
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,20 @@ import type { VipsWorkerMessage, OmitBetterStrict } from "$lib/types";
|
||||||
export class VipsConverter extends Converter {
|
export class VipsConverter extends Converter {
|
||||||
private worker: Worker = browser ? new VipsWorker() : null!;
|
private worker: Worker = browser ? new VipsWorker() : null!;
|
||||||
private id = 0;
|
private id = 0;
|
||||||
public supportedFormats = [""];
|
public supportedFormats = [
|
||||||
|
".jpg",
|
||||||
|
".jpeg",
|
||||||
|
".png",
|
||||||
|
".webp",
|
||||||
|
".tiff",
|
||||||
|
".tif",
|
||||||
|
".gif",
|
||||||
|
".svg",
|
||||||
|
".webp",
|
||||||
|
".jfif",
|
||||||
|
".ico",
|
||||||
|
".bmp",
|
||||||
|
];
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,92 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Uploader from "$lib/components/visual/Uploader.svelte";
|
import Uploader from "$lib/components/visual/Uploader.svelte";
|
||||||
|
import { converters } from "$lib/converters";
|
||||||
|
|
||||||
|
let conversionTypes = $state<string[]>([]);
|
||||||
|
let downloadFns = $state<(() => void)[]>([]);
|
||||||
let files = $state<FileList>();
|
let files = $state<FileList>();
|
||||||
|
let iterableFiles = $derived.by(() => {
|
||||||
|
if (!files) return [];
|
||||||
|
return Array.from(files);
|
||||||
|
});
|
||||||
|
|
||||||
|
const convertAllFiles = async () => {
|
||||||
|
const promises = iterableFiles.map(async (file, i) => {
|
||||||
|
let conversionType = conversionTypes[i];
|
||||||
|
const converter = converters[0];
|
||||||
|
const convertedFile = await converter.convert(
|
||||||
|
{
|
||||||
|
name: file.name,
|
||||||
|
buffer: await file.arrayBuffer(),
|
||||||
|
},
|
||||||
|
conversionType,
|
||||||
|
);
|
||||||
|
downloadFns[i] = () => {
|
||||||
|
const url = URL.createObjectURL(
|
||||||
|
new Blob([convertedFile.buffer]),
|
||||||
|
);
|
||||||
|
const a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
if (conversionType.startsWith("."))
|
||||||
|
conversionType = conversionType.slice(1);
|
||||||
|
a.download = `${file.name}.${conversionType}`;
|
||||||
|
a.target = "_self";
|
||||||
|
a.click();
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
await Promise.all(promises);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex items-center justify-center h-full">
|
<div class="flex flex-col items-center">
|
||||||
<div class="w-full max-w-screen-lg h-80">
|
<div class="max-w-screen-lg w-full">
|
||||||
<Uploader bind:files />
|
<div class="h-80 justify-self-center mt-40">
|
||||||
|
<Uploader bind:files />
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
{#each iterableFiles as file, i}
|
||||||
|
<div
|
||||||
|
class="flex items-center w-full max-w-screen-lg border-2 border-solid border-foreground rounded-xl px-4 py-2 mt-4"
|
||||||
|
>
|
||||||
|
<div class="flex items-center flex-grow">
|
||||||
|
{file.name}
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-4 flex-shrink-0">
|
||||||
|
{#if downloadFns[i]}
|
||||||
|
<button
|
||||||
|
class="px-4 py-2 border-2 border-solid border-foreground rounded-xl"
|
||||||
|
onclick={downloadFns[i]}
|
||||||
|
>
|
||||||
|
Download
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
<!-- <input
|
||||||
|
type="text"
|
||||||
|
class="border-2 border-solid border-foreground rounded-xl px-4 py-2 focus:!outline-none"
|
||||||
|
bind:value={conversionTypes[i]}
|
||||||
|
placeholder="jpeg"
|
||||||
|
/> -->
|
||||||
|
<select
|
||||||
|
class="border-2 border-solid border-foreground rounded-xl px-4 py-2 focus:!outline-none"
|
||||||
|
bind:value={conversionTypes[i]}
|
||||||
|
>
|
||||||
|
{#each converters[0].supportedFormats as conversionType}
|
||||||
|
<option value={conversionType}
|
||||||
|
>{conversionType}</option
|
||||||
|
>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
<button
|
||||||
|
class="mt-4 px-4 py-2 border-2 border-solid border-foreground rounded-xl"
|
||||||
|
onclick={convertAllFiles}
|
||||||
|
>
|
||||||
|
Convert
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue