mirror of https://github.com/VERT-sh/VERT.git
115 lines
3.4 KiB
Svelte
115 lines
3.4 KiB
Svelte
<script lang="ts">
|
|
import { flip } from "$lib/animation";
|
|
import Uploader from "$lib/components/functional/Uploader.svelte";
|
|
import Panel from "$lib/components/visual/Panel.svelte";
|
|
import { files } from "$lib/store/index.svelte";
|
|
import { quintOut } from "svelte/easing";
|
|
import { blur } from "svelte/transition";
|
|
import { m } from "$lib/paraglide/messages";
|
|
|
|
const images = $derived(
|
|
files.files.filter((f) =>
|
|
f.converters.map((c) => c.name).includes("imagemagick"),
|
|
),
|
|
);
|
|
|
|
let forcedBlobURLs = $state<Map<string, string>>(new Map());
|
|
|
|
const jpegify = () => {
|
|
const imgs = [...images];
|
|
imgs.map(async (f, i) => {
|
|
f.to = ".jpeg";
|
|
const result = await f.convert(compression);
|
|
if (!result) return;
|
|
forcedBlobURLs.set(f.id, URL.createObjectURL(result.file));
|
|
forcedBlobURLs = new Map([...forcedBlobURLs]);
|
|
});
|
|
};
|
|
|
|
let compressionInverted = $state(10);
|
|
const compression = $derived(100 - compressionInverted);
|
|
const processing = $derived(images.map((f) => f.processing).includes(true));
|
|
</script>
|
|
|
|
<div class="mx-auto w-full max-w-[778px] flex flex-col gap-8">
|
|
<h1 class="text-5xl text-center">{m["jpegify.title"]()}</h1>
|
|
<p class="text-muted text-center -mt-4 font-normal italic">
|
|
{m["jpegify.subtitle"]()}
|
|
</p>
|
|
<Uploader class="w-full h-64" jpegify={true} />
|
|
<input
|
|
type="range"
|
|
min="1"
|
|
max="100"
|
|
step="1"
|
|
class="w-full h-2 bg-panel rounded-lg appearance-none cursor-pointer"
|
|
bind:value={compressionInverted}
|
|
disabled={processing}
|
|
/>
|
|
<button
|
|
onclick={jpegify}
|
|
disabled={processing}
|
|
class="btn bg-accent text-black rounded-2xl text-2xl w-full mx-auto"
|
|
>{m["jpegify.button"]({ compression: compressionInverted })}</button
|
|
>
|
|
<div class="flex flex-wrap flex-row justify-center gap-4">
|
|
{#each images as file, i (file.id)}
|
|
<div
|
|
class="max-w-full w-full h-96"
|
|
animate:flip={{ duration: 400, easing: quintOut }}
|
|
transition:blur={{
|
|
duration: 400,
|
|
amount: 8,
|
|
easing: quintOut,
|
|
}}
|
|
>
|
|
<Panel class="w-full h-full flex flex-col gap-4 relative z-0">
|
|
<div
|
|
class="relative rounded-xl flex-grow overflow-hidden flex items-center justify-center"
|
|
>
|
|
<img
|
|
src={forcedBlobURLs.get(file.id) ||
|
|
file.result?.blobUrl ||
|
|
file.blobUrl}
|
|
alt={file.name}
|
|
class="h-full relative"
|
|
/>
|
|
<img
|
|
src={forcedBlobURLs.get(file.id) ||
|
|
file.result?.blobUrl ||
|
|
file.blobUrl}
|
|
alt={file.name}
|
|
class="h-full absolute top-0 left-0 w-full object-cover blur-2xl -z-10"
|
|
/>
|
|
</div>
|
|
<div class="flex-shrink-0 flex items-center gap-4 w-full">
|
|
<button
|
|
onclick={() => {
|
|
file?.download();
|
|
}}
|
|
disabled={!!!file.result}
|
|
class="btn bg-accent text-black rounded-2xl text-2xl w-full mx-auto"
|
|
>
|
|
{m["jpegify.download"]()}
|
|
</button>
|
|
<button
|
|
onclick={() => {
|
|
URL.revokeObjectURL(
|
|
forcedBlobURLs.get(file.id) || "",
|
|
);
|
|
forcedBlobURLs.delete(file.id);
|
|
files.files = files.files.filter(
|
|
(f) => f.id !== file.id,
|
|
);
|
|
}}
|
|
class="btn border-accent-red border-2 bg-transparent text-black dynadark:text-white rounded-2xl text-2xl w-full mx-auto"
|
|
>
|
|
{m["jpegify.delete"]()}
|
|
</button>
|
|
</div>
|
|
</Panel>
|
|
</div>
|
|
{/each}
|
|
</div>
|
|
</div>
|