mirror of https://github.com/VERT-sh/VERT.git
275 lines
6.7 KiB
Svelte
275 lines
6.7 KiB
Svelte
<script lang="ts">
|
|
import { page } from "$app/state";
|
|
import { beforeNavigate, goto } from "$app/navigation";
|
|
import { PUB_HOSTNAME, PUB_PLAUSIBLE_URL } from "$env/static/public";
|
|
import { duration, fly } from "$lib/animation";
|
|
import VertVBig from "$lib/assets/vert-bg.svg?component";
|
|
import featuredImage from "$lib/assets/VERT_Feature.webp";
|
|
import Navbar from "$lib/components/functional/Navbar.svelte";
|
|
import Footer from "$lib/components/visual/Footer.svelte";
|
|
import Logo from "$lib/components/visual/svg/Logo.svelte";
|
|
|
|
import { fade } from "$lib/animation";
|
|
import {
|
|
files,
|
|
gradientColor,
|
|
isMobile,
|
|
motion,
|
|
showGradient,
|
|
} from "$lib/store/index.svelte";
|
|
import {
|
|
InfoIcon,
|
|
RefreshCw,
|
|
SettingsIcon,
|
|
UploadIcon,
|
|
} from "lucide-svelte";
|
|
import { onMount } from "svelte";
|
|
import { quintOut } from "svelte/easing";
|
|
import "../app.scss";
|
|
import { writable } from "svelte/store";
|
|
let { children } = $props();
|
|
|
|
let shouldGoBack = writable(false);
|
|
let navbar = $state<HTMLDivElement>();
|
|
let hover = $state(false);
|
|
|
|
const items = $derived<
|
|
{
|
|
name: string;
|
|
url: string;
|
|
activeMatch: (pathname: string) => boolean;
|
|
icon: any;
|
|
badge?: number;
|
|
}[]
|
|
>([
|
|
{
|
|
name: "Upload",
|
|
url: "/",
|
|
activeMatch: (pathname) => pathname === "/",
|
|
icon: UploadIcon,
|
|
},
|
|
{
|
|
name: "Convert",
|
|
url: "/convert",
|
|
activeMatch: (pathname) => pathname === "/convert",
|
|
icon: RefreshCw,
|
|
badge: files.files.length,
|
|
},
|
|
{
|
|
name: "Settings",
|
|
url: "/settings",
|
|
activeMatch: (pathname) => pathname.startsWith("/settings"),
|
|
icon: SettingsIcon,
|
|
},
|
|
{
|
|
name: "About",
|
|
url: "/about",
|
|
activeMatch: (pathname) => pathname.startsWith("/about"),
|
|
icon: InfoIcon,
|
|
},
|
|
]);
|
|
|
|
const maybeNavToHome = (e: DragEvent) => {
|
|
if (e.dataTransfer?.types.includes("Files")) {
|
|
e.preventDefault();
|
|
goto("/");
|
|
}
|
|
};
|
|
|
|
onMount(() => {
|
|
const mouseEnter = () => {
|
|
hover = true;
|
|
};
|
|
|
|
const mouseLeave = () => {
|
|
hover = false;
|
|
};
|
|
|
|
navbar?.addEventListener("mouseenter", mouseEnter);
|
|
navbar?.addEventListener("mouseleave", mouseLeave);
|
|
|
|
isMobile.set(window.innerWidth <= 768);
|
|
window.addEventListener("resize", () => {
|
|
isMobile.set(window.innerWidth <= 768);
|
|
});
|
|
|
|
// defaults to true if not set
|
|
motion.set(localStorage.getItem("motion") !== "false");
|
|
});
|
|
|
|
let goingLeft = $state(false);
|
|
|
|
beforeNavigate((e) => {
|
|
const oldIndex = items.findIndex((i) =>
|
|
i.activeMatch(e.from?.url.pathname || ""),
|
|
);
|
|
const newIndex = items.findIndex((i) =>
|
|
i.activeMatch(e.to?.url.pathname || ""),
|
|
);
|
|
if (newIndex < oldIndex) {
|
|
goingLeft = true;
|
|
} else {
|
|
goingLeft = false;
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<svelte:head>
|
|
<title>VERT.sh</title>
|
|
<meta name="theme-color" content="#F2ABEE" />
|
|
<meta property="og:image" content={featuredImage} />
|
|
<meta property="twitter:image" content={featuredImage} />
|
|
{#if PUB_PLAUSIBLE_URL}<script
|
|
defer
|
|
data-domain={PUB_HOSTNAME || "vert.sh"}
|
|
src="{PUB_PLAUSIBLE_URL}/js/script.pageview-props.tagged-events.js"
|
|
></script>{/if}
|
|
<script src="/coi-serviceworker.min.js"></script>
|
|
</svelte:head>
|
|
|
|
<div class="flex flex-col min-h-screen h-full">
|
|
<!-- FIXME: if user resizes between desktop/mobile, highlight of page disappears (only shows on original size) -->
|
|
|
|
<div>
|
|
<!-- Mobile logo -->
|
|
<div class="flex md:hidden justify-center items-center p-8">
|
|
<a
|
|
class="flex items-center justify-center w-36 h-[72px] bg-panel p-4 rounded-[20px] shadow-panel"
|
|
href="/"
|
|
>
|
|
<div
|
|
class="h-14 bg-accent rounded-[14px] flex items-center justify-center"
|
|
>
|
|
<div class="w-[128px] h-5">
|
|
<Logo />
|
|
</div>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Desktop navbar -->
|
|
<div class="hidden md:flex p-8 w-screen justify-center z-50">
|
|
<Navbar {items} />
|
|
</div>
|
|
</div>
|
|
|
|
<div class="grid grid-rows-1 grid-cols-1 h-full flex-grow">
|
|
{#key page.url.pathname}
|
|
<div
|
|
class="row-start-1 col-start-1"
|
|
in:fly={{
|
|
x: goingLeft ? -window.innerWidth : window.innerWidth,
|
|
duration,
|
|
easing: quintOut,
|
|
delay: 25,
|
|
}}
|
|
out:fly={{
|
|
x: goingLeft ? window.innerWidth : -window.innerWidth,
|
|
duration,
|
|
easing: quintOut,
|
|
}}
|
|
>
|
|
<div
|
|
class="flex flex-col h-full pb-36 md:pb-0"
|
|
in:fade={{
|
|
duration,
|
|
easing: quintOut,
|
|
delay: $isMobile ? 0 : 100,
|
|
}}
|
|
out:fade={{
|
|
duration,
|
|
easing: quintOut,
|
|
delay: $isMobile ? 0 : 200,
|
|
}}
|
|
>
|
|
{@render children()}
|
|
</div>
|
|
</div>
|
|
{/key}
|
|
</div>
|
|
|
|
<div>
|
|
<div
|
|
class="hidden md:block w-full h-14 border-t border-separator relative mt-12"
|
|
>
|
|
<Footer
|
|
class="w-full h-full"
|
|
items={{
|
|
//"Privacy policy": "#",
|
|
"Source code": "https://github.com/not-nullptr/VERT",
|
|
"Discord server": "https://discord.gg/kqevGxYPak",
|
|
}}
|
|
/>
|
|
</div>
|
|
|
|
<!-- Mobile navbar -->
|
|
<div
|
|
class="fixed md:hidden bottom-0 left-0 w-screen p-8 justify-center z-50"
|
|
>
|
|
<div class="flex flex-col justify-center items-center">
|
|
<Navbar {items} />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Gradients placed here to prevent it overlapping in transitions -->
|
|
{#if page.url.pathname === "/"}
|
|
<div
|
|
class="fixed -z-30 top-0 left-0 w-screen h-screen flex items-center justify-center overflow-hidden"
|
|
>
|
|
<VertVBig class="fill-[--fg] opacity-10 w-[108%] h-[108%]"/>
|
|
</div>
|
|
<div
|
|
id="gradient-bg"
|
|
class="fixed top-0 left-0 w-screen h-screen -z-40 pointer-events-none"
|
|
style="background: var(--bg-gradient);"
|
|
></div>
|
|
{:else if page.url.pathname === "/convert" && $showGradient}
|
|
<div
|
|
id="gradient-bg"
|
|
class="fixed top-0 left-0 w-screen h-screen -z-40 pointer-events-none"
|
|
style="background: var(--bg-gradient-{$gradientColor || 'pink'});"
|
|
></div>
|
|
{:else if page.url.pathname === "/convert" && files.files.length === 1 && files.files[0].blobUrl}
|
|
<div
|
|
class="fixed w-screen h-screen opacity-75 overflow-hidden top-0 left-0 -z-50 pointer-events-none grid grid-cols-1 grid-rows-1"
|
|
>
|
|
<div
|
|
class="w-full relative"
|
|
transition:fade={{
|
|
duration,
|
|
easing: quintOut,
|
|
}}
|
|
>
|
|
<img
|
|
class="object-cover w-full {!$isMobile
|
|
? 'h-[calc(100%-66px)]'
|
|
: 'h-full'} blur-md"
|
|
src={files.files[0].blobUrl}
|
|
alt={files.files[0].name}
|
|
/>
|
|
<!-- <div class="absolute bottom-0 left-0 w-full h-full">
|
|
<ProgressiveBlur
|
|
direction="bottom"
|
|
endIntensity={256}
|
|
iterations={8}
|
|
fadeTo="var(--bg)"
|
|
/>
|
|
</div> -->
|
|
</div>
|
|
</div>
|
|
{:else if page.url.pathname === "/settings"}
|
|
<div
|
|
id="gradient-bg"
|
|
class="fixed top-0 left-0 w-screen h-screen -z-40 pointer-events-none"
|
|
style="background: var(--bg-gradient-blue);"
|
|
></div>
|
|
{:else if page.url.pathname === "/about"}
|
|
<div
|
|
id="gradient-bg"
|
|
class="fixed top-0 left-0 w-screen h-screen -z-40 pointer-events-none"
|
|
style="background: var(--bg-gradient-pink);"
|
|
></div>
|
|
{/if}
|