Spaces:
Runtime error
Runtime error
<script lang="ts"> | |
import { colors, cheersMessages, badgesComponents } from '$lib/utils'; | |
import type { Board } from '../types'; | |
import { fade, scale } from 'svelte/transition'; | |
import { createEventDispatcher, onDestroy, onMount } from 'svelte'; | |
import type { SvelteComponent } from 'svelte'; | |
import { dev } from '$app/env'; | |
const dispatch = createEventDispatcher(); | |
export let board: Board; | |
export let currentRowIndex: number; | |
export let imagePaths: string[]; | |
export let totalStreaks: number; | |
const message = cheersMessages[currentRowIndex]; | |
import domtoimage from 'dom-to-image'; | |
const apiUrl = dev ? 'http://localhost:7860/' : ''; | |
let modalEl: HTMLDivElement; | |
let elToShare: HTMLDivElement; | |
let disableDownload: boolean = false; | |
async function saveFile(node: HTMLDivElement) { | |
disableDownload = true; | |
try { | |
const blob = await domtoimage.toBlob(node, { bgcolor: '#000' }); | |
const a = document.createElement('a'); | |
a.download = `sucess-${Date.now()}.png`; | |
a.target = '_self'; | |
a.onclick = async (e) => { | |
disableDownload = true; | |
if (a.href) { | |
URL.revokeObjectURL(a.href); | |
disableDownload = false; | |
return; | |
} | |
a.href = URL.createObjectURL(blob); | |
disableDownload = false; | |
}; | |
a.click(); | |
console.log('Downloding image.'); | |
} catch (err) { | |
console.log(err.name, err.message); | |
} | |
} | |
const onKeyup = (e: KeyboardEvent) => { | |
if (e.key === 'Escape' || e.key === 'Enter') { | |
dispatch('restart'); | |
} else if (e.key === ' ') { | |
saveFile(elToShare); | |
} | |
}; | |
let badgeComponent: SvelteComponent; | |
onMount(async () => { | |
if (totalStreaks in badgesComponents) { | |
const compName = badgesComponents[totalStreaks]; | |
badgeComponent = (await import(`./badges/${compName}.svelte`)).default; | |
} | |
setTimeout(() => { | |
window.addEventListener('keyup', onKeyup, true); | |
}, 1000); | |
}); | |
onDestroy(() => { | |
window.removeEventListener('keyup', onKeyup, true); | |
}); | |
const s = 10; | |
const p = 1; | |
const rx = s / 10; | |
</script> | |
<!-- Modal made with tailwind --> | |
<div bind:this={modalEl} class="modal relative z-50" transition:fade> | |
<div class="message"> | |
<div class="border-0"> | |
<div class="p-3" bind:this={elToShare}> | |
<header class="p-3 flex justify-between items-center"> | |
<h1 class="text-xs font-bold uppercase whitespace-nowrap">WORDALLE π₯</h1> | |
<span class="font-light">hf.co/wordalle</span> | |
</header> | |
<h2 class="text-center uppercase tracking-widest font-extrabold">{message}</h2> | |
<div class="grid grid-cols-3 gap-2 p-3 relative"> | |
{#if totalStreaks in badgesComponents} | |
<div | |
transition:scale={{ duration: 500 }} | |
class="absolute left-0 right-0 top-0 bottom-0 flex place-content-center place-items-center" | |
> | |
<svelte:component this={badgeComponent} classNames="w-full max-w-[180px]" /> | |
</div> | |
{/if} | |
{#each imagePaths as image} | |
<div> | |
<img src={apiUrl + image} alt="" class="aspect-square w-full h-full" /> | |
</div> | |
{/each} | |
</div> | |
<svg | |
class="w-full p-3 mx-auto max-h-[30vh]" | |
viewBox="0 0 {board[0].length * (p + s) - p} {board.length * (p + s) - p}" | |
xmlns="http://www.w3.org/2000/svg" | |
> | |
{#each board as row, y} | |
{#each row as tile, x} | |
<rect | |
fill={colors[tile.state]} | |
x={x * (s + p)} | |
y={y * (s + p)} | |
width={s} | |
height={s} | |
{rx} | |
/> | |
{/each} | |
{/each} | |
</svg> | |
</div> | |
</div> | |
<div class="p-3 px-6 flex text-base"> | |
<button | |
disabled={disableDownload} | |
class="min-w-[15ch] flex-1 mr-1" | |
on:click={() => saveFile(elToShare)} | |
> | |
{!disableDownload ? 'SAVE SCREENSHOT' : 'SAVING..'} | |
</button> | |
<button class="flex-1 ml-1" on:click={() => dispatch('restart')}> NEXT </button> | |
</div> | |
</div> | |
</div> | |
<style lang="postcss" scoped> | |
.message { | |
@apply text-white bg-black bg-opacity-80 font-semibold p-10 z-20 rounded-md transition-opacity duration-300 ease-in-out mx-auto max-w-lg; | |
} | |
.modal { | |
@apply fixed top-0 left-0 w-screen min-h-screen z-10 bg-black bg-opacity-80 backdrop-blur-sm; | |
transform: translateZ(1000px); | |
transform-style: preserve-3d; | |
} | |
.go-tweet, | |
button { | |
@apply bg-gray-700 hover:bg-gray-900 text-white font-bold p-1 my-1 text-sm rounded transition-opacity duration-500 ease-in-out; | |
} | |
</style> | |