Compare commits
3 commits
55e1d56ba3
...
df0853c111
Author | SHA1 | Date | |
---|---|---|---|
df0853c111 | |||
677c312eaf | |||
1324a51bec |
10 changed files with 88 additions and 27 deletions
|
@ -81,12 +81,6 @@
|
||||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
|
||||||
<script
|
|
||||||
defer
|
|
||||||
src="https://umami.leomurca.xyz/script.js"
|
|
||||||
data-website-id="bd4c0533-36e6-402d-ac04-577993aaf43a"
|
|
||||||
></script>
|
|
||||||
|
|
||||||
<link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96" />
|
<link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
<link rel="shortcut icon" href="/favicon.ico" />
|
<link rel="shortcut icon" href="/favicon.ico" />
|
||||||
|
|
13
src/lib/components/Analytics.svelte
Normal file
13
src/lib/components/Analytics.svelte
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<script>
|
||||||
|
import { isDevelopment } from '$lib/utils/env';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
{#if !isDevelopment()}
|
||||||
|
<script
|
||||||
|
defer
|
||||||
|
src="https://umami.leomurca.xyz/script.js"
|
||||||
|
data-website-id="bd4c0533-36e6-402d-ac04-577993aaf43a"
|
||||||
|
></script>
|
||||||
|
{/if}
|
||||||
|
</svelte:head>
|
|
@ -2,17 +2,30 @@
|
||||||
import { t } from '$lib/translations';
|
import { t } from '$lib/translations';
|
||||||
import renderFileToCanvas from '$lib/file-renderer';
|
import renderFileToCanvas from '$lib/file-renderer';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {ArrayLike<any>}
|
||||||
|
*/
|
||||||
export let files = [];
|
export let files = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {HTMLElement}
|
||||||
|
*/
|
||||||
|
let errorMessageRef;
|
||||||
let canvasRefs = [];
|
let canvasRefs = [];
|
||||||
let colorRefs = [];
|
let colorRefs = [];
|
||||||
let stitchesRefs = [];
|
let stitchesRefs = [];
|
||||||
let sizeRefs = [];
|
let sizeRefs = [];
|
||||||
let errorMessageRef;
|
|
||||||
let localizedStrings = {
|
let localizedStrings = {
|
||||||
stitches: $t('viewer.stitches'),
|
stitches: $t('viewer.stitches'),
|
||||||
dimensions: $t('viewer.dimensions'),
|
dimensions: $t('viewer.dimensions'),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Downloads a given HTMLCanvasElement as a PNG image.
|
||||||
|
*
|
||||||
|
* @param {HTMLCanvasElement} canvas - The canvas element to export as an image.
|
||||||
|
* @param {string} filename - The desired name of the downloaded file (extension will be replaced with `.png`).
|
||||||
|
*/
|
||||||
const downloadCanvasAsImage = (canvas, filename) => {
|
const downloadCanvasAsImage = (canvas, filename) => {
|
||||||
const image = canvas
|
const image = canvas
|
||||||
.toDataURL('image/png')
|
.toDataURL('image/png')
|
||||||
|
@ -24,9 +37,15 @@
|
||||||
link.click();
|
link.click();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cliks the button to render the files when user press enter.
|
||||||
|
*
|
||||||
|
* @param {KeyboardEvent} evt - The event that triggered the language switch.
|
||||||
|
*/
|
||||||
const onKeydown = (evt) => {
|
const onKeydown = (evt) => {
|
||||||
if (evt.key === 'Enter') {
|
if (evt.key === 'Enter') {
|
||||||
document.getElementById('download-button').click();
|
const button = document.getElementById('download-button');
|
||||||
|
if (button) button.click();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -44,8 +63,8 @@
|
||||||
id="download-button"
|
id="download-button"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
on:keydown={onKeydown}
|
onkeydown={onKeydown}
|
||||||
on:click={() => downloadCanvasAsImage(canvasRefs[i], file.name)}
|
onclick={() => downloadCanvasAsImage(canvasRefs[i], file.name)}
|
||||||
>
|
>
|
||||||
{$t('viewer.download')}
|
{$t('viewer.download')}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
|
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
|
||||||
|
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
|
||||||
<div
|
<div
|
||||||
id="dropzone"
|
id="dropzone"
|
||||||
tabindex={0}
|
tabindex={0}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
<script>
|
<script>
|
||||||
export let title;
|
export let title;
|
||||||
|
/**
|
||||||
|
* @type {ArrayLike<any>}
|
||||||
|
*/
|
||||||
export let files = [];
|
export let files = [];
|
||||||
export let isError = false;
|
export let isError = false;
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,15 +1,28 @@
|
||||||
<script>
|
<script>
|
||||||
import { t, locale, locales, SUPPORTED_LOCALES } from '$lib/translations';
|
import { t, locale, SUPPORTED_LOCALES } from '$lib/translations';
|
||||||
import logo from '$lib/assets/logo.webp';
|
import logo from '$lib/assets/logo.webp';
|
||||||
import MediaQuery from './MediaQuery.svelte';
|
import MediaQuery from './MediaQuery.svelte';
|
||||||
|
|
||||||
const configsFor = (/** @type {boolean} */ matches) => {
|
/**
|
||||||
|
*
|
||||||
|
* Returns logo image configuration based on the screen size match.
|
||||||
|
*
|
||||||
|
* @param {boolean} matches - The event that triggered the language switch.
|
||||||
|
*/
|
||||||
|
const configsFor = (matches) => {
|
||||||
return matches
|
return matches
|
||||||
? { src: logo, width: 150, height: 70 } // mobile
|
? { src: logo, width: 150, height: 70 } // mobile
|
||||||
: { src: logo, width: 150, height: 100 }; // desktop
|
: { src: logo, width: 150, height: 100 }; // desktop
|
||||||
};
|
};
|
||||||
|
|
||||||
const onSwitchToOppositeLang = () => {
|
/**
|
||||||
|
* Switches the current locale to the opposite language (EN_US <-> PT_BR).
|
||||||
|
* Prevents the default link behavior (e.g., page jump).
|
||||||
|
*
|
||||||
|
* @param {MouseEvent | KeyboardEvent} e - The event that triggered the language switch.
|
||||||
|
*/
|
||||||
|
const onSwitchToOppositeLang = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
$locale =
|
$locale =
|
||||||
$locale === SUPPORTED_LOCALES.EN_US
|
$locale === SUPPORTED_LOCALES.EN_US
|
||||||
? SUPPORTED_LOCALES.PT_BR
|
? SUPPORTED_LOCALES.PT_BR
|
||||||
|
@ -38,7 +51,7 @@
|
||||||
<MediaQuery query="(max-width: 768px)" let:matches>
|
<MediaQuery query="(max-width: 768px)" let:matches>
|
||||||
<slot let-matches>
|
<slot let-matches>
|
||||||
{#if matches}
|
{#if matches}
|
||||||
<button class="hamburger" on:click={() => (isMenuOpen = !isMenuOpen)}>
|
<button class="hamburger" onclick={() => (isMenuOpen = !isMenuOpen)}>
|
||||||
{#if isMenuOpen}x{:else}☰{/if}
|
{#if isMenuOpen}x{:else}☰{/if}
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -61,17 +74,22 @@
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<a
|
<button
|
||||||
|
type="button"
|
||||||
class="common-switch {$locale === SUPPORTED_LOCALES.EN_US
|
class="common-switch {$locale === SUPPORTED_LOCALES.EN_US
|
||||||
? 'portuguese-switch'
|
? 'portuguese-switch'
|
||||||
: 'english-switch'}"
|
: 'english-switch'}"
|
||||||
href="#"
|
onclick={onSwitchToOppositeLang}
|
||||||
on:click|preventDefault={onSwitchToOppositeLang}
|
onkeydown={(e) => {
|
||||||
|
if (e.key === 'Enter' || e.key === ' ') {
|
||||||
|
onSwitchToOppositeLang(e);
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div style="display: flex; width: fit-content;">
|
<div style="display: flex; width: fit-content;">
|
||||||
<span style="font-size: 20px;">{$t('header.languageSwitch')}</span>
|
<span style="font-size: 20px;">{$t('header.languageSwitch')}</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
@ -130,7 +148,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.common-switch {
|
.common-switch {
|
||||||
|
border: none;
|
||||||
|
background-color: unset;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.portuguese-switch {
|
.portuguese-switch {
|
||||||
|
|
|
@ -50,12 +50,12 @@
|
||||||
<meta property="og:type" content={ogType} />
|
<meta property="og:type" content={ogType} />
|
||||||
<meta property="og:title" content={$t(ogTitle)} />
|
<meta property="og:title" content={$t(ogTitle)} />
|
||||||
<meta property="og:description" content={$t(ogDescription)} />
|
<meta property="og:description" content={$t(ogDescription)} />
|
||||||
<meta property="og:image" content={$t(ogImage)} />
|
<!-- <meta property="og:image" content={$t(ogImage)} /> -->
|
||||||
<meta property="og:url" content={$t(url)} />
|
<meta property="og:url" content={$t(url)} />
|
||||||
|
|
||||||
<!-- Twitter -->
|
<!-- Twitter -->
|
||||||
<meta name="twitter:card" content={$t(twitterCard)} />
|
<meta name="twitter:card" content={$t(twitterCard)} />
|
||||||
<meta name="twitter:title" content={$t(twitterTitle)} />
|
<meta name="twitter:title" content={$t(twitterTitle)} />
|
||||||
<meta name="twitter:description" content={$t(twitterDescription)} />
|
<meta name="twitter:description" content={$t(twitterDescription)} />
|
||||||
<meta name="twitter:image" content={$t(twitterImage)} />
|
<!-- <meta name="twitter:image" content={$t(twitterImage)} /> -->
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
|
@ -4,4 +4,8 @@ function appVersion() {
|
||||||
return APP_VERSION;
|
return APP_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
export { appVersion };
|
function isDevelopment() {
|
||||||
|
return import.meta.env.MODE === 'development';
|
||||||
|
}
|
||||||
|
|
||||||
|
export { appVersion, isDevelopment };
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
import Header from '$lib/components/Header.svelte';
|
import Header from '$lib/components/Header.svelte';
|
||||||
import Footer from '$lib/components/Footer.svelte';
|
import Footer from '$lib/components/Footer.svelte';
|
||||||
|
import Analytics from '$lib/components/Analytics.svelte';
|
||||||
|
|
||||||
let mounted = false;
|
let mounted = false;
|
||||||
|
|
||||||
|
@ -14,6 +15,8 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<Analytics />
|
||||||
|
|
||||||
{#if mounted}
|
{#if mounted}
|
||||||
<Header />
|
<Header />
|
||||||
<main>
|
<main>
|
||||||
|
|
|
@ -24,7 +24,14 @@
|
||||||
maxSize: 1000000,
|
maxSize: 1000000,
|
||||||
};
|
};
|
||||||
|
|
||||||
function onSubmit() {
|
/**
|
||||||
|
* Update the flag that indicates that the files were rendered.
|
||||||
|
*
|
||||||
|
* @param {SubmitEvent} e
|
||||||
|
*/
|
||||||
|
function onSubmit(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
areAcceptedFilesRendered = true;
|
areAcceptedFilesRendered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,11 +85,7 @@
|
||||||
|
|
||||||
<Seo {...metadata} />
|
<Seo {...metadata} />
|
||||||
|
|
||||||
<form
|
<form id="form" enctype="multipart/form-data" onsubmit={onSubmit}>
|
||||||
id="form"
|
|
||||||
enctype="multipart/form-data"
|
|
||||||
on:submit|preventDefault|stopPropagation={onSubmit}
|
|
||||||
>
|
|
||||||
<div class="title-container">
|
<div class="title-container">
|
||||||
<h2>{$t('viewer.title')}</h2>
|
<h2>{$t('viewer.title')}</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Reference in a new issue