- +
+ -
-
+
+ +
- - -
- + +
-
- {#key data.pathname} -
+ +
+ {#key page.url.pathname} +
-
- {@render children()} -
+ {@render children()}
{/key}
+ +
+ {#each toastList as { id, type, message, durations }} + + {/each} +
+ +
+ + + +
+
+ +
+
+
+ + +{#if page.url.pathname === "/"} +
+ +
+
+{:else if page.url.pathname === "/convert" && $showGradient} +
+{:else if page.url.pathname === "/convert" && files.files.length === 1 && files.files[0].blobUrl} +
+
+ {files.files[0].name} +
+ +
+
+{:else if page.url.pathname === "/settings"} +
+{:else if page.url.pathname === "/about"} +
+{/if} diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index 3687dcf..73e4c9c 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -1,6 +1,4 @@ import { browser } from "$app/environment"; -import { theme } from "$lib/store/index.svelte"; -import JSCookie from "js-cookie"; export const load = ({ data }) => { if (!browser) return; @@ -11,20 +9,7 @@ export const load = ({ data }) => { status: 200, }); }); - const themeStr = JSCookie.get("theme"); - if (typeof themeStr === "undefined") { - theme.dark = window.matchMedia("(prefers-color-scheme: dark)").matches; - JSCookie.set("theme", theme.dark ? "dark" : "light", { - sameSite: "strict", - path: "/", - expires: 2147483647, - }); - } else { - theme.dark = themeStr === "dark"; - } - theme.dark = JSCookie.get("theme") === "dark"; - window.plausible("Theme set", { - props: { theme: theme.dark ? "dark" : "light" }, - }); return data; }; + +export const prerender = true; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 5fd9a71..089af4b 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,251 +1,84 @@ - - VERT.sh — Free, fast, and awesome file convert - - - - - - - - - - -{#snippet sellingPoint(text: string)} -
  • -
    - -
    - {text} -
  • -{/snippet} - -
    - c.supportedFormats)), - ]} - /> -
    - -
    -

    - Free, fast, and awesome file converting BETA -

    -
    -
    - - {#each ["Very fast, all processing done on device", "No file or size limit", "No ads, and open source", "Beautiful and straightforward UI"] as text, i} -
    - {@render sellingPoint(text)} +
    +
    +
    +
    +
    +

    + The file converter you'll love. +

    +

    + All processing is done on your device. No file size + limit, no ads, and completely open source. +

    - {/each} +
    + +
    +
    diff --git a/src/routes/about/+page.svelte b/src/routes/about/+page.svelte index fb8b32f..b5d2dd2 100644 --- a/src/routes/about/+page.svelte +++ b/src/routes/about/+page.svelte @@ -1,159 +1,130 @@ - - About VERT - - - - - -
    -

    - ⁉️ about VERT +
    +

    + + About

    -

    - You know what sucks? File converters! They're usually riddled with ads, - and take an ungodly amount of time to complete. So we made a better one! -

    -

    - VERT is a file converter that's open source, completely ad free, and - much much faster than you're used to. All the converting is done on your - device, which makes it both private and very speedy. And it of course - has a beautiful UI! ✨ -

    -

    - 🖼️ supported formats -

    -

    - As of right now, VERT supports image and audio conversion of most - popular formats. We'll add support for more formats in the future! -

    + +
    + +
    -

    - 🔗 resources -

    -
      -
    • - Source code (hosted on GitHub, licensed under AGPL-3.0) -
    • - -
    • - Discord server (for chit-chat, suggestions, and support) -
    • -
    - -

    - 🎨 credits -

    -
    - {#each credits as credit, i} - - {/each} + +
    + + + +
    - -

    - (obviously inspired by cobalt.tools) -

    - - diff --git a/src/routes/convert/+page.svelte b/src/routes/convert/+page.svelte index 0ce24c2..86f717a 100644 --- a/src/routes/convert/+page.svelte +++ b/src/routes/convert/+page.svelte @@ -1,568 +1,180 @@ - - Your Conversions - - - - - -
    - {#if files.files.length === 0} -

    - No files uploaded. Head to the Upload tab to begin! -

    - {:else} -
    -
    +
    + {#if !file.converter} + + {:else if isAudio} + + {:else} + + {/if} +
    + {#if file.processing} + + {:else} +

    + {file.name} +

    + {/if} +
    + - - -
    -
    -
    - {#each reversedFiles as file, i (file.id)} - {@const converter = (() => { - return converters.find((c) => - c.supportedFormats.includes( - file.from.toLowerCase(), - ), - ); - })()} -
    -
    -
    -
    -
    -
    - {#if processings[files.files.length - i - 1]} -
    - -
    - {:else} -

    - {file.file.name} -

    - {/if} -
    - -
    -
    -
    -
    -
    -
    - {#if converter && converter.supportedFormats.includes(file.from.toLowerCase())} - from - {file.from} - to -
    - { - file.result = - null; - }} - /> -
    - {:else} - {file.from} - - - is not supported! - - {/if} -
    -
    - -
    -
    -
    - {#if converter && converter.supportedFormats.includes(file.from.toLowerCase())} - -
    - {#if file.blobUrl} -
    -
    - -
    - {:else} -
    - -
    - {/if} -
    - {/if} -
    -
    - {/each} -
    + +
    - {/if} + {#if !file.converter} +
    +

    We can't convert this file.

    +

    + Only image and audio files are supported +

    +
    + {:else} +
    +
    +
    + {#if file.blobUrl} + {file.name} + {:else} +
    + {#if isAudio} + + {:else} + + {/if} +
    + {/if} +
    +
    +
    +
    + file.result && (file.result = null)} + /> +
    + + +
    +
    +
    +
    + {/if} + +{/snippet} + +
    +
    + +
    + +
    + {#each files.files as file, i (file.id)} + {#if files.files.length >= 2 && i === 1} + + {/if} + {@render fileItem(file, i)} + {#if files.files.length < 2} + + {/if} + {/each} + {#if files.files.length === 0} + + {/if} +
    - - diff --git a/src/routes/settings/+page.svelte b/src/routes/settings/+page.svelte new file mode 100644 index 0000000..1c79d95 --- /dev/null +++ b/src/routes/settings/+page.svelte @@ -0,0 +1,31 @@ + + +
    +

    + + Settings +

    + +
    + +
    + +
    + +
    + +
    +
    + + +
    diff --git a/static/coi-serviceworker.min.js b/static/coi-serviceworker.min.js new file mode 100644 index 0000000..117f9f8 --- /dev/null +++ b/static/coi-serviceworker.min.js @@ -0,0 +1,2 @@ +/*! coi-serviceworker v0.1.7 - Guido Zuidhof and contributors, licensed under MIT */ +let coepCredentialless=!1;"undefined"==typeof window?(self.addEventListener("install",(()=>self.skipWaiting())),self.addEventListener("activate",(e=>e.waitUntil(self.clients.claim()))),self.addEventListener("message",(e=>{e.data&&("deregister"===e.data.type?self.registration.unregister().then((()=>self.clients.matchAll())).then((e=>{e.forEach((e=>e.navigate(e.url)))})):"coepCredentialless"===e.data.type&&(coepCredentialless=e.data.value))})),self.addEventListener("fetch",(function(e){const o=e.request;if("only-if-cached"===o.cache&&"same-origin"!==o.mode)return;const s=coepCredentialless&&"no-cors"===o.mode?new Request(o,{credentials:"omit"}):o;e.respondWith(fetch(s).then((e=>{if(0===e.status)return e;const o=new Headers(e.headers);return o.set("Cross-Origin-Embedder-Policy",coepCredentialless?"credentialless":"require-corp"),coepCredentialless||o.set("Cross-Origin-Resource-Policy","cross-origin"),o.set("Cross-Origin-Opener-Policy","same-origin"),new Response(e.body,{status:e.status,statusText:e.statusText,headers:o})})).catch((e=>console.error(e))))}))):(()=>{const e=window.sessionStorage.getItem("coiReloadedBySelf");window.sessionStorage.removeItem("coiReloadedBySelf");const o="coepdegrade"==e,s={shouldRegister:()=>!e,shouldDeregister:()=>!1,coepCredentialless:()=>!0,coepDegrade:()=>!0,doReload:()=>window.location.reload(),quiet:!1,...window.coi},r=navigator,t=r.serviceWorker&&r.serviceWorker.controller;t&&!window.crossOriginIsolated&&window.sessionStorage.setItem("coiCoepHasFailed","true");const i=window.sessionStorage.getItem("coiCoepHasFailed");if(t){const e=s.coepDegrade()&&!(o||window.crossOriginIsolated);r.serviceWorker.controller.postMessage({type:"coepCredentialless",value:!(e||i&&s.coepDegrade())&&s.coepCredentialless()}),e&&(!s.quiet&&console.log("Reloading page to degrade COEP."),window.sessionStorage.setItem("coiReloadedBySelf","coepdegrade"),s.doReload("coepdegrade")),s.shouldDeregister()&&r.serviceWorker.controller.postMessage({type:"deregister"})}!1===window.crossOriginIsolated&&s.shouldRegister()&&(window.isSecureContext?r.serviceWorker?r.serviceWorker.register(window.document.currentScript.src).then((e=>{!s.quiet&&console.log("COOP/COEP Service Worker registered",e.scope),e.addEventListener("updatefound",(()=>{!s.quiet&&console.log("Reloading page to make use of updated COOP/COEP Service Worker."),window.sessionStorage.setItem("coiReloadedBySelf","updatefound"),s.doReload()})),e.active&&!r.serviceWorker.controller&&(!s.quiet&&console.log("Reloading page to make use of COOP/COEP Service Worker."),window.sessionStorage.setItem("coiReloadedBySelf","notcontrolling"),s.doReload())}),(e=>{!s.quiet&&console.error("COOP/COEP Service Worker failed to register:",e)})):!s.quiet&&console.error("COOP/COEP Service Worker not registered, perhaps due to private mode."):!s.quiet&&console.log("COOP/COEP Service Worker not registered, a secure context is required."))})(); \ No newline at end of file diff --git a/static/favicon.png b/static/favicon.png index 4f8beeb..1e9a539 100644 Binary files a/static/favicon.png and b/static/favicon.png differ diff --git a/static/favicon.webp b/static/favicon.webp new file mode 100644 index 0000000..389e4d2 Binary files /dev/null and b/static/favicon.webp differ diff --git a/static/magick.wasm b/static/magick.wasm deleted file mode 100644 index 626cd6d..0000000 Binary files a/static/magick.wasm and /dev/null differ diff --git a/svelte.config.js b/svelte.config.js index 2a86860..76b86fe 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -1,4 +1,4 @@ -import adapter from "svelte-adapter-bun"; +import adapter from "@sveltejs/adapter-static"; import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"; /** @type {import('@sveltejs/kit').Config} */ diff --git a/tailwind.config.ts b/tailwind.config.ts index 2cc0fae..4dab3f9 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -5,15 +5,38 @@ export default { content: ["./src/**/*.{html,js,svelte,ts}"], theme: { extend: { - colors: { - background: "var(--bg)", + backgroundColor: { + panel: "var(--bg-panel)", + "panel-accented": "var(--bg-panel-accented)", + separator: "var(--bg-separator)", + button: "var(--bg-button)", + "panel-alt": "var(--bg-button)", + badge: "var(--bg-badge)", + }, + borderColor: { + separator: "var(--bg-separator)", + button: "var(--bg-button)", + }, + textColor: { foreground: "var(--fg)", - "foreground-muted": "var(--fg-muted)", - "foreground-muted-alt": "var(--fg-muted-alt)", - "foreground-failure": "var(--fg-failure)", - "foreground-highlight": "var(--fg-highlight)", - "accent-background": "var(--accent-bg)", - "accent-foreground": "var(--accent-fg)", + muted: "var(--fg-muted)", + "on-accent": "var(--fg-on-accent)", + "on-badge": "var(--fg-on-badge)", + }, + colors: { + accent: "var(--accent)", + "accent-alt": "var(--accent-alt)", + "accent-pink": "var(--accent-pink)", + "accent-pink-alt": "var(--accent-pink-alt)", + "accent-red": "var(--accent-red)", + "accent-red-alt": "var(--accent-red-alt)", + "accent-purple-alt": "var(--accent-purple-alt)", + "accent-purple": "var(--accent-purple)", + "accent-blue": "var(--accent-blue)", + "accent-blue-alt": "var(--accent-blue-alt)", + }, + boxShadow: { + panel: "var(--shadow-panel)", }, fontFamily: { display: "var(--font-display)", @@ -22,6 +45,9 @@ export default { blur: { xs: "2px", }, + borderRadius: { + "2.5xl": "1.25rem", + }, }, }, diff --git a/vite.config.ts b/vite.config.ts index d48daa2..56a46a8 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,5 +1,6 @@ import { sveltekit } from "@sveltejs/kit/vite"; import { defineConfig } from "vite"; +import svg from "@poppanator/sveltekit-svg"; export default defineConfig({ plugins: [ @@ -17,6 +18,19 @@ export default defineConfig({ }); }, }, + svg({ + includePaths: ["./src/lib/assets"], + svgoOptions: { + multipass: true, + plugins: [ + { + name: "preset-default", + params: { overrides: { removeViewBox: false } }, + }, + { name: "removeAttrs", params: { attrs: "(fill|stroke)" } }, + ], + }, + }), ], optimizeDeps: { exclude: [